nexa-ui-kit 0.11.6 → 0.11.9

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 (95) hide show
  1. package/dist/components/NAlert.js +2 -14
  2. package/dist/components/NAlert.nexa +3 -14
  3. package/dist/components/NAutocomplete.js +1 -1
  4. package/dist/components/NAutocomplete.nexa +2 -1
  5. package/dist/components/NAvatar.js +0 -5
  6. package/dist/components/NAvatar.nexa +1 -5
  7. package/dist/components/NBadge.js +0 -6
  8. package/dist/components/NBadge.nexa +1 -6
  9. package/dist/components/NBottomSheet.js +0 -5
  10. package/dist/components/NBottomSheet.nexa +1 -5
  11. package/dist/components/NButton.js +219 -296
  12. package/dist/components/NButton.nexa +241 -320
  13. package/dist/components/NCard.js +39 -82
  14. package/dist/components/NCard.nexa +27 -71
  15. package/dist/components/NCheckbox.js +74 -63
  16. package/dist/components/NCheckbox.nexa +64 -44
  17. package/dist/components/NChips.nexa +1 -0
  18. package/dist/components/NDataTable.js +300 -356
  19. package/dist/components/NDataTable.nexa +265 -320
  20. package/dist/components/NDatepicker.js +4 -25
  21. package/dist/components/NDatepicker.nexa +5 -25
  22. package/dist/components/NForm.nexa +1 -0
  23. package/dist/components/NFormField.js +0 -5
  24. package/dist/components/NFormField.nexa +1 -5
  25. package/dist/components/NImage.js +1 -6
  26. package/dist/components/NImage.nexa +2 -6
  27. package/dist/components/NInput.js +96 -263
  28. package/dist/components/NInput.nexa +89 -259
  29. package/dist/components/NInputNumber.nexa +1 -1
  30. package/dist/components/NModal.js +1 -118
  31. package/dist/components/NModal.nexa +2 -119
  32. package/dist/components/NMultiSelect.js +1 -1
  33. package/dist/components/NMultiSelect.nexa +2 -1
  34. package/dist/components/NPaginator.js +1 -11
  35. package/dist/components/NPaginator.nexa +2 -11
  36. package/dist/components/NPassword.nexa +1 -0
  37. package/dist/components/NProgressBar.js +0 -11
  38. package/dist/components/NProgressBar.nexa +1 -11
  39. package/dist/components/NRadio.js +1 -8
  40. package/dist/components/NRadio.nexa +2 -8
  41. package/dist/components/NScrollView.js +0 -6
  42. package/dist/components/NScrollView.nexa +1 -6
  43. package/dist/components/NSelect.js +7 -35
  44. package/dist/components/NSelect.nexa +8 -35
  45. package/dist/components/NSkeleton.js +3 -9
  46. package/dist/components/NSkeleton.nexa +4 -9
  47. package/dist/components/NSwitch.js +0 -6
  48. package/dist/components/NSwitch.nexa +1 -6
  49. package/dist/components/NTabs.js +0 -11
  50. package/dist/components/NTabs.nexa +1 -11
  51. package/dist/components/NTag.js +1 -11
  52. package/dist/components/NTag.nexa +2 -11
  53. package/dist/components/NToastContainer.js +3 -27
  54. package/dist/components/NToastContainer.nexa +4 -27
  55. package/dist/components/NTooltip.js +0 -13
  56. package/dist/components/NTooltip.nexa +1 -13
  57. package/dist/components/NTreeMenu.js +1 -21
  58. package/dist/components/NTreeMenu.nexa +2 -21
  59. package/dist/components/NVirtualList.js +0 -2
  60. package/dist/components/NVirtualList.nexa +1 -2
  61. package/dist/styles/tokens.css +82 -173
  62. package/package.json +5 -5
  63. package/src/components/NAlert.nexa +3 -14
  64. package/src/components/NAutocomplete.nexa +2 -1
  65. package/src/components/NAvatar.nexa +1 -5
  66. package/src/components/NBadge.nexa +1 -6
  67. package/src/components/NBottomSheet.nexa +1 -5
  68. package/src/components/NButton.nexa +241 -320
  69. package/src/components/NCard.nexa +27 -71
  70. package/src/components/NCheckbox.nexa +64 -44
  71. package/src/components/NChips.nexa +1 -0
  72. package/src/components/NDataTable.nexa +265 -320
  73. package/src/components/NDatepicker.nexa +5 -25
  74. package/src/components/NForm.nexa +1 -0
  75. package/src/components/NFormField.nexa +1 -5
  76. package/src/components/NImage.nexa +2 -6
  77. package/src/components/NInput.nexa +89 -259
  78. package/src/components/NInputNumber.nexa +1 -1
  79. package/src/components/NModal.nexa +2 -119
  80. package/src/components/NMultiSelect.nexa +2 -1
  81. package/src/components/NPaginator.nexa +2 -11
  82. package/src/components/NPassword.nexa +1 -0
  83. package/src/components/NProgressBar.nexa +1 -11
  84. package/src/components/NRadio.nexa +2 -8
  85. package/src/components/NScrollView.nexa +1 -6
  86. package/src/components/NSelect.nexa +8 -35
  87. package/src/components/NSkeleton.nexa +4 -9
  88. package/src/components/NSwitch.nexa +1 -6
  89. package/src/components/NTabs.nexa +1 -11
  90. package/src/components/NTag.nexa +2 -11
  91. package/src/components/NToastContainer.nexa +4 -27
  92. package/src/components/NTooltip.nexa +1 -13
  93. package/src/components/NTreeMenu.nexa +2 -21
  94. package/src/components/NVirtualList.nexa +1 -2
  95. package/src/styles/tokens.css +82 -173
