@mixd-id/web-scaffold 0.1.230406221 → 0.1.230406223

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@mixd-id/web-scaffold",
3
3
  "private": false,
4
- "version": "0.1.230406221",
4
+ "version": "0.1.230406223",
5
5
  "scripts": {
6
6
  "dev": "vite serve",
7
7
  "build": "vite build",
@@ -1,7 +1,7 @@
1
1
  <template>
2
2
  <div :class="$style.comp">
3
3
  <input :id="id" type="checkbox" :checked="checked" @change="onChange" :disabled="isDisabled"/>
4
- <label :for="id">
4
+ <label :for="id" :class="labelClass">
5
5
  <div :class="$style.indicator" v-if="Boolean(showIcon)">
6
6
  <Transition name="checkbox">
7
7
  <div v-if="checked">
@@ -29,7 +29,8 @@ export default {
29
29
  showIcon: {
30
30
  type: undefined,
31
31
  default: true
32
- }
32
+ },
33
+ itemClass: String
33
34
  },
34
35
 
35
36
  computed: {
@@ -42,6 +43,14 @@ export default {
42
43
  return parseBoolean(this.disabled)
43
44
  },
44
45
 
46
+ labelClass(){
47
+ return [
48
+ this.$style.label,
49
+ this.itemClass,
50
+ ]
51
+ .join(' ')
52
+ },
53
+
45
54
  checked(){
46
55
  if(this.value !== undefined){
47
56
  if(Array.isArray(this.modelValue)){
@@ -120,6 +129,10 @@ export default {
120
129
  @apply flex flex-row items-start gap-2;
121
130
  }
122
131
 
132
+ .comp label *{
133
+ @apply pointer-events-none;
134
+ }
135
+
123
136
  .comp label>*:last-child{
124
137
  @apply flex-1;
125
138
  }
@@ -79,7 +79,7 @@ export default{
79
79
 
80
80
  hash: String,
81
81
 
82
- height: String,
82
+ height: [ String, Number ],
83
83
 
84
84
  dock: String,
85
85
 
@@ -92,7 +92,7 @@ export default{
92
92
 
93
93
  transition: String,
94
94
 
95
- width: String,
95
+ width: [ String, Number ],
96
96
 
97
97
  useForm: {
98
98
  type: Boolean,
@@ -305,7 +305,7 @@ export default{
305
305
  @apply fixed;
306
306
  @apply bg-base-400;
307
307
  @apply border-[1px] border-text-50 z-20 flex max-h-[90vh];
308
- @apply rounded-xl overflow-hidden;
308
+ @apply rounded-xl overflow-hidden transition-all;
309
309
  }
310
310
 
311
311
  .modal.v-show{
@@ -239,11 +239,11 @@ export default{
239
239
  }
240
240
 
241
241
  .item:hover{
242
- @apply bg-text-50;
242
+ @apply bg-primary-50;
243
243
  }
244
244
 
245
245
  .item.trSelected{
246
- @apply bg-text-100;
246
+ @apply bg-primary-100;
247
247
  }
248
248
 
249
249
  .highlight{
@@ -18,7 +18,7 @@ const plugin = Plugin(function({ addBase, config, theme }) {
18
18
 
19
19
  '--base-50': '255, 255, 255',
20
20
  '--base-200': '222, 224, 227',
21
- '--base-300': '246, 248, 251',
21
+ '--base-300': '237, 243, 255',
22
22
  '--base-400': '255, 255, 255',
23
23
  '--base-500': '255, 255, 255',
24
24
  '--base': '236, 236, 236',
@@ -1,29 +1,51 @@
1
1
  <template>
2
2
  <div :class="$style.comp">
3
3
 
4
- <div v-for="(_, idx) in viewTypes"
5
- v-show="viewType === _.value">
6
- <div class="flex flex-col gap-4">
7
- <div>
8
- <strong class="flex-1 text-text-400">Carousel</strong>
9
- <div class="h-[1px] bg-text-100 mt-2"></div>
10
- </div>
4
+ <div>
5
+ <div class="flex flex-row gap-1 items-center cursor-pointer">
6
+ <svg v-if="!expanded['carousel']" width="12" height="12" @click="expanded['carousel'] = !expanded['carousel']" class="fill-text" 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>
7
+ <svg v-else width="12" height="12" @click="expanded['carousel'] = !expanded['carousel']" class="fill-text" 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>
8
+ <strong class="flex-1 text-text-400 line-clamp-1" @click="expanded['carousel'] = !expanded['carousel']">Carousel</strong>
9
+ <button type="button" class="text-primary" @click="$router.replace({ hash:'#select-property' })">
10
+ <svg width="16" height="16" class="fill-text-300 hover:fill-primary-500" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512"><path d="M368 224H224V80c0-8.84-7.16-16-16-16h-32c-8.84 0-16 7.16-16 16v144H16c-8.84 0-16 7.16-16 16v32c0 8.84 7.16 16 16 16h144v144c0 8.84 7.16 16 16 16h32c8.84 0 16-7.16 16-16V288h144c8.84 0 16-7.16 16-16v-32c0-8.84-7.16-16-16-16z"/></svg>
11
+ </button>
12
+ </div>
11
13
 
12
- <div class="grid grid-cols-2 gap-4">
14
+ <div class="h-[1px] bg-text-100 mt-2 mb-4"></div>
13
15
 
14
- <div>
15
- <label class="text-text-400">Gap</label>
16
- <Dropdown v-model="containerGap[idx]" class="mt-1" @change="apply">
17
- <option :value="`${viewType}gap-0`">0</option>
18
- <option :value="`${viewType}gap-1`">1</option>
19
- <option :value="`${viewType}gap-2`">2</option>
20
- <option :value="`${viewType}gap-3`">3</option>
21
- <option :value="`${viewType}gap-4`">4</option>
22
- <option :value="`${viewType}gap-5`">5</option>
23
- <option :value="`${viewType}gap-6`">6</option>
24
- </Dropdown>
16
+ <div v-if="expanded['carousel']" class="flex flex-col gap-8">
17
+
18
+ <div>
19
+ <div class="flex flex-row items-center gap-2">
20
+ <label class="flex-1 text-text-400">Gap</label>
21
+ <button type="button" v-if="containerGap.length < 2" @click="containerGap.push('')">
22
+ <svg width="16" height="16" class="fill-text-300 hover:fill-primary-500" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path d="M352 240v32c0 6.6-5.4 12-12 12h-88v88c0 6.6-5.4 12-12 12h-32c-6.6 0-12-5.4-12-12v-88h-88c-6.6 0-12-5.4-12-12v-32c0-6.6 5.4-12 12-12h88v-88c0-6.6 5.4-12 12-12h32c6.6 0 12 5.4 12 12v88h88c6.6 0 12 5.4 12 12zm96-160v352c0 26.5-21.5 48-48 48H48c-26.5 0-48-21.5-48-48V80c0-26.5 21.5-48 48-48h352c26.5 0 48 21.5 48 48zm-48 346V86c0-3.3-2.7-6-6-6H54c-3.3 0-6 2.7-6 6v340c0 3.3 2.7 6 6 6h340c3.3 0 6-2.7 6-6z"/></svg>
23
+ </button>
24
+ </div>
25
+ <div class="flex flex-row gap-2">
26
+ <div v-for="(_, index) in containerGap" class="items-start">
27
+ <div class="flex flex-row">
28
+ <small class="w-[60px] flex-1 text-text-300">{{ viewTypes[index].text }}</small>
29
+ <button type="button" v-if="index > 0" @click="containerGap.splice(index, 1)">
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="M207.6 256l107.72-107.72c6.23-6.23 6.23-16.34 0-22.58l-25.03-25.03c-6.23-6.23-16.34-6.23-22.58 0L160 208.4 52.28 100.68c-6.23-6.23-16.34-6.23-22.58 0L4.68 125.7c-6.23 6.23-6.23 16.34 0 22.58L112.4 256 4.68 363.72c-6.23 6.23-6.23 16.34 0 22.58l25.03 25.03c6.23 6.23 16.34 6.23 22.58 0L160 303.6l107.72 107.72c6.23 6.23 16.34 6.23 22.58 0l25.03-25.03c6.23-6.23 6.23-16.34 0-22.58L207.6 256z"/></svg>
31
+ </button>
32
+ </div>
33
+ <div class="flex flex-row items-start gap-2">
34
+ <Dropdown v-model="containerGap[index]" class="mt-1 min-w-[100px]" @change="apply">
35
+ <option :value="`${viewType}gap-0`">0</option>
36
+ <option :value="`${viewType}gap-1`">1</option>
37
+ <option :value="`${viewType}gap-2`">2</option>
38
+ <option :value="`${viewType}gap-3`">3</option>
39
+ <option :value="`${viewType}gap-4`">4</option>
40
+ <option :value="`${viewType}gap-5`">5</option>
41
+ <option :value="`${viewType}gap-6`">6</option>
42
+ </Dropdown>
43
+ </div>
44
+ </div>
25
45
  </div>
46
+ </div>
26
47
 
48
+ <div class="grid grid-cols-2 gap-4">
27
49
  <div>
28
50
  <label class="text-text-400">Autoplay</label>
29
51
  <Dropdown v-model="item.props.autoPlay" class="mt-1" @change="apply">
@@ -32,24 +54,25 @@
32
54
  </Dropdown>
33
55
  </div>
34
56
 
35
- <div class="grid grid-cols-2 gap-4">
57
+ <div class="flex flex-row gap-4">
36
58
  <div>
37
59
  <label class="text-text-400">Legend</label>
38
- <div class="mt-1">
60
+ <div class="mt-1 py-2">
39
61
  <Checkbox v-model="item.props.useLegend" @change="apply"/>
40
62
  </div>
41
63
  </div>
42
64
  <div>
43
65
  <label class="text-text-400">Infinite</label>
44
- <div class="mt-1">
66
+ <div class="mt-1 py-2">
45
67
  <Checkbox v-model="item.props.infinite" @change="apply"/>
46
68
  </div>
47
69
  </div>
48
70
  </div>
49
-
50
71
  </div>
72
+
51
73
  </div>
52
- </div>
74
+
75
+ </div>
53
76
 
54
77
  <ComponentSetting2 :item="item"
55
78
  :view-type="viewType"
@@ -127,6 +150,22 @@ export default{
127
150
 
128
151
  computed: {
129
152
 
153
+ componentStore(){
154
+ if(this.store && this.store.components){
155
+ if(!this.store.components.compsetting)
156
+ this.store.components.compsetting = {}
157
+
158
+ return this.store.components.compsetting
159
+ }
160
+ return {}
161
+ },
162
+
163
+ expanded(){
164
+ if(!this.componentStore['expanded'])
165
+ this.componentStore['expanded'] = {}
166
+ return this.componentStore['expanded']
167
+ },
168
+
130
169
  items(){
131
170
  if(!Array.isArray(this.item.items))
132
171
  this.item.items = []
@@ -148,7 +187,7 @@ export default{
148
187
  <style module>
149
188
 
150
189
  .comp{
151
- @apply flex flex-col gap-6;
190
+ @apply flex flex-col gap-8;
152
191
  }
153
192
 
154
193
  </style>
@@ -1,52 +1,61 @@
1
1
  <template>
2
2
  <div :class="$style.comp">
3
3
 
4
- <div class="flex flex-col gap-4">
5
-
6
- <div>
7
- <label class="flex-1 text-text-400">HTML</label>
8
- <Textarea v-model="item.props.html" @keyup.enter="$emit('change')"/>
9
- </div>
10
-
11
- <div>
12
- <label class="flex-1 text-text-400">View box</label>
13
- <Textarea v-model="item.props.viewBox" @keyup.enter="$emit('change')" placeholder="ex: 0 0 480 480"/>
14
- </div>
15
-
16
- <div>
17
- <label class="flex-1 text-text-400">Width</label>
18
- <Dropdown v-model="item.props.svgWidth" @keyup.enter="$emit('change')">
19
- <option value="">Not Set</option>
20
- <option value="11">11</option>
21
- <option value="12">12</option>
22
- <option value="16">16</option>
23
- <option value="18">18</option>
24
- <option value="21">21</option>
25
- <option value="24">24</option>
26
- <option value="32">32</option>
27
- <option value="36">36</option>
28
- <option value="48">48</option>
29
- <option value="56">56</option>
30
- <option value="64">64</option>
31
- </Dropdown>
4
+ <div>
5
+ <div class="flex flex-row gap-1 items-center cursor-pointer">
6
+ <svg v-if="!expanded['svg']" width="12" height="12" @click="expanded['svg'] = !expanded['svg']" class="fill-text" 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>
7
+ <svg v-else width="12" height="12" @click="expanded['svg'] = !expanded['svg']" class="fill-text" 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>
8
+ <strong class="flex-1 text-text-400 line-clamp-1" @click="expanded['svg'] = !expanded['svg']">SVG</strong>
32
9
  </div>
33
10
 
34
- <div>
35
- <label class="flex-1 text-text-400">Width</label>
36
- <Dropdown v-model="item.props.svgHeight" @keyup.enter="$emit('change')">
37
- <option value="">Not Set</option>
38
- <option value="11">11</option>
39
- <option value="12">12</option>
40
- <option value="16">16</option>
41
- <option value="18">18</option>
42
- <option value="21">21</option>
43
- <option value="24">24</option>
44
- <option value="32">32</option>
45
- <option value="36">36</option>
46
- <option value="48">48</option>
47
- <option value="56">56</option>
48
- <option value="64">64</option>
49
- </Dropdown>
11
+ <div class="h-[1px] bg-text-100 mt-2 mb-4"></div>
12
+
13
+ <div v-if="expanded['svg']" class="flex flex-col gap-8">
14
+ <div>
15
+ <label class="flex-1 text-text-400">HTML</label>
16
+ <Textarea v-model="item.props.html" @keyup.enter="$emit('change')"/>
17
+ </div>
18
+
19
+ <div>
20
+ <label class="flex-1 text-text-400">View box</label>
21
+ <Textarea v-model="item.props.viewBox" @keyup.enter="$emit('change')" placeholder="ex: 0 0 480 480"/>
22
+ </div>
23
+
24
+ <div>
25
+ <label class="flex-1 text-text-400">Width</label>
26
+ <Dropdown v-model="item.props.svgWidth" @keyup.enter="$emit('change')">
27
+ <option value="">Not Set</option>
28
+ <option value="11">11</option>
29
+ <option value="12">12</option>
30
+ <option value="16">16</option>
31
+ <option value="18">18</option>
32
+ <option value="21">21</option>
33
+ <option value="24">24</option>
34
+ <option value="32">32</option>
35
+ <option value="36">36</option>
36
+ <option value="48">48</option>
37
+ <option value="56">56</option>
38
+ <option value="64">64</option>
39
+ </Dropdown>
40
+ </div>
41
+
42
+ <div>
43
+ <label class="flex-1 text-text-400">Width</label>
44
+ <Dropdown v-model="item.props.svgHeight" @keyup.enter="$emit('change')">
45
+ <option value="">Not Set</option>
46
+ <option value="11">11</option>
47
+ <option value="12">12</option>
48
+ <option value="16">16</option>
49
+ <option value="18">18</option>
50
+ <option value="21">21</option>
51
+ <option value="24">24</option>
52
+ <option value="32">32</option>
53
+ <option value="36">36</option>
54
+ <option value="48">48</option>
55
+ <option value="56">56</option>
56
+ <option value="64">64</option>
57
+ </Dropdown>
58
+ </div>
50
59
  </div>
51
60
 
52
61
  </div>
@@ -84,7 +93,7 @@ export default{
84
93
  }
85
94
  },
86
95
 
87
- inject: [ 'confirm', 'imageSrc' ],
96
+ inject: [ 'confirm', 'imageSrc', 'store' ],
88
97
 
89
98
  methods: {
90
99
 
@@ -93,6 +102,22 @@ export default{
93
102
 
94
103
  computed: {
95
104
 
105
+ componentStore(){
106
+ if(this.store && this.store.components){
107
+ if(!this.store.components.compsetting)
108
+ this.store.components.compsetting = {}
109
+
110
+ return this.store.components.compsetting
111
+ }
112
+ return {}
113
+ },
114
+
115
+ expanded(){
116
+ if(!this.componentStore['expanded'])
117
+ this.componentStore['expanded'] = {}
118
+ return this.componentStore['expanded']
119
+ },
120
+
96
121
  }
97
122
 
98
123
  }
@@ -102,7 +127,7 @@ export default{
102
127
  <style module>
103
128
 
104
129
  .comp{
105
- @apply flex flex-col gap-6;
130
+ @apply flex flex-col gap-8;
106
131
  }
107
132
 
108
133
  </style>
@@ -256,75 +256,92 @@
256
256
  </div>
257
257
 
258
258
  <div v-if="store.layoutMode && layout" @click="currentArea = 'headers'">
259
- <div class="flex flex-row gap-2">
260
- <label class="flex-1 text-text-400">{{ $t('Header')}}</label>
261
- <button type="button" class="text-primary"
259
+ <div class="flex flex-row gap-1 items-center cursor-pointer">
260
+ <svg v-if="!expanded['headers']" width="12" height="12" @click="expanded['headers'] = !expanded['headers']" class="fill-text" 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>
261
+ <svg v-else width="12" height="12" @click="expanded['headers'] = !expanded['headers']" class="fill-text" 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>
262
+ <strong class="flex-1 text-text-400 line-clamp-1" @click="expanded['headers'] = !expanded['headers']">{{ $t('Header')}}</strong>
263
+ <button type="button" class="text-primary flex flex-row items-center gap-1"
262
264
  @click="openComponentSelector({ items:layout.headers, isLayout:true })">
263
- Add
265
+ <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>
266
+ {{ $t('Add')}}
264
267
  </button>
265
268
  </div>
266
- <TreeView class="mt-2"
267
- v-model="layoutHeaders"
268
- :selected-item="currentItem"
269
- @add="(items) => openComponentSelector({ items })">
270
- <template #default="{ item }">
271
- <div class="flex-1 text-ellipsis whitespace-nowrap overflow-hidden"
272
- :class="!item.props.enabled ? 'line-through' : ''"
273
- @click="select(item.uid)">
274
- {{ item.name ?? item.type }}
275
- </div>
276
- </template>
277
- </TreeView>
269
+ <div v-if="expanded['headers']" class="flex flex-col gap-10">
270
+ <TreeView class="mt-2"
271
+ v-model="layoutHeaders"
272
+ :selected-item="currentItem"
273
+ @add="(items) => openComponentSelector({ items })">
274
+ <template #default="{ item }">
275
+ <div class="flex-1 text-ellipsis whitespace-nowrap overflow-hidden"
276
+ :class="!item.props.enabled ? 'line-through' : ''"
277
+ @click="select(item.uid)">
278
+ {{ item.name ?? item.type }}
279
+ </div>
280
+ </template>
281
+ </TreeView>
282
+ </div>
278
283
  </div>
279
284
 
280
- <div v-if="store.layoutMode && layout" @click="currentArea = 'footers'">
281
- <div class="flex flex-row gap-2">
282
- <label class="flex-1 text-text-400">{{ $t('Footer')}}</label>
283
- <button type="button" class="text-primary"
284
- @click="openComponentSelector({ items:layoutFooters, isLayout:true })">
285
- Add
285
+ <div @click="currentArea = 'components'">
286
+ <div class="flex flex-row gap-1 items-center cursor-pointer">
287
+ <svg v-if="!expanded['components']" width="12" height="12" @click="expanded['components'] = !expanded['components']" class="fill-text" 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>
288
+ <svg v-else width="12" height="12" @click="expanded['components'] = !expanded['components']" class="fill-text" 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>
289
+ <strong class="flex-1 text-text-400 line-clamp-1" @click="expanded['components'] = !expanded['components']">{{ $t('Components')}}</strong>
290
+ <button type="button" class="text-primary flex flex-row items-center gap-1"
291
+ @click="openComponentSelector({ items:page.components }); currentArea = ''">
292
+ <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>
293
+ {{ $t('Add')}}
286
294
  </button>
287
295
  </div>
288
- <TreeView class="mt-2"
289
- v-model="layoutFooters"
290
- :selected-item="currentItem"
291
- @add="(items) => openComponentSelector({ items })">
292
- <template #default="{ item }">
293
- <div class="flex-1 text-ellipsis whitespace-nowrap overflow-hidden"
294
- :class="!item.props.enabled ? 'line-through' : ''"
295
- @click="select(item.uid)">
296
- {{ item.props.name ?? item.type }}
297
- </div>
298
- </template>
299
- </TreeView>
300
- </div>
301
296
 
302
- <div v-if="store.layoutMode && layout">
303
- <small class="text-text-400">{{ $t('Updating layout will affect all pages using this layout, proceed with caution.') }}</small>
297
+ <div v-if="expanded['components']" class="flex flex-col gap-10">
298
+ <TreeView class="mt-2"
299
+ v-model="page.components"
300
+ :selected-item="currentItem"
301
+ @add="(items) => openComponentSelector({ items })"
302
+ @change="pageHistory.commit()">
303
+ <template #default="{ item }">
304
+ <div class="flex-1 text-ellipsis whitespace-nowrap overflow-hidden"
305
+ :class="!item.props.enabled ? 'line-through' : ''"
306
+ @click="select(item.uid)">
307
+ {{ item.props.name ?? item.type }}
308
+ </div>
309
+ </template>
310
+ </TreeView>
311
+ </div>
312
+
304
313
  </div>
305
314
 
306
- <div v-if="!store.layoutMode" @click="currentArea = 'components'">
307
- <div class="flex flex-row gap-4">
308
- <label class="flex-1 text-text-400">{{ $t('Components')}}</label>
315
+ <div v-if="store.layoutMode && layout" @click="currentArea = 'footers'">
316
+ <div class="flex flex-row gap-1 items-center cursor-pointer">
317
+ <svg v-if="!expanded['footers']" width="12" height="12" @click="expanded['footers'] = !expanded['footers']" class="fill-text" 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>
318
+ <svg v-else width="12" height="12" @click="expanded['footers'] = !expanded['footers']" class="fill-text" 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>
319
+ <strong class="flex-1 text-text-400 line-clamp-1" @click="expanded['footers'] = !expanded['footers']">{{ $t('Footer')}}</strong>
309
320
  <button type="button" class="text-primary flex flex-row items-center gap-1"
310
- @click="openComponentSelector({ items:page.components }); currentArea = ''">
321
+ @click="openComponentSelector({ items:layoutFooters, isLayout:true })">
311
322
  <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>
312
323
  {{ $t('Add')}}
313
324
  </button>
314
325
  </div>
315
- <TreeView class="mt-2"
316
- v-model="page.components"
317
- :selected-item="currentItem"
318
- @add="(items) => openComponentSelector({ items })"
319
- @change="pageHistory.commit()">
320
- <template #default="{ item }">
321
- <div class="flex-1 text-ellipsis whitespace-nowrap overflow-hidden"
322
- :class="!item.props.enabled ? 'line-through' : ''"
323
- @click="select(item.uid)">
324
- {{ item.props.name ?? item.type }}
325
- </div>
326
- </template>
327
- </TreeView>
326
+
327
+ <div v-if="expanded['footers']" class="flex flex-col gap-10">
328
+ <TreeView class="mt-2"
329
+ v-model="layoutFooters"
330
+ :selected-item="currentItem"
331
+ @add="(items) => openComponentSelector({ items })">
332
+ <template #default="{ item }">
333
+ <div class="flex-1 text-ellipsis whitespace-nowrap overflow-hidden"
334
+ :class="!item.props.enabled ? 'line-through' : ''"
335
+ @click="select(item.uid)">
336
+ {{ item.props.name ?? item.type }}
337
+ </div>
338
+ </template>
339
+ </TreeView>
340
+ </div>
341
+ </div>
342
+
343
+ <div v-if="store.layoutMode && layout">
344
+ <small class="text-text-400">{{ $t('Updating layout will affect all pages using this layout, proceed with caution.') }}</small>
328
345
  </div>
329
346
 
330
347
  <WebComponentSelector ref="webPageComponentSelector"
@@ -487,7 +504,7 @@
487
504
  @click="currentArea = 'properties'"
488
505
  :style="section3Style">
489
506
 
490
- <div class="px-3 py-4 bg-base-300 flex flex-row items-center gap-2">
507
+ <div class="px-6 py-4 flex flex-row items-center gap-2">
491
508
  <Textbox v-if="currentItem.type !== 'Style'"
492
509
  v-model="currentItem.props.name"
493
510
  :placeholder="currentItem.type"
@@ -1382,6 +1399,22 @@ export default{
1382
1399
 
1383
1400
  computed: {
1384
1401
 
1402
+ componentStore(){
1403
+ if(this.store && this.store.components){
1404
+ if(!this.store.components.compsetting)
1405
+ this.store.components.compsetting = {}
1406
+
1407
+ return this.store.components.compsetting
1408
+ }
1409
+ return {}
1410
+ },
1411
+
1412
+ expanded(){
1413
+ if(!this.componentStore['expanded'])
1414
+ this.componentStore['expanded'] = {}
1415
+ return this.componentStore['expanded']
1416
+ },
1417
+
1385
1418
  availableComponents(){
1386
1419
 
1387
1420
  return [