renusify 3.0.0 → 3.0.2
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/components/avatar/index.vue +1 -2
- package/components/button/index.vue +4 -4
- package/components/confirm/index.vue +3 -3
- package/components/form/checkboxInput/index.vue +6 -2
- package/components/form/dateInput/index.vue +9 -9
- package/components/form/fileInput/index.vue +1 -1
- package/components/form/fileInput/single.vue +10 -5
- package/components/form/numberInput/index.vue +19 -9
- package/components/form/selectInput/index.vue +2 -2
- package/components/form/telInput/index.vue +1 -1
- package/components/formCreator/index.vue +1 -1
- package/components/img/index.vue +3 -2
- package/components/infinite/index.js +2 -1
- package/components/infinite/index.vue +81 -39
- package/components/menu/index.vue +5 -3
- package/components/slider/index.vue +4 -1
- package/components/swiper/index.vue +29 -48
- package/components/table/crud/index.vue +6 -0
- package/components/table/index.vue +24 -4
- package/directive/scroll/index.js +29 -25
- package/index.js +4 -14
- package/package.json +1 -1
- package/style/variables/base.scss +7 -9
- package/tools/icons.js +1 -1
|
@@ -270,9 +270,9 @@ $btn-sizes: (
|
|
|
270
270
|
'xs': 1.5rem, // 24px - 6 units
|
|
271
271
|
'sm': 2rem, // 32px - 8 units
|
|
272
272
|
'md': 2.5rem, // 40px - 10 units
|
|
273
|
-
'lg':
|
|
274
|
-
'xl': 3.
|
|
275
|
-
'xxl':
|
|
273
|
+
'lg': 3rem, // 48px - 12 units
|
|
274
|
+
'xl': 3.5rem, // 56px - 14 units
|
|
275
|
+
'xxl': 4rem, // 64px - 16 units
|
|
276
276
|
) !default;
|
|
277
277
|
|
|
278
278
|
$btn-font-sizes: (
|
|
@@ -313,7 +313,7 @@ $fab-icon-sizes: (
|
|
|
313
313
|
}
|
|
314
314
|
|
|
315
315
|
height: $height;
|
|
316
|
-
padding: 0 math.div($height,
|
|
316
|
+
padding: 0 math.div($height, 3);
|
|
317
317
|
font-size: $font-size;
|
|
318
318
|
border-radius: math.div($height, 10);
|
|
319
319
|
}
|
|
@@ -20,16 +20,16 @@
|
|
|
20
20
|
</r-col>
|
|
21
21
|
</r-row>
|
|
22
22
|
<r-row class="h-end no-gutters">
|
|
23
|
-
<r-btn
|
|
23
|
+
<r-btn v-if="!loading"
|
|
24
24
|
@click.stop="cancel"
|
|
25
25
|
class="color-error-text mx-1"
|
|
26
26
|
outlined
|
|
27
27
|
rounded
|
|
28
|
-
|
|
28
|
+
:loading="loading">
|
|
29
29
|
{{ cancelText || $t('cancel', 'renusify') }}
|
|
30
30
|
</r-btn>
|
|
31
31
|
<r-btn :disabled="hard&&!valid"
|
|
32
|
-
:loading="
|
|
32
|
+
:loading="loading"
|
|
33
33
|
@click.stop="confirm"
|
|
34
34
|
class="color-success-text"
|
|
35
35
|
outlined
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<r-input :class="{
|
|
3
3
|
[`${$r.prefix}checkbox`]:true,
|
|
4
|
-
'checkbox-readonly':
|
|
4
|
+
'checkbox-readonly': readonly,
|
|
5
5
|
}" :modelValue="lazyValue" hide>
|
|
6
6
|
<template v-slot="{isRequired}">
|
|
7
|
-
<div class="
|
|
7
|
+
<div class="checkbox-holder">
|
|
8
8
|
<span class="checkbox-input" :class="{
|
|
9
9
|
[size]:true,
|
|
10
10
|
'br-circle':rounded,
|
|
@@ -102,6 +102,10 @@ const toggle = () => {
|
|
|
102
102
|
width: 100%;
|
|
103
103
|
cursor: pointer;
|
|
104
104
|
|
|
105
|
+
.checkbox-holder {
|
|
106
|
+
display: flex;
|
|
107
|
+
align-items: center;
|
|
108
|
+
}
|
|
105
109
|
.checkbox-label {
|
|
106
110
|
color: var(--color-on-sheet);
|
|
107
111
|
}
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
:month="currentPeriod.month"
|
|
55
55
|
:year="currentPeriod.year"></month>
|
|
56
56
|
|
|
57
|
-
<div v-if="
|
|
57
|
+
<div v-if="rangeMode && rangeSelection.startDate && rangeSelection.endDate" class="range-info">
|
|
58
58
|
<div class="title-3">
|
|
59
59
|
{{ $d(rangeSelection.startDate, withTime ? 'long' : 'medium', locale) }} -
|
|
60
60
|
{{ $d(rangeSelection.endDate, withTime ? 'long' : 'medium', locale) }}
|
|
@@ -115,7 +115,7 @@
|
|
|
115
115
|
</div>
|
|
116
116
|
</div>
|
|
117
117
|
|
|
118
|
-
<div v-if="
|
|
118
|
+
<div v-if="rangeMode&&!showTime" class="date-picker-actions mb-3">
|
|
119
119
|
<r-btn class="color-one mx-5" @click.prevent="confirmRange">{{ $t('confirm', 'renusify') }}</r-btn>
|
|
120
120
|
<r-btn class="mx-5" text @click.prevent="resetRange">{{ $t('reset', 'renusify') }}</r-btn>
|
|
121
121
|
</div>
|
|
@@ -212,7 +212,7 @@ const firstDayOfWeek = computed(() =>
|
|
|
212
212
|
)
|
|
213
213
|
|
|
214
214
|
const modelValueDate = computed(() => {
|
|
215
|
-
if (props.
|
|
215
|
+
if (props.rangeMode && rangeSelection.value.startDate) {
|
|
216
216
|
return rangeSelection.value.startDate
|
|
217
217
|
}
|
|
218
218
|
if (!props.modelValue || !new Date(props.modelValue)) {
|
|
@@ -230,7 +230,7 @@ const lang_zone_offset = computed(() =>
|
|
|
230
230
|
)
|
|
231
231
|
|
|
232
232
|
const displayValue = computed(() => {
|
|
233
|
-
if (props.
|
|
233
|
+
if (props.rangeMode) {
|
|
234
234
|
const {startDate, endDate} = rangeSelection.value
|
|
235
235
|
if (startDate && endDate) {
|
|
236
236
|
const format = props.withTime ? 'long' : 'medium'
|
|
@@ -326,7 +326,7 @@ const createDateCell = (date) => {
|
|
|
326
326
|
inRange: false
|
|
327
327
|
}
|
|
328
328
|
|
|
329
|
-
if (props.
|
|
329
|
+
if (props.rangeMode) {
|
|
330
330
|
cell.isRangeStart = rangeSelection.value.startDate ? areSameDates(date, rangeSelection.value.startDate) : false
|
|
331
331
|
cell.isRangeEnd = rangeSelection.value.endDate ? areSameDates(date, rangeSelection.value.endDate) : false
|
|
332
332
|
cell.inRange = isDateInRange(date)
|
|
@@ -402,7 +402,7 @@ const setMonth = (monthIndex) => {
|
|
|
402
402
|
* @param {Boolean} force - Force close even in range mode
|
|
403
403
|
*/
|
|
404
404
|
const close = (force = false) => {
|
|
405
|
-
if (force || !props.
|
|
405
|
+
if (force || !props.rangeMode) {
|
|
406
406
|
show.value = false
|
|
407
407
|
}
|
|
408
408
|
showTime.value = false
|
|
@@ -415,7 +415,7 @@ const selectTime = () => {
|
|
|
415
415
|
const times = (time.value ? time.value : '00:00:00').split(':')
|
|
416
416
|
const [hours, minutes, seconds] = times.map(t => parseInt(t))
|
|
417
417
|
|
|
418
|
-
if (props.
|
|
418
|
+
if (props.rangeMode) {
|
|
419
419
|
handleRangeTimeSelection(hours, minutes, seconds)
|
|
420
420
|
} else {
|
|
421
421
|
handleSingleTimeSelection(hours, minutes, seconds)
|
|
@@ -478,7 +478,7 @@ const formatTime = (hours, minutes, seconds) => {
|
|
|
478
478
|
*/
|
|
479
479
|
const selectDateItem = (item) => {
|
|
480
480
|
if (!item.disabled) {
|
|
481
|
-
if (props.
|
|
481
|
+
if (props.rangeMode) {
|
|
482
482
|
handleRangeSelection(item.date)
|
|
483
483
|
} else {
|
|
484
484
|
if (props.withTime) {
|
|
@@ -581,7 +581,7 @@ $dateTime.set_format({
|
|
|
581
581
|
'ye': {year: 'numeric', numberingSystem: 'latn'}
|
|
582
582
|
})
|
|
583
583
|
|
|
584
|
-
if (props.
|
|
584
|
+
if (props.rangeMode && Array.isArray(props.modelValue) && props.modelValue.length === 2) {
|
|
585
585
|
rangeSelection.value = {
|
|
586
586
|
startDate: new Date(props.modelValue[0]),
|
|
587
587
|
endDate: new Date(props.modelValue[1]),
|
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
<div class="file-holder text-center">
|
|
4
4
|
<div v-if="file || modelValue" class="image-canvas">
|
|
5
5
|
<r-btn class="image-close color-white" icon size="xs">
|
|
6
|
-
<r-icon
|
|
6
|
+
<r-icon class="color-error-text" v-html="$r.icons.delete"
|
|
7
|
+
@click.prevent="fileDelete()"></r-icon>
|
|
7
8
|
</r-btn>
|
|
8
9
|
<r-progress-circle
|
|
9
10
|
:indeterminate="false"
|
|
@@ -106,6 +107,7 @@ const file = ref(null)
|
|
|
106
107
|
const file_type = ref(null)
|
|
107
108
|
const uploadPercentage = ref(0)
|
|
108
109
|
const $axios = inject('axios')
|
|
110
|
+
const $helper = inject('renusify').$helper
|
|
109
111
|
let CancelTokenSource = null
|
|
110
112
|
|
|
111
113
|
// Computed properties
|
|
@@ -329,7 +331,7 @@ const handleCropped = (croppedFile) => {
|
|
|
329
331
|
|
|
330
332
|
const setValue = (value) => {
|
|
331
333
|
if (value) {
|
|
332
|
-
const fixUrl =
|
|
334
|
+
const fixUrl = $helper?.fix_url || ((url) => url)
|
|
333
335
|
fileLink.value = props.meta ? fixUrl(value['url']) : fixUrl(value)
|
|
334
336
|
metaList.value = props.meta ? value['meta'] : {}
|
|
335
337
|
showAdd.value = false
|
|
@@ -358,8 +360,11 @@ const emitFileLink = () => {
|
|
|
358
360
|
}
|
|
359
361
|
|
|
360
362
|
// Watch for modelValue changes
|
|
361
|
-
|
|
362
|
-
|
|
363
|
+
|
|
364
|
+
watch(() => props.modelValue, (newVal, oldVal) => {
|
|
365
|
+
if (JSON.stringify(newVal) !== JSON.stringify(oldVal)) {
|
|
366
|
+
setValue(newVal)
|
|
367
|
+
}
|
|
363
368
|
}, {immediate: true})
|
|
364
369
|
|
|
365
370
|
// Initialize
|
|
@@ -372,4 +377,4 @@ defineExpose({
|
|
|
372
377
|
fileDelete,
|
|
373
378
|
pickFile
|
|
374
379
|
})
|
|
375
|
-
</script>
|
|
380
|
+
</script>
|
|
@@ -44,10 +44,10 @@ const autofocus = attr.autofocus
|
|
|
44
44
|
|
|
45
45
|
const props = defineProps({
|
|
46
46
|
/**
|
|
47
|
-
* The input's model value
|
|
48
|
-
* @type {
|
|
47
|
+
* The input's model value
|
|
48
|
+
* @type {String}
|
|
49
49
|
*/
|
|
50
|
-
modelValue:
|
|
50
|
+
modelValue: String,
|
|
51
51
|
/**
|
|
52
52
|
* Step value for increment/decrement buttons
|
|
53
53
|
* @type {Number}
|
|
@@ -78,7 +78,12 @@ const props = defineProps({
|
|
|
78
78
|
* Maximum allowed value
|
|
79
79
|
* @type {Number}
|
|
80
80
|
*/
|
|
81
|
-
max: Number
|
|
81
|
+
max: Number,
|
|
82
|
+
/**
|
|
83
|
+
* allowe float number
|
|
84
|
+
* @type {Number}
|
|
85
|
+
*/
|
|
86
|
+
isFloat: Boolean
|
|
82
87
|
})
|
|
83
88
|
|
|
84
89
|
const emit = defineEmits([
|
|
@@ -91,6 +96,9 @@ const emit = defineEmits([
|
|
|
91
96
|
|
|
92
97
|
// Reactive data
|
|
93
98
|
const number = ref(props.modelValue)
|
|
99
|
+
if (!props.isFloat && number.value !== undefined && number.value !== null && number.value !== "") {
|
|
100
|
+
number.value = parseInt(number.value).toString()
|
|
101
|
+
}
|
|
94
102
|
const active = ref(false)
|
|
95
103
|
|
|
96
104
|
// Methods
|
|
@@ -111,14 +119,16 @@ const emitValue = (e = false) => {
|
|
|
111
119
|
|
|
112
120
|
let value = number.value
|
|
113
121
|
|
|
114
|
-
if (props.max !== undefined && value > props.max) {
|
|
122
|
+
if (props.max !== undefined && parseFloat(value) > props.max) {
|
|
115
123
|
value = props.max
|
|
116
124
|
}
|
|
117
|
-
if (props.min !== undefined && value < props.min) {
|
|
125
|
+
if (props.min !== undefined && parseFloat(value) < props.min) {
|
|
118
126
|
emit('update:modelValue', undefined)
|
|
119
127
|
return;
|
|
120
128
|
}
|
|
121
|
-
|
|
129
|
+
if (!props.isFloat) {
|
|
130
|
+
value = parseInt(value).toString()
|
|
131
|
+
}
|
|
122
132
|
number.value = value
|
|
123
133
|
emit('update:modelValue', number.value)
|
|
124
134
|
}
|
|
@@ -128,7 +138,7 @@ const emitValue = (e = false) => {
|
|
|
128
138
|
*/
|
|
129
139
|
const plus = () => {
|
|
130
140
|
const currentValue = parseFloat(props.modelValue || props.min || 0)
|
|
131
|
-
number.value = currentValue + props.step
|
|
141
|
+
number.value = (currentValue + props.step).toString()
|
|
132
142
|
emitValue()
|
|
133
143
|
}
|
|
134
144
|
|
|
@@ -137,7 +147,7 @@ const plus = () => {
|
|
|
137
147
|
*/
|
|
138
148
|
const minus = () => {
|
|
139
149
|
const currentValue = parseFloat(props.modelValue || 0)
|
|
140
|
-
number.value = currentValue - props.step
|
|
150
|
+
number.value = (currentValue - props.step).toString()
|
|
141
151
|
emitValue()
|
|
142
152
|
}
|
|
143
153
|
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
v-for="(item,key) in chips"
|
|
14
14
|
:key="key"
|
|
15
15
|
:class="{'px-0':!multiple,'chip body-3':multiple}"
|
|
16
|
-
class=" ms-0 d-flex v-center">
|
|
16
|
+
class="select-text ms-0 d-flex v-center">
|
|
17
17
|
{{ item ? item[text] : '' }}
|
|
18
18
|
<r-icon v-if="multiple" class="chip-icon cursor-pointer ms-1" height="16" width="16"
|
|
19
19
|
@click="handleChip(false,key)"
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
|
|
22
22
|
</span>
|
|
23
23
|
<span>
|
|
24
|
-
<input v-if="!disableSearch"
|
|
24
|
+
<input v-if="!disableSearch&&showMode!=='modal'"
|
|
25
25
|
ref="inputRef"
|
|
26
26
|
:autofocus="autofocus"
|
|
27
27
|
:placeholder="modelValue?'':placeholder"
|
|
@@ -146,7 +146,7 @@ const emitValue = () => {
|
|
|
146
146
|
nextTick(() => {
|
|
147
147
|
tel.value.phone = tel.value.phone.replaceAll(' ', '')
|
|
148
148
|
if (tel.value.phone.startsWith('0')) {
|
|
149
|
-
tel.value.phone = tel.value.phone.substring(1,
|
|
149
|
+
tel.value.phone = tel.value.phone.substring(1, tel.value.phone.length)
|
|
150
150
|
emit('update:modelValue', tel.value.country_code + ' ' + tel.value.phone)
|
|
151
151
|
} else {
|
|
152
152
|
emit('update:modelValue', tel.value.country_code + ' ' + tel.value.phone)
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
</r-row>
|
|
19
19
|
<template v-for="(item,i) in errors"
|
|
20
20
|
:key="i">
|
|
21
|
-
<div class="mb-2 br-md color-error d-flex">
|
|
21
|
+
<div class="mb-2 br-md color-error d-flex pa-3">
|
|
22
22
|
<span>{{ $t(i) }}:</span>
|
|
23
23
|
<span class="flex-grow-1">
|
|
24
24
|
<div v-for="(er,k) in item" :key="k+'-'+i">
|
package/components/img/index.vue
CHANGED
|
@@ -256,13 +256,14 @@ const getSize = () => {
|
|
|
256
256
|
return false
|
|
257
257
|
}
|
|
258
258
|
|
|
259
|
-
const activate = () => {
|
|
259
|
+
const activate = (n = 0) => {
|
|
260
|
+
if (n > 10) return;
|
|
260
261
|
getSize()
|
|
261
262
|
if (size.value.width !== 0 || size.value.height) {
|
|
262
263
|
load.value = true
|
|
263
264
|
} else {
|
|
264
265
|
nextTick(() => {
|
|
265
|
-
activate()
|
|
266
|
+
activate(n++)
|
|
266
267
|
})
|
|
267
268
|
}
|
|
268
269
|
}
|
|
@@ -3,4 +3,5 @@ export * as l_card from '../card/index.js'
|
|
|
3
3
|
export * as l_container from '../container/index.js'
|
|
4
4
|
export * as l_row from '../container/row.js'
|
|
5
5
|
export * as l_col from '../container/col.js'
|
|
6
|
-
export * as l_switch from '../form/switchInput/index.js'
|
|
6
|
+
export * as l_switch from '../form/switchInput/index.js'
|
|
7
|
+
export * as d_scroll from '../../directive/scroll/index.js'
|
|
@@ -1,20 +1,21 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<r-container :class="[$r.prefix+'infinite']">
|
|
3
3
|
<div ref="chat"
|
|
4
|
-
v-scroll
|
|
4
|
+
v-scroll="{handler:onScroll,target:target}"
|
|
5
5
|
:style="{'max-height': height,'height': height}"
|
|
6
|
-
class="infinite-page-container">
|
|
6
|
+
:class="{'overflow-div':height}" class="infinite-page-container">
|
|
7
7
|
<transition-group :class="{'flex-column-reverse':isChat}"
|
|
8
8
|
:name="isChat?'slide-up':'slide-down'"
|
|
9
|
-
class="row"
|
|
9
|
+
class="row"
|
|
10
|
+
tag="div">
|
|
10
11
|
<!-- Default slot for contents. Provide items, total props -->
|
|
11
12
|
<slot :items="datacollection" :total="total">{{ datacollection }}</slot>
|
|
13
|
+
<r-col key="loading" class="col-12">
|
|
14
|
+
<r-progress-line v-show="loading"
|
|
15
|
+
color="color-two"></r-progress-line>
|
|
16
|
+
</r-col>
|
|
12
17
|
</transition-group>
|
|
13
18
|
</div>
|
|
14
|
-
<r-progress-line v-show="loading"
|
|
15
|
-
color="color-two"
|
|
16
|
-
|
|
17
|
-
></r-progress-line>
|
|
18
19
|
<div v-if="noItem"
|
|
19
20
|
class="text-center title-2"
|
|
20
21
|
>{{ noItemMsg }}
|
|
@@ -22,7 +23,16 @@
|
|
|
22
23
|
</r-container>
|
|
23
24
|
</template>
|
|
24
25
|
<script setup>
|
|
25
|
-
import {
|
|
26
|
+
import {
|
|
27
|
+
ref,
|
|
28
|
+
computed,
|
|
29
|
+
onMounted,
|
|
30
|
+
onUnmounted,
|
|
31
|
+
onActivated,
|
|
32
|
+
onDeactivated,
|
|
33
|
+
watch,
|
|
34
|
+
inject, nextTick
|
|
35
|
+
} from 'vue'
|
|
26
36
|
|
|
27
37
|
const props = defineProps({
|
|
28
38
|
/**
|
|
@@ -125,7 +135,7 @@ const loading = ref(false)
|
|
|
125
135
|
const total = ref(0)
|
|
126
136
|
const noItem = ref(false)
|
|
127
137
|
|
|
128
|
-
const
|
|
138
|
+
const target = computed(() => props.height ? false : 'window')
|
|
129
139
|
|
|
130
140
|
// Methods
|
|
131
141
|
const onScroll = (e) => {
|
|
@@ -145,13 +155,13 @@ const onScroll = (e) => {
|
|
|
145
155
|
}
|
|
146
156
|
}
|
|
147
157
|
} else {
|
|
148
|
-
if (active.value &&
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
158
|
+
if (active.value &&
|
|
159
|
+
(document.body.offsetHeight < ((window.innerHeight + window.scrollY) + props.distanceLoad)) &&
|
|
160
|
+
!loading.value &&
|
|
161
|
+
(datacollection.value.length < total.value)
|
|
162
|
+
) {
|
|
163
|
+
page.value++
|
|
164
|
+
get()
|
|
155
165
|
}
|
|
156
166
|
}
|
|
157
167
|
}
|
|
@@ -161,15 +171,21 @@ const get = () => {
|
|
|
161
171
|
loading.value = true
|
|
162
172
|
noItem.value = false
|
|
163
173
|
|
|
164
|
-
|
|
174
|
+
let end = true
|
|
175
|
+
let params = {'page': page.value}
|
|
176
|
+
|
|
177
|
+
if (props.live === true) {
|
|
178
|
+
params = {'page': 1}
|
|
179
|
+
end = false
|
|
180
|
+
}
|
|
165
181
|
if (typeof props.query === 'object') {
|
|
166
182
|
Object.assign(params, props.query)
|
|
167
183
|
}
|
|
168
184
|
|
|
169
185
|
$axios.get(props.url, {params, headers: props.headers})
|
|
170
|
-
.then((
|
|
171
|
-
push(
|
|
172
|
-
total.value =
|
|
186
|
+
.then(({data}) => {
|
|
187
|
+
push(data.data, end)
|
|
188
|
+
total.value = data.total
|
|
173
189
|
if (total.value === 0) {
|
|
174
190
|
noItem.value = true
|
|
175
191
|
}
|
|
@@ -180,27 +196,48 @@ const get = () => {
|
|
|
180
196
|
})
|
|
181
197
|
}
|
|
182
198
|
|
|
183
|
-
const push = (data) => {
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
datacollection.value.
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
199
|
+
const push = (data, end = false) => {
|
|
200
|
+
if (!end) {
|
|
201
|
+
let d = data
|
|
202
|
+
const lng = datacollection.value.length
|
|
203
|
+
for (let key = 0; key < lng; key++) {
|
|
204
|
+
if (key <= data.length) {
|
|
205
|
+
if ($helper.searchArray(d, '_id', datacollection.value[key]['_id']) === false) {
|
|
206
|
+
d.push(datacollection.value[key])
|
|
207
|
+
}
|
|
208
|
+
} else {
|
|
209
|
+
d.push(datacollection.value[key])
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
datacollection.value = d
|
|
192
213
|
} else {
|
|
193
|
-
|
|
214
|
+
let d = datacollection.value
|
|
215
|
+
const lng = data.length
|
|
216
|
+
for (let key = 0; key < lng; key++) {
|
|
217
|
+
if ($helper.searchArray(d, '_id', data[key]['_id']) === false) {
|
|
218
|
+
d.push(data[key])
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
datacollection.value = d
|
|
194
222
|
}
|
|
195
|
-
|
|
223
|
+
nextTick(() => {
|
|
224
|
+
let el = chat.value
|
|
225
|
+
let can = false
|
|
226
|
+
if (props.isChat) {
|
|
227
|
+
can = el.scrollHeight <= el.scrollTop + el.clientHeight
|
|
228
|
+
} else {
|
|
229
|
+
can = el.scrollTop === 0
|
|
230
|
+
}
|
|
196
231
|
|
|
197
|
-
if (
|
|
198
|
-
|
|
199
|
-
|
|
232
|
+
if (props.isChat) {
|
|
233
|
+
if (first.value || can) {
|
|
234
|
+
el.scrollTop = el.scrollHeight
|
|
235
|
+
first.value = false
|
|
236
|
+
}
|
|
237
|
+
} else if (can) {
|
|
238
|
+
el.scrollTop = 0
|
|
200
239
|
}
|
|
201
|
-
}
|
|
202
|
-
el.scrollTop = 0;
|
|
203
|
-
}
|
|
240
|
+
})
|
|
204
241
|
}
|
|
205
242
|
|
|
206
243
|
let liveInterval = null
|
|
@@ -231,6 +268,7 @@ onDeactivated(() => {
|
|
|
231
268
|
|
|
232
269
|
watch(() => props.live, (newValue) => {
|
|
233
270
|
if (newValue) {
|
|
271
|
+
get()
|
|
234
272
|
setupLiveUpdates()
|
|
235
273
|
} else {
|
|
236
274
|
clearInterval(liveInterval)
|
|
@@ -248,7 +286,11 @@ onUnmounted(() => {
|
|
|
248
286
|
@use "../../style" as *;
|
|
249
287
|
|
|
250
288
|
.#{$prefix}infinite {
|
|
251
|
-
|
|
252
|
-
|
|
289
|
+
width: 100%;
|
|
290
|
+
|
|
291
|
+
.overflow-div {
|
|
292
|
+
overflow-y: auto;
|
|
293
|
+
overflow-x: hidden;
|
|
294
|
+
}
|
|
253
295
|
}
|
|
254
296
|
</style>
|
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div ref="menuRef" v-click-outside="close" :class="$r.prefix+'menu'">
|
|
3
3
|
<div class="d-flex h-start flex-row v-center">
|
|
4
|
-
<
|
|
4
|
+
<slot name="label">
|
|
5
|
+
<span v-if="label" class="menu-label" @click.prevent="open">{{ label }}</span>
|
|
6
|
+
</slot>
|
|
5
7
|
<transition name="fade" mode="out-in">
|
|
6
8
|
<!-- Header Navigation Menu Icons -->
|
|
7
|
-
<r-btn
|
|
9
|
+
<r-btn v-if="show" key="on" icon size="sm" text @click.prevent="close">
|
|
8
10
|
<r-icon v-html="$r.icons.chevron_up"></r-icon>
|
|
9
11
|
</r-btn>
|
|
10
|
-
<r-btn
|
|
12
|
+
<r-btn v-else key="off" icon size="sm" text @click.prevent="open">
|
|
11
13
|
<r-icon v-html="icon||$r.icons.chevron_down"></r-icon>
|
|
12
14
|
</r-btn>
|
|
13
15
|
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
</template>
|
|
49
49
|
|
|
50
50
|
<script setup>
|
|
51
|
-
import {ref, computed, onMounted, onUnmounted} from 'vue'
|
|
51
|
+
import {ref, computed, onMounted, onUnmounted, watch} from 'vue'
|
|
52
52
|
|
|
53
53
|
/**
|
|
54
54
|
* @example // Slider usage
|
|
@@ -338,6 +338,9 @@ const goToSlide = (i) => {
|
|
|
338
338
|
emit('index', currentIndex.value)
|
|
339
339
|
}
|
|
340
340
|
|
|
341
|
+
watch(() => props.slides, () => {
|
|
342
|
+
init()
|
|
343
|
+
})
|
|
341
344
|
onMounted(() => {
|
|
342
345
|
init()
|
|
343
346
|
})
|
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
<div :class="`${$r.prefix}swiper`"
|
|
3
3
|
ref="swiperRef"
|
|
4
4
|
>
|
|
5
|
-
<!-- @slot
|
|
6
|
-
@binding {Function}
|
|
7
|
-
<slot
|
|
5
|
+
<!-- @slot Previous navigation slot
|
|
6
|
+
@binding {Function} previous - Function to navigate previous -->
|
|
7
|
+
<slot :previous="previous" name="previous"></slot>
|
|
8
8
|
|
|
9
|
-
<!-- @slot
|
|
10
|
-
@binding {Function}
|
|
11
|
-
<slot
|
|
9
|
+
<!-- @slot Next navigation slot
|
|
10
|
+
@binding {Function} next - Function to navigate next -->
|
|
11
|
+
<slot :next="next" name="next"></slot>
|
|
12
12
|
|
|
13
13
|
<div class="swiper-container"
|
|
14
14
|
ref="containerRef"
|
|
@@ -138,18 +138,6 @@ const itemWidth = computed(() => {
|
|
|
138
138
|
})
|
|
139
139
|
|
|
140
140
|
|
|
141
|
-
const canGoNext = computed(() => {
|
|
142
|
-
const r = $r.rtl ? 1 : -1
|
|
143
|
-
const maxX = (containerRef.value?.scrollWidth - swiperRef.value?.offsetWidth) / r
|
|
144
|
-
return x.value * r < maxX
|
|
145
|
-
})
|
|
146
|
-
|
|
147
|
-
const canGoPrev = computed(() => {
|
|
148
|
-
const r = $r.rtl ? 1 : -1
|
|
149
|
-
return x.value * r > 0
|
|
150
|
-
})
|
|
151
|
-
|
|
152
|
-
|
|
153
141
|
/**
|
|
154
142
|
* Navigates to a specific slide
|
|
155
143
|
* @param {Number} n - Slide number (1-indexed)
|
|
@@ -165,41 +153,19 @@ const goToSlide = (n) => {
|
|
|
165
153
|
}
|
|
166
154
|
|
|
167
155
|
/**
|
|
168
|
-
* Navigates to the next
|
|
169
|
-
* @param {Number|null} customX - Custom distance to move in pixels
|
|
156
|
+
* Navigates to the next slide
|
|
170
157
|
*/
|
|
171
|
-
const
|
|
172
|
-
if (
|
|
173
|
-
|
|
174
|
-
const moveX = customX || itemWidth.value || 200
|
|
175
|
-
clearTimeout(timer.value)
|
|
176
|
-
|
|
177
|
-
timer.value = nextTick(() => {
|
|
178
|
-
inMove.value = true
|
|
179
|
-
const direction = $r.rtl ? 1 : -1
|
|
180
|
-
x.value = prePosition.value - (moveX * direction)
|
|
181
|
-
end()
|
|
182
|
-
clearTimeout(timer.value)
|
|
183
|
-
})
|
|
158
|
+
const next = () => {
|
|
159
|
+
if (currentSlide.value + 1 > slides.value) return
|
|
160
|
+
goToSlide(currentSlide.value + 1)
|
|
184
161
|
}
|
|
185
162
|
|
|
186
163
|
/**
|
|
187
|
-
* Navigates to the previous
|
|
188
|
-
* @param {Number|null} customX - Custom distance to move in pixels
|
|
164
|
+
* Navigates to the previous slide
|
|
189
165
|
*/
|
|
190
|
-
const
|
|
191
|
-
if (
|
|
192
|
-
|
|
193
|
-
const moveX = customX || itemWidth.value || 200
|
|
194
|
-
clearTimeout(timer.value)
|
|
195
|
-
|
|
196
|
-
timer.value = setTimeout(() => {
|
|
197
|
-
inMove.value = true
|
|
198
|
-
const direction = $r.rtl ? 1 : -1
|
|
199
|
-
x.value = prePosition.value + (moveX * direction)
|
|
200
|
-
end()
|
|
201
|
-
clearTimeout(timer.value)
|
|
202
|
-
}, 50)
|
|
166
|
+
const previous = () => {
|
|
167
|
+
if (currentSlide.value === 1) return
|
|
168
|
+
goToSlide(currentSlide.value - 1)
|
|
203
169
|
}
|
|
204
170
|
|
|
205
171
|
/**
|
|
@@ -294,6 +260,21 @@ watch(() => props.items, () => {
|
|
|
294
260
|
|
|
295
261
|
handleResize()
|
|
296
262
|
}, {deep: true})
|
|
263
|
+
|
|
264
|
+
defineExpose({
|
|
265
|
+
/**
|
|
266
|
+
* Navigates to the previous slide
|
|
267
|
+
*/
|
|
268
|
+
previous,
|
|
269
|
+
/**
|
|
270
|
+
* Navigates to the next slide
|
|
271
|
+
*/
|
|
272
|
+
next,
|
|
273
|
+
/**
|
|
274
|
+
* Return Current Slide
|
|
275
|
+
*/
|
|
276
|
+
currentSlide
|
|
277
|
+
})
|
|
297
278
|
</script>
|
|
298
279
|
|
|
299
280
|
<style lang="scss">
|
|
@@ -142,6 +142,7 @@
|
|
|
142
142
|
</template>
|
|
143
143
|
<r-table v-else :headers="headerTable" :items="table.data" :key-item="itemId"
|
|
144
144
|
:responsive="responsive"
|
|
145
|
+
:editable="editable"
|
|
145
146
|
transition="table-row">
|
|
146
147
|
<template v-slot:header="{header}">
|
|
147
148
|
<th v-for="(item,key) in header"
|
|
@@ -310,6 +311,11 @@ const props = defineProps({
|
|
|
310
311
|
* @type {Boolean}
|
|
311
312
|
*/
|
|
312
313
|
responsive: Boolean,
|
|
314
|
+
/**
|
|
315
|
+
* Enables editable table behavior
|
|
316
|
+
* @type {Boolean}
|
|
317
|
+
*/
|
|
318
|
+
editable: Boolean,
|
|
313
319
|
/**
|
|
314
320
|
* Displays data in cards view instead of table
|
|
315
321
|
* @type {Boolean}
|
|
@@ -33,7 +33,8 @@
|
|
|
33
33
|
class="text-start text-no-wrap"
|
|
34
34
|
@click.prevent="sorting(item.value)">
|
|
35
35
|
{{ translate ? $t(item.text, 'renusify') : item.text }}
|
|
36
|
-
<r-icon v-if="sortKey===item.value" :class="{'sort-desc':!sortAsc}"
|
|
36
|
+
<r-icon v-if="sortKey===item.value" :class="{'sort-desc':!sortAsc}"
|
|
37
|
+
v-html="$r.icons.arrow_up"></r-icon>
|
|
37
38
|
</th>
|
|
38
39
|
</slot>
|
|
39
40
|
</tr>
|
|
@@ -207,6 +208,11 @@ const props = defineProps({
|
|
|
207
208
|
* @type {Boolean}
|
|
208
209
|
*/
|
|
209
210
|
editable: Boolean,
|
|
211
|
+
/**
|
|
212
|
+
* Table key for configuration editing
|
|
213
|
+
* @type {String}
|
|
214
|
+
*/
|
|
215
|
+
tableKey: String,
|
|
210
216
|
/**
|
|
211
217
|
* Applies stripped row styling
|
|
212
218
|
* @type {Boolean}
|
|
@@ -293,11 +299,22 @@ const lists = computed(() => {
|
|
|
293
299
|
|
|
294
300
|
const th = computed(() => {
|
|
295
301
|
const res = []
|
|
296
|
-
const
|
|
302
|
+
const lng = cols.value.length
|
|
303
|
+
const list = lng > 0 ? cols.value : th_all.value
|
|
297
304
|
|
|
298
305
|
list.forEach((item) => {
|
|
299
306
|
if (item && !(item.value in hidden.value) && !(item.value in hidden_col.value)) {
|
|
300
|
-
|
|
307
|
+
if (lng > 0) {
|
|
308
|
+
for (let i = 0; i < lng; i++) {
|
|
309
|
+
const t = th_all.value[i]
|
|
310
|
+
if (t.value === item.value) {
|
|
311
|
+
res.push(t)
|
|
312
|
+
break
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
} else {
|
|
316
|
+
res.push(item)
|
|
317
|
+
}
|
|
301
318
|
}
|
|
302
319
|
})
|
|
303
320
|
return res
|
|
@@ -324,7 +341,10 @@ const th_all = computed(() => {
|
|
|
324
341
|
})
|
|
325
342
|
|
|
326
343
|
const hash_key = computed(() => {
|
|
327
|
-
let r =
|
|
344
|
+
let r = window.location
|
|
345
|
+
if (props.tableKey) {
|
|
346
|
+
r += props.tableKey
|
|
347
|
+
}
|
|
328
348
|
th_all.value.forEach((item) => {
|
|
329
349
|
if (item) {
|
|
330
350
|
r += item.value
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* <div class="scroll-areas">
|
|
6
6
|
* <div class="scroll-area">
|
|
7
7
|
* <h3>Window Scroll</h3>
|
|
8
|
-
* <div v-scroll
|
|
8
|
+
* <div v-scroll="{handler:handleWindowScroll,target:'window'}" class="scroll-content window-scroll">
|
|
9
9
|
* <div class="scroll-info">
|
|
10
10
|
* <div class="info-item">
|
|
11
11
|
* <span>Scroll Top:</span>
|
|
@@ -242,35 +242,39 @@
|
|
|
242
242
|
* }
|
|
243
243
|
* </style>
|
|
244
244
|
* */
|
|
245
|
-
function mounted
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
245
|
+
function mounted(el, binding) {
|
|
246
|
+
let callback = binding.value
|
|
247
|
+
if (typeof binding.value === 'object') {
|
|
248
|
+
binding = binding.value
|
|
249
|
+
callback = binding.handler
|
|
250
|
+
}
|
|
251
|
+
const options = binding.options || {
|
|
252
|
+
passive: true
|
|
253
|
+
}
|
|
250
254
|
let target = el
|
|
251
|
-
if (binding.
|
|
255
|
+
if (binding.target === 'window') {
|
|
252
256
|
target = window
|
|
253
|
-
} else if (binding.
|
|
254
|
-
target = document.querySelector(binding.
|
|
257
|
+
} else if (binding.target) {
|
|
258
|
+
target = document.querySelector(binding.target)
|
|
259
|
+
}
|
|
260
|
+
if (!target) return
|
|
261
|
+
target.addEventListener('scroll', callback, options)
|
|
262
|
+
el._onScroll = {
|
|
263
|
+
callback,
|
|
264
|
+
options,
|
|
265
|
+
target
|
|
255
266
|
}
|
|
256
|
-
if (!target) return
|
|
257
|
-
target.addEventListener('scroll', callback, options)
|
|
258
|
-
el._onScroll = {
|
|
259
|
-
callback,
|
|
260
|
-
options,
|
|
261
|
-
target
|
|
262
|
-
}
|
|
263
267
|
}
|
|
264
268
|
|
|
265
|
-
function unmounted
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
269
|
+
function unmounted(el) {
|
|
270
|
+
if (!el._onScroll) return
|
|
271
|
+
const {
|
|
272
|
+
callback,
|
|
273
|
+
options,
|
|
274
|
+
target
|
|
275
|
+
} = el._onScroll
|
|
276
|
+
target.removeEventListener('scroll', callback, options)
|
|
277
|
+
delete el._onScroll
|
|
274
278
|
}
|
|
275
279
|
|
|
276
280
|
export default {
|
package/index.js
CHANGED
|
@@ -18,38 +18,28 @@ function breakpoint() {
|
|
|
18
18
|
const width = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
|
|
19
19
|
const height = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;
|
|
20
20
|
const points = {
|
|
21
|
-
'
|
|
22
|
-
'sm': 576,
|
|
21
|
+
'sm': 0,
|
|
23
22
|
'md': 768,
|
|
24
|
-
'lg':
|
|
25
|
-
'xl': 1440
|
|
23
|
+
'lg': 1200
|
|
26
24
|
}
|
|
27
25
|
let data = {
|
|
28
26
|
points: points,
|
|
29
|
-
|
|
30
|
-
smOnly: points.sm <= width && width < points.md,
|
|
31
|
-
smAndDown: width < points.md,
|
|
32
|
-
smAndUp: width >= points.sm,
|
|
27
|
+
smOnly: width < points.md,
|
|
33
28
|
mdOnly: points.md <= width && width < points.lg,
|
|
34
29
|
mdAndDown: width < points.lg,
|
|
35
30
|
mdAndUp: width >= points.md,
|
|
36
31
|
lgOnly: points.lg <= width && width < points.xl,
|
|
37
32
|
lgAndDown: width < points.xl,
|
|
38
33
|
lgAndUp: width >= points.lg,
|
|
39
|
-
xlOnly: points.xl <= width,
|
|
40
34
|
width: width,
|
|
41
35
|
height: height
|
|
42
36
|
}
|
|
43
|
-
if (data.
|
|
44
|
-
data.name = 'xs'
|
|
45
|
-
} else if (data.smOnly) {
|
|
37
|
+
if (data.smOnly) {
|
|
46
38
|
data.name = 'sm'
|
|
47
39
|
} else if (data.mdOnly) {
|
|
48
40
|
data.name = 'md'
|
|
49
41
|
} else if (data.lgOnly) {
|
|
50
42
|
data.name = 'lg'
|
|
51
|
-
} else if (data.xlOnly) {
|
|
52
|
-
data.name = 'xl'
|
|
53
43
|
}
|
|
54
44
|
return data
|
|
55
45
|
}
|
package/package.json
CHANGED
|
@@ -25,10 +25,9 @@ $borders: (
|
|
|
25
25
|
$cursor: ('pointer', 'auto', 'grab', 'grabbing') !default;
|
|
26
26
|
|
|
27
27
|
$grid-breakpoints: (
|
|
28
|
-
'
|
|
29
|
-
'
|
|
30
|
-
'
|
|
31
|
-
'lg': 64rem, // Large devices (desktops, 1024px)
|
|
28
|
+
'sm': 0,
|
|
29
|
+
'md': 48rem, // Small devices (tablets, 768px)
|
|
30
|
+
'lg': 75rem, // Large devices (laptops, 1200px)
|
|
32
31
|
) !default;
|
|
33
32
|
|
|
34
33
|
$base-font-size: 1rem;
|
|
@@ -39,10 +38,9 @@ $grid-columns: 12 !default;
|
|
|
39
38
|
$container-padding-x: math.div($grid-gutter, 2) !default;
|
|
40
39
|
|
|
41
40
|
$grid-gutters: (
|
|
42
|
-
'
|
|
43
|
-
'sm': math.div($grid-gutter, 6),
|
|
41
|
+
'sm': math.div($grid-gutter, 12),
|
|
44
42
|
'md': math.div($grid-gutter, 3),
|
|
45
|
-
'lg':$grid-gutter
|
|
43
|
+
'lg':$grid-gutter,
|
|
46
44
|
) !default;
|
|
47
45
|
|
|
48
46
|
$box-shadows: (
|
|
@@ -56,8 +54,8 @@ $box-shadows: (
|
|
|
56
54
|
) !default;
|
|
57
55
|
|
|
58
56
|
$container-max-widths: (
|
|
59
|
-
'md': map.get($grid-breakpoints, 'md')- 3rem,
|
|
60
|
-
'lg': map.get($grid-breakpoints, 'lg')- 4rem
|
|
57
|
+
'md': map.get($grid-breakpoints, 'md') - 3rem,
|
|
58
|
+
'lg': map.get($grid-breakpoints, 'lg') - 4rem
|
|
61
59
|
) !default;
|
|
62
60
|
|
|
63
61
|
$font-weights: (
|
package/tools/icons.js
CHANGED
|
@@ -23,7 +23,7 @@ export let Icons = {
|
|
|
23
23
|
'attachment': '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" preserveAspectRatio="xMidYMid meet" viewBox="0 0 24 24"><path fill="currentColor" d="M7.5 18A5.5 5.5 0 0 1 2 12.5A5.5 5.5 0 0 1 7.5 7H18a4 4 0 0 1 4 4a4 4 0 0 1-4 4H9.5A2.5 2.5 0 0 1 7 12.5A2.5 2.5 0 0 1 9.5 10H17v1.5H9.5a1 1 0 0 0-1 1a1 1 0 0 0 1 1H18a2.5 2.5 0 0 0 2.5-2.5A2.5 2.5 0 0 0 18 8.5H7.5a4 4 0 0 0-4 4a4 4 0 0 0 4 4H17V18H7.5Z"/></svg>',
|
|
24
24
|
'send': '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" preserveAspectRatio="xMidYMid meet" viewBox="0 0 24 24"><path fill="currentColor" d="m2 21l21-9L2 3v7l15 2l-15 2v7Z"/></svg>',
|
|
25
25
|
'sticker': '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" preserveAspectRatio="xMidYMid meet" viewBox="0 0 24 24"><path fill="currentColor" d="M5.5 2C3.56 2 2 3.56 2 5.5v13C2 20.44 3.56 22 5.5 22H16l6-6V5.5C22 3.56 20.44 2 18.5 2h-13m.25 2h12.5A1.75 1.75 0 0 1 20 5.75V15h-1.5c-1.94 0-3.5 1.56-3.5 3.5V20H5.75A1.75 1.75 0 0 1 4 18.25V5.75A1.75 1.75 0 0 1 5.75 4m8.69 2.77c-.16 0-.32.02-.47.06c-.94.26-1.47 1.22-1.23 2.17c.05.15.12.3.21.44l3.23-.88c0-.17-.02-.34-.06-.51c-.21-.75-.9-1.28-1.68-1.28M8.17 8.5c-.17 0-.32 0-.47.05c-.93.26-1.48 1.22-1.23 2.15c.03.16.12.3.21.46l3.23-.88c0-.17-.02-.34-.06-.5A1.72 1.72 0 0 0 8.17 8.5m8.55 2.76l-9.13 2.51a5.266 5.266 0 0 0 5.36 1.64a5.273 5.273 0 0 0 3.77-4.15Z"/></svg>',
|
|
26
|
-
'search': '<svg xmlns="http://www.w3.org/2000/svg"
|
|
26
|
+
'search': '<svg width="24" height="24" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M8.25 15.5625C4.215 15.5625 0.9375 12.285 0.9375 8.25C0.9375 4.215 4.215 0.9375 8.25 0.9375C12.285 0.9375 15.5625 4.215 15.5625 8.25C15.5625 12.285 12.285 15.5625 8.25 15.5625ZM8.25 2.0625C4.8375 2.0625 2.0625 4.8375 2.0625 8.25C2.0625 11.6625 4.8375 14.4375 8.25 14.4375C11.6625 14.4375 14.4375 11.6625 14.4375 8.25C14.4375 4.8375 11.6625 2.0625 8.25 2.0625Z" fill="currentColor"/><path d="M15.12 17.0925C15.06 17.0925 15 17.085 14.9475 17.0775C14.595 17.0325 13.9575 16.7925 13.5975 15.72C13.41 15.1575 13.4775 14.595 13.785 14.1675C14.0925 13.74 14.61 13.5 15.2025 13.5C15.9675 13.5 16.5675 13.7925 16.8375 14.31C17.1075 14.8275 17.0325 15.4875 16.605 16.125C16.0725 16.9275 15.495 17.0925 15.12 17.0925ZM14.67 15.3675C14.7975 15.7575 14.9775 15.9525 15.0975 15.9675C15.2175 15.9825 15.4425 15.84 15.675 15.5025C15.8925 15.18 15.9075 14.9475 15.855 14.8425C15.8025 14.7375 15.5925 14.625 15.2025 14.625C14.97 14.625 14.7975 14.7 14.7 14.8275C14.61 14.955 14.595 15.15 14.67 15.3675Z" fill="currentColor"/></svg>',
|
|
27
27
|
'drag': '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" preserveAspectRatio="xMidYMid meet" viewBox="0 0 24 24"><path fill="currentColor" d="M7 19v-2h2v2H7m4 0v-2h2v2h-2m4 0v-2h2v2h-2m-8-4v-2h2v2H7m4 0v-2h2v2h-2m4 0v-2h2v2h-2m-8-4V9h2v2H7m4 0V9h2v2h-2m4 0V9h2v2h-2M7 7V5h2v2H7m4 0V5h2v2h-2m4 0V5h2v2h-2Z"/></svg>',
|
|
28
28
|
'setting': '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" preserveAspectRatio="xMidYMid meet" viewBox="0 0 24 24"><path fill="currentColor" d="M19.14 12.94c.04-.3.06-.61.06-.94c0-.32-.02-.64-.07-.94l2.03-1.58a.49.49 0 0 0 .12-.61l-1.92-3.32a.488.488 0 0 0-.59-.22l-2.39.96c-.5-.38-1.03-.7-1.62-.94l-.36-2.54a.484.484 0 0 0-.48-.41h-3.84c-.24 0-.43.17-.47.41l-.36 2.54c-.59.24-1.13.57-1.62.94l-2.39-.96c-.22-.08-.47 0-.59.22L2.74 8.87c-.12.21-.08.47.12.61l2.03 1.58c-.05.3-.09.63-.09.94s.02.64.07.94l-2.03 1.58a.49.49 0 0 0-.12.61l1.92 3.32c.12.22.37.29.59.22l2.39-.96c.5.38 1.03.7 1.62.94l.36 2.54c.05.24.24.41.48.41h3.84c.24 0 .44-.17.47-.41l.36-2.54c.59-.24 1.13-.56 1.62-.94l2.39.96c.22.08.47 0 .59-.22l1.92-3.32c.12-.22.07-.47-.12-.61l-2.01-1.58zM12 15.6c-1.98 0-3.6-1.62-3.6-3.6s1.62-3.6 3.6-3.6s3.6 1.62 3.6 3.6s-1.62 3.6-3.6 3.6z"/></svg>',
|
|
29
29
|
'star': '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" preserveAspectRatio="xMidYMid meet" viewBox="0 0 24 24"><path fill="currentColor" d="M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.62L12 2L9.19 8.62L2 9.24l5.45 4.73L5.82 21L12 17.27Z"/></svg>',
|