@a-vision-software/vue-input-components 1.4.31 → 2.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/dist/src/App.vue.d.ts +2 -0
- package/dist/src/components/Action.vue.d.ts +9 -49
- package/dist/src/components/Checkbox.vue.d.ts +19 -81
- package/dist/src/components/Dropdown.vue.d.ts +22 -83
- package/dist/src/components/FileUpload.vue.d.ts +12 -20
- package/dist/src/components/List.vue.d.ts +18 -36
- package/dist/src/components/Modal.vue.d.ts +22 -58
- package/dist/src/components/Navigation.vue.d.ts +5 -15
- package/dist/src/components/TextInput.vue.d.ts +0 -1
- package/dist/src/global.d.ts +0 -1
- package/dist/src/index.d.ts +0 -1
- package/dist/src/main.d.ts +0 -1
- package/dist/src/types/list.d.ts +1 -1
- package/dist/src/types/textinput.d.ts +2 -0
- package/dist/src/views/ActionTestView.vue.d.ts +2 -0
- package/dist/src/views/CheckboxTestView.vue.d.ts +2 -0
- package/dist/src/views/DashboardView.vue.d.ts +2 -0
- package/dist/src/views/DropdownTestView.vue.d.ts +2 -0
- package/dist/src/views/FileUploadTestView.vue.d.ts +2 -0
- package/dist/src/views/ListTestView.vue.d.ts +2 -0
- package/dist/src/views/ModalTestView.vue.d.ts +2 -0
- package/dist/src/views/NavigationTestView.vue.d.ts +2 -0
- package/dist/src/views/TextInputTestView.vue.d.ts +2 -0
- package/dist/vue-input-components.cjs.js +38 -2
- package/dist/vue-input-components.css +2 -1
- package/dist/vue-input-components.es.js +15325 -9896
- package/dist/vue-input-components.umd.js +38 -2
- package/package.json +27 -26
- package/src/components/Dropdown.vue +9 -4
- package/src/components/List.vue +60 -2
- package/src/components/TextInput.vue +15 -4
- package/src/types/list.ts +1 -0
- package/src/types/textinput.ts +3 -0
- package/src/views/ListTestView.vue +2 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@a-vision-software/vue-input-components",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.2",
|
|
4
4
|
"description": "A collection of reusable Vue 3 input components with TypeScript support",
|
|
5
5
|
"author": "A-Vision Software",
|
|
6
6
|
"license": "MIT",
|
|
@@ -54,8 +54,8 @@
|
|
|
54
54
|
"test": "vitest"
|
|
55
55
|
},
|
|
56
56
|
"peerDependencies": {
|
|
57
|
-
"vue": "^
|
|
58
|
-
"
|
|
57
|
+
"floating-vue": "^5.2.2",
|
|
58
|
+
"vue": "^3.5.0"
|
|
59
59
|
},
|
|
60
60
|
"peerDependenciesMeta": {
|
|
61
61
|
"floating-vue": {
|
|
@@ -63,34 +63,35 @@
|
|
|
63
63
|
}
|
|
64
64
|
},
|
|
65
65
|
"dependencies": {
|
|
66
|
-
"@fortawesome/fontawesome-svg-core": "^
|
|
67
|
-
"@fortawesome/free-regular-svg-icons": "^
|
|
68
|
-
"@fortawesome/free-solid-svg-icons": "^
|
|
69
|
-
"@fortawesome/vue-fontawesome": "^3.
|
|
70
|
-
"@vuepic/vue-datepicker": "^
|
|
71
|
-
"floating-vue": "^5.2.2"
|
|
66
|
+
"@fortawesome/fontawesome-svg-core": "^7.2.0",
|
|
67
|
+
"@fortawesome/free-regular-svg-icons": "^7.2.0",
|
|
68
|
+
"@fortawesome/free-solid-svg-icons": "^7.2.0",
|
|
69
|
+
"@fortawesome/vue-fontawesome": "^3.1.3",
|
|
70
|
+
"@vuepic/vue-datepicker": "^12.1.0",
|
|
71
|
+
"floating-vue": "^5.2.2",
|
|
72
|
+
"xlsx": "https://cdn.sheetjs.com/xlsx-0.20.3/xlsx-0.20.3.tgz"
|
|
72
73
|
},
|
|
73
74
|
"devDependencies": {
|
|
74
|
-
"@tsconfig/node20": "^20.1.
|
|
75
|
-
"@types/node": "^
|
|
76
|
-
"@vitejs/plugin-vue": "^
|
|
77
|
-
"@vue/eslint-config-prettier": "^
|
|
78
|
-
"@vue/eslint-config-typescript": "^
|
|
79
|
-
"@vue/test-utils": "^2.4.
|
|
80
|
-
"@vue/tsconfig": "^0.
|
|
81
|
-
"eslint": "^
|
|
82
|
-
"eslint-plugin-vue": "^
|
|
75
|
+
"@tsconfig/node20": "^20.1.9",
|
|
76
|
+
"@types/node": "^25.5.0",
|
|
77
|
+
"@vitejs/plugin-vue": "^6.0.5",
|
|
78
|
+
"@vue/eslint-config-prettier": "^10.2.0",
|
|
79
|
+
"@vue/eslint-config-typescript": "^14.7.0",
|
|
80
|
+
"@vue/test-utils": "^2.4.6",
|
|
81
|
+
"@vue/tsconfig": "^0.9.0",
|
|
82
|
+
"eslint": "^10.0.3",
|
|
83
|
+
"eslint-plugin-vue": "^10.8.0",
|
|
83
84
|
"npm-run-all": "^4.1.5",
|
|
84
|
-
"prettier": "^3.
|
|
85
|
-
"typescript": "~5.3
|
|
86
|
-
"vite": "^
|
|
87
|
-
"vite-plugin-dts": "^
|
|
88
|
-
"vitest": "^1.
|
|
89
|
-
"vue-router": "^
|
|
90
|
-
"vue-tsc": "^
|
|
85
|
+
"prettier": "^3.8.1",
|
|
86
|
+
"typescript": "~5.9.3",
|
|
87
|
+
"vite": "^8.0.0",
|
|
88
|
+
"vite-plugin-dts": "^4.5.4",
|
|
89
|
+
"vitest": "^4.1.0",
|
|
90
|
+
"vue-router": "^5.0.3",
|
|
91
|
+
"vue-tsc": "^3.2.6"
|
|
91
92
|
},
|
|
92
93
|
"engines": {
|
|
93
|
-
"node": "
|
|
94
|
+
"node": "^20.19.0 || >=22.12.0"
|
|
94
95
|
},
|
|
95
96
|
"publishConfig": {
|
|
96
97
|
"access": "public"
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div
|
|
3
|
+
ref="dropdownRef"
|
|
3
4
|
class="dropdown"
|
|
4
5
|
:class="{
|
|
5
6
|
'dropdown--open': isOpen,
|
|
@@ -81,7 +82,9 @@
|
|
|
81
82
|
>required</span
|
|
82
83
|
>
|
|
83
84
|
<transition name="fade">
|
|
84
|
-
<span v-if="showSaved && !error" class="status-indicator saved-indicator"
|
|
85
|
+
<span v-if="showSaved && !showChanged && !error" class="status-indicator saved-indicator"
|
|
86
|
+
>saved</span
|
|
87
|
+
>
|
|
85
88
|
</transition>
|
|
86
89
|
<transition name="fade">
|
|
87
90
|
<span v-if="showChanged && !error" class="status-indicator changed-indicator">changed</span>
|
|
@@ -161,6 +164,7 @@ const emit = defineEmits<{
|
|
|
161
164
|
(e: 'saved'): void
|
|
162
165
|
}>()
|
|
163
166
|
|
|
167
|
+
const dropdownRef = ref<HTMLElement | null>(null)
|
|
164
168
|
const isOpen = ref(false)
|
|
165
169
|
const filterText = ref('')
|
|
166
170
|
const filterInput = ref<HTMLInputElement | null>(null)
|
|
@@ -230,18 +234,19 @@ const deselectOption = (option: DropdownOption) => {
|
|
|
230
234
|
if (props.multiple && Array.isArray(props.modelValue)) {
|
|
231
235
|
const newValue = props.modelValue.filter((id) => id !== option.id)
|
|
232
236
|
emit('update:modelValue', newValue)
|
|
237
|
+
debounceAutosave(newValue)
|
|
233
238
|
}
|
|
234
239
|
}
|
|
235
240
|
|
|
236
241
|
const clearSelection = () => {
|
|
237
242
|
if (props.disabled) return
|
|
238
243
|
emit('update:modelValue', props.multiple ? [] : '')
|
|
244
|
+
debounceAutosave(props.multiple ? [] : '')
|
|
239
245
|
}
|
|
240
246
|
|
|
241
247
|
// Close dropdown when clicking outside
|
|
242
248
|
const handleClickOutside = (event: MouseEvent) => {
|
|
243
|
-
|
|
244
|
-
if (!target.closest('.dropdown')) {
|
|
249
|
+
if (dropdownRef.value && !dropdownRef.value.contains(event.target as Node)) {
|
|
245
250
|
closeDropdown()
|
|
246
251
|
}
|
|
247
252
|
}
|
|
@@ -288,7 +293,7 @@ const debounceAutosave = (value: string | string[]) => {
|
|
|
288
293
|
}
|
|
289
294
|
|
|
290
295
|
// Show changed indicator immediately
|
|
291
|
-
if (!props.error) {
|
|
296
|
+
if (!props.error && props.autosave) {
|
|
292
297
|
showChanged.value = true
|
|
293
298
|
}
|
|
294
299
|
|
package/src/components/List.vue
CHANGED
|
@@ -47,6 +47,17 @@
|
|
|
47
47
|
},
|
|
48
48
|
]
|
|
49
49
|
: []),
|
|
50
|
+
...(props.XLSXDownload !== undefined
|
|
51
|
+
? [
|
|
52
|
+
{
|
|
53
|
+
id: 'xlsx-download',
|
|
54
|
+
label: 'Download',
|
|
55
|
+
icon: 'file-excel',
|
|
56
|
+
color: 'var(--primary-color)',
|
|
57
|
+
onActionClick: handleXLSXDownload,
|
|
58
|
+
},
|
|
59
|
+
]
|
|
60
|
+
: []),
|
|
50
61
|
...(actions || []),
|
|
51
62
|
]"
|
|
52
63
|
:key="actionIndex"
|
|
@@ -224,6 +235,7 @@ import Checkbox from './Checkbox.vue'
|
|
|
224
235
|
import type { ListProps, ListEmits, ListColumn, ListRowData } from '../types/list'
|
|
225
236
|
import type { ListActionProps } from '../types/action'
|
|
226
237
|
import { config } from '../config'
|
|
238
|
+
import { utils, writeFileXLSX } from 'xlsx'
|
|
227
239
|
|
|
228
240
|
const props = withDefaults(defineProps<ListProps>(), {
|
|
229
241
|
presentation: 'default',
|
|
@@ -258,8 +270,7 @@ const handleCSVDownload = () => {
|
|
|
258
270
|
const headerRow = []
|
|
259
271
|
const headerKeys = []
|
|
260
272
|
for (const column of props.columns) {
|
|
261
|
-
|
|
262
|
-
if (dataType !== 'object') {
|
|
273
|
+
if (['checkbox', 'icon', 'action'].indexOf(column.type as string) === -1) {
|
|
263
274
|
const columnName = column.label || column.key
|
|
264
275
|
headerRow.push(columnName)
|
|
265
276
|
headerKeys.push(column.key)
|
|
@@ -290,6 +301,53 @@ const handleCSVDownload = () => {
|
|
|
290
301
|
URL.revokeObjectURL(url)
|
|
291
302
|
}
|
|
292
303
|
|
|
304
|
+
const handleXLSXDownload = () => {
|
|
305
|
+
if (!props.XLSXDownload) return
|
|
306
|
+
|
|
307
|
+
const downloadName = props.XLSXDownload || 'data'
|
|
308
|
+
const fileName = downloadName.toLowerCase().endsWith('.xlsx')
|
|
309
|
+
? downloadName
|
|
310
|
+
: downloadName + '.xlsx'
|
|
311
|
+
|
|
312
|
+
const workbook = utils.book_new()
|
|
313
|
+
|
|
314
|
+
const columns = []
|
|
315
|
+
for (const column of props.columns) {
|
|
316
|
+
if (['checkbox', 'icon', 'action'].indexOf(column.type as string) === -1) {
|
|
317
|
+
columns.push({
|
|
318
|
+
field: column.key,
|
|
319
|
+
label: column.label || column.key,
|
|
320
|
+
})
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
const rows = []
|
|
325
|
+
for (const row of props.data) {
|
|
326
|
+
const rowData: any = {}
|
|
327
|
+
columns.forEach((column) => {
|
|
328
|
+
const value = row[column.field]
|
|
329
|
+
if (value == null) {
|
|
330
|
+
rowData[column.field] = ''
|
|
331
|
+
} else {
|
|
332
|
+
rowData[column.field] = value
|
|
333
|
+
}
|
|
334
|
+
})
|
|
335
|
+
rows.push(rowData)
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
const sheetName =
|
|
339
|
+
downloadName.lastIndexOf('.') !== -1
|
|
340
|
+
? downloadName.substring(0, downloadName.lastIndexOf('.')) || 'Sheet1'
|
|
341
|
+
: downloadName
|
|
342
|
+
const worksheet = utils.json_to_sheet(rows)
|
|
343
|
+
utils.book_append_sheet(
|
|
344
|
+
workbook,
|
|
345
|
+
worksheet,
|
|
346
|
+
sheetName.length > 31 ? sheetName.substring(0, 31) : sheetName,
|
|
347
|
+
)
|
|
348
|
+
writeFileXLSX(workbook, fileName)
|
|
349
|
+
}
|
|
350
|
+
|
|
293
351
|
const handleFilter = () => {
|
|
294
352
|
// No need to do anything here as the watch handles the filtering
|
|
295
353
|
}
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
<div v-if="icon" class="text-input__icon" @click="focusInput">
|
|
34
34
|
<font-awesome-icon :icon="icon" />
|
|
35
35
|
</div>
|
|
36
|
-
<
|
|
36
|
+
<VueDatePicker
|
|
37
37
|
v-if="type === 'date' || type === 'datetime'"
|
|
38
38
|
:id="id"
|
|
39
39
|
v-model="dateValue"
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
:readonly="readonly"
|
|
43
43
|
:min-date="min"
|
|
44
44
|
:max-date="max"
|
|
45
|
-
:
|
|
45
|
+
:formats="dateFormat"
|
|
46
46
|
:enable-time-picker="type === 'datetime'"
|
|
47
47
|
:clearable="true"
|
|
48
48
|
:input-class-name="['text-input__input', { 'text-input__input--has-icon': icon }]"
|
|
@@ -137,7 +137,7 @@
|
|
|
137
137
|
<script setup lang="ts">
|
|
138
138
|
import { computed, ref, onUnmounted, onMounted, watch, nextTick } from 'vue'
|
|
139
139
|
import { TextInputProps } from '../types/textinput'
|
|
140
|
-
import
|
|
140
|
+
import { VueDatePicker } from '@vuepic/vue-datepicker'
|
|
141
141
|
import '@vuepic/vue-datepicker/dist/main.css'
|
|
142
142
|
|
|
143
143
|
const props = withDefaults(defineProps<TextInputProps>(), {
|
|
@@ -160,6 +160,7 @@ const props = withDefaults(defineProps<TextInputProps>(), {
|
|
|
160
160
|
bgColor: 'var(--input-color, #ffffffee)',
|
|
161
161
|
width: '100%',
|
|
162
162
|
autosaveOnBlur: true,
|
|
163
|
+
dateformat: null,
|
|
163
164
|
})
|
|
164
165
|
|
|
165
166
|
const emit = defineEmits<{
|
|
@@ -211,7 +212,17 @@ const formattedMoney = computed(() => {
|
|
|
211
212
|
})
|
|
212
213
|
|
|
213
214
|
const dateFormat = computed(() => {
|
|
214
|
-
return props.
|
|
215
|
+
return props.dateformat
|
|
216
|
+
? props.dateformat
|
|
217
|
+
: props.type === 'datetime'
|
|
218
|
+
? {
|
|
219
|
+
input: 'dd/MM/yyyy HH:mm',
|
|
220
|
+
display: 'dd/MM/yyyy HH:mm',
|
|
221
|
+
}
|
|
222
|
+
: {
|
|
223
|
+
input: 'dd/MM/yyyy',
|
|
224
|
+
display: 'dd/MM/yyyy',
|
|
225
|
+
}
|
|
215
226
|
})
|
|
216
227
|
|
|
217
228
|
const labelStyle = computed(() => {
|
package/src/types/list.ts
CHANGED
package/src/types/textinput.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { FormatsConfig } from '@vuepic/vue-datepicker'
|
|
2
|
+
|
|
1
3
|
export type TextInputProps = {
|
|
2
4
|
required?: boolean
|
|
3
5
|
placeholder?: string
|
|
@@ -16,6 +18,7 @@ export type TextInputProps = {
|
|
|
16
18
|
maxHeight?: string
|
|
17
19
|
bgColor?: string
|
|
18
20
|
currencyFormatter?: Intl.NumberFormat
|
|
21
|
+
dateformat?: FormatsConfig | null
|
|
19
22
|
autosave?: (value: string) => Promise<void>
|
|
20
23
|
autosaveOnBlur?: boolean
|
|
21
24
|
error?: string
|
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
@row-click="handleRowClick"
|
|
20
20
|
@row-dblclick="handleRowDblClick"
|
|
21
21
|
:CSVDownload="'users'"
|
|
22
|
+
:XLSXDownload="'users'"
|
|
22
23
|
/>
|
|
23
24
|
</section>
|
|
24
25
|
|
|
@@ -35,6 +36,7 @@
|
|
|
35
36
|
@row-click="handleRowClick"
|
|
36
37
|
@row-dblclick="handleRowDblClick"
|
|
37
38
|
:CSVDownload="'user-list'"
|
|
39
|
+
:XLSXDownload="'user-list.xlsx'"
|
|
38
40
|
/>
|
|
39
41
|
</section>
|
|
40
42
|
|