renusify 3.0.1 → 3.1.0

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.
@@ -180,7 +180,7 @@ const saveImage = () => {
180
180
  overflow: hidden;
181
181
  background-color: var(--color-sheet);
182
182
 
183
- img, svg{
183
+ img, svg {
184
184
  width: 100%;
185
185
  height: 100%;
186
186
  object-fit: cover;
@@ -20,12 +20,12 @@
20
20
  </r-col>
21
21
  </r-row>
22
22
  <r-row class="h-end no-gutters">
23
- <r-btn :loading="loading"
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
- v-if="!loading">
28
+ :loading="loading">
29
29
  {{ cancelText || $t('cancel', 'renusify') }}
30
30
  </r-btn>
31
31
  <r-btn :disabled="hard&&!valid"
@@ -102,7 +102,7 @@ const toggle = () => {
102
102
  width: 100%;
103
103
  cursor: pointer;
104
104
 
105
- .checkbox-holder{
105
+ .checkbox-holder {
106
106
  display: flex;
107
107
  align-items: center;
108
108
  }
@@ -54,7 +54,7 @@
54
54
  :month="currentPeriod.month"
55
55
  :year="currentPeriod.year"></month>
56
56
 
57
- <div v-if="isRangeMode && rangeSelection.startDate && rangeSelection.endDate" class="range-info">
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="isRangeMode&&!showTime" class="date-picker-actions mb-3">
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.isRangeMode && rangeSelection.value.startDate) {
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.isRangeMode) {
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.isRangeMode) {
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.isRangeMode) {
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.isRangeMode) {
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.isRangeMode) {
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.isRangeMode && Array.isArray(props.modelValue) && props.modelValue.length === 2) {
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,15 +3,15 @@
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 @click.prevent="fileDelete()" class="color-error-text"
7
- v-html="$r.icons.delete"></r-icon>
6
+ <r-icon class="color-error-text" v-html="$r.icons.delete"
7
+ @click.prevent="fileDelete()"></r-icon>
8
8
  </r-btn>
9
9
  <r-progress-circle
10
- :indeterminate="false"
11
- :model-value="uploadPercentage"
12
- :width="2"
13
- class="image-progress"
14
- size="50"
10
+ :indeterminate="false"
11
+ :model-value="uploadPercentage"
12
+ :width="2"
13
+ class="image-progress"
14
+ size="50"
15
15
  >
16
16
  {{ `% ${uploadPercentage}` }}
17
17
  </r-progress-circle>
@@ -26,48 +26,48 @@
26
26
  </div>
27
27
  <div class="file-meta pa-1" v-if="meta && uploadPercentage===100">
28
28
  <r-text-input
29
- v-for="(m,k) in meta"
30
- :key="k"
31
- v-model="metaList[m]"
32
- :label="$t(m,'renusify')"
33
- :rules="metaRequired?['required']:[]"
34
- @update:model-value="emitFileLink"
29
+ v-for="(m,k) in meta"
30
+ :key="k"
31
+ v-model="metaList[m]"
32
+ :label="$t(m,'renusify')"
33
+ :rules="metaRequired?['required']:[]"
34
+ @update:model-value="emitFileLink"
35
35
  ></r-text-input>
36
36
  </div>
37
37
  </div>
38
38
 
39
39
  <r-icon
40
- v-if="showAdd"
41
- class="pick-icon cursor-pointer d-flex h-center v-center color-one-text"
42
- height="100"
43
- width="100"
44
- v-html="$r.icons.plus"
45
- @click.prevent.stop="pickFile"
40
+ v-if="showAdd"
41
+ class="pick-icon cursor-pointer d-flex h-center v-center color-one-text"
42
+ height="100"
43
+ width="100"
44
+ v-html="$r.icons.plus"
45
+ @click.prevent.stop="pickFile"
46
46
  ></r-icon>
47
47
  <input
48
- v-if="showFile"
49
- ref="fileInput"
50
- :accept="accept"
51
- style="display: none"
52
- type="file"
53
- @change="addFile"
48
+ v-if="showFile"
49
+ ref="fileInput"
50
+ :accept="accept"
51
+ style="display: none"
52
+ type="file"
53
+ @change="addFile"
54
54
  >
55
55
  <r-modal v-model="showCrop" max-width="300px" no-close-btn>
56
56
  <r-cropper
57
- v-if="wPH && file"
58
- :img-src="file"
59
- :select-img="false"
60
- :w-p-h="wPH || 1"
61
- get-blob
62
- show-cropped
63
- @cropped="handleCropped"
57
+ v-if="wPH && file"
58
+ :img-src="file"
59
+ :select-img="false"
60
+ :w-p-h="wPH || 1"
61
+ get-blob
62
+ show-cropped
63
+ @cropped="handleCropped"
64
64
  ></r-cropper>
65
65
  </r-modal>
66
66
  </div>
67
67
  </template>
68
68
 
69
69
  <script setup>
70
- import { ref, computed, watch, onMounted, nextTick, inject } from 'vue'
70
+ import {ref, computed, watch, onMounted, nextTick, inject} from 'vue'
71
71
 
72
72
  const props = defineProps({
73
73
  accept: {
@@ -202,7 +202,7 @@ const checkSave = () => {
202
202
  // Calculate allowed aspect ratios
203
203
  const allowedWPH = calculateAllowedWPH(props.wPH)
204
204
 
205
- img.onload = function() {
205
+ img.onload = function () {
206
206
  const currentWPH = parseFloat((this.width / this.height).toFixed(4))
207
207
 
208
208
  if (!allowedWPH.includes(currentWPH)) {
@@ -289,8 +289,8 @@ const saveImage = async () => {
289
289
  onUploadProgress: (progressEvent) => {
290
290
  if (progressEvent.total) {
291
291
  uploadPercentage.value = Math.min(
292
- parseInt(Math.floor((progressEvent.loaded * 100) / progressEvent.total)),
293
- 98
292
+ parseInt(Math.floor((progressEvent.loaded * 100) / progressEvent.total)),
293
+ 98
294
294
  )
295
295
  }
296
296
  },
@@ -313,7 +313,7 @@ const deleteImage = async () => {
313
313
 
314
314
  try {
315
315
  const response = await $axios.delete(props.uploadLink, {
316
- data: { link: fileLink.value },
316
+ data: {link: fileLink.value},
317
317
  headers: props.headers
318
318
  })
319
319
  return response
@@ -352,7 +352,7 @@ const getUrl = (value) => {
352
352
 
353
353
  const emitFileLink = () => {
354
354
  if (props.meta) {
355
- emit('file-link', { 'url': fileLink.value, 'meta': metaList.value })
355
+ emit('file-link', {'url': fileLink.value, 'meta': metaList.value})
356
356
  } else {
357
357
  emit('file-link', fileLink.value)
358
358
  }
@@ -365,7 +365,7 @@ watch(() => props.modelValue, (newVal, oldVal) => {
365
365
  if (JSON.stringify(newVal) !== JSON.stringify(oldVal)) {
366
366
  setValue(newVal)
367
367
  }
368
- }, { immediate: true })
368
+ }, {immediate: true})
369
369
 
370
370
  // Initialize
371
371
  onMounted(() => {
@@ -44,10 +44,10 @@ const autofocus = attr.autofocus
44
44
 
45
45
  const props = defineProps({
46
46
  /**
47
- * The input's model value (number or string)
48
- * @type {Number|String}
47
+ * The input's model value
48
+ * @type {String}
49
49
  */
50
- modelValue: [Number, String],
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"
@@ -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">
@@ -256,8 +256,8 @@ const getSize = () => {
256
256
  return false
257
257
  }
258
258
 
259
- const activate = (n=0) => {
260
- if (n>10)return;
259
+ const activate = (n = 0) => {
260
+ if (n > 10) return;
261
261
  getSize()
262
262
  if (size.value.width !== 0 || size.value.height) {
263
263
  load.value = true
@@ -3,36 +3,30 @@
3
3
  <div ref="chat"
4
4
  v-scroll="{handler:onScroll,target:target}"
5
5
  :style="{'max-height': height,'height': height}"
6
- class="infinite-page-container" :class="{'overflow-div':height}">
7
- <transition-group :class="{'flex-column-reverse':isChat}"
6
+ :class="{'overflow-div':height}" class="infinite-page-container">
7
+ <transition-group v-if="!noItem" :class="{'flex-column-reverse':isChat}"
8
8
  :name="isChat?'slide-up':'slide-down'"
9
9
  class="row"
10
10
  tag="div">
11
11
  <!-- Default slot for contents. Provide items, total props -->
12
12
  <slot :items="datacollection" :total="total">{{ datacollection }}</slot>
13
- <r-col class="col-12" key="loading">
14
- <r-progress-line color="color-two"
15
- v-show="loading"></r-progress-line>
13
+ <r-col key="loading" class="col-12">
14
+ <r-progress-line v-show="loading"
15
+ color="color-two"></r-progress-line>
16
16
  </r-col>
17
17
  </transition-group>
18
18
  </div>
19
- <div v-if="noItem"
20
- class="text-center title-2"
21
- >{{ noItemMsg }}
22
- </div>
19
+ <!-- noItem slot for empty contents. Provide noItem, noItemMsg props -->
20
+ <slot :noItem="noItem" :noItemMsg="noItemMsg" name="noItem">
21
+ <div v-if="noItem"
22
+ class="text-center title-2"
23
+ >{{ noItemMsg }}
24
+ </div>
25
+ </slot>
23
26
  </r-container>
24
27
  </template>
25
28
  <script setup>
26
- import {
27
- ref,
28
- computed,
29
- onMounted,
30
- onUnmounted,
31
- onActivated,
32
- onDeactivated,
33
- watch,
34
- inject,nextTick
35
- } from 'vue'
29
+ import {computed, inject, nextTick, onActivated, onDeactivated, onMounted, onUnmounted, ref, watch} from 'vue'
36
30
 
37
31
  const props = defineProps({
38
32
  /**
@@ -2,14 +2,14 @@
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 class="menu-label" v-if="label" @click.prevent="open">{{ label }}</span>
5
+ <span v-if="label" class="menu-label" @click.prevent="open">{{ label }}</span>
6
6
  </slot>
7
7
  <transition name="fade" mode="out-in">
8
8
  <!-- Header Navigation Menu Icons -->
9
- <r-btn icon text v-if="show" key="on" size="sm" @click.prevent="close">
9
+ <r-btn v-if="show" key="on" icon size="sm" text @click.prevent="close">
10
10
  <r-icon v-html="$r.icons.chevron_up"></r-icon>
11
11
  </r-btn>
12
- <r-btn icon text v-else key="off" size="sm" @click.prevent="open">
12
+ <r-btn v-else key="off" icon size="sm" text @click.prevent="open">
13
13
  <r-icon v-html="icon||$r.icons.chevron_down"></r-icon>
14
14
  </r-btn>
15
15
 
@@ -48,7 +48,7 @@
48
48
  </template>
49
49
 
50
50
  <script setup>
51
- import {ref, computed, onMounted, onUnmounted,watch} from 'vue'
51
+ import {ref, computed, onMounted, onUnmounted, watch} from 'vue'
52
52
 
53
53
  /**
54
54
  * @example // Slider usage
@@ -338,7 +338,9 @@ const goToSlide = (i) => {
338
338
  emit('index', currentIndex.value)
339
339
  }
340
340
 
341
- watch(()=>props.slides,()=>{init()})
341
+ watch(() => props.slides, () => {
342
+ init()
343
+ })
342
344
  onMounted(() => {
343
345
  init()
344
346
  })
@@ -4,11 +4,11 @@
4
4
  >
5
5
  <!-- @slot Previous navigation slot
6
6
  @binding {Function} previous - Function to navigate previous -->
7
- <slot name="previous" :previous="previous"></slot>
7
+ <slot :previous="previous" name="previous"></slot>
8
8
 
9
9
  <!-- @slot Next navigation slot
10
10
  @binding {Function} next - Function to navigate next -->
11
- <slot name="next" :next="next"></slot>
11
+ <slot :next="next" name="next"></slot>
12
12
 
13
13
  <div class="swiper-container"
14
14
  ref="containerRef"
@@ -49,7 +49,7 @@
49
49
  </template>
50
50
 
51
51
  <script setup>
52
- import { ref, computed, onMounted, onUnmounted, inject, nextTick, watch } from 'vue'
52
+ import {ref, computed, onMounted, onUnmounted, inject, nextTick, watch} from 'vue'
53
53
 
54
54
  /**
55
55
  * @example // Swiper usage
@@ -114,7 +114,7 @@ const props = defineProps({
114
114
  numShow: [Number, Object]
115
115
  })
116
116
 
117
- const { $r } = inject('renusify')
117
+ const {$r} = inject('renusify')
118
118
 
119
119
  const timer = ref(null)
120
120
  const inMove = ref(false)
@@ -156,16 +156,16 @@ const goToSlide = (n) => {
156
156
  * Navigates to the next slide
157
157
  */
158
158
  const next = () => {
159
- if(currentSlide.value+1>slides.value)return
160
- goToSlide(currentSlide.value+1)
159
+ if (currentSlide.value + 1 > slides.value) return
160
+ goToSlide(currentSlide.value + 1)
161
161
  }
162
162
 
163
163
  /**
164
164
  * Navigates to the previous slide
165
165
  */
166
166
  const previous = () => {
167
- if(currentSlide.value===1)return
168
- goToSlide(currentSlide.value-1)
167
+ if (currentSlide.value === 1) return
168
+ goToSlide(currentSlide.value - 1)
169
169
  }
170
170
 
171
171
  /**
@@ -259,7 +259,7 @@ watch(() => props.items, () => {
259
259
  currentSlide.value = 1
260
260
 
261
261
  handleResize()
262
- }, { deep: true })
262
+ }, {deep: true})
263
263
 
264
264
  defineExpose({
265
265
  /**
@@ -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"
@@ -258,7 +259,7 @@
258
259
  </template>
259
260
 
260
261
  <script setup>
261
- import {ref, computed, watch, onMounted, inject} from 'vue'
262
+ import {computed, inject, onMounted, ref, watch} from 'vue'
262
263
  import ManageFooter from "./footer.vue";
263
264
  import ManageHeader from "./header.vue";
264
265
 
@@ -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}
@@ -537,8 +543,6 @@ const sortSetup = (item) => {
537
543
  const ok = () => {
538
544
  table.value.startTime = false
539
545
  page.value = 1
540
- sortBy.value = null
541
- sortType.value = 0
542
546
  autoSend.value = false
543
547
  showForm.value = false
544
548
  refresh()
@@ -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}" v-html="$r.icons.arrow_up"></r-icon>
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 list = cols.value.length > 0 ? cols.value : th_all.value
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
- res.push(item)
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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "renusify",
3
- "version": "3.0.1",
3
+ "version": "3.1.0",
4
4
  "description": "Vue3 Framework",
5
5
  "keywords": [
6
6
  "vuejs",
@@ -0,0 +1,281 @@
1
+ import SimpleRng from "./random";
2
+
3
+ export default class Cryptor {
4
+ constructor() {
5
+ this.matrix = 32;
6
+ }
7
+
8
+ packUint32BE(value) {
9
+ const bytes = new Uint8Array(4);
10
+ bytes[0] = (value >> 24) & 0xFF;
11
+ bytes[1] = (value >> 16) & 0xFF;
12
+ bytes[2] = (value >> 8) & 0xFF;
13
+ bytes[3] = value & 0xFF;
14
+ return bytes;
15
+ }
16
+
17
+ unpackUint32BE(bytes, offset = 0) {
18
+ return ((bytes[offset] << 24) |
19
+ (bytes[offset + 1] << 16) |
20
+ (bytes[offset + 2] << 8) |
21
+ bytes[offset + 3]) >>> 0;
22
+ }
23
+
24
+ encrypt(data, key) {
25
+ const matrixSize = this.matrix;
26
+ const pad = (matrixSize - ((10 + data.length) % matrixSize)) % matrixSize;
27
+ const keyBytes = this.generatePassword(matrixSize, this.stringToBytes(key));
28
+
29
+ const dataSize = this.packUint32BE(data.length);
30
+
31
+ const randomPrefix = this.getRandomBytes(6);
32
+ const seedRandom = randomPrefix.reduce((sum, b) => sum + b, 0);
33
+
34
+ const paddedText = new Uint8Array(10 + data.length + pad);
35
+ paddedText.set(dataSize, 0);
36
+ paddedText.set(randomPrefix, 4);
37
+ paddedText.set(data, 10);
38
+
39
+ if (pad > 0) {
40
+ paddedText.fill(1, 10 + data.length, 10 + data.length + pad);
41
+ }
42
+
43
+ const seedSum = keyBytes.reduce((sum, b) => sum + b, 0);
44
+ this.shuffle(paddedText, seedSum + seedRandom, 5);
45
+
46
+ for (let i = 0; i < paddedText.length; i += matrixSize) {
47
+ const end = Math.min(i + matrixSize, paddedText.length);
48
+ const seed = (i + matrixSize < paddedText.length) ? paddedText[i + matrixSize] : keyBytes[0];
49
+ const chunkCopy = new Uint8Array(paddedText.slice(i, end));
50
+ this.shuffle(chunkCopy, seed + seedRandom, 2);
51
+ paddedText.set(chunkCopy, i);
52
+ }
53
+
54
+ this.mix(matrixSize, paddedText, keyBytes);
55
+
56
+ const result = new Uint8Array(paddedText.length + 2);
57
+ result.set(paddedText, 0);
58
+ result[paddedText.length] = (seedRandom >> 8) & 0xFF;
59
+ result[paddedText.length + 1] = seedRandom & 0xFF;
60
+
61
+ return result;
62
+ }
63
+
64
+ encryptText(text, key) {
65
+ const data = this.stringToBytes(text);
66
+ const encrypted = this.encrypt(data, key);
67
+ return this.base64UrlEncode(encrypted);
68
+ }
69
+
70
+ decrypt(encoded, key) {
71
+ if (encoded.length < 8) {
72
+ throw new Error('Invalid Token Matrix Length.');
73
+ }
74
+
75
+ const seedRandom = (encoded[encoded.length - 2] << 8) | encoded[encoded.length - 1];
76
+ const decoded = new Uint8Array(encoded.slice(0, -2));
77
+ const matrixSize = this.matrix;
78
+
79
+ const keyBytes = this.generatePassword(matrixSize, this.stringToBytes(key));
80
+ this.unmix(matrixSize, decoded, keyBytes);
81
+
82
+ for (let i = Math.floor(decoded.length / matrixSize) * matrixSize; i >= 0; i -= matrixSize) {
83
+ const end = Math.min(i + matrixSize, decoded.length);
84
+ const seed = (i + matrixSize < decoded.length) ? decoded[i + matrixSize] : keyBytes[0];
85
+ const chunkCopy = new Uint8Array(decoded.slice(i, end));
86
+ this.unshuffle(chunkCopy, seed + seedRandom, 2);
87
+ decoded.set(chunkCopy, i);
88
+ }
89
+
90
+ const seedSum = keyBytes.reduce((sum, b) => sum + b, 0);
91
+ this.unshuffle(decoded, seedSum + seedRandom, 5);
92
+
93
+ const dataSize = this.unpackUint32BE(decoded, 0);
94
+
95
+ if (decoded.length < dataSize + 10) {
96
+ throw new Error('Invalid Token Matrix Length');
97
+ }
98
+
99
+ return decoded.slice(10, 10 + dataSize);
100
+ }
101
+
102
+ decryptText(encoded, key) {
103
+ const padding = encoded.length % 4;
104
+ const paddedInput = padding === 0 ? encoded : encoded + '='.repeat(4 - padding);
105
+
106
+ const data = this.base64UrlDecode(paddedInput);
107
+ const decrypted = this.decrypt(data, key);
108
+ return this.bytesToString(decrypted);
109
+ }
110
+
111
+ setMatrix(size) {
112
+ if (size > 0) {
113
+ this.matrix = size;
114
+ }
115
+ }
116
+
117
+ generatePassword(matrix, password) {
118
+ const result = new Uint8Array(matrix);
119
+ const passwordLen = password.length;
120
+
121
+ if (passwordLen === 0) {
122
+ return result;
123
+ }
124
+
125
+ const repeats = Math.floor(matrix / passwordLen);
126
+ const remainder = matrix % passwordLen;
127
+
128
+ for (let i = 0; i < repeats; i++) {
129
+ const start = i * passwordLen;
130
+ result.set(password, start);
131
+ }
132
+
133
+ if (remainder > 0) {
134
+ const start = repeats * passwordLen;
135
+ result.set(password.slice(0, remainder), start);
136
+ }
137
+
138
+ return result;
139
+ }
140
+
141
+ shuffle(data, seed, step) {
142
+ const rng = new SimpleRng(seed);
143
+ const length = data.length;
144
+
145
+ for (let i = length - 1; i > 0; i -= step) {
146
+ const j = Math.floor(rng.genRange(0, i));
147
+ [data[i], data[j]] = [data[j], data[i]];
148
+ }
149
+ }
150
+
151
+ unshuffle(data, seed, step) {
152
+ const rng = new SimpleRng(seed);
153
+ const length = data.length;
154
+ const swaps = [];
155
+
156
+ for (let i = length - 1; i > 0; i -= step) {
157
+ const j = Math.floor(rng.genRange(0, i));
158
+ swaps.push([i, j]);
159
+ }
160
+
161
+ for (let k = swaps.length - 1; k >= 0; k--) {
162
+ const [i, j] = swaps[k];
163
+ [data[i], data[j]] = [data[j], data[i]];
164
+ }
165
+ }
166
+
167
+ mix(blockSize, buf, key) {
168
+ let prevBlock = new Uint8Array(key);
169
+
170
+ for (let i = 0; i < buf.length; i += blockSize) {
171
+ const blockEnd = Math.min(i + blockSize, buf.length);
172
+ for (let j = 0; j < blockEnd - i && j < prevBlock.length; j++) {
173
+ buf[i + j] ^= prevBlock[j];
174
+ }
175
+ prevBlock = new Uint8Array(buf.slice(i, blockEnd));
176
+ }
177
+ }
178
+
179
+ unmix(blockSize, buf, key) {
180
+ const blocks = [];
181
+ for (let i = 0; i < buf.length; i += blockSize) {
182
+ const end = Math.min(i + blockSize, buf.length);
183
+ blocks.push(new Uint8Array(buf.slice(i, end)));
184
+ }
185
+
186
+ for (let i = blocks.length - 1; i >= 0; i--) {
187
+ if (i === 0) {
188
+ for (let j = 0; j < blocks[i].length && j < key.length; j++) {
189
+ blocks[i][j] ^= key[j];
190
+ }
191
+ } else {
192
+ for (let j = 0; j < blocks[i].length && j < blocks[i - 1].length; j++) {
193
+ blocks[i][j] ^= blocks[i - 1][j];
194
+ }
195
+ }
196
+ }
197
+
198
+ let offset = 0;
199
+ for (const block of blocks) {
200
+ buf.set(block, offset);
201
+ offset += block.length;
202
+ }
203
+ }
204
+
205
+ getRandomBytes(length) {
206
+ const rng = new SimpleRng(Date.now());
207
+ return rng.getRandomBytes(length);
208
+ }
209
+
210
+ base64UrlEncode(data) {
211
+ if (typeof Buffer !== 'undefined') {
212
+ // Node.js
213
+ return Buffer.from(data)
214
+ .toString('base64')
215
+ .replace(/\+/g, '-')
216
+ .replace(/\//g, '_')
217
+ .replace(/=+$/, '');
218
+ } else {
219
+ // Browser
220
+ let binary = '';
221
+ for (let i = 0; i < data.length; i++) {
222
+ binary += String.fromCharCode(data[i]);
223
+ }
224
+ return btoa(binary)
225
+ .replace(/\+/g, '-')
226
+ .replace(/\//g, '_')
227
+ .replace(/=+$/, '');
228
+ }
229
+ }
230
+
231
+ base64UrlDecode(encoded) {
232
+ let padded = encoded;
233
+ const padding = encoded.length % 4;
234
+ if (padding !== 0) {
235
+ padded += '='.repeat(4 - padding);
236
+ }
237
+ const base64 = padded.replace(/-/g, '+').replace(/_/g, '/');
238
+
239
+ if (typeof Buffer !== 'undefined') {
240
+ // Node.js
241
+ return new Uint8Array(Buffer.from(base64, 'base64'));
242
+ } else {
243
+ // Browser
244
+ const binary = atob(base64);
245
+ const bytes = new Uint8Array(binary.length);
246
+ for (let i = 0; i < binary.length; i++) {
247
+ bytes[i] = binary.charCodeAt(i);
248
+ }
249
+ return bytes;
250
+ }
251
+ }
252
+
253
+ stringToBytes(str) {
254
+ if (typeof TextEncoder !== 'undefined') {
255
+ return new TextEncoder().encode(str);
256
+ }
257
+ if (typeof Buffer !== 'undefined') {
258
+ return new Uint8Array(Buffer.from(str, 'utf-8'));
259
+ }
260
+ const bytes = new Uint8Array(str.length);
261
+ for (let i = 0; i < str.length; i++) {
262
+ bytes[i] = str.charCodeAt(i) & 0xFF;
263
+ }
264
+ return bytes;
265
+ }
266
+
267
+ bytesToString(bytes) {
268
+ if (typeof TextDecoder !== 'undefined') {
269
+ return new TextDecoder('utf-8').decode(bytes);
270
+ }
271
+ if (typeof Buffer !== 'undefined') {
272
+ return Buffer.from(bytes).toString('utf-8');
273
+ }
274
+
275
+ let str = '';
276
+ for (let i = 0; i < bytes.length; i++) {
277
+ str += String.fromCharCode(bytes[i]);
278
+ }
279
+ return str;
280
+ }
281
+ }
@@ -0,0 +1,52 @@
1
+ export default class SimpleRng {
2
+ constructor(seed) {
3
+ this.state = BigInt(seed) & 0xFFFFFFFFFFFFFFFFn;
4
+ }
5
+
6
+ static newWithTimeSeed() {
7
+ return new SimpleRng(Date.now());
8
+ }
9
+
10
+ nextU32() {
11
+ this.state = (this.state * 6364136223846793005n + 1442695040888963407n) & 0xFFFFFFFFFFFFFFFFn;
12
+ return Number((this.state >> 32n) & 0xFFFFFFFFn);
13
+ }
14
+
15
+ nextU64() {
16
+ const high = this.nextU32();
17
+ const low = this.nextU32();
18
+ return (high << 32) | low;
19
+ }
20
+
21
+ nextF64() {
22
+ const val = this.nextU32();
23
+ return val / 4294967295.0;
24
+ }
25
+
26
+ genRange(low, high) {
27
+ return low + (high - low) * this.nextF64();
28
+ }
29
+
30
+ getRandomBytes(length) {
31
+ const byteArray = new Uint8Array(length);
32
+ const chunks = Math.floor(length / 4);
33
+ const remainder = length % 4;
34
+
35
+ for (let i = 0; i < chunks; i++) {
36
+ const random = this.nextU32();
37
+ byteArray[i * 4] = random & 0xFF;
38
+ byteArray[i * 4 + 1] = (random >> 8) & 0xFF;
39
+ byteArray[i * 4 + 2] = (random >> 16) & 0xFF;
40
+ byteArray[i * 4 + 3] = (random >> 24) & 0xFF;
41
+ }
42
+
43
+ if (remainder > 0) {
44
+ const random = this.nextU32();
45
+ for (let i = 0; i < remainder; i++) {
46
+ byteArray[chunks * 4 + i] = (random >> (i * 8)) & 0xFF;
47
+ }
48
+ }
49
+
50
+ return byteArray;
51
+ }
52
+ }