@a-vision-software/vue-input-components 1.4.21 → 1.4.22

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@a-vision-software/vue-input-components",
3
- "version": "1.4.21",
3
+ "version": "1.4.22",
4
4
  "description": "A collection of reusable Vue 3 input components with TypeScript support",
5
5
  "author": "A-Vision Software",
6
6
  "license": "MIT",
@@ -104,6 +104,9 @@
104
104
  :disabled="disabled"
105
105
  class="text-input__input"
106
106
  @input="handleInput"
107
+ @focus="handleFocus"
108
+ @blur="handleBlur"
109
+ @keydown="handleKeydown"
107
110
  ref="inputRef"
108
111
  :readonly="readonly"
109
112
  ></textarea>
@@ -156,6 +159,7 @@ const props = withDefaults(defineProps<TextInputProps>(), {
156
159
  maxHeight: '14rem',
157
160
  bgColor: 'var(--input-color, #ffffffee)',
158
161
  width: '100%',
162
+ autosaveOnBlur: true,
159
163
  })
160
164
 
161
165
  const emit = defineEmits<{
@@ -171,11 +175,12 @@ const id = ref<string>('')
171
175
  const showSaved = ref(false)
172
176
  const showChanged = ref(false)
173
177
  const isChanged = ref(false)
174
- const debounceTimer = ref<number | null>(null)
175
178
  const changedTimer = ref<number | null>(null)
176
179
  const inputRef = ref<HTMLInputElement | null>(null)
177
180
  const dateValue = ref<Date | null>(null)
178
181
  const isFocused = ref(false)
182
+ const originalValue = ref<string | number>('')
183
+ const originalDateValue = ref<Date | null>(null)
179
184
 
180
185
  const defaultCurrencyFormatter = new Intl.NumberFormat('en-NZ', {
181
186
  style: 'currency',
@@ -246,10 +251,7 @@ const handleAutosave = async (value: string) => {
246
251
  }
247
252
  }
248
253
 
249
- const debounceAutosave = (value: string) => {
250
- if (debounceTimer.value) {
251
- clearTimeout(debounceTimer.value)
252
- }
254
+ const showChangedIndicator = () => {
253
255
  if (changedTimer.value) {
254
256
  clearTimeout(changedTimer.value)
255
257
  }
@@ -262,10 +264,6 @@ const debounceAutosave = (value: string) => {
262
264
  emit('changed')
263
265
  isChanged.value = true
264
266
  }, 500)
265
-
266
- debounceTimer.value = window.setTimeout(() => {
267
- handleAutosave(value)
268
- }, 1500)
269
267
  }
270
268
 
271
269
  const focusInput = () => {
@@ -300,11 +298,11 @@ const handleInput = (event: Event) => {
300
298
  const parsed = parseFloat(value)
301
299
  if (!Number.isNaN(parsed)) {
302
300
  emit('update:modelValue', parsed)
303
- debounceAutosave(String(parsed))
301
+ showChangedIndicator()
304
302
  }
305
303
  } else {
306
304
  emit('update:modelValue', value)
307
- debounceAutosave(value)
305
+ showChangedIndicator()
308
306
  if (props.type === 'textarea' && (event.target as HTMLTextAreaElement).tagName === 'TEXTAREA') {
309
307
  adjustHeight(event.target as HTMLTextAreaElement)
310
308
  }
@@ -313,6 +311,10 @@ const handleInput = (event: Event) => {
313
311
 
314
312
  const handleFocus = () => {
315
313
  isFocused.value = true
314
+ originalValue.value = props.modelValue
315
+ if (props.type === 'date') {
316
+ originalDateValue.value = dateValue.value
317
+ }
316
318
  emit('focus')
317
319
  }
318
320
 
@@ -328,9 +330,41 @@ const handleBlur = (event?: Event) => {
328
330
  }
329
331
  isFocused.value = false
330
332
  emit('blur')
333
+
334
+ if (props.autosaveOnBlur && props.autosave) {
335
+ const value = String(props.modelValue)
336
+ handleAutosave(value)
337
+ }
331
338
  }
332
339
 
333
340
  const handleKeydown = (event: KeyboardEvent) => {
341
+ if (event.key === 'Escape') {
342
+ event.preventDefault()
343
+ emit('update:modelValue', originalValue.value)
344
+ if (props.type === 'date') {
345
+ dateValue.value = originalDateValue.value
346
+ }
347
+ if (changedTimer.value) {
348
+ clearTimeout(changedTimer.value)
349
+ changedTimer.value = null
350
+ }
351
+ showSaved.value = false
352
+ showChanged.value = false
353
+ inputRef.value?.blur()
354
+ }
355
+
356
+ if (event.key === 'Enter') {
357
+ if (props.type === 'textarea') {
358
+ if (event.ctrlKey || event.shiftKey) {
359
+ event.preventDefault()
360
+ inputRef.value?.blur()
361
+ }
362
+ } else {
363
+ event.preventDefault()
364
+ inputRef.value?.blur()
365
+ }
366
+ }
367
+
334
368
  emit('keydown', event)
335
369
  }
336
370
 
@@ -349,13 +383,10 @@ const handlePaste = (event: ClipboardEvent) => {
349
383
  const handleDateChange = (date: Date | null) => {
350
384
  const formattedDate = formatDateForModel(date)
351
385
  emit('update:modelValue', formattedDate)
352
- debounceAutosave(formattedDate)
386
+ showChangedIndicator()
353
387
  }
354
388
 
355
389
  onUnmounted(() => {
356
- if (debounceTimer.value) {
357
- clearTimeout(debounceTimer.value)
358
- }
359
390
  if (changedTimer.value) {
360
391
  clearTimeout(changedTimer.value)
361
392
  }
@@ -18,6 +18,7 @@ export type TextInputProps =
18
18
  bgColor?: string
19
19
  currencyFormatter?: Intl.NumberFormat
20
20
  autosave?: (value: string) => Promise<void>
21
+ autosaveOnBlur?: boolean
21
22
  error?: string
22
23
  } & (
23
24
  | {