nexa-ui-kit 0.7.4 → 0.7.6

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 (35) hide show
  1. package/dist/components/NAlert.js +1 -1
  2. package/dist/components/NAutocomplete.js +1 -1
  3. package/dist/components/NAvatar.js +1 -1
  4. package/dist/components/NBadge.js +1 -1
  5. package/dist/components/NBottomSheet.js +1 -1
  6. package/dist/components/NButton.js +1 -1
  7. package/dist/components/NCard.js +1 -1
  8. package/dist/components/NCheckbox.js +1 -1
  9. package/dist/components/NChips.js +1 -1
  10. package/dist/components/NDataTable.js +1 -1
  11. package/dist/components/NDatepicker.js +1 -1
  12. package/dist/components/NForm.js +1 -1
  13. package/dist/components/NFormField.js +1 -1
  14. package/dist/components/NImage.js +1 -1
  15. package/dist/components/NInput.js +1 -1
  16. package/dist/components/NInputNumber.js +43 -14
  17. package/dist/components/NInputNumber.nexa +36 -3
  18. package/dist/components/NModal.js +1 -1
  19. package/dist/components/NMultiSelect.js +1 -1
  20. package/dist/components/NPaginator.js +1 -1
  21. package/dist/components/NPassword.js +1 -1
  22. package/dist/components/NProgressBar.js +1 -1
  23. package/dist/components/NRadio.js +1 -1
  24. package/dist/components/NScrollView.js +1 -1
  25. package/dist/components/NSelect.js +1 -1
  26. package/dist/components/NSkeleton.js +1 -1
  27. package/dist/components/NSwitch.js +1 -1
  28. package/dist/components/NTabs.js +1 -1
  29. package/dist/components/NTag.js +1 -1
  30. package/dist/components/NToastContainer.js +1 -1
  31. package/dist/components/NTooltip.js +1 -1
  32. package/dist/components/NTreeMenu.js +1 -1
  33. package/dist/components/NVirtualList.js +1 -1
  34. package/package.json +4 -4
  35. package/src/components/NInputNumber.nexa +36 -3
@@ -23,7 +23,7 @@ const _sfc_main = defineComponent({
23
23
  })
24
24
  // Injected render function
