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,379 @@
1
+ import { signal, computed, onBeforeUnmount, h, hText, effect, defineComponent, registerComponent, reloadComponent, injectStyle, Teleport } from 'nexa-framework'
2
+ import NInput from './NInput.js'
3
+ import { trackFloatingOverlay } from '../services/FloatingOverlay.js'
4
+
5
+ const _sfc_main = defineComponent({
6
+ __scopeId: 'data-v-69fa2c78',
7
+ __hmrId: 'NDatepicker_nexa',
8
+ props: {
9
+ modelValue: { type: String, default: '' },
10
+ placeholder: { type: String, default: 'Seleccionar fecha' },
11
+ disabled: { type: Boolean, default: false },
12
+ min: { type: String, default: '' },
13
+ max: { type: String, default: '' },
14
+ placement: { type: String, default: 'auto' }
15
+ },
16
+ emits: ['update:modelValue'],
17
+ setup(props, setupContext) {
18
+ const { emit, slots, slots: $slots } = setupContext
19
+ const isOpen = signal(false)
20
+ const viewDate = signal(new Date())
21
+ const instanceId = `n-dp-${Math.random().toString(16).slice(2)}`
22
+ const popupStyle = signal({})
23
+ const resolvedPlacement = signal('bottom')
24
+ let stopTracking = null
25
+ const today = new Date()
26
+ today.setHours(0, 0, 0, 0)
27
+ const year = computed(() => viewDate.value.getFullYear())
28
+ const month = computed(() => viewDate.value.getMonth())
29
+ const daysInMonth = computed(() => new Date(year.value, month.value + 1, 0).getDate())
30
+ const firstDayOfWeek = computed(() => new Date(year.value, month.value, 1).getDay())
31
+ const calendarDays = computed(() => {
32
+ const days = []
33
+ const totalCells = Math.ceil((firstDayOfWeek.value + daysInMonth.value) / 7) * 7
34
+ for (let i = 0; i < totalCells; i++) {
35
+ const day = i - firstDayOfWeek.value + 1
36
+ if (day > 0 && day <= daysInMonth.value) {
37
+ days.push(day)
38
+ } else {
39
+ days.push(null)
40
+ }
41
+ }
42
+ return days
43
+ })
44
+ const formatDate = (d) => {
45
+ const y = d.getFullYear()
46
+ const m = String(d.getMonth() + 1).padStart(2, '0')
47
+ const day = String(d.getDate()).padStart(2, '0')
48
+ return `${y}-${m}-${day}`
49
+ }
50
+ const parseDate = (value) => {
51
+ if (!value) return null
52
+ const parts = String(value).split('-')
53
+ if (parts.length !== 3) return null
54
+ const y = Number(parts[0])
55
+ const m = Number(parts[1])
56
+ const d = Number(parts[2])
57
+ if (!Number.isFinite(y) || !Number.isFinite(m) || !Number.isFinite(d)) return null
58
+ const date = new Date(y, m - 1, d)
59
+ if (date.getFullYear() !== y || date.getMonth() !== m - 1 || date.getDate() !== d) return null
60
+ date.setHours(0, 0, 0, 0)
61
+ return date
62
+ }
63
+ const minDate = computed(() => parseDate(props.min))
64
+ const maxDate = computed(() => parseDate(props.max))
65
+ const isDisabled = (day) => {
66
+ if (day == null) return true
67
+ const d = new Date(year.value, month.value, day)
68
+ d.setHours(0, 0, 0, 0)
69
+ const min = minDate.value
70
+ if (min && d < min) return true
71
+ const max = maxDate.value
72
+ if (max && d > max) return true
73
+ return false
74
+ }
75
+ const closePopup = () => {
76
+ if (!isOpen.value) return
77
+ isOpen.value = false
78
+ if (closeHandler) {
79
+ document.removeEventListener('click', closeHandler)
80
+ closeHandler = null
81
+ }
82
+ if (stopTracking) {
83
+ stopTracking()
84
+ stopTracking = null
85
+ }
86
+ rootEl.value = null
87
+ }
88
+ const syncViewDateFromModel = () => {
89
+ const selected = parseDate(props.modelValue)
90
+ if (!selected) return
91
+ viewDate.value = new Date(selected.getFullYear(), selected.getMonth(), 1)
92
+ }
93
+ const selectDate = (day) => {
94
+ if (day == null) return
95
+ if (isDisabled(day)) return
96
+ const d = new Date(year.value, month.value, day)
97
+ const formatted = formatDate(d)
98
+ emit('update:modelValue', formatted)
99
+ closePopup()
100
+ }
101
+ const prevMonth = () => {
102
+ viewDate.value = new Date(year.value, month.value - 1, 1)
103
+ }
104
+ const nextMonth = () => {
105
+ viewDate.value = new Date(year.value, month.value + 1, 1)
106
+ }
107
+ const monthNames = ['Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio', 'Julio', 'Agosto', 'Septiembre', 'Octubre', 'Noviembre', 'Diciembre']
108
+ const dayNames = ['Do', 'Lu', 'Ma', 'Mi', 'Ju', 'Vi', 'Sa']
109
+ const isSelected = (day) => {
110
+ if (!props.modelValue) return false
111
+ const d = new Date(year.value, month.value, day)
112
+ return props.modelValue === formatDate(d)
113
+ }
114
+ const isToday = (day) => {
115
+ const d = new Date(year.value, month.value, day)
116
+ return formatDate(d) === formatDate(today)
117
+ }
118
+ let closeHandler = null
119
+ const rootEl = signal(null)
120
+ const openPopup = (e) => {
121
+ if (props.disabled) return
122
+ if (isOpen.value) {
123
+ closePopup()
124
+ return
125
+ }
126
+ isOpen.value = true
127
+ syncViewDateFromModel()
128
+ const target = e?.currentTarget || e?.target
129
+ rootEl.value = target?.closest ? target.closest(`[data-datepicker-root="${instanceId}"]`) : null
130
+ stopTracking = trackFloatingOverlay({
131
+ isOpen: () => isOpen.value,
132
+ getAnchor: () => {
133
+ const root = rootEl.value
134
+ return root ? root.querySelector('.n-datepicker-input') : null
135
+ },
136
+ getPopup: () => document.querySelector(`[data-datepicker-popup="${instanceId}"]`),
137
+ placement: props.placement,
138
+ align: 'start',
139
+ matchWidth: true,
140
+ minWidth: 240,
141
+ gap: 6,
142
+ margin: 8,
143
+ zIndex: 9999,
144
+ onUpdate: (result) => {
145
+ popupStyle.value = result.style
146
+ resolvedPlacement.value = result.placement
147
+ },
148
+ isEventInside: (event) => {
149
+ const t = event.target
150
+ if (!t || typeof t.closest !== 'function') return false
151
+ if (t.closest(`[data-datepicker-root="${instanceId}"]`)) return true
152
+ if (t.closest(`[data-datepicker-popup="${instanceId}"]`)) return true
153
+ return false
154
+ },
155
+ onOutside: () => closePopup(),
156
+ })
157
+ if (closeHandler) document.removeEventListener('click', closeHandler)
158
+ closeHandler = (e) => {
159
+ const target = e.target
160
+ if (target && typeof target.closest === 'function') {
161
+ if (target.closest(`[data-datepicker-root="${instanceId}"]`)) return
162
+ if (target.closest(`[data-datepicker-popup="${instanceId}"]`)) return
163
+ }
164
+ closePopup()
165
+ }
166
+ setTimeout(() => document.addEventListener('click', closeHandler), 0)
167
+ }
168
+ onBeforeUnmount(() => {
169
+ closePopup()
170
+ })
171
+ return { 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, trackFloatingOverlay, $slots, emit }
172
+ }
173
+ })
174
+ // Injected render function
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
177
+ return h('div', { class: "n-datepicker", "data-datepicker-root": instanceId, "data-v-69fa2c78": "" }, [
178
+ "\n ",
179
+ h('div', { class: "n-datepicker-input", onClick: openPopup, "data-v-69fa2c78": "" }, [
180
+ "\n ",
181
+ h(_ntc_NInput, { modelValue: modelValue, placeholder: placeholder, disabled: disabled, readonly: true, "data-v-69fa2c78": "" }),
182
+ "\n ",
183
+ h('span', { class: "n-datepicker-icon", "data-v-69fa2c78": "" }, [
184
+ "📅"
185
+ ]),
186
+ "\n "
187
+ ]),
188
+ "\n\n ",
189
+ h(_ntc_Teleport, { to: "body", "data-v-69fa2c78": "" }, [
190
+ "\n ",
191
+ (isOpen.value) ? h('div', { class: ["n-datepicker-dropdown", { 'is-top': resolvedPlacement.value === 'top' }], "data-datepicker-popup": instanceId, style: popupStyle.value, "data-v-69fa2c78": "" }, [
192
+ "\n ",
193
+ h('div', { class: "n-datepicker-header", "data-v-69fa2c78": "" }, [
194
+ "\n ",
195
+ h('button', { class: "n-datepicker-nav", type: "button", onClick: prevMonth, "data-v-69fa2c78": "" }, [
196
+ "‹"
197
+ ]),
198
+ "\n ",
199
+ h('span', { class: "n-datepicker-title", "data-v-69fa2c78": "" }, [
200
+ monthNames[month.value],
201
+ " ",
202
+ year.value
203
+ ]),
204
+ "\n ",
205
+ h('button', { class: "n-datepicker-nav", type: "button", onClick: nextMonth, "data-v-69fa2c78": "" }, [
206
+ "›"
207
+ ]),
208
+ "\n "
209
+ ]),
210
+ "\n\n ",
211
+ h('div', { class: "n-datepicker-grid", "data-v-69fa2c78": "" }, [
212
+ "\n ",
213
+ dayNames.map((d, index) =>
214
+ h('div', { class: "n-datepicker-day-header", key: d, "data-v-69fa2c78": "" }, [
215
+ d
216
+ ])
217
+ ),
218
+ "\n ",
219
+ calendarDays.value.map((day, i) =>
220
+ h('div', { class: {
221
+ 'n-datepicker-day': true,
222
+ 'is-empty': day === null,
223
+ 'is-disabled': day !== null && isDisabled(day),
224
+ 'is-selected': day !== null && isSelected(day),
225
+ 'is-today': day !== null && isToday(day)
226
+ }, key: i, onClick: ($event) => { selectDate(day) }, "data-v-69fa2c78": "" }, [
227
+ day ?? ''
228
+ ])
229
+ ),
230
+ "\n "
231
+ ]),
232
+ "\n "
233
+ ]) : null
234
+ ]),
235
+ "\n "
236
+ ])
237
+ }
238
+ _sfc_main.__scopeId = 'data-v-69fa2c78'
239
+ _sfc_main.__hmrId = 'NDatepicker_nexa'
240
+
241
+ export default _sfc_main
242
+
243
+ const __style = `.n-datepicker[data-v-69fa2c78]{
244
+ position: relative;
245
+ display: inline-block;
246
+ font-family: var(--n-font-sans);
247
+ }
248
+
249
+ .n-datepicker-input[data-v-69fa2c78]{
250
+ position: relative;
251
+ cursor: pointer;
252
+ }
253
+
254
+ .n-datepicker-input .n-input[data-v-69fa2c78]{
255
+ cursor: pointer;
256
+ }
257
+
258
+ .n-datepicker-icon[data-v-69fa2c78]{
259
+ position: absolute;
260
+ right: 0.75rem;
261
+ top: 50%;
262
+ transform: translateY(-50%);
263
+ font-size: 1rem;
264
+ pointer-events: none;
265
+ }
266
+
267
+ .n-datepicker-dropdown[data-v-69fa2c78]{
268
+ position: absolute;
269
+ top: calc(100% + 4px);
270
+ left: 0;
271
+ z-index: var(--n-z-dropdown);
272
+ background: var(--n-color-surface-elevated);
273
+ border: 1px solid var(--n-color-border);
274
+ border-radius: var(--n-radius-lg);
275
+ box-shadow: var(--n-shadow-lg);
276
+ padding: 1rem;
277
+ width: 280px;
278
+ animation: fade-in 0.15s ease;
279
+ }
280
+
281
+ @keyframes fade-in {
282
+ from[data-v-69fa2c78]{ opacity: 0; transform: translateY(-4px); }
283
+ to[data-v-69fa2c78]{ opacity: 1; transform: translateY(0); }
284
+ }
285
+
286
+ .n-datepicker-dropdown.is-top[data-v-69fa2c78]{
287
+ animation: fade-in-top 0.15s ease;
288
+ }
289
+
290
+ @keyframes fade-in-top {
291
+ from[data-v-69fa2c78]{ opacity: 0; transform: translateY(4px); }
292
+ to[data-v-69fa2c78]{ opacity: 1; transform: translateY(0); }
293
+ }
294
+
295
+ .n-datepicker-header[data-v-69fa2c78]{
296
+ display: flex;
297
+ align-items: center;
298
+ justify-content: space-between;
299
+ margin-bottom: 0.75rem;
300
+ }
301
+
302
+ .n-datepicker-title[data-v-69fa2c78]{
303
+ font-weight: var(--n-weight-semibold);
304
+ font-size: var(--n-text-sm);
305
+ color: var(--n-color-text);
306
+ }
307
+
308
+ .n-datepicker-nav[data-v-69fa2c78]{
309
+ background: none;
310
+ border: 1px solid var(--n-color-border);
311
+ color: var(--n-color-text-secondary);
312
+ width: 28px;
313
+ height: 28px;
314
+ border-radius: var(--n-radius-sm);
315
+ cursor: pointer;
316
+ font-size: 1.1rem;
317
+ display: flex;
318
+ align-items: center;
319
+ justify-content: center;
320
+ transition: all var(--n-transition-fast);
321
+ }
322
+
323
+ .n-datepicker-nav[data-v-69fa2c78]:hover{
324
+ background: var(--n-color-surface-hover);
325
+ color: var(--n-color-text);
326
+ }
327
+
328
+ .n-datepicker-grid[data-v-69fa2c78]{
329
+ display: grid;
330
+ grid-template-columns: repeat(7, 1fr);
331
+ gap: 2px;
332
+ }
333
+
334
+ .n-datepicker-day-header[data-v-69fa2c78]{
335
+ text-align: center;
336
+ font-size: var(--n-text-xs);
337
+ color: var(--n-color-text-muted);
338
+ font-weight: var(--n-weight-semibold);
339
+ padding: 0.35rem 0;
340
+ }
341
+
342
+ .n-datepicker-day[data-v-69fa2c78]{
343
+ text-align: center;
344
+ padding: 0.4rem 0;
345
+ font-size: var(--n-text-sm);
346
+ color: var(--n-color-text);
347
+ border-radius: var(--n-radius-sm);
348
+ cursor: pointer;
349
+ transition: all var(--n-transition-fast);
350
+ }
351
+
352
+ .n-datepicker-day[data-v-69fa2c78]:hover:not(.is-empty){
353
+ background: var(--n-color-primary-light);
354
+ }
355
+
356
+ .n-datepicker-day.is-empty[data-v-69fa2c78]{
357
+ cursor: default;
358
+ }
359
+
360
+ .n-datepicker-day.is-disabled[data-v-69fa2c78]{
361
+ opacity: 0.4;
362
+ cursor: not-allowed;
363
+ }
364
+
365
+ .n-datepicker-day.is-disabled[data-v-69fa2c78]:hover{
366
+ background: transparent;
367
+ }
368
+
369
+ .n-datepicker-day.is-today[data-v-69fa2c78]{
370
+ font-weight: var(--n-weight-bold);
371
+ color: var(--n-color-primary);
372
+ }
373
+
374
+ .n-datepicker-day.is-selected[data-v-69fa2c78]{
375
+ background: var(--n-color-primary);
376
+ color: white;
377
+ font-weight: var(--n-weight-semibold);
378
+ }`
379
+ injectStyle('data-v-69fa2c78', __style)