@@ -233,25 +233,20 @@ onBeforeUnmount(() => {
233
233
  display: inline-block;
234
234
  font-family: var(--n-font-sans);
235
235
  }
236
-
237
236
  .n-datepicker-input {
238
237
  position: relative;
239
238
  cursor: pointer;
240
239
  }
241
-
242
240
  .n-datepicker-input .n-input {
243
241
  cursor: pointer;
244
242
  }
245
-
246
243
  .n-datepicker-icon {
247
244
  position: absolute;
248
245
  right: 0.75rem;
249
246
  top: 50%;
250
- transform: translateY(-50%);
251
247
  font-size: 1rem;
252
248
  pointer-events: none;
253
249
  }
254
-
255
250
  .n-datepicker-dropdown {
256
251
  position: absolute;
257
252
  top: calc(100% + 4px);
@@ -265,34 +260,28 @@ onBeforeUnmount(() => {
265
260
  width: 280px;
266
261
  animation: fade-in 0.15s ease;
267
262
  }
268
-
269
263
  @keyframes fade-in {
270
- from { opacity: 0; transform: translateY(-4px); }
271
- to { opacity: 1; transform: translateY(0); }
264
+ from { opacity: 0; }
265
+ to { opacity: 1; }
272
266
  }
273
-
274
267
  .n-datepicker-dropdown.is-top {
275
268
  animation: fade-in-top 0.15s ease;
276
269
  }
277
-
278
270
  @keyframes fade-in-top {
279
- from { opacity: 0; transform: translateY(4px); }
280
- to { opacity: 1; transform: translateY(0); }
271
+ from { opacity: 0; }
272
+ to { opacity: 1; }
281
273
  }
282
-
283
274
  .n-datepicker-header {
284
275
  display: flex;
285
276
  align-items: center;
286
277
  justify-content: space-between;
287
278
  margin-bottom: 0.75rem;
288
279
  }
289
-
290
280
  .n-datepicker-title {
291
281
  font-weight: var(--n-weight-semibold);
292
282
  font-size: var(--n-text-sm);
293
283
  color: var(--n-color-text);
294
284
  }
295
-
296
285
  .n-datepicker-nav {
297
286
  background: none;
298
287
  border: 1px solid var(--n-color-border);
@@ -307,18 +296,15 @@ onBeforeUnmount(() => {
307
296
  justify-content: center;
308
297
  transition: all var(--n-transition-fast);
309
298
  }
310
-
311
299
  .n-datepicker-nav:hover {
312
300
  background: var(--n-color-surface-hover);
313
301
  color: var(--n-color-text);
314
302
  }
315
-
316
303
  .n-datepicker-grid {
317
304
  display: grid;
318
305
  grid-template-columns: repeat(7, 1fr);
319
306
  gap: 2px;
320
307
  }
321
-
322
308
  .n-datepicker-day-header {
323
309
  text-align: center;
324
310
  font-size: var(--n-text-xs);
@@ -326,7 +312,6 @@ onBeforeUnmount(() => {
326
312
  font-weight: var(--n-weight-semibold);
327
313
  padding: 0.35rem 0;
328
314
  }
329
-
330
315
  .n-datepicker-day {
331
316
  text-align: center;
332
317
  padding: 0.4rem 0;
@@ -336,32 +321,27 @@ onBeforeUnmount(() => {
336
321
  cursor: pointer;
337
322
  transition: all var(--n-transition-fast);
338
323
  }
339
-
340
324
  .n-datepicker-day:hover:not(.is-empty) {
341
325
  background: var(--n-color-primary-light);
342
326
  }
343
-
344
327
  .n-datepicker-day.is-empty {
345
328
  cursor: default;
346
329
  }
347
-
348
330
  .n-datepicker-day.is-disabled {
349
331
  opacity: 0.4;
350
332
  cursor: not-allowed;
351
333
  }
352
-
353
334
  .n-datepicker-day.is-disabled:hover {
354
335
  background: transparent;
355
336
  }
356
-
357
337
  .n-datepicker-day.is-today {
358
338
  font-weight: var(--n-weight-bold);
359
339
  color: var(--n-color-primary);
360
340
  }
361
-
362
341
  .n-datepicker-day.is-selected {
363
342
  background: var(--n-color-primary);
364
343
  color: white;
365
344
  font-weight: var(--n-weight-semibold);
366
345
  }
346
+
367
347
  </style>
@@ -130,4 +130,5 @@ provide('nexa-ui:form', {
130
130
  gap: var(--n-space-4);
131
131
  width: 100%;
132
132
  }
133
+
133
134
  </style>
@@ -141,31 +141,27 @@ onUnmounted(() => {
141
141
  gap: var(--n-space-2);
142
142
  width: 100%;
143
143
  }
144
-
145
144
  .n-form-field-label {
146
145
  font-size: var(--n-text-sm);
147
146
  font-weight: var(--n-weight-semibold);
148
147
  color: var(--n-color-text-secondary);
149
148
  margin-left: var(--n-space-1);
150
149
  }
151
-
152
150
  .n-form-field-control {
153
151
  width: 100%;
154
152
  }
155
-
156
153
  .n-form-field-help {
157
154
  font-size: var(--n-text-xs);
158
155
  color: var(--n-color-text-muted);
159
156
  padding: 0 var(--n-space-1);
160
157
  }
161
-
162
158
  .n-form-field-error {
163
159
  font-size: var(--n-text-xs);
164
160
  color: var(--n-color-danger);
165
161
  padding: 0 var(--n-space-1);
166
162
  }
167
-
168
163
  .is-disabled {
169
164
  opacity: 0.6;
170
165
  }
166
+
171
167
  </style>
@@ -90,28 +90,24 @@ const onError = () => { error.value = true; loaded.value = true }
90
90
  background: var(--n-color-surface-hover, #1a1a2e);
91
91
  display: inline-block;
92
92
  }
93
-
94
93
  .n-image-skeleton {
95
94
  position: absolute;
96
95
  inset: 0;
97
- background: linear-gradient(
98
- 90deg,
99
- var(--n-color-surface, #111827) 25%,
96
+ background-color: var(--n-color-surface); 25%,
100
97
  var(--n-color-surface-hover, #1f2937) 50%,
101
98
  var(--n-color-surface, #111827) 75%
102
99
  );
103
100
  background-size: 200% 100%;
104
101
  animation: n-img-shimmer 1.5s infinite;
105
102
  }
106
-
107
103
  @keyframes n-img-shimmer {
108
104
  0% { background-position: 200% 0; }
109
105
  100% { background-position: -200% 0; }
110
106
  }
111
-
112
107
  .n-image {
113
108
  display: block;
114
109
  position: relative;
115
110
  z-index: 1;
116
111
  }
112
+
117
113
  </style>
@@ -1,5 +1,5 @@
1
1
  <script setup>
2
- import { signal, computed, inject, effect } from 'nexa-framework'
2
+ import { signal, computed } from 'nexa-framework'
3
3
 
4
4
  const props = defineProps({
5
5
  modelValue: { type: [String, Number], default: '' },
@@ -7,327 +7,157 @@ const props = defineProps({
7
7
  placeholder: { type: String, default: '' },
8
8
  label: { type: String, default: '' },
9
9
  error: { type: String, default: '' },
10
- id: { type: String, default: '' },
11
- name: { type: String, default: '' },
12
- autocomplete: { type: String, default: '' },
13
- ariaDescribedby: { type: String, default: '' },
14
- ariaInvalid: { type: [Boolean, String], default: false },
15
- bindField: { type: Boolean, default: false },
16
10
  disabled: { type: Boolean, default: false },
17
11
  readonly: { type: Boolean, default: false },
12
+ required: { type: Boolean, default: false },
18
13
  clearable: { type: Boolean, default: false },
19
- maxlength: { type: Number, default: 0 },
20
- prefixIcon: { type: String, default: '' },
21
- suffixIcon: { type: String, default: '' }
14
+ prefix: { type: String, default: '' },
15
+ suffix: { type: String, default: '' }
22
16
  })
23
17
 
24
- const emit = defineEmits(['update:modelValue', 'clear', 'focus', 'blur'])
18
+ const emit = defineEmits(['update:modelValue', 'focus', 'blur', 'clear'])
25
19
 
26
- const field = inject('nexa-ui:form-field', undefined)
27
-
28
- const showPassword = signal(false)
29
20
  const isFocused = signal(false)
30
21
 
31
- const effectiveValue = computed(() => {
32
- if (props.bindField && field?.value) return field.value.value
33
- return props.modelValue
34
- })
35
-
36
- const draft = signal(String(effectiveValue.value ?? ''))
37
-
38
- effect(() => {
39
- const next = String(effectiveValue.value ?? '')
40
- if (draft.value === next) return
41
- draft.value = next
42
- })
43
-
44
- const effectiveId = computed(() => {
45
- if (props.id) return props.id
46
- if (props.bindField && field?.inputId) return field.inputId.value
47
- return ''
48
- })
49
-
50
- const effectiveDescribedBy = computed(() => {
51
- if (props.ariaDescribedby) return props.ariaDescribedby
52
- if (props.bindField && field?.describedBy) return field.describedBy.value || ''
53
- return ''
54
- })
55
-
56
- const effectiveInvalid = computed(() => {
57
- if (props.bindField && field?.invalid) return field.invalid.value
58
- return props.ariaInvalid
59
- })
60
-
61
- const effectiveError = computed(() => {
62
- if (props.error) return props.error
63
- if (props.bindField && field?.error) return field.error.value || ''
64
- return ''
65
- })
66
-
67
- const effectiveDisabled = computed(() => {
68
- if (props.disabled) return true
69
- if (props.bindField && field?.disabled) return !!field.disabled.value
70
- return false
71
- })
72
-
73
- const inputType = computed(() => {
74
- if (props.type === 'password' && showPassword.value) return 'text'
75
- return props.type
76
- })
77
-
78
- const currentLength = computed(() => draft.value.length)
79
-
80
- const onInput = (e) => {
81
- const next = e.target.value
82
- if (draft.value !== next) draft.value = next
83
- if (props.bindField && field?.setValue) {
84
- field.setValue(next)
85
- return
86
- }
87
- emit('update:modelValue', next)
22
+ const handleInput = (e) => {
23
+ emit('update:modelValue', e.target.value)
88
24
  }
89
25
 
90
- const onFocus = () => {
26
+ const handleFocus = (e) => {
91
27
  isFocused.value = true
92
- emit('focus')
28
+ emit('focus', e)
93
29
  }
94
30
 
95
- const onBlur = () => {
31
+ const handleBlur = (e) => {
96
32
  isFocused.value = false
97
- if (props.bindField && field?.onBlur) {
98
- field.onBlur()
99
- }
100
- emit('blur')
33
+ emit('blur', e)
101
34
  }
102
35
 
103
- const clear = () => {
104
- if (draft.value) draft.value = ''
105
- if (props.bindField && field?.setValue) {
106
- field.setValue('')
107
- emit('clear')
108
- return
109
- }
36
+ const handleClear = () => {
110
37
  emit('update:modelValue', '')
111
38
  emit('clear')
112
39
  }
113
-
114
- const togglePassword = () => {
115
- showPassword.value = !showPassword.value
116
- }
117
40
  </script>
118
41
 
119
42
  <template>
120
- <div class="n-input-group">
121
- <label v-if="label" class="n-input-label">{{ label }}</label>
122
- <div class="n-input-wrapper" :class="{ 'is-focused': isFocused.value, 'has-error': effectiveError.value, 'is-disabled': effectiveDisabled.value }">
123
- <span v-if="prefixIcon" class="n-input-icon is-prefix">{{ prefixIcon }}</span>
43
+ <div class="n-input-wrapper" :class="{ 'is-focused': isFocused, 'is-error': error, 'is-disabled': disabled }">
44
+ <label v-if="label" class="n-input-label">
45
+ {{ label }}
46
+ <span v-if="required" class="n-input-required">*</span>
47
+ </label>
48
+ <div class="n-input-container">
49
+ <span v-if="prefix" class="n-input-prefix">{{ prefix }}</span>
124
50
  <input
125
- :id="effectiveId.value || undefined"
126
- :name="name || undefined"
127
- :type="inputType.value"
128
- :value="draft.value"
51
+ :type="type"
52
+ :value="modelValue"
129
53
  :placeholder="placeholder"
130
- :disabled="effectiveDisabled.value"
54
+ :disabled="disabled"
131
55
  :readonly="readonly"
132
- :autocomplete="autocomplete || undefined"
133
- :aria-describedby="effectiveDescribedBy.value || undefined"
134
- :aria-invalid="effectiveInvalid.value || undefined"
135
- :maxlength="maxlength || undefined"
56
+ :required="required"
136
57
  class="n-input"
137
- :class="{ 'has-prefix': !!prefixIcon, 'has-suffix': !!suffixIcon || clearable || type === 'password' }"
138
- @input="onInput"
139
- @focus="onFocus"
140
- @blur="onBlur"
58
+ @input="handleInput"
59
+ @focus="handleFocus"
60
+ @blur="handleBlur"
141
61
  />
142
- <div class="n-input-focus-ring"></div>
143
- <div class="n-input-actions">
144
- <button v-if="clearable && draft.value" class="n-input-action" @click="clear" tabindex="-1" type="button" aria-label="Clear"><svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" focusable="false" aria-hidden="true"><path d="M18 6L6 18"/><path d="M6 6l12 12"/></svg></button>
145
- <button v-if="type === 'password'" class="n-input-action" @click="togglePassword" tabindex="-1" type="button" :aria-label="showPassword.value ? 'Hide password' : 'Show password'">
146
- <svg v-if="!showPassword.value" viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" focusable="false" aria-hidden="true"><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/><circle cx="12" cy="12" r="3"/></svg>
147
- <svg v-else viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" focusable="false" aria-hidden="true"><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/><circle cx="12" cy="12" r="3"/><path d="M23 1L1 23"/></svg>
148
- </button>
149
- <span v-if="suffixIcon" class="n-input-icon is-suffix">{{ suffixIcon }}</span>
150
- </div>
151
- </div>
152
- <div class="n-input-bottom">
153
- <span v-if="effectiveError.value" class="n-input-error-msg">{{ effectiveError.value }}</span>
154
- <span v-if="maxlength > 0" class="n-input-counter">{{ currentLength.value }}/{{ maxlength }}</span>
62
+ <button v-if="clearable && modelValue" class="n-input-clear" @click="handleClear" type="button">
63
+ <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round">
64
+ <line x1="18" y1="6" x2="6" y2="18"/>
65
+ <line x1="6" y1="6" x2="18" y2="18"/>
66
+ </svg>
67
+ </button>
68
+ <span v-if="suffix" class="n-input-suffix">{{ suffix }}</span>
155
69
  </div>
70
+ <span v-if="error" class="n-input-error">{{ error }}</span>
156
71
  </div>
157
72
  </template>
158
73
 
159
74
  <style scoped>
160
- .n-input-group {
75
+ .n-input-wrapper {
161
76
  display: flex;
162
77
  flex-direction: column;
163
- gap: var(--n-space-2);
78
+ gap: 0.5rem;
164
79
  width: 100%;
165
80
  }
166
-
167
81
  .n-input-label {
168
- font-size: var(--n-text-sm);
169
- font-weight: var(--n-weight-medium);
170
- color: var(--n-color-text-secondary);
171
- margin-left: var(--n-space-1);
172
- letter-spacing: 0.01em;
82
+ font-size: 0.875rem;
83
+ font-weight: 500;
84
+ color: var(--n-color-text);
85
+ letter-spacing: normal;
173
86
  }
174
-
175
- .n-input-wrapper {
87
+ .n-input-required {
88
+ color: var(--n-color-danger);
89
+ margin-left: 0.25rem;
90
+ }
91
+ .n-input-container {
176
92
  position: relative;
177
93
  display: flex;
178
94
  align-items: center;
179
- transition: all var(--n-transition-fast);
180
- }
181
-
182
- .n-input {
183
- position: relative;
184
- z-index: 1;
185
- width: 100%;
186
- min-height: 44px;
187
- background: var(--n-color-bg);
95
+ background-color: var(--n-color-surface);
188
96
  border: 1px solid var(--n-color-border);
189
- color: var(--n-color-text);
190
- padding: 0.75rem 1.125rem;
191
97
  border-radius: var(--n-radius-md);
192
- font-family: inherit;
193
- font-size: var(--n-text-base);
194
- line-height: 1.2;
195
- box-sizing: border-box;
196
- transition: all var(--n-transition-normal) cubic-bezier(0.16, 1, 0.3, 1);
197
- outline: none;
198
- caret-color: var(--n-color-primary);
199
- -webkit-font-smoothing: antialiased;
200
- -moz-osx-font-smoothing: grayscale;
201
- }
202
-
203
- .n-input.has-prefix {
204
- padding-left: 2.5rem;
205
- }
206
-
207
- .n-input.has-suffix {
208
- padding-right: 2.5rem;
209
- }
210
-
211
- .n-input::placeholder {
212
- color: var(--n-color-text-muted);
98
+ transition: background-color var(--n-transition-fast), border-color var(--n-transition-fast), color var(--n-transition-fast), box-shadow var(--n-transition-fast);
213
99
  }
214
-
215
- .n-input-focus-ring {
216
- position: absolute;
217
- inset: 0;
218
- border-radius: var(--n-radius-md);
219
- background: linear-gradient(135deg, var(--n-color-primary), var(--n-color-info));
220
- opacity: 0;
221
- pointer-events: none;
222
- transition: opacity var(--n-transition-normal) cubic-bezier(0.16, 1, 0.3, 1);
223
- z-index: 0;
100
+ .n-input-container:hover {
101
+ border-color: var(--n-color-border-hover);
224
102
  }
225
-
226
- .is-focused .n-input-focus-ring {
227
- opacity: 0.15;
228
- }
229
-
230
- .is-focused .n-input {
103
+ .is-focused .n-input-container {
231
104
  border-color: var(--n-color-primary);
232
- background: var(--n-color-surface);
233
- box-shadow:
234
- 0 0 0 3px var(--n-color-primary-light),
235
- 0 0 0 1px var(--n-color-primary),
236
- inset 0 1px 3px rgba(0,0,0,0.04);
105
+ box-shadow: var(--n-ring-primary);
237
106
  }
238
-
239
- .has-error .n-input {
107
+ .is-error .n-input-container {
240
108
  border-color: var(--n-color-danger);
241
109
  }
242
-
243
- .has-error .n-input-focus-ring {
244
- background: var(--n-color-danger);
245
- opacity: 0.35;
110
+ .is-error.is-focused .n-input-container {
111
+ box-shadow: var(--n-ring-danger);
246
112
  }
247
-
248
- .n-input-icon {
249
- position: absolute;
250
- top: 50%;
251
- transform: translateY(-50%);
252
- color: var(--n-color-text-muted);
253
- font-size: var(--n-text-sm);
254
- pointer-events: none;
255
- display: flex;
256
- align-items: center;
257
- line-height: 1;
113
+ .is-disabled .n-input-container {
114
+ opacity: 0.6;
115
+ cursor: not-allowed;
116
+ background-color: var(--n-color-surface-alt);
258
117
  }
259
-
260
- .n-input-icon.is-prefix {
261
- left: 0.85rem;
118
+ .n-input {
119
+ flex: 1;
120
+ background: transparent;
121
+ border: none;
122
+ outline: none;
123
+ padding: 0.5rem 0.75rem;
124
+ font-size: 0.875rem;
125
+ color: var(--n-color-text);
126
+ font-family: inherit;
127
+ width: 100%;
262
128
  }
263
-
264
- .n-input-icon.is-suffix {
265
- right: 0.85rem;
129
+ .n-input::placeholder {
130
+ color: var(--n-color-text-muted);
266
131
  }
267
-
268
- .n-input-actions {
269
- position: absolute;
270
- right: 0.5rem;
271
- top: 50%;
272
- transform: translateY(-50%);
273
- display: flex;
274
- align-items: center;
275
- gap: 0.15rem;
132
+ .n-input:disabled {
133
+ cursor: not-allowed;
276
134
  }
277
-
278
- .n-input-action {
135
+ .n-input-prefix,
136
+ .n-input-suffix {
137
+ padding: 0 0.75rem;
138
+ color: var(--n-color-text-muted);
139
+ font-size: 0.875rem;
140
+ user-select: none;
141
+ }
142
+ .n-input-clear {
279
143
  background: transparent;
280
144
  border: none;
281
- color: var(--n-color-text-muted);
282
145
  cursor: pointer;
283
- padding: 0.25rem;
284
- font-size: var(--n-text-sm);
285
- border-radius: var(--n-radius-sm);
286
- transition: all var(--n-transition-fast);
146
+ padding: 0.5rem;
147
+ color: var(--n-color-text-muted);
148
+ transition: color var(--n-transition-fast);
287
149
  display: flex;
288
150
  align-items: center;
289
- line-height: 1;
151
+ justify-content: center;
290
152
  }
291
-
292
- .n-input-action:hover {
153
+ .n-input-clear:hover {
293
154
  color: var(--n-color-text);
294
- background: var(--n-color-glass);
295
155
  }
296
-
297
- .n-input-bottom {
156
+ .n-input-error {
157
+ font-size: 0.75rem;
158
+ color: var(--n-color-danger);
298
159
  display: flex;
299
- justify-content: space-between;
300
160
  align-items: center;
301
- padding: 0 var(--n-space-1);
302
- }
303
-
304
- .n-input-error-msg {
305
- font-size: var(--n-text-xs);
306
- color: var(--n-color-danger);
307
- }
308
-
309
- .n-input-counter {
310
- font-size: var(--n-text-xs);
311
- color: var(--n-color-text-muted);
312
- margin-left: auto;
313
- }
314
-
315
- .is-disabled {
316
- position: relative;
317
- }
318
-
319
- .is-disabled::after {
320
- content: '';
321
- position: absolute;
322
- inset: 0;
323
- background: var(--n-color-glass);
324
- border-radius: var(--n-radius-md);
325
- pointer-events: none;
326
- z-index: 2;
327
- }
328
-
329
- .is-disabled .n-input {
330
- cursor: not-allowed;
331
- background: var(--n-color-surface-alt);
161
+ gap: 0.25rem;
332
162
  }
333
163
  </style>
@@ -227,6 +227,6 @@ const onFocus = () => {
227
227
  </div>
228
228
  </template>
229
229
 
230
- <style scoped>
230
+ <style scoped>
231
231
  .n-inum{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)}
232
232
  </style>