@mixd-id/web-scaffold 0.1.230406001
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/LICENSE +21 -0
- package/README.md +3 -0
- package/package.json +71 -0
- package/public/images/mixd-logo2.png +0 -0
- package/src/App.vue +17 -0
- package/src/components/Ahref.vue +34 -0
- package/src/components/Alert.vue +160 -0
- package/src/components/Button.vue +253 -0
- package/src/components/ButtonGroup.vue +101 -0
- package/src/components/Carousel.vue +293 -0
- package/src/components/ChatTyping.vue +69 -0
- package/src/components/Checkbox.vue +152 -0
- package/src/components/ContextMenu.vue +261 -0
- package/src/components/CopyToClipboard.vue +59 -0
- package/src/components/Countdown.vue +213 -0
- package/src/components/Datepicker.vue +312 -0
- package/src/components/Dropdown.vue +198 -0
- package/src/components/DynamicTemplate.vue +44 -0
- package/src/components/ErrorText.vue +36 -0
- package/src/components/Feed.vue +118 -0
- package/src/components/Gmaps.vue +227 -0
- package/src/components/Grid.vue +29 -0
- package/src/components/GridColumn.vue +31 -0
- package/src/components/HTMLEditor.vue +396 -0
- package/src/components/Image.vue +207 -0
- package/src/components/Image360.vue +140 -0
- package/src/components/ImageFullScreen.vue +101 -0
- package/src/components/ImagePreview.vue +71 -0
- package/src/components/ImportModal.vue +247 -0
- package/src/components/ListItem.vue +147 -0
- package/src/components/ListPage1.vue +1331 -0
- package/src/components/ListPage1Filter.vue +170 -0
- package/src/components/Modal.vue +253 -0
- package/src/components/OTPField.vue +126 -0
- package/src/components/Radio.vue +134 -0
- package/src/components/SearchButton.vue +57 -0
- package/src/components/Slider.vue +285 -0
- package/src/components/SplitPane.vue +129 -0
- package/src/components/Switch.vue +89 -0
- package/src/components/TabView.vue +106 -0
- package/src/components/TableView.vue +201 -0
- package/src/components/TableViewHead.vue +159 -0
- package/src/components/Tabs.vue +74 -0
- package/src/components/TextEditor.vue +85 -0
- package/src/components/Textarea.vue +184 -0
- package/src/components/Textbox.vue +200 -0
- package/src/components/Timepicker.vue +108 -0
- package/src/components/Toast.vue +93 -0
- package/src/components/VirtualScroll.vue +215 -0
- package/src/components/VirtualTable.vue +497 -0
- package/src/entry-client.js +27 -0
- package/src/entry-server.js +73 -0
- package/src/index.css +3 -0
- package/src/index.js +255 -0
- package/src/main.js +38 -0
- package/src/router.js +57 -0
- package/src/themes/default/index.js +200 -0
- package/src/utils/helpers.js +185 -0
- package/src/utils/helpers.mjs +197 -0
- package/src/utils/importer.js +156 -0
- package/src/utils/listpage1.js +1371 -0
- package/src/utils/selection.js +64 -0
|
@@ -0,0 +1,497 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div :class="$style.comp">
|
|
3
|
+
<div :class="$style.header" v-if="visibleColumns.length > 0">
|
|
4
|
+
<table :class="$style.table" ref="tableHead" :style="tableHeadStyle">
|
|
5
|
+
<thead>
|
|
6
|
+
<tr>
|
|
7
|
+
<th v-for="column in visibleColumns" :style="thStyle(column)">
|
|
8
|
+
<slot v-if="$slots['col-' + column.key]" :name="'col-' + column.key" :column="column"></slot>
|
|
9
|
+
<div v-else :class="headerColumnClass(column)">
|
|
10
|
+
<span v-if="column.label && !column.label.startsWith('(')">{{ column.label }}</span>
|
|
11
|
+
</div>
|
|
12
|
+
<div :class="$style.separator" @mousedown="startResize($event, column)"></div>
|
|
13
|
+
</th>
|
|
14
|
+
<th :class="$style.spacer"></th>
|
|
15
|
+
</tr>
|
|
16
|
+
</thead>
|
|
17
|
+
</table>
|
|
18
|
+
</div>
|
|
19
|
+
|
|
20
|
+
<div ref="cont">
|
|
21
|
+
<div ref="scroller" v-if="visibleColumns.length > 0" :class="$style.scroller" :style="scrollerStyle">
|
|
22
|
+
<div :class="$style.spacer" ref="spacer" :style="spacerStyle">
|
|
23
|
+
<table :class="$style.table">
|
|
24
|
+
<thead>
|
|
25
|
+
<tr>
|
|
26
|
+
<th v-for="column in visibleColumns" :style="thStyle(column)"></th>
|
|
27
|
+
<th :class="$style.spacer"></th>
|
|
28
|
+
</tr>
|
|
29
|
+
</thead>
|
|
30
|
+
<tbody>
|
|
31
|
+
<tr v-for="(item, index) in visibleItems" :key="item"
|
|
32
|
+
@click="select(item, index)"
|
|
33
|
+
:class="[ selectedIndex === ((item && item.id) ? item.id : visibleStartIndex + index) ? $style.trSelected : '', item._highlight ? $style.highlight : '' ].join(' ')">
|
|
34
|
+
<td v-for="column in visibleColumns">
|
|
35
|
+
<slot v-if="$slots[column.key]" :name="column.key" :column="column" :item="item" :index="visibleStartIndex + index"></slot>
|
|
36
|
+
<div v-else :class="columnClass(column)" v-html="formatColumn(item[column.key ?? ''] ?? '', column)"></div>
|
|
37
|
+
</td>
|
|
38
|
+
<td :class="$style.spacer"></td>
|
|
39
|
+
</tr>
|
|
40
|
+
</tbody>
|
|
41
|
+
</table>
|
|
42
|
+
</div>
|
|
43
|
+
</div>
|
|
44
|
+
<div :class="$style.calc" v-if="visibleColumns.length > 0 && items && items.length > 0" ref="calc">
|
|
45
|
+
<table :class="$style.table">
|
|
46
|
+
<tbody>
|
|
47
|
+
<tr>
|
|
48
|
+
<td v-for="column in columns" :style="thStyle(column)">
|
|
49
|
+
<slot v-if="$slots[column.key]" :name="column.key" :column="column" :item="items[0]"></slot>
|
|
50
|
+
<div v-else :class="columnClass(column)" v-html="formatColumn(items[0][column.key ?? ''] ?? '', column)"></div>
|
|
51
|
+
</td>
|
|
52
|
+
<td :class="$style.spacer"></td>
|
|
53
|
+
</tr>
|
|
54
|
+
</tbody>
|
|
55
|
+
</table>
|
|
56
|
+
</div>
|
|
57
|
+
<div v-else-if="visibleColumns.length <= 0" class="text-center p-3 flex-1 min-h-[100%] flex items-center justify-center">
|
|
58
|
+
<h5 class="text-text-300">No active column</h5>
|
|
59
|
+
</div>
|
|
60
|
+
<div v-else class="text-center p-3 flex-1 min-h-[100%] flex items-center justify-center">
|
|
61
|
+
<h5 class="text-text-300">No data available</h5>
|
|
62
|
+
</div>
|
|
63
|
+
</div>
|
|
64
|
+
</div>
|
|
65
|
+
</template>
|
|
66
|
+
|
|
67
|
+
<script>
|
|
68
|
+
|
|
69
|
+
import throttle from "lodash/throttle";
|
|
70
|
+
import dayjs from "dayjs";
|
|
71
|
+
|
|
72
|
+
const _DEFAULT_COLUMN_WIDTH = '100px'
|
|
73
|
+
|
|
74
|
+
export default{
|
|
75
|
+
|
|
76
|
+
emits: [ 'scroll-end' ],
|
|
77
|
+
|
|
78
|
+
props:{
|
|
79
|
+
columns: Array,
|
|
80
|
+
|
|
81
|
+
items: Array,
|
|
82
|
+
|
|
83
|
+
pinned: Function,
|
|
84
|
+
|
|
85
|
+
defaultColumnWidth: {
|
|
86
|
+
type: String,
|
|
87
|
+
default: _DEFAULT_COLUMN_WIDTH
|
|
88
|
+
},
|
|
89
|
+
|
|
90
|
+
appearances: {
|
|
91
|
+
type: Object,
|
|
92
|
+
default: {}
|
|
93
|
+
}
|
|
94
|
+
},
|
|
95
|
+
|
|
96
|
+
data(){
|
|
97
|
+
return {
|
|
98
|
+
scrollTop: 0,
|
|
99
|
+
scrollLeft: 0,
|
|
100
|
+
itemHeight: 0,
|
|
101
|
+
maxVisibleItems: 0,
|
|
102
|
+
isOnEndScroll: false,
|
|
103
|
+
selectedIndex: -1
|
|
104
|
+
}
|
|
105
|
+
},
|
|
106
|
+
|
|
107
|
+
computed:{
|
|
108
|
+
|
|
109
|
+
visibleStartIndex(){
|
|
110
|
+
return Math.round(this.scrollTop / this.itemHeight)
|
|
111
|
+
},
|
|
112
|
+
|
|
113
|
+
sortedItems(){
|
|
114
|
+
if(!Array.isArray(this.items)) return []
|
|
115
|
+
|
|
116
|
+
if(typeof this.pinned === 'function'){
|
|
117
|
+
const pinnedItems = []
|
|
118
|
+
const unpinnedItems = []
|
|
119
|
+
this.items.forEach((item) => {
|
|
120
|
+
if(this.pinned(item))
|
|
121
|
+
pinnedItems.push(item)
|
|
122
|
+
else
|
|
123
|
+
unpinnedItems.push(item)
|
|
124
|
+
})
|
|
125
|
+
|
|
126
|
+
return [
|
|
127
|
+
...pinnedItems,
|
|
128
|
+
...unpinnedItems
|
|
129
|
+
]
|
|
130
|
+
}
|
|
131
|
+
return this.items
|
|
132
|
+
},
|
|
133
|
+
|
|
134
|
+
visibleItems(){
|
|
135
|
+
if(this.itemHeight <= 0) return []
|
|
136
|
+
return this.sortedItems.slice(this.visibleStartIndex, this.visibleStartIndex + this.maxVisibleItems)
|
|
137
|
+
},
|
|
138
|
+
|
|
139
|
+
spacerStyle(){
|
|
140
|
+
return {
|
|
141
|
+
transform: "translateY(" + (this.visibleStartIndex * this.itemHeight) + "px)"
|
|
142
|
+
}
|
|
143
|
+
},
|
|
144
|
+
|
|
145
|
+
scrollerStyle(){
|
|
146
|
+
if(!this.items || this.items.length < 1)
|
|
147
|
+
return {}
|
|
148
|
+
|
|
149
|
+
const height = (this.items.length * this.itemHeight)
|
|
150
|
+
const width = this.visibleColumns.reduce((r, item) => r + parseInt(item.width ?? _DEFAULT_COLUMN_WIDTH), 0)
|
|
151
|
+
|
|
152
|
+
//console.log('scrollerStyle', { width, height, columns:this.columns })
|
|
153
|
+
|
|
154
|
+
return {
|
|
155
|
+
height: height + 'px',
|
|
156
|
+
width: width + 'px'
|
|
157
|
+
}
|
|
158
|
+
},
|
|
159
|
+
|
|
160
|
+
tableHeadStyle(){
|
|
161
|
+
return {
|
|
162
|
+
transform: "translate3d(" + (this.scrollLeft * -1) + "px, 0, 0)"
|
|
163
|
+
}
|
|
164
|
+
},
|
|
165
|
+
|
|
166
|
+
visibleColumns(){
|
|
167
|
+
const columns = this.columns.filter(_ => _.visible)
|
|
168
|
+
return columns
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
},
|
|
172
|
+
|
|
173
|
+
mounted(){
|
|
174
|
+
|
|
175
|
+
this.$refs.cont.addEventListener(
|
|
176
|
+
"scroll",
|
|
177
|
+
this.handleScroll,
|
|
178
|
+
this.passiveScrollSupported() ? { passive: true } : false
|
|
179
|
+
)
|
|
180
|
+
|
|
181
|
+
this.resize()
|
|
182
|
+
|
|
183
|
+
},
|
|
184
|
+
|
|
185
|
+
methods: {
|
|
186
|
+
|
|
187
|
+
select(item, index){
|
|
188
|
+
this.selectedIndex = (item && item.id) ? item.id : this.visibleStartIndex + index
|
|
189
|
+
if(item._highlight){
|
|
190
|
+
delete item._highlight
|
|
191
|
+
}
|
|
192
|
+
},
|
|
193
|
+
|
|
194
|
+
thStyle(column){
|
|
195
|
+
const width = parseInt(column.width ?? this.defaultColumnWidth)
|
|
196
|
+
return {
|
|
197
|
+
width: width + 'px'
|
|
198
|
+
}
|
|
199
|
+
},
|
|
200
|
+
|
|
201
|
+
async resize(){
|
|
202
|
+
|
|
203
|
+
this.$nextTick(() => {
|
|
204
|
+
if(this.$refs.calc){
|
|
205
|
+
const elHeight = parseInt(window.getComputedStyle(this.$el).height !== '0px' ?
|
|
206
|
+
window.getComputedStyle(this.$el).height :
|
|
207
|
+
window.getComputedStyle(this.$el).maxHeight)
|
|
208
|
+
this.itemHeight = parseInt(window.getComputedStyle(this.$refs.calc).height)
|
|
209
|
+
this.maxVisibleItems = elHeight > 0 ? Math.ceil(elHeight / this.itemHeight) + 1 : this.items.length
|
|
210
|
+
|
|
211
|
+
//console.log('Virtual table scroll resize', { elHeight, itemHeight:this.itemHeight, maxVisibleItems:this.maxVisibleItems })
|
|
212
|
+
|
|
213
|
+
if(this.itemHeight <= 0){
|
|
214
|
+
console.error('[VirtualTable] Unable to calculate item height, make sure not async component.')
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
})
|
|
218
|
+
|
|
219
|
+
},
|
|
220
|
+
|
|
221
|
+
handleScroll: throttle(function(){
|
|
222
|
+
this.scrollTop = this.$refs.cont.scrollTop
|
|
223
|
+
this.scrollLeft = this.$refs.cont.scrollLeft
|
|
224
|
+
|
|
225
|
+
if(this.scrollTop > this.$refs.scroller.offsetHeight - this.$refs.cont.clientHeight - this.itemHeight){
|
|
226
|
+
if(!this.isOnEndScroll){
|
|
227
|
+
this.$emit('scroll-end')
|
|
228
|
+
this.isOnEndScroll = true
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
else{
|
|
232
|
+
if(this.isOnEndScroll){
|
|
233
|
+
this.isOnEndScroll = false
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
}, 10),
|
|
237
|
+
|
|
238
|
+
passiveScrollSupported() {
|
|
239
|
+
let passiveSupported = false;
|
|
240
|
+
|
|
241
|
+
try {
|
|
242
|
+
const options = {
|
|
243
|
+
get passive() {
|
|
244
|
+
passiveSupported = true;
|
|
245
|
+
return false;
|
|
246
|
+
}
|
|
247
|
+
};
|
|
248
|
+
window.addEventListener("test", null, options);
|
|
249
|
+
window.removeEventListener("test", null, options);
|
|
250
|
+
} catch (err) {
|
|
251
|
+
passiveSupported = false;
|
|
252
|
+
}
|
|
253
|
+
return passiveSupported;
|
|
254
|
+
},
|
|
255
|
+
|
|
256
|
+
startResize(e, column){
|
|
257
|
+
|
|
258
|
+
const idx = this.columns.findIndex((_) => _ === column)
|
|
259
|
+
let x1 = e.touches ? e.touches[0].clientX : e.clientX
|
|
260
|
+
|
|
261
|
+
const onMouseMove = (e) => {
|
|
262
|
+
const x2 = e.touches ? e.touches[0].clientX : e.clientX
|
|
263
|
+
const d = x2 - x1
|
|
264
|
+
x1 = x2
|
|
265
|
+
|
|
266
|
+
let width = parseInt(this.columns[idx].width ?? _DEFAULT_COLUMN_WIDTH) + d
|
|
267
|
+
if(width < 20) width = 20
|
|
268
|
+
this.columns[idx].width = width
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
const onMouseUp = (e) => {
|
|
272
|
+
window.removeEventListener('mousemove', onMouseMove)
|
|
273
|
+
window.removeEventListener('mouseup', onMouseUp)
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
window.addEventListener('mousemove', onMouseMove)
|
|
277
|
+
window.addEventListener('mouseup', onMouseUp)
|
|
278
|
+
},
|
|
279
|
+
|
|
280
|
+
columnClass(column){
|
|
281
|
+
|
|
282
|
+
let align
|
|
283
|
+
if(!column.align){
|
|
284
|
+
switch(column.type){
|
|
285
|
+
case 'currency':
|
|
286
|
+
align = 'right'
|
|
287
|
+
break
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
return [
|
|
292
|
+
this.$style.tdDiv,
|
|
293
|
+
this.$style['align-' + align]
|
|
294
|
+
]
|
|
295
|
+
.join(' ')
|
|
296
|
+
},
|
|
297
|
+
|
|
298
|
+
headerColumnClass(column){
|
|
299
|
+
|
|
300
|
+
let align
|
|
301
|
+
if(!column.align){
|
|
302
|
+
switch(column.type){
|
|
303
|
+
case 'currency':
|
|
304
|
+
align = 'right'
|
|
305
|
+
break
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
return [
|
|
310
|
+
this.$style.headerCol,
|
|
311
|
+
this.$style['align-' + align]
|
|
312
|
+
]
|
|
313
|
+
},
|
|
314
|
+
|
|
315
|
+
formatColumn(value, column){
|
|
316
|
+
|
|
317
|
+
if(this.appearances[column.key] && this.appearances[column.key].length){
|
|
318
|
+
const formatted = this.appearances[column.key].filter((appearance) => {
|
|
319
|
+
if(appearance.value === value){
|
|
320
|
+
return true
|
|
321
|
+
}
|
|
322
|
+
return false
|
|
323
|
+
}).pop()
|
|
324
|
+
|
|
325
|
+
if(formatted){
|
|
326
|
+
const fStyle = this.$style['style' + formatted.style]
|
|
327
|
+
const fColor = this.$style['color-' + formatted.color]
|
|
328
|
+
const fValue = formatted.text ?? value
|
|
329
|
+
return `<div class="${fStyle} ${fColor}">${fValue}</div>`
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
let text = value
|
|
334
|
+
let dateFormat, val
|
|
335
|
+
switch(column.type){
|
|
336
|
+
|
|
337
|
+
case 'date':
|
|
338
|
+
dateFormat = column.format ?? 'D MMM YY HH:mm:ss'
|
|
339
|
+
val = dayjs(value)
|
|
340
|
+
text = val.isValid() ? val.format(dateFormat) : value
|
|
341
|
+
break
|
|
342
|
+
|
|
343
|
+
case 'currency':
|
|
344
|
+
const num = parseInt(value)
|
|
345
|
+
text = !isNaN(num) ? num.toLocaleString() : ''
|
|
346
|
+
break
|
|
347
|
+
|
|
348
|
+
case 'enum':
|
|
349
|
+
const enumObj = column.typeParams.filter((_) => _.value === value).pop()
|
|
350
|
+
text = enumObj ? enumObj.text : value
|
|
351
|
+
break
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
return text
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
},
|
|
358
|
+
|
|
359
|
+
watch: {
|
|
360
|
+
|
|
361
|
+
items: {
|
|
362
|
+
deep: true,
|
|
363
|
+
handler(){
|
|
364
|
+
this.resize()
|
|
365
|
+
}
|
|
366
|
+
},
|
|
367
|
+
|
|
368
|
+
columns: {
|
|
369
|
+
deep: true,
|
|
370
|
+
handler(){
|
|
371
|
+
this.resize()
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
</script>
|
|
380
|
+
|
|
381
|
+
<style module>
|
|
382
|
+
|
|
383
|
+
.comp{
|
|
384
|
+
@apply flex flex-col overflow-hidden;
|
|
385
|
+
@apply border-[1px] border-text-50 rounded-sm bg-base-500;
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
.comp>*:last-child{
|
|
389
|
+
@apply flex-1 overflow-auto relative max-h-[100vh];
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
.header{
|
|
393
|
+
@apply border-b-[1px] border-text-50 bg-base-500;
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
.headerCol{
|
|
397
|
+
@apply p-2 overflow-hidden text-ellipsis whitespace-nowrap;
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
.scroller{
|
|
401
|
+
position: relative;
|
|
402
|
+
overflow: hidden;
|
|
403
|
+
will-change: auto;
|
|
404
|
+
min-width: 100%;
|
|
405
|
+
@apply bg-base-500;
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
.spacer{
|
|
409
|
+
will-change: auto;
|
|
410
|
+
position: relative;
|
|
411
|
+
height: 0;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
.calc{
|
|
415
|
+
@apply absolute top-[-100vh] invisible;
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
.table{
|
|
419
|
+
@apply border-collapse;
|
|
420
|
+
table-layout: fixed;
|
|
421
|
+
width: 100%;
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
.table th{
|
|
425
|
+
@apply relative text-left;
|
|
426
|
+
}
|
|
427
|
+
.table th:nth-child(odd){
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
.table tbody td{
|
|
431
|
+
@apply border-b-[1px] border-text-50;
|
|
432
|
+
}
|
|
433
|
+
.table tbody td:nth-child(odd){
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
.table tbody tr:hover{
|
|
437
|
+
@apply bg-primary-50;
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
.table tbody tr.trSelected{
|
|
441
|
+
@apply bg-primary-200;
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
.table tbody tr.highlight{
|
|
445
|
+
animation: highlight 1s 1 forwards;
|
|
446
|
+
}
|
|
447
|
+
@keyframes highlight {
|
|
448
|
+
0% {
|
|
449
|
+
@apply bg-transparent;
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
100% {
|
|
453
|
+
@apply bg-primary-100;
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
.tdDiv{
|
|
458
|
+
@apply p-2 whitespace-nowrap text-ellipsis overflow-hidden;
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
.separator{
|
|
462
|
+
@apply w-[5px] absolute top-0 bottom-0 right-0 cursor-e-resize border-text-50;
|
|
463
|
+
@apply border-r-[1px];
|
|
464
|
+
}
|
|
465
|
+
.table th:hover .separator{
|
|
466
|
+
@apply border-text-100;
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
.spacer{
|
|
470
|
+
@apply w-full
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
.align-left{ @apply text-left; }
|
|
474
|
+
.align-center{ @apply text-center; }
|
|
475
|
+
.align-right{ @apply text-right; }
|
|
476
|
+
|
|
477
|
+
.style40{
|
|
478
|
+
@apply inline-block m-1 rounded-md px-2 text-sm;
|
|
479
|
+
}
|
|
480
|
+
.style40.color-red{ @apply bg-red-600 text-white; }
|
|
481
|
+
.style40.color-orange{ @apply bg-orange-600 text-white; }
|
|
482
|
+
.style40.color-yellow{ @apply bg-yellow-600 text-white; }
|
|
483
|
+
.style40.color-green{ @apply bg-green-600 text-white; }
|
|
484
|
+
.style40.color-teal{ @apply bg-teal-600 text-white; }
|
|
485
|
+
.style40.color-indigo{ @apply bg-indigo-600 text-white; }
|
|
486
|
+
.style40.color-purple{ @apply bg-purple-600 text-white; }
|
|
487
|
+
.style40.color-fuchsia{ @apply bg-fuchsia-600 text-white; }
|
|
488
|
+
|
|
489
|
+
|
|
490
|
+
.style41{
|
|
491
|
+
@apply inline-block m-1 rounded-md bg-red-600 border-red-400 text-white px-2 text-sm;
|
|
492
|
+
}
|
|
493
|
+
.style42{
|
|
494
|
+
@apply inline-block m-1 rounded-md bg-orange-600 text-white px-2 text-sm;
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
</style>
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { createApp } from './main'
|
|
2
|
+
import NProgress from "nprogress";
|
|
3
|
+
import 'nprogress/nprogress.css';
|
|
4
|
+
|
|
5
|
+
const { app, router, pinia } = createApp()
|
|
6
|
+
|
|
7
|
+
if(typeof window.__hydration !== 'undefined'){
|
|
8
|
+
pinia.state.value = window.__hydration ?? {}
|
|
9
|
+
document.getElementById('aHlj').remove()
|
|
10
|
+
document.getElementById('aHlk').remove()
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
NProgress.configure({ showSpinner: false });
|
|
14
|
+
|
|
15
|
+
router.beforeEach(async (to, from, next) => {
|
|
16
|
+
NProgress.start()
|
|
17
|
+
next()
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
router.afterEach(() => {
|
|
21
|
+
NProgress.done()
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
// wait until router is ready before mounting to ensure hydration match
|
|
25
|
+
router.isReady().then(() => {
|
|
26
|
+
app.mount(document.body.firstElementChild)
|
|
27
|
+
})
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { createApp } from './main'
|
|
2
|
+
import { renderToString } from 'vue/server-renderer'
|
|
3
|
+
import path, { basename } from 'path'
|
|
4
|
+
|
|
5
|
+
export async function render(req, manifest) {
|
|
6
|
+
|
|
7
|
+
let url = req.originalUrl
|
|
8
|
+
let redirect = undefined
|
|
9
|
+
let cookie = []
|
|
10
|
+
|
|
11
|
+
const { app, router, pinia } = createApp()
|
|
12
|
+
|
|
13
|
+
// set the router to the desired URL before rendering
|
|
14
|
+
router.push({ path:url })
|
|
15
|
+
await router.isReady()
|
|
16
|
+
|
|
17
|
+
const ctx = {}
|
|
18
|
+
const html = await renderToString(app, ctx)
|
|
19
|
+
|
|
20
|
+
const preloadLinks = renderPreloadLinks(ctx.modules, manifest)
|
|
21
|
+
const serializePinia = "null"
|
|
22
|
+
const modalOverlay = ctx.teleports ? ctx.teleports['.bW9k'] ?? '' : ''
|
|
23
|
+
const contextOverlay = ctx.teleports ? ctx.teleports['.Y29u'] ?? '' : ''
|
|
24
|
+
const alertOverlay = ctx.teleports ? ctx.teleports['.YWxl'] ?? '' : ''
|
|
25
|
+
const toastOverlay = ctx.teleports ? ctx.teleports['.dG9h'] ?? '' : ''
|
|
26
|
+
|
|
27
|
+
return [ html, preloadLinks, serializePinia, redirect, cookie, modalOverlay, alertOverlay, contextOverlay, toastOverlay ]
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function renderPreloadLinks(modules, manifest) {
|
|
31
|
+
let links = ''
|
|
32
|
+
const seen = new Set()
|
|
33
|
+
modules.forEach((id) => {
|
|
34
|
+
const files = manifest[id]
|
|
35
|
+
if (files) {
|
|
36
|
+
files.forEach((file) => {
|
|
37
|
+
if (!seen.has(file)) {
|
|
38
|
+
seen.add(file)
|
|
39
|
+
const filename = basename(file)
|
|
40
|
+
if (manifest[filename]) {
|
|
41
|
+
for (const depFile of manifest[filename]) {
|
|
42
|
+
links += renderPreloadLink(depFile)
|
|
43
|
+
seen.add(depFile)
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
links += renderPreloadLink(file)
|
|
47
|
+
}
|
|
48
|
+
})
|
|
49
|
+
}
|
|
50
|
+
})
|
|
51
|
+
return links
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function renderPreloadLink(file) {
|
|
55
|
+
if (file.endsWith('.js')) {
|
|
56
|
+
return `<link rel="modulepreload" crossorigin href="${file}">`
|
|
57
|
+
} else if (file.endsWith('.css')) {
|
|
58
|
+
return `<link rel="stylesheet" href="${file}">`
|
|
59
|
+
} else if (file.endsWith('.woff')) {
|
|
60
|
+
return ` <link rel="preload" href="${file}" as="font" type="font/woff" crossorigin>`
|
|
61
|
+
} else if (file.endsWith('.woff2')) {
|
|
62
|
+
return ` <link rel="preload" href="${file}" as="font" type="font/woff2" crossorigin>`
|
|
63
|
+
} else if (file.endsWith('.gif')) {
|
|
64
|
+
return ` <link rel="preload" href="${file}" as="image" type="image/gif">`
|
|
65
|
+
} else if (file.endsWith('.jpg') || file.endsWith('.jpeg')) {
|
|
66
|
+
return ` <link rel="preload" href="${file}" as="image" type="image/jpeg">`
|
|
67
|
+
} else if (file.endsWith('.png')) {
|
|
68
|
+
return ` <link rel="preload" href="${file}" as="image" type="image/png">`
|
|
69
|
+
} else {
|
|
70
|
+
// TODO
|
|
71
|
+
return ''
|
|
72
|
+
}
|
|
73
|
+
}
|
package/src/index.css
ADDED