@mixd-id/web-scaffold 0.1.230406053 → 0.1.230406055

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.230406053",
4
+ "version": "0.1.230406055",
5
5
  "scripts": {
6
6
  "dev": "vite serve",
7
7
  "build": "vite build",
@@ -138,7 +138,7 @@ export default {
138
138
  if(caller){
139
139
 
140
140
  const media = this.$util.calculateMediaPrefix(window.innerWidth)
141
- let maxHeight, transformOrigin
141
+ let maxHeight, transformOrigin, transform
142
142
  let top, right, bottom, left
143
143
  if([ '*', 'sm' ].includes(media)){
144
144
  this.$nextTick(() => {
@@ -149,12 +149,24 @@ export default {
149
149
  maxHeight = this.$refs.contextMenu.clientHeight > window.innerHeight * .8 ?
150
150
  Math.round(window.innerHeight * .8) : this.$refs.contextMenu.clientHeight + 30
151
151
 
152
+ if(top + this.$refs.contextMenu.clientHeight >= (window.innerHeight - 16)){
153
+ top = undefined
154
+ bottom = rect.height
155
+ transformOrigin = 'bottom left'
156
+ transform = 'translate3d(0, -' + rect.height + 'px, 0)'
157
+ }
158
+ else{
159
+ transform = 'translate3d(0, 10px, 0)'
160
+ }
161
+
152
162
  this.computedStyle = {
153
163
  left: '10px',
154
164
  right: '10px',
155
165
  top: top ? top + 'px' : top,
166
+ bottom: bottom ? bottom + 'px' : bottom,
156
167
  maxHeight: maxHeight ? maxHeight + 'px' : maxHeight,
157
- transformOrigin: transformOrigin
168
+ transformOrigin: transformOrigin,
169
+ transform
158
170
  }
159
171
 
160
172
  this.onOpen()
@@ -288,11 +300,10 @@ export default {
288
300
  <style module>
289
301
 
290
302
  .contextMenu{
291
- @apply fixed z-20 bg-base-300 backdrop-blur-md min-w-[150px] overflow-y-auto rounded-xl;
292
- @apply border-[1px] border-text-50 shadow-2xl whitespace-nowrap;
303
+ @apply fixed z-20 bg-base-400 dark:bg-base-300 backdrop-blur-md min-w-[150px] overflow-y-auto rounded-xl;
304
+ @apply border-[2px] border-text-50 shadow-2xl whitespace-nowrap;
293
305
  transition: all 150ms cubic-bezier(0.25, 1, 0.5, 1);
294
306
  opacity: 0;
295
- transform: translate3d(0, -10px, 0);
296
307
  }
297
308
 
298
309
  .active{
@@ -1,8 +1,8 @@
1
1
  <template>
2
2
  <Modal :state="isOpen" width="400" height="400" :class="$style.previewModal">
3
- <div class="flex-1">
3
+ <div class="flex-1 flex flex-col">
4
4
  <div class="flex flex-row justify-end items-center p-3">
5
- <a :href="imageUrl" download>
5
+ <a v-if="download" :href="imageUrl" download>
6
6
  <svg xmlns="http://www.w3.org/2000/svg" width="42" height="42" viewBox="0 0 24 24" class="fill-text"><path class="primary" d="M15 15v-3a3 3 0 0 0-6 0v3H6a4 4 0 0 1-.99-7.88 5.5 5.5 0 0 1 10.86-.82A4.49 4.49 0 0 1 22 10.5a4.5 4.5 0 0 1-4.5 4.5H15z"/><path class="secondary" d="M11 18.59V12a1 1 0 0 1 2 0v6.59l1.3-1.3a1 1 0 0 1 1.4 1.42l-3 3a1 1 0 0 1-1.4 0l-3-3a1 1 0 0 1 1.4-1.42l1.3 1.3z"/></svg>
7
7
  </a>
8
8
  <button class="ml-3" @click="close">
@@ -10,7 +10,7 @@
10
10
  </button>
11
11
  </div>
12
12
  <div class="flex items-center justify-center">
13
- <img :src="imageUrl" class="max-h-[85vh]"/>
13
+ <img :src="imageUrl" class="max-h-[75vh]"/>
14
14
  </div>
15
15
  </div>
16
16
  </Modal>
@@ -20,6 +20,15 @@
20
20
 
21
21
  export default{
22
22
 
23
+ props: {
24
+
25
+ download: {
26
+ type: Boolean,
27
+ default: false
28
+ },
29
+
30
+ },
31
+
23
32
  data(){
24
33
  return {
25
34
  isOpen: false,
@@ -62,10 +71,10 @@ export default{
62
71
  }
63
72
 
64
73
  .previewModal{
65
- @apply !w-screen !h-screen !bg-base-300;
74
+ @apply !w-screen !h-screen !bg-base-300 top-0;
66
75
  z-index: 21 !important;
67
76
  max-width: unset !important;
68
77
  max-height: unset !important;
69
78
  }
70
79
 
71
- </style>
80
+ </style>
@@ -167,4 +167,4 @@ export default{
167
167
  @apply py-4;
168
168
  }
169
169
 
170
- </style>
170
+ </style>
@@ -2,22 +2,22 @@
2
2
  <div :class="$style.comp" v-if="configLoaded">
3
3
 
4
4
  <slot v-if="$slots.head" name="head"></slot>
5
- <div v-else class="flex flex-row items-center gap-4 px-6 md:px-0 py-4 md:py-0">
5
+ <div v-else class="flex flex-row items-center gap-4 px-6 md:px-0 py-4 md:py-0 bg-base-400 dark:bg-base-300 md:bg-transparent">
6
6
  <div class="flex-1 flex flex-row gap-4">
7
7
  <button type="button" ref="presetSelectorBtn"
8
8
  class="flex-1 md:flex-none flex flex-row gap-1 items-center text-left md:ml-2"
9
- @click="$refs.presetSelector.open($refs.presetSelectorBtn)">
10
- <h3 class="overflow-hidden whitespace-nowrap text-ellipsis">{{ preset.name }}</h3>
11
- <svg width="16" height="16" class="fill-text-300 hover:fill-primary" 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>
9
+ @click="$refs.presetSelector.toggle($refs.presetSelectorBtn)">
10
+ <h4 class="overflow-hidden whitespace-nowrap text-ellipsis">{{ preset.name }}</h4>
11
+ <svg width="16" height="16" class="fill-text hover:fill-primary" 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
12
  </button>
13
13
  <button type="button" @click="openPreset()">
14
- <svg width="19" height="19" class="fill-text-300 hover:fill-primary" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="M452.515 237l31.843-18.382c9.426-5.441 13.996-16.542 11.177-27.054-11.404-42.531-33.842-80.547-64.058-110.797-7.68-7.688-19.575-9.246-28.985-3.811l-31.785 18.358a196.276 196.276 0 0 0-32.899-19.02V39.541a24.016 24.016 0 0 0-17.842-23.206c-41.761-11.107-86.117-11.121-127.93-.001-10.519 2.798-17.844 12.321-17.844 23.206v36.753a196.276 196.276 0 0 0-32.899 19.02l-31.785-18.358c-9.41-5.435-21.305-3.877-28.985 3.811-30.216 30.25-52.654 68.265-64.058 110.797-2.819 10.512 1.751 21.613 11.177 27.054L59.485 237a197.715 197.715 0 0 0 0 37.999l-31.843 18.382c-9.426 5.441-13.996 16.542-11.177 27.054 11.404 42.531 33.842 80.547 64.058 110.797 7.68 7.688 19.575 9.246 28.985 3.811l31.785-18.358a196.202 196.202 0 0 0 32.899 19.019v36.753a24.016 24.016 0 0 0 17.842 23.206c41.761 11.107 86.117 11.122 127.93.001 10.519-2.798 17.844-12.321 17.844-23.206v-36.753a196.34 196.34 0 0 0 32.899-19.019l31.785 18.358c9.41 5.435 21.305 3.877 28.985-3.811 30.216-30.25 52.654-68.266 64.058-110.797 2.819-10.512-1.751-21.613-11.177-27.054L452.515 275c1.22-12.65 1.22-25.35 0-38zm-52.679 63.019l43.819 25.289a200.138 200.138 0 0 1-33.849 58.528l-43.829-25.309c-31.984 27.397-36.659 30.077-76.168 44.029v50.599a200.917 200.917 0 0 1-67.618 0v-50.599c-39.504-13.95-44.196-16.642-76.168-44.029l-43.829 25.309a200.15 200.15 0 0 1-33.849-58.528l43.819-25.289c-7.63-41.299-7.634-46.719 0-88.038l-43.819-25.289c7.85-21.229 19.31-41.049 33.849-58.529l43.829 25.309c31.984-27.397 36.66-30.078 76.168-44.029V58.845a200.917 200.917 0 0 1 67.618 0v50.599c39.504 13.95 44.196 16.642 76.168 44.029l43.829-25.309a200.143 200.143 0 0 1 33.849 58.529l-43.819 25.289c7.631 41.3 7.634 46.718 0 88.037zM256 160c-52.935 0-96 43.065-96 96s43.065 96 96 96 96-43.065 96-96-43.065-96-96-96zm0 144c-26.468 0-48-21.532-48-48 0-26.467 21.532-48 48-48s48 21.533 48 48c0 26.468-21.532 48-48 48z"/></svg>
14
+ <svg width="19" height="19" class="fill-text hover:fill-primary" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="M452.515 237l31.843-18.382c9.426-5.441 13.996-16.542 11.177-27.054-11.404-42.531-33.842-80.547-64.058-110.797-7.68-7.688-19.575-9.246-28.985-3.811l-31.785 18.358a196.276 196.276 0 0 0-32.899-19.02V39.541a24.016 24.016 0 0 0-17.842-23.206c-41.761-11.107-86.117-11.121-127.93-.001-10.519 2.798-17.844 12.321-17.844 23.206v36.753a196.276 196.276 0 0 0-32.899 19.02l-31.785-18.358c-9.41-5.435-21.305-3.877-28.985 3.811-30.216 30.25-52.654 68.265-64.058 110.797-2.819 10.512 1.751 21.613 11.177 27.054L59.485 237a197.715 197.715 0 0 0 0 37.999l-31.843 18.382c-9.426 5.441-13.996 16.542-11.177 27.054 11.404 42.531 33.842 80.547 64.058 110.797 7.68 7.688 19.575 9.246 28.985 3.811l31.785-18.358a196.202 196.202 0 0 0 32.899 19.019v36.753a24.016 24.016 0 0 0 17.842 23.206c41.761 11.107 86.117 11.122 127.93.001 10.519-2.798 17.844-12.321 17.844-23.206v-36.753a196.34 196.34 0 0 0 32.899-19.019l31.785 18.358c9.41 5.435 21.305 3.877 28.985-3.811 30.216-30.25 52.654-68.266 64.058-110.797 2.819-10.512-1.751-21.613-11.177-27.054L452.515 275c1.22-12.65 1.22-25.35 0-38zm-52.679 63.019l43.819 25.289a200.138 200.138 0 0 1-33.849 58.528l-43.829-25.309c-31.984 27.397-36.659 30.077-76.168 44.029v50.599a200.917 200.917 0 0 1-67.618 0v-50.599c-39.504-13.95-44.196-16.642-76.168-44.029l-43.829 25.309a200.15 200.15 0 0 1-33.849-58.528l43.819-25.289c-7.63-41.299-7.634-46.719 0-88.038l-43.819-25.289c7.85-21.229 19.31-41.049 33.849-58.529l43.829 25.309c31.984-27.397 36.66-30.078 76.168-44.029V58.845a200.917 200.917 0 0 1 67.618 0v50.599c39.504 13.95 44.196 16.642 76.168 44.029l43.829-25.309a200.143 200.143 0 0 1 33.849 58.529l-43.819 25.289c7.631 41.3 7.634 46.718 0 88.037zM256 160c-52.935 0-96 43.065-96 96s43.065 96 96 96 96-43.065 96-96-43.065-96-96-96zm0 144c-26.468 0-48-21.532-48-48 0-26.467 21.532-48 48-48s48 21.533 48 48c0 26.468-21.532 48-48 48z"/></svg>
15
15
  </button>
16
16
 
17
17
  <ContextMenu ref="presetSelector">
18
- <div class="flex-1 flex flex-col w-[270px] cursor-pointer">
18
+ <div class="flex-1 flex flex-col md:w-[270px] cursor-pointer">
19
19
  <button type="button" v-for="(preset, idx) in config.presets"
20
- class="p-3 text-left hover:bg-primary hover:text-white"
20
+ class="p-3 text-left hover:bg-primary hover:text-white block"
21
21
  @click="selectPreset(idx)">
22
22
  {{ preset.name }}
23
23
  </button>
@@ -60,7 +60,7 @@
60
60
  </Textbox>
61
61
  </div>
62
62
 
63
- <div v-if="mediaPrefix === 'sm'" class="px-6 py-4 border-b-[1px] border-text-50">
63
+ <div v-if="mediaPrefix === 'sm'" class="px-6 pb-4 border-b-[1px] border-text-50 bg-base-400 dark:bg-base-300">
64
64
  <Textbox :placeholder="$t('Search...')" :clearable="true" @clear="clearSearch" v-model="preset.search"
65
65
  @keyup.enter="load" :class="$style.searchBox">
66
66
  <template #start>
@@ -72,7 +72,8 @@
72
72
  </div>
73
73
 
74
74
  <div class="flex-1 flex" v-if="mediaPrefix">
75
- <VirtualTable v-if="mediaPrefix !== 'sm'" ref="table1" :columns="presetColumns" :items="items" class="flex-1"
75
+ <VirtualTable v-if="mediaPrefix !== 'sm'" ref="table1" :columns="presetColumns" :items="items"
76
+ class="flex-1 bg-base-400 dark:bg-base-300"
76
77
  @scroll-end="loadNext">
77
78
  <template v-for="column in presetColumns" #[colOf(column.key)]="{}">
78
79
  <div :class="getHeader(column)" @click="openColumnOptions(column.key, $event.target.closest('.' + $style.header))">
@@ -106,7 +107,7 @@
106
107
  <slot :name="slot" :item="item" :index="index"></slot>
107
108
  </template>
108
109
  </VirtualTable>
109
- <VirtualScroll v-else :items="items" class="flex-1" @scroll-end="loadNext">
110
+ <VirtualScroll v-else :items="items" ref="table2" class="flex-1 bg-base-400 dark:bg-base-300" @scroll-end="loadNext">
110
111
  <template #item="{ item }">
111
112
  <slot name="mobileItem" :item="item"></slot>
112
113
  </template>
@@ -136,7 +137,7 @@
136
137
  </div>
137
138
  <div v-if="presetCurrentFilters.length > 0">
138
139
  <ListPage1Filter v-if="preset.filters" v-for="filter in presetCurrentFilters"
139
- :filter="filter" :column="config.columns[filter.key]"
140
+ :filter="filter" :column="config.columns[config.columns.findIndex((_) => _.key === filter.key)]"
140
141
  @remove="removeFilter(filter)" @change="load" />
141
142
  </div>
142
143
  <div v-else>
@@ -271,7 +272,7 @@ export default{
271
272
  },
272
273
 
273
274
  loadNext(){
274
- this.$refs.table1 ? this.$refs.table1.setState(2) : undefined
275
+ this.$refs.table1 ? this.$refs.table1.setState(2) : this.$refs.table2.setState(2)
275
276
  this.socketEmit2(this.src, {
276
277
  preset: this.preset,
277
278
  afterItem: this.items[this.items.length - 1]
@@ -284,12 +285,15 @@ export default{
284
285
  this.toast(err)
285
286
  })
286
287
  .finally(() => {
287
- this.$refs.table1 ? this.$refs.table1.setState(1) : undefined
288
+ this.$refs.table1 ? this.$refs.table1.setState(1) : this.$refs.table2.setState(1)
288
289
  })
289
290
  },
290
291
 
291
292
  async loadConfig(){
292
- if(!this.configStoreObj) return
293
+ if(!this.configStoreObj || 'reset' in ((this.$route ?? {}).query ?? {})){
294
+ this.configLoaded = true
295
+ return
296
+ }
293
297
 
294
298
  switch(this.configStoreObj.type){
295
299
  case 'socket':
@@ -518,7 +522,7 @@ export default{
518
522
 
519
523
  data(){
520
524
  return {
521
- items: [],
525
+ items: null,
522
526
  hasNext: false,
523
527
  count: null,
524
528
  configLoaded: false,
@@ -568,6 +572,10 @@ export default{
568
572
  @apply flex-1 flex flex-col md:gap-4;
569
573
  }
570
574
 
575
+ .searchBox{
576
+ @apply !bg-base-300 dark:!bg-base-400;
577
+ }
578
+
571
579
  .header{
572
580
  @apply p-2 cursor-pointer border-b-[2px] border-transparent overflow-hidden;
573
581
  }
@@ -75,7 +75,7 @@
75
75
  <div class="flex flex-col" v-else-if="config.presetTab === 'filter'">
76
76
  <div v-if="filterableColumns.length > 0">
77
77
  <ListPage1Filter v-if="preset.filters" v-for="filter in preset.filters"
78
- :filter="filter" :column="config.columns[filter.key]"
78
+ :filter="filter" :column="config.columns[config.columns.findIndex((_) => _.key === filter.key)]"
79
79
  @remove="removeFilter(filter)" @change="$emit('change')"/>
80
80
  <div class="py-8">
81
81
  <Dropdown @change="addFilter" v-model="presetFilterSelector">
@@ -406,7 +406,7 @@ export default{
406
406
  <style module>
407
407
 
408
408
  .comp{
409
- @apply flex flex-col gap-4 bg-base-300;
409
+ @apply flex flex-col gap-4;
410
410
  }
411
411
 
412
412
  .column{
@@ -1,5 +1,10 @@
1
1
  <template>
2
2
  <div :class="$style.comp">
3
+ <div v-if="state === 2" ref="spinner" class="h-[44px] relative">
4
+ <div class="absolute top-0 left-0 w-screen h-[44px] flex items-center justify-center">
5
+ <svg class="animate-spin aspect-square w-[16px] h-[16px] 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>
6
+ </div>
7
+ </div>
3
8
  <div ref="scroller" :class="$style.scroller" :style="scrollerStyle">
4
9
  <div v-if="visibleItems && visibleItems.length > 0" :class="$style.spacer" ref="spacer" :style="spacerStyle">
5
10
  <div v-for="(item, index) in visibleItems" :key="item" :data-id="item.id"
@@ -8,11 +13,16 @@
8
13
  <slot name="item" :item="item" :index="index"></slot>
9
14
  </div>
10
15
  </div>
11
- <div v-else class="flex p-8 justify-center items-center">
16
+ <div v-else-if="Array.isArray(items) && items.length <= 0" class="flex p-8 justify-center items-center">
12
17
  <slot v-if="$slots['empty']" name="empty"></slot>
13
18
  <div v-else>No data</div>
14
19
  </div>
15
20
  </div>
21
+ <div v-if="state === 2" ref="spinner" class="h-[44px] relative">
22
+ <div class="absolute top-0 left-0 w-screen h-[44px] flex items-center justify-center">
23
+ <svg class="animate-spin aspect-square w-[16px] h-[16px] 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>
24
+ </div>
25
+ </div>
16
26
  <div :class="$style.calc" v-if="items && items.length > 0" ref="calc">
17
27
  <slot name="item" :item="items[0]" :index="0"></slot>
18
28
  </div>
@@ -95,7 +105,8 @@ export default{
95
105
  itemHeight: 0,
96
106
  maxVisibleItems: 0,
97
107
  isOnEndScroll: false,
98
- selectedIndex: -1
108
+ selectedIndex: -1,
109
+ state: 1
99
110
  }
100
111
  },
101
112
 
@@ -177,6 +188,10 @@ export default{
177
188
  }
178
189
  })
179
190
 
191
+ },
192
+
193
+ setState(state){
194
+ this.state = state
180
195
  }
181
196
 
182
197
  },
@@ -215,11 +230,11 @@ export default{
215
230
  }
216
231
 
217
232
  .item:hover{
218
- @apply bg-primary-50;
233
+ @apply bg-text-50;
219
234
  }
220
235
 
221
236
  .item.trSelected{
222
- @apply bg-primary-200;
237
+ @apply bg-text-100;
223
238
  }
224
239
 
225
240
  .highlight{
@@ -62,7 +62,7 @@
62
62
  <div v-else-if="visibleColumns.length <= 0 && Array.isArray(columns)" class="text-center p-3 flex-1 min-h-[100%] flex items-center justify-center">
63
63
  <h5 class="text-text-300">No active column</h5>
64
64
  </div>
65
- <div v-else-if="Array.isArray(columns)" class="text-center p-3 flex-1 min-h-[100%] flex items-center justify-center">
65
+ <div v-else-if="Array.isArray(items) && items.length <= 0" class="text-center p-3 flex-1 min-h-[100%] flex items-center justify-center">
66
66
  <h5 class="text-text-300">No data available</h5>
67
67
  </div>
68
68
  </div>
@@ -64,7 +64,7 @@ const plugin = Plugin(function({ addBase, config, theme }) {
64
64
  "--base-500": '22, 26, 33',
65
65
  "--base": '22, 26, 33',
66
66
 
67
- "--text-50": '34, 40, 47',
67
+ "--text-50": '28, 34, 41',
68
68
  "--text-100": '48, 54, 61',
69
69
  "--text-200": '53, 59, 66',
70
70
  "--text-300": '77, 77, 77',
@@ -90,8 +90,12 @@ const plugin = Plugin(function({ addBase, config, theme }) {
90
90
  },
91
91
 
92
92
  '@media screen and (orientation: portrait)': {
93
+ '*': {
94
+ 'fontSize': '14px',
95
+ },
96
+
93
97
  'body': {
94
- 'fontSize': '16px',
98
+ 'fontSize': '14px',
95
99
  },
96
100
 
97
101
  "input, input[type='text'], input[type='number'], textarea, select, option": { fontSize:"16px" }
@@ -3,6 +3,7 @@ const Sequelize = module.parent.require('sequelize')
3
3
  const dayjs = require("dayjs");
4
4
  const Exceljs = require("exceljs");
5
5
  const { getPresetSortWhereParams } = require("./helpers");
6
+ const { sleep } = require('@mixd-id/web-scaffold/helpers')
6
7
 
7
8
  let ListPage1 = {
8
9
 
@@ -90,6 +91,8 @@ let ListPage1 = {
90
91
 
91
92
  async load(params){
92
93
 
94
+ await sleep(500)
95
+
93
96
  const { items, hasNext, count } = await this._load(params)
94
97
 
95
98
  if(this.name){
@@ -1489,4 +1492,4 @@ let ListPage1 = {
1489
1492
 
1490
1493
  }
1491
1494
 
1492
- module.exports = ListPage1
1495
+ module.exports = ListPage1