25
25
  _sfc_main.render = function(ctx) {
26
- const { visible, dismiss, icons, $slots, emit, variant, title, closable, icon, Fragment: _ntc_Fragment } = ctx
26
+ let { visible, dismiss, icons, $slots, emit, variant, title, closable, icon, Fragment: _ntc_Fragment } = ctx
27
27
  return (visible.value) ? h('div', { class: ["n-alert", `is-${variant}`], "data-v-22a3a541": "" }, [
28
28
  "\n ",
29
29
  h('span', { class: "n-alert-icon", "data-v-22a3a541": "" }, [
@@ -39,7 +39,7 @@ const _sfc_main = defineComponent({
39
39
  })
40
40
  // Injected render function
41
41
  _sfc_main.render = function(ctx) {
42
- const { instanceId, listboxId, inputId, isOpen, query, focusedIndex, rootEl, popupStyle, resolvedPlacement, stopTracking, completeTimer, normalizeOption, normalizedOptions, filteredOptions, activeId, close, open, requestComplete, onInput, onFocus, onKeydown, selectOption, clearValue, openAll, onBeforeUnmount, trackFloatingOverlay, $slots, emit, modelValue, options, placeholder, label, disabled, readonly, clearable, minLength, delay, loading, dropdown, emptyMessage, placement, Fragment: _ntc_Fragment, Teleport: _ntc_Teleport } = ctx
42
+ let { instanceId, listboxId, inputId, isOpen, query, focusedIndex, rootEl, popupStyle, resolvedPlacement, stopTracking, completeTimer, normalizeOption, normalizedOptions, filteredOptions, activeId, close, open, requestComplete, onInput, onFocus, onKeydown, selectOption, clearValue, openAll, onBeforeUnmount, trackFloatingOverlay, $slots, emit, modelValue, options, placeholder, label, disabled, readonly, clearable, minLength, delay, loading, dropdown, emptyMessage, placement, Fragment: _ntc_Fragment, Teleport: _ntc_Teleport } = ctx
43
43
  return h('div', { class: "n-ac", "data-autocomplete-root": instanceId, "data-v-741257a1": "" }, [
44
44
  "\n ",
45
45
  (label) ? h('label', { class: "n-ac-label", for: inputId, "data-v-741257a1": "" }, [
@@ -26,7 +26,7 @@ const _sfc_main = defineComponent({
26
26
  })
27
27
  // Injected render function
28
28
  _sfc_main.render = function(ctx) {
29
- const { initials, $slots, label, size, variant, image, shape, Fragment: _ntc_Fragment } = ctx
29
+ let { initials, $slots, label, size, variant, image, shape, Fragment: _ntc_Fragment } = ctx
30
30
  return h('div', { class: ['n-avatar', `is-${size}`, `is-${variant}`, `is-${shape}`], "vBind:style": "image ? { backgroundImage: `url(${image})` } : {}", "aria-label": label, "data-v-147134": "" }, [
31
31
  "\n ",
32
32
  (!image) ? h('span', { class: "n-avatar-initials", "data-v-147134": "" }, [
@@ -17,7 +17,7 @@ const _sfc_main = defineComponent({
17
17
  })
18
18
  // Injected render function
19
19
  _sfc_main.render = function(ctx) {
20
- const { $slots, variant, size, rounded, dot, position, Fragment: _ntc_Fragment } = ctx
20
+ let { $slots, variant, size, rounded, dot, position, Fragment: _ntc_Fragment } = ctx
21
21
  return (dot) ? h('span', { class: ["n-badge-dot", [`is-${variant}`, position ? `is-${position}` : '']], "data-v-ff3cf3e": "" }) : (true) ? h('span', { class: ['n-badge', `n-badge-${variant}`, `n-badge-${size}`, rounded ? 'is-rounded' : ''], "data-v-ff3cf3e": "" }, [
22
22
  "\n ",
23
23
  ctx.$slots.default ? ctx.$slots.default() : null,
@@ -60,7 +60,7 @@ const _sfc_main = defineComponent({
60
60
  })
61
61
  // Injected render function
62
62
  _sfc_main.render = function(ctx) {
63
- const { yOffset, isDragging, currentSnap, gestures, sortedPoints, translateY, overlayOpacity, useGestures, $slots, emit, show, snapPoints, Fragment: _ntc_Fragment, Teleport: _ntc_Teleport } = ctx
63
+ let { yOffset, isDragging, currentSnap, gestures, sortedPoints, translateY, overlayOpacity, useGestures, $slots, emit, show, snapPoints, Fragment: _ntc_Fragment, Teleport: _ntc_Teleport } = ctx
64
64
  return h(_ntc_Teleport, { to: "body", "data-v-55f61938": "" }, [
65
65
  "\n ",
66
66
  h('div', { class: ["n-bottom-sheet-root", { 'is-active': show || isDragging.value }], "data-v-55f61938": "" }, [
@@ -45,7 +45,7 @@ const _sfc_main = defineComponent({
45
45
  })
46
46
  // Injected render function
47
47
  _sfc_main.render = function(ctx) {
48
- const { ripple, handleClick, btnClass, $slots, emit, variant, size, type, disabled, loading, block, rounded, loadingText, Fragment: _ntc_Fragment } = ctx
48
+ let { ripple, handleClick, btnClass, $slots, emit, variant, size, type, disabled, loading, block, rounded, loadingText, Fragment: _ntc_Fragment } = ctx
49
49
  return h('button', { class: btnClass.value, type: type, disabled: disabled || loading, onClick: handleClick, "data-v-27fd765": "" }, [
50
50
  "\n ",
51
51
  (loading) ? h('span', { class: "n-btn-loader", "data-v-27fd765": "" }) : null,
@@ -18,7 +18,7 @@ const _sfc_main = defineComponent({
18
18
  })
19
19
  // Injected render function
20
20
  _sfc_main.render = function(ctx) {
21
- const { $slots, title, subtitle, padding, hoverable, variant, image, Fragment: _ntc_Fragment } = ctx
21
+ let { $slots, title, subtitle, padding, hoverable, variant, image, Fragment: _ntc_Fragment } = ctx
22
22
  return h('div', { class: ['n-card', `is-${variant}`, hoverable ? 'is-hoverable' : ''], "data-v-34850782": "" }, [
23
23
  "\n ",
24
24
  (image) ? h('img', { class: "n-card-image", src: image, "data-v-34850782": "" }) : null,
@@ -21,7 +21,7 @@ const _sfc_main = defineComponent({
21
21
  })
22
22
  // Injected render function
23
23
  _sfc_main.render = function(ctx) {
24
- const { toggle, $slots, emit, modelValue, label, disabled, indeterminate, Fragment: _ntc_Fragment } = ctx
24
+ let { toggle, $slots, emit, modelValue, label, disabled, indeterminate, Fragment: _ntc_Fragment } = ctx
25
25
  return h('label', { class: ["n-checkbox", { 'is-checked': modelValue && !indeterminate, 'is-indeterminate': indeterminate, 'is-disabled': disabled }], "data-v-761e94fe": "" }, [
26
26
  "\n ",
27
27
  h('div', { class: "n-checkbox-box", onClick: toggle, "data-v-761e94fe": "" }, [
@@ -45,7 +45,7 @@ const _sfc_main = defineComponent({
45
45
  })
46
46
  // Injected render function
47
47
  _sfc_main.render = function(ctx) {
48
- const { resolvedModel, normalize, chips, removeAt, $slots, emit, modelValue, removable, disabled, Fragment: _ntc_Fragment } = ctx
48
+ let { resolvedModel, normalize, chips, removeAt, $slots, emit, modelValue, removable, disabled, Fragment: _ntc_Fragment } = ctx
49
49
  return h('div', { class: ["n-chips", { 'is-disabled': disabled }], "data-v-606f06fb": "" }, [
50
50
  "\n ",
51
51
  (chips.value).map((chip, i) =>
@@ -166,7 +166,7 @@ const _sfc_main = defineComponent({
166
166
  })
167
167
  // Injected render function
168
168
  _sfc_main.render = function(ctx) {
169
- const { internalFirst, internalRows, internalSortField, internalSortOrder, internalFilters, effectiveFilters, columnWidths, resizing, internalSelection, lastPropGlobal, lastPropSelection, normalizeColumns, getRowKey, effectiveSelection, isRowSelected, toggleRowSelection, allVisibleSelected, toggleAllVisible, getHeaderContent, getRawValue, getCellContent, matchFilter, filteredRows, sortedRows, totalRecords, visibleRows, setSort, onSortClick, setGlobal, setColumnFilter, onColumnFilterInput, onPage, getWidth, startResize, NPaginator: _ntc_NPaginator, $slots, emit, value, columns, stripedRows, hoverRows, size, scrollable, paginator, rows, first, rowsPerPageOptions, selectionMode, selection, dataKey, sortField, sortOrder, resizableColumns, columnResizeMode, filterDisplay, globalFilter, globalFilterFields, filters, lazy, emptyMessage, showGridlines, Fragment: _ntc_Fragment } = ctx
169
+ let { internalFirst, internalRows, internalSortField, internalSortOrder, internalFilters, effectiveFilters, columnWidths, resizing, internalSelection, lastPropGlobal, lastPropSelection, normalizeColumns, getRowKey, effectiveSelection, isRowSelected, toggleRowSelection, allVisibleSelected, toggleAllVisible, getHeaderContent, getRawValue, getCellContent, matchFilter, filteredRows, sortedRows, totalRecords, visibleRows, setSort, onSortClick, setGlobal, setColumnFilter, onColumnFilterInput, onPage, getWidth, startResize, NPaginator: _ntc_NPaginator, $slots, emit, value, columns, stripedRows, hoverRows, size, scrollable, paginator, rows, first, rowsPerPageOptions, selectionMode, selection, dataKey, sortField, sortOrder, resizableColumns, columnResizeMode, filterDisplay, globalFilter, globalFilterFields, filters, lazy, emptyMessage, showGridlines, Fragment: _ntc_Fragment } = ctx
170
170
  return h('div', { class: ["n-dt", [`n-dt-${size}`, showGridlines ? 'is-grid' : '', scrollable ? 'is-scroll' : '']], "data-v-17a3d2ce": "" }, [
171
171
  "\n ",
172
172
  h('div', { class: "n-dt-toolbar", "data-v-17a3d2ce": "" }, [
@@ -173,7 +173,7 @@ const _sfc_main = defineComponent({
173
173
  })
174
174
  // Injected render function
175
175
  _sfc_main.render = function(ctx) {
176
- const { isOpen, viewDate, instanceId, popupStyle, resolvedPlacement, stopTracking, today, year, month, daysInMonth, firstDayOfWeek, calendarDays, formatDate, parseDate, minDate, maxDate, isDisabled, closePopup, syncViewDateFromModel, selectDate, prevMonth, nextMonth, monthNames, dayNames, isSelected, isToday, closeHandler, rootEl, openPopup, onBeforeUnmount, NInput: _ntc_NInput, trackFloatingOverlay, $slots, emit, modelValue, placeholder, disabled, min, max, placement, Fragment: _ntc_Fragment, Teleport: _ntc_Teleport } = ctx
176
+ let { isOpen, viewDate, instanceId, popupStyle, resolvedPlacement, stopTracking, today, year, month, daysInMonth, firstDayOfWeek, calendarDays, formatDate, parseDate, minDate, maxDate, isDisabled, closePopup, syncViewDateFromModel, selectDate, prevMonth, nextMonth, monthNames, dayNames, isSelected, isToday, closeHandler, rootEl, openPopup, onBeforeUnmount, NInput: _ntc_NInput, trackFloatingOverlay, $slots, emit, modelValue, placeholder, disabled, min, max, placement, Fragment: _ntc_Fragment, Teleport: _ntc_Teleport } = ctx
177
177
  return h('div', { class: "n-datepicker", "data-datepicker-root": instanceId, "data-v-69fa2c78": "" }, [
178
178
  "\n ",
179
179
  h('div', { class: "n-datepicker-input", onClick: openPopup, "data-v-69fa2c78": "" }, [
@@ -111,7 +111,7 @@ const _sfc_main = defineComponent({
111
111
  })
112
112
  // Injected render function
113
113
  _sfc_main.render = function(ctx) {
114
- const { fieldNames, fields, registerField, getValues, values, errors, pending, valid, validateAll, reset, submit, onSubmit, provide, $slots, emit, validateOn, disabled, Fragment: _ntc_Fragment } = ctx
114
+ let { fieldNames, fields, registerField, getValues, values, errors, pending, valid, validateAll, reset, submit, onSubmit, provide, $slots, emit, validateOn, disabled, Fragment: _ntc_Fragment } = ctx
115
115
  return h('form', { class: "n-form", onSubmit: onSubmit, "data-v-38e99ca2": "" }, [
116
116
  "\n ",
117
117
  ctx.$slots.default ? ctx.$slots.default({ values: values, errors: errors, valid: valid, pending: pending, submit: submit, reset: reset }) : null,
@@ -112,7 +112,7 @@ const _sfc_main = defineComponent({
112
112
  })
113
113
  // Injected render function
114
114
  _sfc_main.render = function(ctx) {
115
- const { nextAutoId, form, autoId, inputId, helpId, errorId, describedBy, value, initialValue, touched, pending, errors, dirty, error, invalid, shouldValidateOn, validate, setValue, onBlur, reset, unregister, inject, provide, $slots, emit, name, label, help, id, modelValue, rules, validateOn, showError, disabled, Fragment: _ntc_Fragment } = ctx
115
+ let { nextAutoId, form, autoId, inputId, helpId, errorId, describedBy, value, initialValue, touched, pending, errors, dirty, error, invalid, shouldValidateOn, validate, setValue, onBlur, reset, unregister, inject, provide, $slots, emit, name, label, help, id, modelValue, rules, validateOn, showError, disabled, Fragment: _ntc_Fragment } = ctx
116
116
  return h('div', { class: ["n-form-field", { 'is-invalid': invalid.value, 'is-disabled': disabled, 'is-pending': pending.value }], "data-v-30bdb720": "" }, [
117
117
  "\n ",
118
118
  (label) ? h('label', { class: "n-form-field-label", for: inputId.value, "data-v-30bdb720": "" }, [
@@ -65,7 +65,7 @@ const _sfc_main = defineComponent({
65
65
  })
66
66
  // Injected render function
67
67
  _sfc_main.render = function(ctx) {
68
- const { loaded, error, visible, observer, imgRef, currentSrc, wrapperStyle, imgStyle, setRef, onLoad, onError, $slots, src, alt, fallback, fit, lazy, width, height, rounded, blur, Fragment: _ntc_Fragment } = ctx
68
+ let { loaded, error, visible, observer, imgRef, currentSrc, wrapperStyle, imgStyle, setRef, onLoad, onError, $slots, src, alt, fallback, fit, lazy, width, height, rounded, blur, Fragment: _ntc_Fragment } = ctx
69
69
  return h('span', { class: "n-image-wrapper", style: wrapperStyle.value, ref: setRef, "data-v-309b6eb8": "" }, [
70
70
  "\n ",
71
71
  (!loaded.value) ? h('span', { class: "n-image-skeleton", "data-v-309b6eb8": "" }) : null,
@@ -105,7 +105,7 @@ const _sfc_main = defineComponent({
105
105
  })
106
106
  // Injected render function
107
107
  _sfc_main.render = function(ctx) {
108
- const { field, showPassword, isFocused, effectiveValue, draft, effectiveId, effectiveDescribedBy, effectiveInvalid, effectiveError, effectiveDisabled, inputType, currentLength, onInput, onFocus, onBlur, clear, togglePassword, inject, $slots, emit, modelValue, type, placeholder, label, error, id, name, autocomplete, ariaDescribedby, ariaInvalid, bindField, disabled, readonly, clearable, maxlength, prefixIcon, suffixIcon, Fragment: _ntc_Fragment } = ctx
108
+ let { field, showPassword, isFocused, effectiveValue, draft, effectiveId, effectiveDescribedBy, effectiveInvalid, effectiveError, effectiveDisabled, inputType, currentLength, onInput, onFocus, onBlur, clear, togglePassword, inject, $slots, emit, modelValue, type, placeholder, label, error, id, name, autocomplete, ariaDescribedby, ariaInvalid, bindField, disabled, readonly, clearable, maxlength, prefixIcon, suffixIcon, Fragment: _ntc_Fragment } = ctx
109
109
  return h('div', { class: "n-input-group", "data-v-7dbed0f8": "" }, [
110
110
  "\n ",
111
111
  (label) ? h('label', { class: "n-input-label", "data-v-7dbed0f8": "" }, [
@@ -1,7 +1,7 @@
1
1
  import { signal, computed, inject, effect, batch, h, hText, defineComponent, registerComponent, reloadComponent, injectStyle } from 'nexa-framework'
2
2
 
3
3
  const _sfc_main = defineComponent({
4
- __scopeId: 'data-v-6dd313',
4
+ __scopeId: 'data-v-76a3e703',
5
5
  __hmrId: 'NInputNumber_nexa',
6
6
  props: {
7
7
  modelValue: { type: Number, default: 0 },
@@ -12,7 +12,9 @@ const _sfc_main = defineComponent({
12
12
  disabled: { type: Boolean, default: false },
13
13
  readonly: { type: Boolean, default: false },
14
14
  label: { type: String, default: '' },
15
- placeholder: { type: String, default: '' }
15
+ placeholder: { type: String, default: '' },
16
+ currency: { type: String, default: undefined },
17
+ locale: { type: String, default: undefined },
16
18
  },
17
19
  emits: ['update:modelValue', 'focus', 'blur'],
18
20
  setup(props, setupContext) {
@@ -38,6 +40,29 @@ const _sfc_main = defineComponent({
38
40
  text.value = nextText
39
41
  })
40
42
  const canEdit = computed(() => !effectiveDisabled.value && !props.readonly)
43
+ const isFocused = signal(false)
44
+ const nfSignal = signal(null)
45
+ effect(() => {
46
+ if (props.currency) {
47
+ nfSignal.value = new Intl.NumberFormat(props.locale || undefined, {
48
+ style: 'currency',
49
+ currency: props.currency,
50
+ minimumFractionDigits: 2,
51
+ maximumFractionDigits: 2,
52
+ })
53
+ } else {
54
+ nfSignal.value = null
55
+ }
56
+ })
57
+ const displayText = computed(() => {
58
+ const raw = text.value
59
+ const nf = nfSignal.value
60
+ if (!nf || isFocused.value) return raw
61
+ if (!raw) return raw
62
+ const n = parseFloat(raw)
63
+ if (Number.isNaN(n)) return raw
64
+ return nf.format(n)
65
+ })
41
66
  const sanitize = (raw) => {
42
67
  const input = String(raw ?? '')
43
68
  if (!input) return ''
@@ -153,6 +178,7 @@ const _sfc_main = defineComponent({
153
178
  const onBlur = () => {
154
179
  emit('blur')
155
180
  if (props.bindField && field?.onBlur) field.onBlur()
181
+ isFocused.value = false
156
182
  const n = parse(text.value)
157
183
  const clamped = clamp(n)
158
184
  if (clamped == null) {
@@ -165,27 +191,30 @@ const _sfc_main = defineComponent({
165
191
  else emit('update:modelValue', clamped)
166
192
  })
167
193
  }
168
- const onFocus = () => emit('focus')
169
- return { field, effectiveValue, effectiveDisabled, text, canEdit, sanitize, clamp, parse, setValue, inc, dec, onInput, onBeforeInput, onPaste, onKeydown, onBlur, onFocus, inject, batch, $slots, emit }
194
+ const onFocus = () => {
195
+ isFocused.value = true
196
+ emit('focus')
197
+ }
198
+ return { field, effectiveValue, effectiveDisabled, text, canEdit, isFocused, nfSignal, displayText, sanitize, clamp, parse, setValue, inc, dec, onInput, onBeforeInput, onPaste, onKeydown, onBlur, onFocus, inject, batch, $slots, emit }
170
199
  }
171
200
  })
172
201
  // Injected render function
173
202
  _sfc_main.render = function(ctx) {
174
- const { field, effectiveValue, effectiveDisabled, text, canEdit, sanitize, clamp, parse, setValue, inc, dec, onInput, onBeforeInput, onPaste, onKeydown, onBlur, onFocus, inject, batch, $slots, emit, modelValue, min, max, step, bindField, disabled, readonly, label, placeholder, Fragment: _ntc_Fragment } = ctx
175
- return h('div', { class: "n-inum", "data-v-6dd313": "" }, [
203
+ let { field, effectiveValue, effectiveDisabled, text, canEdit, isFocused, nfSignal, displayText, sanitize, clamp, parse, setValue, inc, dec, onInput, onBeforeInput, onPaste, onKeydown, onBlur, onFocus, inject, batch, $slots, emit, modelValue, min, max, step, bindField, disabled, readonly, label, placeholder, currency, locale, Fragment: _ntc_Fragment } = ctx
204
+ return h('div', { class: "n-inum", "data-v-76a3e703": "" }, [
176
205
  "\n ",
177
- (label) ? h('label', { class: "n-inum-label", "data-v-6dd313": "" }, [
206
+ (label) ? h('label', { class: "n-inum-label", "data-v-76a3e703": "" }, [
178
207
  label
179
208
  ]) : null,
180
- h('div', { class: ["n-inum-wrap", { 'is-disabled': effectiveDisabled.value }], "data-v-6dd313": "" }, [
209
+ h('div', { class: ["n-inum-wrap", { 'is-disabled': effectiveDisabled.value }], "data-v-76a3e703": "" }, [
181
210
  "\n ",
182
- h('button', { class: "n-inum-btn n-inum-dec", type: "button", disabled: effectiveDisabled.value || readonly, "aria-label": "Decrement", onClick: dec, "data-v-6dd313": "" }, [
211
+ h('button', { class: "n-inum-btn n-inum-dec", type: "button", disabled: effectiveDisabled.value || readonly, "aria-label": "Decrement", onClick: dec, "data-v-76a3e703": "" }, [
183
212
  "−"
184
213
  ]),
185
214
  "\n ",
186
- h('input', { class: "n-inum-input", type: "text", value: text.value, placeholder: placeholder, disabled: effectiveDisabled.value, readonly: readonly, inputmode: "decimal", autocomplete: "off", onBeforeinput: onBeforeInput, onKeydown: onKeydown, onPaste: onPaste, onInput: onInput, onFocus: onFocus, onBlur: onBlur, "data-v-6dd313": "" }),
215
+ h('input', { class: "n-inum-input", type: "text", value: displayText.value, placeholder: placeholder, disabled: effectiveDisabled.value, readonly: readonly, inputmode: "decimal", autocomplete: "off", onBeforeinput: onBeforeInput, onKeydown: onKeydown, onPaste: onPaste, onInput: onInput, onFocus: onFocus, onBlur: onBlur, "data-v-76a3e703": "" }),
187
216
  "\n ",
188
- h('button', { class: "n-inum-btn n-inum-inc", type: "button", disabled: effectiveDisabled.value || readonly, "aria-label": "Increment", onClick: inc, "data-v-6dd313": "" }, [
217
+ h('button', { class: "n-inum-btn n-inum-inc", type: "button", disabled: effectiveDisabled.value || readonly, "aria-label": "Increment", onClick: inc, "data-v-76a3e703": "" }, [
189
218
  "+"
190
219
  ]),
191
220
  "\n "
@@ -193,10 +222,10 @@ _sfc_main.render = function(ctx) {
193
222
  "\n "
194
223
  ])
195
224
  }
196
- _sfc_main.__scopeId = 'data-v-6dd313'
225
+ _sfc_main.__scopeId = 'data-v-76a3e703'
197
226
  _sfc_main.__hmrId = 'NInputNumber_nexa'
198
227
 
199
228
  export default _sfc_main
200
229
 
201
- const __style = `.n-inum[data-v-6dd313]{display:flex;flex-direction:column;gap:var(--n-space-2);width:100%;font-family:var(--n-font-sans)}.n-inum-label{display:block;font-size:var(--n-text-sm);font-weight:var(--n-weight-medium);color:var(--n-color-text-secondary);margin-bottom:var(--n-space-2)}.n-inum-wrap{display:flex;align-items:stretch;min-height:44px;background:var(--n-color-surface);border:1px solid var(--n-color-border);border-radius:var(--n-radius-md);overflow:hidden;transition:all var(--n-transition-fast)}.n-inum-wrap:focus-within{border-color:var(--n-color-primary);box-shadow:0 0 0 3px var(--n-color-primary-light)}.n-inum-input{flex:1;background:transparent;border:none;outline:none;padding:0.75rem 0.75rem;color:var(--n-color-text);font-size:var(--n-text-base);font-family:inherit;text-align:center;line-height:1.2;box-sizing:border-box}.n-inum-btn{width:2.5rem;background:transparent;border:none;color:var(--n-color-text-muted);cursor:pointer;display:flex;align-items:center;justify-content:center;font-size:var(--n-text-base);transition:all var(--n-transition-fast)}.n-inum-btn:hover:not(:disabled){background:var(--n-color-glass);color:var(--n-color-text)}.n-inum-btn:disabled{opacity:0.5;cursor:not-allowed}.is-disabled{opacity:0.6;cursor:not-allowed;background:var(--n-color-surface-alt)}`
202
- injectStyle('data-v-6dd313', __style)
230
+ const __style = `.n-inum[data-v-76a3e703]{display:flex;flex-direction:column;gap:var(--n-space-2);width:100%;font-family:var(--n-font-sans)}.n-inum-label{display:block;font-size:var(--n-text-sm);font-weight:var(--n-weight-medium);color:var(--n-color-text-secondary);margin-bottom:var(--n-space-2)}.n-inum-wrap{display:flex;align-items:stretch;min-height:44px;background:var(--n-color-surface);border:1px solid var(--n-color-border);border-radius:var(--n-radius-md);overflow:hidden;transition:all var(--n-transition-fast)}.n-inum-wrap:focus-within{border-color:var(--n-color-primary);box-shadow:0 0 0 3px var(--n-color-primary-light)}.n-inum-input{flex:1;background:transparent;border:none;outline:none;padding:0.75rem 0.75rem;color:var(--n-color-text);font-size:var(--n-text-base);font-family:inherit;text-align:center;line-height:1.2;box-sizing:border-box}.n-inum-btn{width:2.5rem;background:transparent;border:none;color:var(--n-color-text-muted);cursor:pointer;display:flex;align-items:center;justify-content:center;font-size:var(--n-text-base);transition:all var(--n-transition-fast)}.n-inum-btn:hover:not(:disabled){background:var(--n-color-glass);color:var(--n-color-text)}.n-inum-btn:disabled{opacity:0.5;cursor:not-allowed}.is-disabled{opacity:0.6;cursor:not-allowed;background:var(--n-color-surface-alt)}`
231
+ injectStyle('data-v-76a3e703', __style)
@@ -10,7 +10,9 @@ const props = defineProps({
10
10
  disabled: { type: Boolean, default: false },
11
11
  readonly: { type: Boolean, default: false },
12
12
  label: { type: String, default: '' },
13
- placeholder: { type: String, default: '' }
13
+ placeholder: { type: String, default: '' },
14
+ currency: { type: String, default: undefined },
15
+ locale: { type: String, default: undefined },
14
16
  })
15
17
 
16
18
  const emit = defineEmits(['update:modelValue', 'focus', 'blur'])
@@ -42,6 +44,33 @@ effect(() => {
42
44
 
43
45
  const canEdit = computed(() => !effectiveDisabled.value && !props.readonly)
44
46
 
47
+ const isFocused = signal(false)
48
+
49
+ const nfSignal = signal(null)
50
+
51
+ effect(() => {
52
+ if (props.currency) {
53
+ nfSignal.value = new Intl.NumberFormat(props.locale || undefined, {
54
+ style: 'currency',
55
+ currency: props.currency,
56
+ minimumFractionDigits: 2,
57
+ maximumFractionDigits: 2,
58
+ })
59
+ } else {
60
+ nfSignal.value = null
61
+ }
62
+ })
63
+
64
+ const displayText = computed(() => {
65
+ const raw = text.value
66
+ const nf = nfSignal.value
67
+ if (!nf || isFocused.value) return raw
68
+ if (!raw) return raw
69
+ const n = parseFloat(raw)
70
+ if (Number.isNaN(n)) return raw
71
+ return nf.format(n)
72
+ })
73
+
45
74
  const sanitize = (raw) => {
46
75
  const input = String(raw ?? '')
47
76
  if (!input) return ''
@@ -167,6 +196,7 @@ const onKeydown = (e) => {
167
196
  const onBlur = () => {
168
197
  emit('blur')
169
198
  if (props.bindField && field?.onBlur) field.onBlur()
199
+ isFocused.value = false
170
200
  const n = parse(text.value)
171
201
  const clamped = clamp(n)
172
202
  if (clamped == null) {
@@ -180,7 +210,10 @@ const onBlur = () => {
180
210
  })
181
211
  }
182
212
 
183
- const onFocus = () => emit('focus')
213
+ const onFocus = () => {
214
+ isFocused.value = true
215
+ emit('focus')
216
+ }
184
217
  </script>
185
218
 
186
219
  <template>
@@ -188,7 +221,7 @@ const onFocus = () => emit('focus')
188
221
  <label v-if="label" class="n-inum-label">{{ label }}</label>
189
222
  <div class="n-inum-wrap" :class="{ 'is-disabled': effectiveDisabled.value }">
190
223
  <button type="button" class="n-inum-btn n-inum-dec" :disabled="effectiveDisabled.value || readonly" aria-label="Decrement" @click="dec">−</button>
191
- <input class="n-inum-input" type="text" :value="text.value" :placeholder="placeholder" :disabled="effectiveDisabled.value" :readonly="readonly" inputmode="decimal" autocomplete="off" @beforeinput="onBeforeInput" @keydown="onKeydown" @paste="onPaste" @input="onInput" @focus="onFocus" @blur="onBlur" />
224
+ <input class="n-inum-input" type="text" :value="displayText.value" :placeholder="placeholder" :disabled="effectiveDisabled.value" :readonly="readonly" inputmode="decimal" autocomplete="off" @beforeinput="onBeforeInput" @keydown="onKeydown" @paste="onPaste" @input="onInput" @focus="onFocus" @blur="onBlur" />
192
225
  <button type="button" class="n-inum-btn n-inum-inc" :disabled="effectiveDisabled.value || readonly" aria-label="Increment" @click="inc">+</button>
193
226
  </div>
194
227
  </div>
@@ -78,7 +78,7 @@ const _sfc_main = defineComponent({
78
78
  })
79
79
  // Injected render function
80
80
  _sfc_main.render = function(ctx) {
81
- const { isVisible, modalEl, previousFocus, bodyOverflow, setModalRef, sizeMap, close, handleEsc, handleOverlayClick, focusableSelector, handleKeydown, $slots, emit, show, title, size, closable, closeLeft, Fragment: _ntc_Fragment, Teleport: _ntc_Teleport } = ctx
81
+ let { isVisible, modalEl, previousFocus, bodyOverflow, setModalRef, sizeMap, close, handleEsc, handleOverlayClick, focusableSelector, handleKeydown, $slots, emit, show, title, size, closable, closeLeft, Fragment: _ntc_Fragment, Teleport: _ntc_Teleport } = ctx
82
82
  return h(_ntc_Teleport, { to: "body", "data-v-655f39d1": "" }, [
83
83
  "\n ",
84
84
  (isVisible.value) ? h('div', { class: "n-modal-root", "data-v-655f39d1": "" }, [
@@ -64,7 +64,7 @@ const _sfc_main = defineComponent({
64
64
  })
65
65
  // Injected render function
66
66
  _sfc_main.render = function(ctx) {
67
- const { field, instanceId, isOpen, query, queryDraft, focusedIndex, popupStyle, resolvedPlacement, rootEl, stopTracking, outsideHandler, normalizeOption, normalizedOptions, effectiveModelValue, effectiveDisabled, selectedSet, filteredOptions, selectedLabels, close, open, toggleOpen, setModel, toggleValue, clear, removeChip, onKeydown, onSearchInput, inject, onBeforeUnmount, batch, trackFloatingOverlay, $slots, emit, modelValue, options, placeholder, label, disabled, bindField, searchable, clearable, placement, appendTo, maxChips, Fragment: _ntc_Fragment, Teleport: _ntc_Teleport } = ctx
67
+ let { field, instanceId, isOpen, query, queryDraft, focusedIndex, popupStyle, resolvedPlacement, rootEl, stopTracking, outsideHandler, normalizeOption, normalizedOptions, effectiveModelValue, effectiveDisabled, selectedSet, filteredOptions, selectedLabels, close, open, toggleOpen, setModel, toggleValue, clear, removeChip, onKeydown, onSearchInput, inject, onBeforeUnmount, batch, trackFloatingOverlay, $slots, emit, modelValue, options, placeholder, label, disabled, bindField, searchable, clearable, placement, appendTo, maxChips, Fragment: _ntc_Fragment, Teleport: _ntc_Teleport } = ctx
68
68
  return h('div', { class: ["n-ms", { 'is-open': isOpen.value, 'is-disabled': effectiveDisabled.value }], "data-ms-root": instanceId, "data-v-12b3b8c4": "" }, [
69
69
  "\n ",
70
70
  (label) ? h('label', { class: "n-ms-label", "data-v-12b3b8c4": "" }, [
@@ -51,7 +51,7 @@ const _sfc_main = defineComponent({
51
51
  })
52
52
  // Injected render function
53
53
  _sfc_main.render = function(ctx) {
54
- const { safeFirst, safeRows, page, pageCount, canPrev, canNext, goToPage, prev, next, firstPage, lastPage, changeRows, start, end, $slots, emit, first, rows, totalRecords, rowsPerPageOptions, Fragment: _ntc_Fragment } = ctx
54
+ let { safeFirst, safeRows, page, pageCount, canPrev, canNext, goToPage, prev, next, firstPage, lastPage, changeRows, start, end, $slots, emit, first, rows, totalRecords, rowsPerPageOptions, Fragment: _ntc_Fragment } = ctx
55
55
  return h('div', { class: "n-paginator", "data-v-372b30ac": "" }, [
56
56
  "\n ",
57
57
  h('div', { class: "n-paginator-left", "data-v-372b30ac": "" }, [
@@ -98,7 +98,7 @@ const _sfc_main = defineComponent({
98
98
  })
99
99
  // Injected render function
100
100
  _sfc_main.render = function(ctx) {
101
- const { instanceId, inputId, masked, type, hasValue, requirements, strength, internalError, errorMessage, ariaInvalid, describedBy, onInput, clear, toggle, $slots, emit, modelValue, placeholder, label, error, disabled, readonly, name, autocomplete, id, clearable, toggleMask, showStrength, validate, showRequirements, minLength, requireLower, requireUpper, requireNumber, requireSpecial, Fragment: _ntc_Fragment } = ctx
101
+ let { instanceId, inputId, masked, type, hasValue, requirements, strength, internalError, errorMessage, ariaInvalid, describedBy, onInput, clear, toggle, $slots, emit, modelValue, placeholder, label, error, disabled, readonly, name, autocomplete, id, clearable, toggleMask, showStrength, validate, showRequirements, minLength, requireLower, requireUpper, requireNumber, requireSpecial, Fragment: _ntc_Fragment } = ctx
102
102
  return h('div', { class: "n-password", "data-v-7b897096": "" }, [
103
103
  "\n ",
104
104
  (label) ? h('label', { class: "n-password-label", for: inputId.value, "data-v-7b897096": "" }, [
@@ -20,7 +20,7 @@ const _sfc_main = defineComponent({
20
20
  })
21
21
  // Injected render function
22
22
  _sfc_main.render = function(ctx) {
23
- const { percentage, $slots, value, max, variant, size, showLabel, striped, animated, Fragment: _ntc_Fragment } = ctx
23
+ let { percentage, $slots, value, max, variant, size, showLabel, striped, animated, Fragment: _ntc_Fragment } = ctx
24
24
  return h('div', { class: ["n-progress", [`is-${size}`, striped ? 'is-striped' : '', animated ? 'is-animated' : '']], "data-v-daaa1d0": "" }, [
25
25
  "\n ",
26
26
  h('div', { class: "n-progress-track", "data-v-daaa1d0": "" }, [
@@ -23,7 +23,7 @@ const _sfc_main = defineComponent({
23
23
  })
24
24
  // Injected render function
25
25
  _sfc_main.render = function(ctx) {
26
- const { isChecked, select, $slots, emit, modelValue, value, label, disabled, name, Fragment: _ntc_Fragment } = ctx
26
+ let { isChecked, select, $slots, emit, modelValue, value, label, disabled, name, Fragment: _ntc_Fragment } = ctx
27
27
  return h('label', { class: ["n-radio", { 'is-checked': isChecked(), 'is-disabled': disabled }], "data-v-5c3cc2": "" }, [
28
28
  "\n ",
29
29
  h('div', { class: "n-radio-circle", onClick: select, "data-v-5c3cc2": "" }, [
@@ -63,7 +63,7 @@ const _sfc_main = defineComponent({
63
63
  })
64
64
  // Injected render function
65
65
  _sfc_main.render = function(ctx) {
66
- const { isRefreshing, pullDelta, refreshThreshold, touchStartY, startScrollTop, pullProgress, spinnerScale, onTouchStart, onTouchMove, onTouchEnd, onScroll, $slots, onRefresh, onEndReached, endReachedThreshold, horizontal, Fragment: _ntc_Fragment } = ctx
66
+ let { isRefreshing, pullDelta, refreshThreshold, touchStartY, startScrollTop, pullProgress, spinnerScale, onTouchStart, onTouchMove, onTouchEnd, onScroll, $slots, onRefresh, onEndReached, endReachedThreshold, horizontal, Fragment: _ntc_Fragment } = ctx
67
67
  return h('div', { class: ["n-scroll-view", { 'n-scroll-view--horizontal': horizontal }], onScroll: onScroll, onTouchstart: onTouchStart, onTouchmove: onTouchMove, onTouchend: onTouchEnd, "data-v-7469d561": "" }, [
68
68
  "\n ",
69
69
  (onRefresh) ? h('div', { class: ["n-scroll-view-ptr", { 'is-refreshing': isRefreshing.value }], style: { height: pullDelta.value + 'px' }, "data-v-7469d561": "" }, [
@@ -174,7 +174,7 @@ const _sfc_main = defineComponent({
174
174
  })
175
175
  // Injected render function
176
176
  _sfc_main.render = function(ctx) {
177
- const { isOpen, query, focusedIndex, instanceId, popupStyle, resolvedPlacement, rootEl, stopTracking, outsideHandler, filteredOptions, selectedOption, close, open, toggle, select, clear, handleKeydown, getFlatOptions, onBeforeUnmount, trackFloatingOverlay, $slots, emit, modelValue, options, placeholder, label, disabled, searchable, clearable, placement, appendTo, Fragment: _ntc_Fragment, Teleport: _ntc_Teleport } = ctx
177
+ let { isOpen, query, focusedIndex, instanceId, popupStyle, resolvedPlacement, rootEl, stopTracking, outsideHandler, filteredOptions, selectedOption, close, open, toggle, select, clear, handleKeydown, getFlatOptions, onBeforeUnmount, trackFloatingOverlay, $slots, emit, modelValue, options, placeholder, label, disabled, searchable, clearable, placement, appendTo, Fragment: _ntc_Fragment, Teleport: _ntc_Teleport } = ctx
178
178
  return h('div', { class: ["n-select", { 'is-open': isOpen.value, 'is-disabled': disabled }], "data-select-root": instanceId, "data-v-fef169b": "" }, [
179
179
  "\n ",
180
180
  (label) ? h('label', { class: "n-select-label", "data-v-fef169b": "" }, [
@@ -17,7 +17,7 @@ const _sfc_main = defineComponent({
17
17
  })
18
18
  // Injected render function
19
19
  _sfc_main.render = function(ctx) {
20
- const { lineArray, $slots, variant, lines, width, height, Fragment: _ntc_Fragment } = ctx
20
+ let { lineArray, $slots, variant, lines, width, height, Fragment: _ntc_Fragment } = ctx
21
21
  return h('div', { class: ["n-skeleton", `is-${variant}`], style: { width, height }, "data-v-6b9116c8": "" }, [
22
22
  "\n ",
23
23
  (variant === 'text') ? h('div', { class: "n-skeleton-lines", "data-v-6b9116c8": "" }, [
@@ -20,7 +20,7 @@ const _sfc_main = defineComponent({
20
20
  })
21
21
  // Injected render function
22
22
  _sfc_main.render = function(ctx) {
23
- const { toggle, $slots, emit, modelValue, disabled, label, Fragment: _ntc_Fragment } = ctx
23
+ let { toggle, $slots, emit, modelValue, disabled, label, Fragment: _ntc_Fragment } = ctx
24
24
  return h('label', { class: ["n-switch", { 'is-checked': modelValue, 'is-disabled': disabled }], "data-v-3cd56cb4": "" }, [
25
25
  "\n ",
26
26
  h('div', { class: "n-switch-track", onClick: toggle, "data-v-3cd56cb4": "" }, [
@@ -22,7 +22,7 @@ const _sfc_main = defineComponent({
22
22
  })
23
23
  // Injected render function
24
24
  _sfc_main.render = function(ctx) {
25
- const { activeKey, select, activeIndex, $slots, emit, tabs, modelValue, Fragment: _ntc_Fragment } = ctx
25
+ let { activeKey, select, activeIndex, $slots, emit, tabs, modelValue, Fragment: _ntc_Fragment } = ctx
26
26
  return h('div', { class: "n-tabs", "data-v-339e5ee5": "" }, [
27
27
  "\n ",
28
28
  h('div', { class: "n-tabs-header", "data-v-339e5ee5": "" }, [
@@ -17,7 +17,7 @@ const _sfc_main = defineComponent({
17
17
  })
18
18
  // Injected render function
19
19
  _sfc_main.render = function(ctx) {
20
- const { $slots, emit, variant, size, closable, rounded, Fragment: _ntc_Fragment } = ctx
20
+ let { $slots, emit, variant, size, closable, rounded, Fragment: _ntc_Fragment } = ctx
21
21
  return h('span', { class: ['n-tag', `n-tag-${variant}`, `n-tag-${size}`, rounded ? 'is-rounded' : ''], "data-v-4d63a958": "" }, [
22
22
  "\n ",
23
23
  ctx.$slots.default ? ctx.$slots.default() : null,
@@ -16,7 +16,7 @@ const _sfc_main = defineComponent({
16
16
  })
17
17
  // Injected render function
18
18
  _sfc_main.render = function(ctx) {
19
- const { toasts, remove, positionClass, useToast, $slots, position, Fragment: _ntc_Fragment, Teleport: _ntc_Teleport } = ctx
19
+ let { toasts, remove, positionClass, useToast, $slots, position, Fragment: _ntc_Fragment, Teleport: _ntc_Teleport } = ctx
20
20
  return h(_ntc_Teleport, { to: "body", "data-v-8ac4158": "" }, [
21
21
  "\n ",
22
22
  h('div', { class: ["n-toast-container", positionClass], "data-v-8ac4158": "" }, [
@@ -66,7 +66,7 @@ const _sfc_main = defineComponent({
66
66
  })
67
67
  // Injected render function
68
68
  _sfc_main.render = function(ctx) {
69
- const { isVisible, instanceId, popupStyle, resolvedPlacement, rootEl, stopTracking, showTimer, hideTimer, startTracking, stop, show, hide, trackFloatingOverlay, $slots, text, position, delay, hideDelay, Fragment: _ntc_Fragment, Teleport: _ntc_Teleport } = ctx
69
+ let { isVisible, instanceId, popupStyle, resolvedPlacement, rootEl, stopTracking, showTimer, hideTimer, startTracking, stop, show, hide, trackFloatingOverlay, $slots, text, position, delay, hideDelay, Fragment: _ntc_Fragment, Teleport: _ntc_Teleport } = ctx
70
70
  return h('div', { class: "n-tooltip-wrapper", "data-tooltip-root": instanceId, onMouseenter: show, onMouseleave: hide, onFocusin: show, onFocusout: hide, "data-v-522b965d": "" }, [
71
71
  "\n ",
72
72
  ctx.$slots.default ? ctx.$slots.default() : null,
@@ -47,7 +47,7 @@ const _sfc_main = defineComponent({
47
47
  })
48
48
  // Injected render function
49
49
  _sfc_main.render = function(ctx) {
50
- const { expanded, toggleExpand, selectItem, hasChildren, isExpanded, isSelected, flatTree, toggle, $slots, emit, items, selectable, selected, Fragment: _ntc_Fragment } = ctx
50
+ let { expanded, toggleExpand, selectItem, hasChildren, isExpanded, isSelected, flatTree, toggle, $slots, emit, items, selectable, selected, Fragment: _ntc_Fragment } = ctx
51
51
  return h('div', { class: "n-tree-menu", "data-v-44b3942a": "" }, [
52
52
  "\n ",
53
53
  (flatTree.value).map((item, index) =>
@@ -51,7 +51,7 @@ const _sfc_main = defineComponent({
51
51
  })
52
52
  // Injected render function
53
53
  _sfc_main.render = function(ctx) {
54
- const { containerRef, scrollTop, containerHeight, totalHeight, visibleRange, visibleItems, resizeObserver, onScroll, $slots, items, itemHeight, overscan, renderItem, keyFn, Fragment: _ntc_Fragment } = ctx
54
+ let { containerRef, scrollTop, containerHeight, totalHeight, visibleRange, visibleItems, resizeObserver, onScroll, $slots, items, itemHeight, overscan, renderItem, keyFn, Fragment: _ntc_Fragment } = ctx
55
55
  return h('div', { class: "n-virtual-list", onScroll: onScroll, ref: el => containerRef.value = el, "data-v-2d5f09ed": "" }, [
56
56
  "\n ",
57
57
  h('div', { class: "n-virtual-list-spacer", style: { height: totalHeight.value + 'px', position: 'relative' }, "data-v-2d5f09ed": "" }, [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nexa-ui-kit",
3
- "version": "0.7.4",
3
+ "version": "0.7.6",
4
4
  "description": "Premium component library for Nexa Framework",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -22,12 +22,12 @@
22
22
  "src"
23
23
  ],
24
24
  "dependencies": {
25
- "nexa-framework": "0.7.4",
26
- "nexa-mobile": "0.7.4"
25
+ "nexa-framework": "0.7.6",
26
+ "nexa-mobile": "0.7.6"
27
27
  },
28
28
  "devDependencies": {
29
29
  "cpx": "^1.5.0",
30
- "nexa-compiler": "0.7.4"
30
+ "nexa-compiler": "0.7.6"
31
31
  },
32
32
  "scripts": {
33
33
  "build": "tsc && node scripts/compile-nexa.js && node scripts/patch-imports.js && cpx \"src/**/*.nexa\" dist && cpx \"src/styles/*.css\" dist/styles",
@@ -10,7 +10,9 @@ const props = defineProps({
10
10
  disabled: { type: Boolean, default: false },
11
11
  readonly: { type: Boolean, default: false },
12
12
  label: { type: String, default: '' },
13
- placeholder: { type: String, default: '' }
13
+ placeholder: { type: String, default: '' },
14
+ currency: { type: String, default: undefined },
15
+ locale: { type: String, default: undefined },
14
16
  })
15
17
 
16
18
  const emit = defineEmits(['update:modelValue', 'focus', 'blur'])
@@ -42,6 +44,33 @@ effect(() => {
42
44
 
43
45
  const canEdit = computed(() => !effectiveDisabled.value && !props.readonly)
44
46
 
47
+ const isFocused = signal(false)
48
+
49
+ const nfSignal = signal(null)
50
+
51
+ effect(() => {
52
+ if (props.currency) {
53
+ nfSignal.value = new Intl.NumberFormat(props.locale || undefined, {
54
+ style: 'currency',
55
+ currency: props.currency,
56
+ minimumFractionDigits: 2,
57
+ maximumFractionDigits: 2,
58
+ })
59
+ } else {
60
+ nfSignal.value = null
61
+ }
62
+ })
63
+
64
+ const displayText = computed(() => {
65
+ const raw = text.value
66
+ const nf = nfSignal.value
67
+ if (!nf || isFocused.value) return raw
68
+ if (!raw) return raw
69
+ const n = parseFloat(raw)
70
+ if (Number.isNaN(n)) return raw
71
+ return nf.format(n)
72
+ })
73
+
45
74
  const sanitize = (raw) => {
46
75
  const input = String(raw ?? '')
47
76
  if (!input) return ''
@@ -167,6 +196,7 @@ const onKeydown = (e) => {
167
196
  const onBlur = () => {
168
197
  emit('blur')
169
198
  if (props.bindField && field?.onBlur) field.onBlur()
199
+ isFocused.value = false
170
200
  const n = parse(text.value)
171
201
  const clamped = clamp(n)
172
202
  if (clamped == null) {
@@ -180,7 +210,10 @@ const onBlur = () => {
180
210
  })
181
211
  }
182
212
 
183
- const onFocus = () => emit('focus')
213
+ const onFocus = () => {
214
+ isFocused.value = true
215
+ emit('focus')
216
+ }
184
217
  </script>
185
218
 
186
219
  <template>
@@ -188,7 +221,7 @@ const onFocus = () => emit('focus')
188
221
  <label v-if="label" class="n-inum-label">{{ label }}</label>
189
222
  <div class="n-inum-wrap" :class="{ 'is-disabled': effectiveDisabled.value }">
190
223
  <button type="button" class="n-inum-btn n-inum-dec" :disabled="effectiveDisabled.value || readonly" aria-label="Decrement" @click="dec">−</button>
191
- <input class="n-inum-input" type="text" :value="text.value" :placeholder="placeholder" :disabled="effectiveDisabled.value" :readonly="readonly" inputmode="decimal" autocomplete="off" @beforeinput="onBeforeInput" @keydown="onKeydown" @paste="onPaste" @input="onInput" @focus="onFocus" @blur="onBlur" />
224
+ <input class="n-inum-input" type="text" :value="displayText.value" :placeholder="placeholder" :disabled="effectiveDisabled.value" :readonly="readonly" inputmode="decimal" autocomplete="off" @beforeinput="onBeforeInput" @keydown="onKeydown" @paste="onPaste" @input="onInput" @focus="onFocus" @blur="onBlur" />
192
225
  <button type="button" class="n-inum-btn n-inum-inc" :disabled="effectiveDisabled.value || readonly" aria-label="Increment" @click="inc">+</button>
193
226
  </div>
194
227
  </div>