@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.
Files changed (34) hide show
  1. package/dist/src/App.vue.d.ts +2 -0
  2. package/dist/src/components/Action.vue.d.ts +9 -49
  3. package/dist/src/components/Checkbox.vue.d.ts +19 -81
  4. package/dist/src/components/Dropdown.vue.d.ts +22 -83
  5. package/dist/src/components/FileUpload.vue.d.ts +12 -20
  6. package/dist/src/components/List.vue.d.ts +18 -36
  7. package/dist/src/components/Modal.vue.d.ts +22 -58
  8. package/dist/src/components/Navigation.vue.d.ts +5 -15
  9. package/dist/src/components/TextInput.vue.d.ts +0 -1
  10. package/dist/src/global.d.ts +0 -1
  11. package/dist/src/index.d.ts +0 -1
  12. package/dist/src/main.d.ts +0 -1
  13. package/dist/src/types/list.d.ts +1 -1
  14. package/dist/src/types/textinput.d.ts +2 -0
  15. package/dist/src/views/ActionTestView.vue.d.ts +2 -0
  16. package/dist/src/views/CheckboxTestView.vue.d.ts +2 -0
  17. package/dist/src/views/DashboardView.vue.d.ts +2 -0
  18. package/dist/src/views/DropdownTestView.vue.d.ts +2 -0
  19. package/dist/src/views/FileUploadTestView.vue.d.ts +2 -0
  20. package/dist/src/views/ListTestView.vue.d.ts +2 -0
  21. package/dist/src/views/ModalTestView.vue.d.ts +2 -0
  22. package/dist/src/views/NavigationTestView.vue.d.ts +2 -0
  23. package/dist/src/views/TextInputTestView.vue.d.ts +2 -0
  24. package/dist/vue-input-components.cjs.js +38 -2
  25. package/dist/vue-input-components.css +2 -1
  26. package/dist/vue-input-components.es.js +15325 -9896
  27. package/dist/vue-input-components.umd.js +38 -2
  28. package/package.json +27 -26
  29. package/src/components/Dropdown.vue +9 -4
  30. package/src/components/List.vue +60 -2
  31. package/src/components/TextInput.vue +15 -4
  32. package/src/types/list.ts +1 -0
  33. package/src/types/textinput.ts +3 -0
  34. 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": "1.4.31",
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": "^3.5.0",
58
- "floating-vue": "^5.2.2"
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": "^6.7.0",
67
- "@fortawesome/free-regular-svg-icons": "^6.7.0",
68
- "@fortawesome/free-solid-svg-icons": "^6.7.0",
69
- "@fortawesome/vue-fontawesome": "^3.0.0",
70
- "@vuepic/vue-datepicker": "^11.0.2",
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.2",
75
- "@types/node": "^20.11.0",
76
- "@vitejs/plugin-vue": "^5.0.0",
77
- "@vue/eslint-config-prettier": "^9.0.0",
78
- "@vue/eslint-config-typescript": "^12.0.0",
79
- "@vue/test-utils": "^2.4.0",
80
- "@vue/tsconfig": "^0.5.1",
81
- "eslint": "^8.56.0",
82
- "eslint-plugin-vue": "^9.21.0",
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.2.0",
85
- "typescript": "~5.3.0",
86
- "vite": "^5.0.0",
87
- "vite-plugin-dts": "^3.7.0",
88
- "vitest": "^1.2.0",
89
- "vue-router": "^4.2.0",
90
- "vue-tsc": "^1.8.0"
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": ">=18.0.0"
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">saved</span>
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
- const target = event.target as HTMLElement
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
 
@@ -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
- const dataType = typeof props.data[0][column.key]
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
- <Datepicker
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
- :format="dateFormat"
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 Datepicker from '@vuepic/vue-datepicker'
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.type === 'datetime' ? 'dd/MM/yyyy HH:mm' : 'dd/MM/yyyy'
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
@@ -52,6 +52,7 @@ interface ListProps {
52
52
  data: ListRowData[]
53
53
  actions?: ListActionProps[]
54
54
  CSVDownload?: string
55
+ XLSXDownload?: string
55
56
  filter?: {
56
57
  placeholder?: string
57
58
  }
@@ -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