nexa-ui-kit 0.6.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.
Files changed (114) hide show
  1. package/dist/NBadge.nexa +40 -0
  2. package/dist/NBottomSheet.nexa +124 -0
  3. package/dist/NButton.nexa +123 -0
  4. package/dist/NCard.nexa +74 -0
  5. package/dist/NInput.nexa +116 -0
  6. package/dist/NModal.nexa +165 -0
  7. package/dist/NSelect.nexa +169 -0
  8. package/dist/NToastContainer.nexa +86 -0
  9. package/dist/NTooltip.nexa +115 -0
  10. package/dist/components/NAlert.js +134 -0
  11. package/dist/components/NAlert.nexa +115 -0
  12. package/dist/components/NAutocomplete.js +94 -0
  13. package/dist/components/NAutocomplete.nexa +58 -0
  14. package/dist/components/NAvatar.js +75 -0
  15. package/dist/components/NAvatar.nexa +67 -0
  16. package/dist/components/NBadge.js +74 -0
  17. package/dist/components/NBadge.nexa +61 -0
  18. package/dist/components/NBottomSheet.js +149 -0
  19. package/dist/components/NBottomSheet.nexa +145 -0
  20. package/dist/components/NButton.js +284 -0
  21. package/dist/components/NButton.nexa +275 -0
  22. package/dist/components/NCard.js +117 -0
  23. package/dist/components/NCard.nexa +100 -0
  24. package/dist/components/NCheckbox.js +108 -0
  25. package/dist/components/NCheckbox.nexa +90 -0
  26. package/dist/components/NChips.js +72 -0
  27. package/dist/components/NChips.nexa +57 -0
  28. package/dist/components/NDataTable.js +252 -0
  29. package/dist/components/NDataTable.nexa +186 -0
  30. package/dist/components/NDatepicker.js +379 -0
  31. package/dist/components/NDatepicker.nexa +367 -0
  32. package/dist/components/NForm.js +132 -0
  33. package/dist/components/NForm.nexa +133 -0
  34. package/dist/components/NFormField.js +173 -0
  35. package/dist/components/NFormField.nexa +171 -0
  36. package/dist/components/NInput.js +311 -0
  37. package/dist/components/NInput.nexa +311 -0
  38. package/dist/components/NInputNumber.js +202 -0
  39. package/dist/components/NInputNumber.nexa +199 -0
  40. package/dist/components/NModal.js +221 -0
  41. package/dist/components/NModal.nexa +221 -0
  42. package/dist/components/NMultiSelect.js +156 -0
  43. package/dist/components/NMultiSelect.nexa +77 -0
  44. package/dist/components/NPaginator.js +117 -0
  45. package/dist/components/NPaginator.nexa +77 -0
  46. package/dist/components/NPassword.js +193 -0
  47. package/dist/components/NPassword.nexa +178 -0
  48. package/dist/components/NProgressBar.js +127 -0
  49. package/dist/components/NProgressBar.nexa +111 -0
  50. package/dist/components/NRadio.js +96 -0
  51. package/dist/components/NRadio.nexa +81 -0
  52. package/dist/components/NSelect.js +468 -0
  53. package/dist/components/NSelect.nexa +452 -0
  54. package/dist/components/NSkeleton.js +98 -0
  55. package/dist/components/NSkeleton.nexa +74 -0
  56. package/dist/components/NSwitch.js +92 -0
  57. package/dist/components/NSwitch.nexa +76 -0
  58. package/dist/components/NTabs.js +129 -0
  59. package/dist/components/NTabs.nexa +113 -0
  60. package/dist/components/NTag.js +108 -0
  61. package/dist/components/NTag.nexa +93 -0
  62. package/dist/components/NToastContainer.js +242 -0
  63. package/dist/components/NToastContainer.nexa +221 -0
  64. package/dist/components/NTooltip.js +163 -0
  65. package/dist/components/NTooltip.nexa +166 -0
  66. package/dist/components/NTreeMenu.js +151 -0
  67. package/dist/components/NTreeMenu.nexa +142 -0
  68. package/dist/index.d.ts +32 -0
  69. package/dist/index.js +34 -0
  70. package/dist/services/FloatingOverlay.d.ts +27 -0
  71. package/dist/services/FloatingOverlay.js +98 -0
  72. package/dist/services/FormValidation.d.ts +8 -0
  73. package/dist/services/FormValidation.js +46 -0
  74. package/dist/services/ToastService.d.ts +16 -0
  75. package/dist/services/ToastService.js +26 -0
  76. package/dist/styles/theme.d.ts +1 -0
  77. package/dist/styles/theme.js +144 -0
  78. package/package.json +32 -0
  79. package/src/components/NAlert.nexa +115 -0
  80. package/src/components/NAutocomplete.nexa +58 -0
  81. package/src/components/NAvatar.nexa +67 -0
  82. package/src/components/NBadge.nexa +61 -0
  83. package/src/components/NBottomSheet.nexa +145 -0
  84. package/src/components/NButton.nexa +275 -0
  85. package/src/components/NCard.nexa +100 -0
  86. package/src/components/NCheckbox.nexa +90 -0
  87. package/src/components/NChips.nexa +57 -0
  88. package/src/components/NDataTable.nexa +186 -0
  89. package/src/components/NDatepicker.nexa +367 -0
  90. package/src/components/NForm.nexa +133 -0
  91. package/src/components/NFormField.nexa +171 -0
  92. package/src/components/NInput.nexa +311 -0
  93. package/src/components/NInputNumber.nexa +199 -0
  94. package/src/components/NModal.nexa +221 -0
  95. package/src/components/NMultiSelect.nexa +77 -0
  96. package/src/components/NPaginator.nexa +77 -0
  97. package/src/components/NPassword.nexa +178 -0
  98. package/src/components/NProgressBar.nexa +111 -0
  99. package/src/components/NRadio.nexa +81 -0
  100. package/src/components/NSelect.nexa +452 -0
  101. package/src/components/NSkeleton.nexa +74 -0
  102. package/src/components/NSwitch.nexa +76 -0
  103. package/src/components/NTabs.nexa +113 -0
  104. package/src/components/NTag.nexa +93 -0
  105. package/src/components/NToastContainer.nexa +221 -0
  106. package/src/components/NTooltip.nexa +166 -0
  107. package/src/components/NTreeMenu.nexa +142 -0
  108. package/src/index.ts +36 -0
  109. package/src/services/FloatingOverlay.ts +133 -0
  110. package/src/services/FormValidation.ts +44 -0
  111. package/src/services/ToastService.ts +41 -0
  112. package/src/shims.d.ts +5 -0
  113. package/src/styles/theme.ts +146 -0
  114. package/src/styles/tokens.css +170 -0
@@ -0,0 +1,173 @@
1
+ import { signal, computed, inject, provide, effect, onUnmounted, h, hText, defineComponent, registerComponent, reloadComponent, injectStyle } from 'nexa-framework'
2
+
3
+ const _sfc_main = defineComponent({
4
+ __scopeId: 'data-v-30bdb720',
5
+ __hmrId: 'NFormField_nexa',
6
+ props: {
7
+ name: { type: String, default: '' },
8
+ label: { type: String, default: '' },
9
+ help: { type: String, default: '' },
10
+ id: { type: String, default: '' },
11
+ modelValue: { type: null, default: '' },
12
+ rules: { type: Array, default: () => [] },
13
+ validateOn: { type: String, default: '' },
14
+ showError: { type: Boolean, default: true },
15
+ disabled: { type: Boolean, default: false }
16
+ },
17
+ emits: ['update:modelValue'],
18
+ setup(props, setupContext) {
19
+ const { emit, slots, slots: $slots } = setupContext
20
+ let nextAutoId = 1
21
+ const form = inject('nexa-ui:form', undefined)
22
+ const autoId = `n-field-${nextAutoId++}`
23
+ const inputId = computed(() => props.id || autoId)
24
+ const helpId = computed(() => `${inputId.value}-help`)
25
+ const errorId = computed(() => `${inputId.value}-error`)
26
+ const describedBy = computed(() => {
27
+ const parts = []
28
+ if (props.help) parts.push(helpId.value)
29
+ if (props.showError && error.value) parts.push(errorId.value)
30
+ return parts.join(' ') || undefined
31
+ })
32
+ const value = signal(props.modelValue)
33
+ const initialValue = signal(props.modelValue)
34
+ const touched = signal(false)
35
+ const pending = signal(false)
36
+ const errors = signal([])
37
+ const dirty = computed(() => value.value !== initialValue.value)
38
+ const error = computed(() => errors.value[0] || '')
39
+ const invalid = computed(() => errors.value.length > 0)
40
+ effect(() => {
41
+ if (props.modelValue === value.value) return
42
+ value.value = props.modelValue
43
+ })
44
+ const shouldValidateOn = (reason) => {
45
+ const mode = props.validateOn || form?.validateOn || 'submit'
46
+ if (mode === 'change' && (reason === 'change' || reason === 'input')) return true
47
+ if (mode === 'blur' && reason === 'blur') return true
48
+ if (mode === 'submit' && reason === 'submit') return true
49
+ return false
50
+ }
51
+ const validate = async (reason = 'submit') => {
52
+ if (!shouldValidateOn(reason) && reason !== 'submit') return errors.value
53
+ if (form?.disabled || props.disabled) return []
54
+ const rules = Array.isArray(props.rules) ? props.rules : []
55
+ if (rules.length === 0) {
56
+ errors.value = []
57
+ return []
58
+ }
59
+ pending.value = true
60
+ const nextErrors = []
61
+ const values = form?.getValues ? form.getValues() : { [props.name]: value.value }
62
+ for (const rule of rules) {
63
+ if (!rule) continue
64
+ const res = await rule(value.value, values)
65
+ if (!res) continue
66
+ nextErrors.push(String(res))
67
+ }
68
+ errors.value = nextErrors
69
+ pending.value = false
70
+ return nextErrors
71
+ }
72
+ const setValue = (next) => {
73
+ if (form?.disabled || props.disabled) return
74
+ value.value = next
75
+ emit('update:modelValue', next)
76
+ validate('change')
77
+ }
78
+ const onBlur = () => {
79
+ touched.value = true
80
+ validate('blur')
81
+ }
82
+ provide('nexa-ui:form-field', {
83
+ inputId,
84
+ describedBy,
85
+ invalid,
86
+ error,
87
+ errors,
88
+ touched,
89
+ dirty,
90
+ pending,
91
+ value,
92
+ setValue,
93
+ onBlur,
94
+ disabled: computed(() => !!(props.disabled || form?.disabled)),
95
+ })
96
+ const reset = () => {
97
+ touched.value = false
98
+ errors.value = []
99
+ pending.value = false
100
+ initialValue.value = props.modelValue
101
+ value.value = props.modelValue
102
+ }
103
+ let unregister = null
104
+ if (form?.registerField && props.name) {
105
+ unregister = form.registerField(props.name, { value, touched, dirty, errors, pending, validate, reset })
106
+ }
107
+ onUnmounted(() => {
108
+ if (unregister) unregister()
109
+ })
110
+ return { 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 }
111
+ }
112
+ })
113
+ // Injected render function
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
116
+ return h('div', { class: ["n-form-field", { 'is-invalid': invalid.value, 'is-disabled': disabled, 'is-pending': pending.value }], "data-v-30bdb720": "" }, [
117
+ "\n ",
118
+ (label) ? h('label', { class: "n-form-field-label", for: inputId.value, "data-v-30bdb720": "" }, [
119
+ label
120
+ ]) : null,
121
+ h('div', { class: "n-form-field-control", "data-v-30bdb720": "" }, [
122
+ "\n ",
123
+ ctx.$slots.default ? ctx.$slots.default() : null,
124
+ "\n "
125
+ ]),
126
+ "\n ",
127
+ (help) ? h('div', { class: "n-form-field-help", id: helpId.value, "data-v-30bdb720": "" }, [
128
+ help
129
+ ]) : null,
130
+ (showError && error.value) ? h('div', { class: "n-form-field-error", id: errorId.value, "data-v-30bdb720": "" }, [
131
+ error.value
132
+ ]) : null
133
+ ])
134
+ }
135
+ _sfc_main.__scopeId = 'data-v-30bdb720'
136
+ _sfc_main.__hmrId = 'NFormField_nexa'
137
+
138
+ export default _sfc_main
139
+
140
+ const __style = `.n-form-field[data-v-30bdb720]{
141
+ display: flex;
142
+ flex-direction: column;
143
+ gap: var(--n-space-2);
144
+ width: 100%;
145
+ }
146
+
147
+ .n-form-field-label[data-v-30bdb720]{
148
+ font-size: var(--n-text-sm);
149
+ font-weight: var(--n-weight-semibold);
150
+ color: var(--n-color-text-secondary);
151
+ margin-left: var(--n-space-1);
152
+ }
153
+
154
+ .n-form-field-control[data-v-30bdb720]{
155
+ width: 100%;
156
+ }
157
+
158
+ .n-form-field-help[data-v-30bdb720]{
159
+ font-size: var(--n-text-xs);
160
+ color: var(--n-color-text-muted);
161
+ padding: 0 var(--n-space-1);
162
+ }
163
+
164
+ .n-form-field-error[data-v-30bdb720]{
165
+ font-size: var(--n-text-xs);
166
+ color: var(--n-color-danger);
167
+ padding: 0 var(--n-space-1);
168
+ }
169
+
170
+ .is-disabled[data-v-30bdb720]{
171
+ opacity: 0.6;
172
+ }`
173
+ injectStyle('data-v-30bdb720', __style)
@@ -0,0 +1,171 @@
1
+ <script setup>
2
+ import { signal, computed, inject, provide, effect, onUnmounted } from 'nexa-framework'
3
+
4
+ let nextAutoId = 1
5
+
6
+ const props = defineProps({
7
+ name: { type: String, default: '' },
8
+ label: { type: String, default: '' },
9
+ help: { type: String, default: '' },
10
+ id: { type: String, default: '' },
11
+ modelValue: { type: null, default: '' },
12
+ rules: { type: Array, default: () => [] },
13
+ validateOn: { type: String, default: '' },
14
+ showError: { type: Boolean, default: true },
15
+ disabled: { type: Boolean, default: false }
16
+ })
17
+
18
+ const emit = defineEmits(['update:modelValue'])
19
+
20
+ const form = inject('nexa-ui:form', undefined)
21
+ const autoId = `n-field-${nextAutoId++}`
22
+
23
+ const inputId = computed(() => props.id || autoId)
24
+ const helpId = computed(() => `${inputId.value}-help`)
25
+ const errorId = computed(() => `${inputId.value}-error`)
26
+ const describedBy = computed(() => {
27
+ const parts = []
28
+ if (props.help) parts.push(helpId.value)
29
+ if (props.showError && error.value) parts.push(errorId.value)
30
+ return parts.join(' ') || undefined
31
+ })
32
+
33
+ const value = signal(props.modelValue)
34
+ const initialValue = signal(props.modelValue)
35
+ const touched = signal(false)
36
+ const pending = signal(false)
37
+ const errors = signal([])
38
+
39
+ const dirty = computed(() => value.value !== initialValue.value)
40
+ const error = computed(() => errors.value[0] || '')
41
+ const invalid = computed(() => errors.value.length > 0)
42
+
43
+ effect(() => {
44
+ if (props.modelValue === value.value) return
45
+ value.value = props.modelValue
46
+ })
47
+
48
+ const shouldValidateOn = (reason) => {
49
+ const mode = props.validateOn || form?.validateOn || 'submit'
50
+ if (mode === 'change' && (reason === 'change' || reason === 'input')) return true
51
+ if (mode === 'blur' && reason === 'blur') return true
52
+ if (mode === 'submit' && reason === 'submit') return true
53
+ return false
54
+ }
55
+
56
+ const validate = async (reason = 'submit') => {
57
+ if (!shouldValidateOn(reason) && reason !== 'submit') return errors.value
58
+ if (form?.disabled || props.disabled) return []
59
+ const rules = Array.isArray(props.rules) ? props.rules : []
60
+ if (rules.length === 0) {
61
+ errors.value = []
62
+ return []
63
+ }
64
+
65
+ pending.value = true
66
+ const nextErrors = []
67
+ const values = form?.getValues ? form.getValues() : { [props.name]: value.value }
68
+
69
+ for (const rule of rules) {
70
+ if (!rule) continue
71
+ const res = await rule(value.value, values)
72
+ if (!res) continue
73
+ nextErrors.push(String(res))
74
+ }
75
+
76
+ errors.value = nextErrors
77
+ pending.value = false
78
+ return nextErrors
79
+ }
80
+
81
+ const setValue = (next) => {
82
+ if (form?.disabled || props.disabled) return
83
+ value.value = next
84
+ emit('update:modelValue', next)
85
+ validate('change')
86
+ }
87
+
88
+ const onBlur = () => {
89
+ touched.value = true
90
+ validate('blur')
91
+ }
92
+
93
+ provide('nexa-ui:form-field', {
94
+ inputId,
95
+ describedBy,
96
+ invalid,
97
+ error,
98
+ errors,
99
+ touched,
100
+ dirty,
101
+ pending,
102
+ value,
103
+ setValue,
104
+ onBlur,
105
+ disabled: computed(() => !!(props.disabled || form?.disabled)),
106
+ })
107
+
108
+ const reset = () => {
109
+ touched.value = false
110
+ errors.value = []
111
+ pending.value = false
112
+ initialValue.value = props.modelValue
113
+ value.value = props.modelValue
114
+ }
115
+
116
+ let unregister = null
117
+ if (form?.registerField && props.name) {
118
+ unregister = form.registerField(props.name, { value, touched, dirty, errors, pending, validate, reset })
119
+ }
120
+
121
+ onUnmounted(() => {
122
+ if (unregister) unregister()
123
+ })
124
+ </script>
125
+
126
+ <template>
127
+ <div class="n-form-field" :class="{ 'is-invalid': invalid.value, 'is-disabled': disabled, 'is-pending': pending.value }">
128
+ <label v-if="label" class="n-form-field-label" :for="inputId.value">{{ label }}</label>
129
+ <div class="n-form-field-control">
130
+ <slot />
131
+ </div>
132
+ <div v-if="help" :id="helpId.value" class="n-form-field-help">{{ help }}</div>
133
+ <div v-if="showError && error.value" :id="errorId.value" class="n-form-field-error">{{ error.value }}</div>
134
+ </div>
135
+ </template>
136
+
137
+ <style scoped>
138
+ .n-form-field {
139
+ display: flex;
140
+ flex-direction: column;
141
+ gap: var(--n-space-2);
142
+ width: 100%;
143
+ }
144
+
145
+ .n-form-field-label {
146
+ font-size: var(--n-text-sm);
147
+ font-weight: var(--n-weight-semibold);
148
+ color: var(--n-color-text-secondary);
149
+ margin-left: var(--n-space-1);
150
+ }
151
+
152
+ .n-form-field-control {
153
+ width: 100%;
154
+ }
155
+
156
+ .n-form-field-help {
157
+ font-size: var(--n-text-xs);
158
+ color: var(--n-color-text-muted);
159
+ padding: 0 var(--n-space-1);
160
+ }
161
+
162
+ .n-form-field-error {
163
+ font-size: var(--n-text-xs);
164
+ color: var(--n-color-danger);
165
+ padding: 0 var(--n-space-1);
166
+ }
167
+
168
+ .is-disabled {
169
+ opacity: 0.6;
170
+ }
171
+ </style>
@@ -0,0 +1,311 @@
1
+ import { signal, computed, inject, effect, h, hText, defineComponent, registerComponent, reloadComponent, injectStyle } from 'nexa-framework'
2
+
3
+ const _sfc_main = defineComponent({
4
+ __scopeId: 'data-v-7dbed0f8',
5
+ __hmrId: 'NInput_nexa',
6
+ props: {
7
+ modelValue: { type: [String, Number], default: '' },
8
+ type: { type: String, default: 'text' },
9
+ placeholder: { type: String, default: '' },
10
+ label: { type: String, default: '' },
11
+ error: { type: String, default: '' },
12
+ id: { type: String, default: '' },
13
+ name: { type: String, default: '' },
14
+ autocomplete: { type: String, default: '' },
15
+ ariaDescribedby: { type: String, default: '' },
16
+ ariaInvalid: { type: [Boolean, String], default: false },
17
+ bindField: { type: Boolean, default: false },
18
+ disabled: { type: Boolean, default: false },
19
+ readonly: { type: Boolean, default: false },
20
+ clearable: { type: Boolean, default: false },
21
+ maxlength: { type: Number, default: 0 },
22
+ prefixIcon: { type: String, default: '' },
23
+ suffixIcon: { type: String, default: '' }
24
+ },
25
+ emits: ['update:modelValue', 'clear', 'focus', 'blur'],
26
+ setup(props, setupContext) {
27
+ const { emit, slots, slots: $slots } = setupContext
28
+ const field = inject('nexa-ui:form-field', undefined)
29
+ const showPassword = signal(false)
30
+ const isFocused = signal(false)
31
+ const effectiveValue = computed(() => {
32
+ if (props.bindField && field?.value) return field.value.value
33
+ return props.modelValue
34
+ })
35
+ const draft = signal(String(effectiveValue.value ?? ''))
36
+ effect(() => {
37
+ const next = String(effectiveValue.value ?? '')
38
+ if (draft.value === next) return
39
+ draft.value = next
40
+ })
41
+ const effectiveId = computed(() => {
42
+ if (props.id) return props.id
43
+ if (props.bindField && field?.inputId) return field.inputId.value
44
+ return ''
45
+ })
46
+ const effectiveDescribedBy = computed(() => {
47
+ if (props.ariaDescribedby) return props.ariaDescribedby
48
+ if (props.bindField && field?.describedBy) return field.describedBy.value || ''
49
+ return ''
50
+ })
51
+ const effectiveInvalid = computed(() => {
52
+ if (props.bindField && field?.invalid) return field.invalid.value
53
+ return props.ariaInvalid
54
+ })
55
+ const effectiveError = computed(() => {
56
+ if (props.error) return props.error
57
+ if (props.bindField && field?.error) return field.error.value || ''
58
+ return ''
59
+ })
60
+ const effectiveDisabled = computed(() => {
61
+ if (props.disabled) return true
62
+ if (props.bindField && field?.disabled) return !!field.disabled.value
63
+ return false
64
+ })
65
+ const inputType = computed(() => {
66
+ if (props.type === 'password' && showPassword.value) return 'text'
67
+ return props.type
68
+ })
69
+ const currentLength = computed(() => draft.value.length)
70
+ const onInput = (e) => {
71
+ const next = e.target.value
72
+ if (draft.value !== next) draft.value = next
73
+ if (props.bindField && field?.setValue) {
74
+ field.setValue(next)
75
+ return
76
+ }
77
+ emit('update:modelValue', next)
78
+ }
79
+ const onFocus = () => {
80
+ isFocused.value = true
81
+ emit('focus')
82
+ }
83
+ const onBlur = () => {
84
+ isFocused.value = false
85
+ if (props.bindField && field?.onBlur) {
86
+ field.onBlur()
87
+ }
88
+ emit('blur')
89
+ }
90
+ const clear = () => {
91
+ if (draft.value) draft.value = ''
92
+ if (props.bindField && field?.setValue) {
93
+ field.setValue('')
94
+ emit('clear')
95
+ return
96
+ }
97
+ emit('update:modelValue', '')
98
+ emit('clear')
99
+ }
100
+ const togglePassword = () => {
101
+ showPassword.value = !showPassword.value
102
+ }
103
+ return { field, showPassword, isFocused, effectiveValue, draft, effectiveId, effectiveDescribedBy, effectiveInvalid, effectiveError, effectiveDisabled, inputType, currentLength, onInput, onFocus, onBlur, clear, togglePassword, inject, $slots, emit }
104
+ }
105
+ })
106
+ // Injected render function
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
109
+ return h('div', { class: "n-input-group", "data-v-7dbed0f8": "" }, [
110
+ "\n ",
111
+ (label) ? h('label', { class: "n-input-label", "data-v-7dbed0f8": "" }, [
112
+ label
113
+ ]) : null,
114
+ h('div', { class: ["n-input-wrapper", { 'is-focused': isFocused.value, 'has-error': effectiveError.value, 'is-disabled': effectiveDisabled.value }], "data-v-7dbed0f8": "" }, [
115
+ "\n ",
116
+ (prefixIcon) ? h('span', { class: "n-input-icon is-prefix", "data-v-7dbed0f8": "" }, [
117
+ prefixIcon
118
+ ]) : null,
119
+ h('input', { class: ["n-input", { 'has-prefix': !!prefixIcon, 'has-suffix': !!suffixIcon || clearable || type === 'password' }], id: effectiveId.value || undefined, name: name || undefined, type: inputType.value, value: draft.value, placeholder: placeholder, disabled: effectiveDisabled.value, readonly: readonly, autocomplete: autocomplete || undefined, "aria-describedby": effectiveDescribedBy.value || undefined, "aria-invalid": effectiveInvalid.value || undefined, maxlength: maxlength || undefined, onInput: onInput, onFocus: onFocus, onBlur: onBlur, "data-v-7dbed0f8": "" }),
120
+ "\n ",
121
+ h('div', { class: "n-input-focus-ring", "data-v-7dbed0f8": "" }),
122
+ "\n ",
123
+ h('div', { class: "n-input-actions", "data-v-7dbed0f8": "" }, [
124
+ "\n ",
125
+ (clearable && draft.value) ? h('button', { class: "n-input-action", onClick: clear, tabindex: "-1", type: "button", "data-v-7dbed0f8": "" }, [
126
+ "✕"
127
+ ]) : null,
128
+ (type === 'password') ? h('button', { class: "n-input-action", onClick: togglePassword, tabindex: "-1", type: "button", "data-v-7dbed0f8": "" }, [
129
+ "\n ",
130
+ showPassword.value ? '◉' : '◎',
131
+ "\n "
132
+ ]) : null,
133
+ (suffixIcon) ? h('span', { class: "n-input-icon is-suffix", "data-v-7dbed0f8": "" }, [
134
+ suffixIcon
135
+ ]) : null
136
+ ]),
137
+ "\n "
138
+ ]),
139
+ "\n ",
140
+ h('div', { class: "n-input-bottom", "data-v-7dbed0f8": "" }, [
141
+ "\n ",
142
+ (effectiveError.value) ? h('span', { class: "n-input-error-msg", "data-v-7dbed0f8": "" }, [
143
+ effectiveError.value
144
+ ]) : null,
145
+ (maxlength > 0) ? h('span', { class: "n-input-counter", "data-v-7dbed0f8": "" }, [
146
+ currentLength.value,
147
+ "/",
148
+ maxlength
149
+ ]) : null
150
+ ]),
151
+ "\n "
152
+ ])
153
+ }
154
+ _sfc_main.__scopeId = 'data-v-7dbed0f8'
155
+ _sfc_main.__hmrId = 'NInput_nexa'
156
+
157
+ export default _sfc_main
158
+
159
+ const __style = `.n-input-group[data-v-7dbed0f8]{
160
+ display: flex;
161
+ flex-direction: column;
162
+ gap: var(--n-space-2);
163
+ width: 100%;
164
+ }
165
+
166
+ .n-input-label[data-v-7dbed0f8]{
167
+ font-size: var(--n-text-sm);
168
+ font-weight: var(--n-weight-semibold);
169
+ color: var(--n-color-text-secondary);
170
+ margin-left: var(--n-space-1);
171
+ }
172
+
173
+ .n-input-wrapper[data-v-7dbed0f8]{
174
+ position: relative;
175
+ display: flex;
176
+ align-items: center;
177
+ transition: all var(--n-transition-fast);
178
+ }
179
+
180
+ .n-input[data-v-7dbed0f8]{
181
+ position: relative;
182
+ z-index: 1;
183
+ width: 100%;
184
+ min-height: 44px;
185
+ background: var(--n-color-bg);
186
+ border: 1px solid var(--n-color-border);
187
+ color: var(--n-color-text);
188
+ padding: 0.75rem 1rem;
189
+ border-radius: var(--n-radius-md);
190
+ font-family: inherit;
191
+ font-size: var(--n-text-base);
192
+ line-height: 1.2;
193
+ box-sizing: border-box;
194
+ transition: all var(--n-transition-normal);
195
+ outline: none;
196
+ }
197
+
198
+ .n-input.has-prefix[data-v-7dbed0f8]{
199
+ padding-left: 2.5rem;
200
+ }
201
+
202
+ .n-input.has-suffix[data-v-7dbed0f8]{
203
+ padding-right: 2.5rem;
204
+ }
205
+
206
+ .n-input[data-v-7dbed0f8]::placeholder{
207
+ color: var(--n-color-text-muted);
208
+ }
209
+
210
+ .n-input-focus-ring[data-v-7dbed0f8]{
211
+ position: absolute;
212
+ inset: 0;
213
+ border-radius: var(--n-radius-md);
214
+ background: linear-gradient(135deg, var(--n-color-primary), var(--n-color-info));
215
+ opacity: 0;
216
+ pointer-events: none;
217
+ transition: opacity var(--n-transition-normal);
218
+ z-index: 0;
219
+ }
220
+
221
+ .is-focused .n-input-focus-ring[data-v-7dbed0f8]{
222
+ opacity: 0.35;
223
+ }
224
+
225
+ .is-focused .n-input[data-v-7dbed0f8]{
226
+ border-color: var(--n-color-primary);
227
+ background: var(--n-color-surface);
228
+ }
229
+
230
+ .has-error .n-input[data-v-7dbed0f8]{
231
+ border-color: var(--n-color-danger);
232
+ }
233
+
234
+ .has-error .n-input-focus-ring[data-v-7dbed0f8]{
235
+ background: var(--n-color-danger);
236
+ opacity: 0.35;
237
+ }
238
+
239
+ .n-input-icon[data-v-7dbed0f8]{
240
+ position: absolute;
241
+ top: 50%;
242
+ transform: translateY(-50%);
243
+ color: var(--n-color-text-muted);
244
+ font-size: var(--n-text-sm);
245
+ pointer-events: none;
246
+ display: flex;
247
+ align-items: center;
248
+ line-height: 1;
249
+ }
250
+
251
+ .n-input-icon.is-prefix[data-v-7dbed0f8]{
252
+ left: 0.85rem;
253
+ }
254
+
255
+ .n-input-icon.is-suffix[data-v-7dbed0f8]{
256
+ right: 0.85rem;
257
+ }
258
+
259
+ .n-input-actions[data-v-7dbed0f8]{
260
+ position: absolute;
261
+ right: 0.5rem;
262
+ top: 50%;
263
+ transform: translateY(-50%);
264
+ display: flex;
265
+ align-items: center;
266
+ gap: 0.15rem;
267
+ }
268
+
269
+ .n-input-action[data-v-7dbed0f8]{
270
+ background: transparent;
271
+ border: none;
272
+ color: var(--n-color-text-muted);
273
+ cursor: pointer;
274
+ padding: 0.25rem;
275
+ font-size: var(--n-text-sm);
276
+ border-radius: var(--n-radius-sm);
277
+ transition: all var(--n-transition-fast);
278
+ display: flex;
279
+ align-items: center;
280
+ line-height: 1;
281
+ }
282
+
283
+ .n-input-action[data-v-7dbed0f8]:hover{
284
+ color: var(--n-color-text);
285
+ background: var(--n-color-glass);
286
+ }
287
+
288
+ .n-input-bottom[data-v-7dbed0f8]{
289
+ display: flex;
290
+ justify-content: space-between;
291
+ align-items: center;
292
+ padding: 0 var(--n-space-1);
293
+ }
294
+
295
+ .n-input-error-msg[data-v-7dbed0f8]{
296
+ font-size: var(--n-text-xs);
297
+ color: var(--n-color-danger);
298
+ }
299
+
300
+ .n-input-counter[data-v-7dbed0f8]{
301
+ font-size: var(--n-text-xs);
302
+ color: var(--n-color-text-muted);
303
+ margin-left: auto;
304
+ }
305
+
306
+ .is-disabled .n-input[data-v-7dbed0f8]{
307
+ opacity: 0.5;
308
+ cursor: not-allowed;
309
+ background: var(--n-color-surface-alt);
310
+ }`
311
+ injectStyle('data-v-7dbed0f8', __style)