nexa-ui-kit 0.7.10 → 0.8.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 (41) 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 +225 -226
  7. package/dist/components/NButton.nexa +274 -275
  8. package/dist/components/NCard.js +3 -3
  9. package/dist/components/NCheckbox.js +1 -1
  10. package/dist/components/NChips.js +1 -1
  11. package/dist/components/NDataTable.js +59 -61
  12. package/dist/components/NDataTable.nexa +203 -204
  13. package/dist/components/NDatepicker.js +1 -1
  14. package/dist/components/NForm.js +1 -1
  15. package/dist/components/NFormField.js +1 -1
  16. package/dist/components/NImage.js +1 -1
  17. package/dist/components/NInput.js +1 -1
  18. package/dist/components/NInputNumber.js +17 -17
  19. package/dist/components/NInputNumber.nexa +232 -232
  20. package/dist/components/NModal.js +131 -131
  21. package/dist/components/NModal.nexa +226 -226
  22. package/dist/components/NMultiSelect.js +1 -1
  23. package/dist/components/NPaginator.js +1 -1
  24. package/dist/components/NPassword.js +1 -1
  25. package/dist/components/NProgressBar.js +1 -1
  26. package/dist/components/NRadio.js +1 -1
  27. package/dist/components/NScrollView.js +1 -1
  28. package/dist/components/NSelect.js +1 -1
  29. package/dist/components/NSkeleton.js +1 -1
  30. package/dist/components/NSwitch.js +1 -1
  31. package/dist/components/NTabs.js +1 -1
  32. package/dist/components/NTag.js +1 -1
  33. package/dist/components/NToastContainer.js +1 -1
  34. package/dist/components/NTooltip.js +1 -1
  35. package/dist/components/NTreeMenu.js +1 -1
  36. package/dist/components/NVirtualList.js +1 -1
  37. package/package.json +4 -4
  38. package/src/components/NButton.nexa +274 -275
  39. package/src/components/NDataTable.nexa +203 -204
  40. package/src/components/NInputNumber.nexa +232 -232
  41. package/src/components/NModal.nexa +226 -226
@@ -1,204 +1,203 @@
1
- <script setup>
2
- import { signal, computed, effect } from 'nexa-framework'
3
- import NPaginator from './NPaginator.nexa'
4
- const props = defineProps({ value: { type: Array, default: () => [] }, columns: { type: Array, default: () => [] }, stripedRows: { type: Boolean, default: false }, hoverRows: { type: Boolean, default: true }, size: { type: String, default: 'md' }, scrollable: { type: Boolean, default: true }, paginator: { type: Boolean, default: true }, rows: { type: Number, default: 10 }, first: { type: Number, default: 0 }, rowsPerPageOptions: { type: Array, default: () => [10, 20, 50] }, selectionMode: { type: String, default: '' }, selection: { type: null, default: null }, dataKey: { type: String, default: '' }, sortField: { type: String, default: '' }, sortOrder: { type: Number, default: 1 }, resizableColumns: { type: Boolean, default: true }, columnResizeMode: { type: String, default: 'fit' }, filterDisplay: { type: String, default: 'row' }, globalFilter: { type: String, default: '' }, globalFilterFields: { type: Array, default: null }, filters: { type: null, default: null }, lazy: { type: Boolean, default: false }, totalRecords: { type: Number, default: 0 }, emptyMessage: { type: String, default: 'No records found' }, showGridlines: { type: Boolean, default: false } })
5
- const emit = defineEmits(['update:first', 'update:rows', 'update:selection', 'update:sortField', 'update:sortOrder', 'update:globalFilter', 'update:filters', 'updateFirst', 'updateRows', 'updateSelection', 'updateSortField', 'updateSortOrder', 'updateGlobalFilter', 'updateFilters', 'page', 'rowSelect', 'rowUnselect', 'sort', 'filter'])
6
- const internalFirst = signal(props.first || 0)
7
- const internalRows = signal(props.rows || 10)
8
- const internalSortField = signal(props.sortField || '')
9
- const internalSortOrder = signal(props.sortOrder || 1)
10
- const internalFilters = signal((props.filters && typeof props.filters === 'object') ? props.filters : { __global: props.globalFilter || '' })
11
- const effectiveFilters = computed(() => (props.filters && typeof props.filters === 'object') ? props.filters : internalFilters.value)
12
- const columnWidths = signal({})
13
- const resizing = signal(null)
14
- const internalSelection = signal(props.selection)
15
-
16
- effect(() => { internalFirst.value = props.first || 0 })
17
- effect(() => { internalRows.value = props.rows || 10 })
18
- effect(() => { internalSortField.value = props.sortField || '' })
19
- effect(() => { internalSortOrder.value = props.sortOrder || 1 })
20
- let lastPropGlobal = props.globalFilter || ''
21
- effect(() => {
22
- const next = props.globalFilter || ''
23
- if (next === lastPropGlobal) return
24
- lastPropGlobal = next
25
- if (props.filters && typeof props.filters === 'object') return
26
- internalFilters.value = { ...internalFilters.value, __global: next }
27
- })
28
-
29
- let lastPropSelection = props.selection
30
- effect(() => {
31
- const next = props.selection
32
- if (next === lastPropSelection) return
33
- lastPropSelection = next
34
- internalSelection.value = next
35
- })
36
- const normalizeColumns = computed(() => (props.columns || []).map((c, idx) => { const field = c.field || `col_${idx}`; const header = c.header ?? field; const sortable = !!c.sortable; const filterable = c.filterable !== false; const type = c.type || 'text'; const width = c.width || ''; const minWidth = c.minWidth || '120px'; const align = c.align || (type === 'number' ? 'right' : 'left'); const filterMatchMode = c.filterMatchMode || 'contains'; return { ...c, field, header, sortable, filterable, type, width, minWidth, align, filterMatchMode } }))
37
- const getRowKey = (row, index) => (props.dataKey && row && typeof row === 'object' && props.dataKey in row) ? String(row[props.dataKey]) : String(index)
38
- const effectiveSelection = computed(() => internalSelection.value)
39
- const isRowSelected = (row, index) => {
40
- if (!props.selectionMode) return false
41
- const selection = effectiveSelection.value
42
- const key = getRowKey(row, index)
43
- if (props.selectionMode === 'single') {
44
- if (!selection) return false
45
- if (props.dataKey && typeof selection === 'object' && selection && props.dataKey in selection) return String(selection[props.dataKey]) === key
46
- return selection === row
47
- }
48
- const current = Array.isArray(selection) ? selection : []
49
- if (props.dataKey) return current.some(s => s && typeof s === 'object' && props.dataKey in s && String(s[props.dataKey]) === key)
50
- return current.includes(row)
51
- }
52
- const toggleRowSelection = (row, index) => {
53
- if (!props.selectionMode) return
54
- const selected = isRowSelected(row, index)
55
- if (props.selectionMode === 'single') {
56
- const next = selected ? null : row
57
- internalSelection.value = next
58
- emit('update:selection', next)
59
- emit('updateSelection', next)
60
- emit(selected ? 'rowUnselect' : 'rowSelect', { data: row })
61
- return
62
- }
63
- const current = Array.isArray(effectiveSelection.value) ? effectiveSelection.value : []
64
- const key = getRowKey(row, index)
65
- const next = selected
66
- ? (props.dataKey ? current.filter(r => String(r?.[props.dataKey]) !== key) : current.filter(r => r !== row))
67
- : [...current, row]
68
- internalSelection.value = next
69
- emit('update:selection', next)
70
- emit('updateSelection', next)
71
- emit(selected ? 'rowUnselect' : 'rowSelect', { data: row })
72
- }
73
-
74
- const allVisibleSelected = computed(() => {
75
- if (props.selectionMode !== 'multiple') return false
76
- const rows = visibleRows.value
77
- if (rows.length === 0) return false
78
- for (let i = 0; i < rows.length; i++) {
79
- if (!isRowSelected(rows[i], i + (internalFirst.value || 0))) return false
80
- }
81
- return true
82
- })
83
-
84
- const toggleAllVisible = () => {
85
- if (props.selectionMode !== 'multiple') return
86
- const current = Array.isArray(effectiveSelection.value) ? effectiveSelection.value : []
87
- const rows = visibleRows.value
88
- const startIndex = internalFirst.value || 0
89
- if (rows.length === 0) return
90
- if (allVisibleSelected.value) {
91
- if (!props.dataKey) {
92
- const next = current.filter(r => !rows.includes(r))
93
- internalSelection.value = next
94
- emit('update:selection', next)
95
- emit('updateSelection', next)
96
- return
97
- }
98
- const keys = rows.map((r, i) => getRowKey(r, startIndex + i))
99
- const next = current.filter(r => !keys.includes(String(r?.[props.dataKey])))
100
- internalSelection.value = next
101
- emit('update:selection', next)
102
- emit('updateSelection', next)
103
- return
104
- }
105
- if (!props.dataKey) {
106
- const next = [...current, ...rows.filter(r => !current.includes(r))]
107
- internalSelection.value = next
108
- emit('update:selection', next)
109
- emit('updateSelection', next)
110
- return
111
- }
112
- const existing = new Set(current.map(r => String(r?.[props.dataKey])))
113
- const next = [...current, ...rows.filter((r) => !existing.has(String(r?.[props.dataKey])))]
114
- internalSelection.value = next
115
- emit('update:selection', next)
116
- emit('updateSelection', next)
117
- }
118
- const getHeaderContent = (col) => (col.headerTemplate && typeof col.headerTemplate === 'function') ? col.headerTemplate(col) : col.header
119
- const getRawValue = (row, col) => { if (!row) return ''; if (col.field && typeof row === 'object' && col.field in row) return row[col.field]; return '' }
120
- const getCellContent = (row, col, index) => { const raw = getRawValue(row, col); if (col.body && typeof col.body === 'function') return col.body(row, { index, column: col, field: col.field, value: raw }); return raw }
121
- const matchFilter = (value, query, mode) => { const q = String(query ?? '').toLowerCase().trim(); if (!q) return true; const v = String(value ?? '').toLowerCase(); if (mode === 'equals') return v === q; if (mode === 'startsWith') return v.startsWith(q); if (mode === 'endsWith') return v.endsWith(q); return v.includes(q) }
122
- const filteredRows = computed(() => { const rows = props.value || []; if (props.lazy) return rows; const cols = normalizeColumns.value; const filters = effectiveFilters.value || {}; const global = String(filters.__global || '').trim(); const keys = Object.keys(filters).filter(k => k !== '__global'); if (!global && keys.length === 0) return rows; const globalFields = Array.isArray(props.globalFilterFields) && props.globalFilterFields.length ? props.globalFilterFields : cols.map(c => c.field); return rows.filter((row) => { if (global) { const ok = globalFields.some((f) => matchFilter(getRawValue(row, { field: f }), global, 'contains')); if (!ok) return false } for (const c of cols) { const f = filters[c.field]; if (!f) continue; if (!matchFilter(getRawValue(row, c), f.value, f.matchMode || c.filterMatchMode || 'contains')) return false } return true }) })
123
- const sortedRows = computed(() => { if (props.lazy) return filteredRows.value; const rows = [...filteredRows.value]; const field = internalSortField.value; if (!field) return rows; const col = normalizeColumns.value.find(c => c.field === field); const order = internalSortOrder.value === -1 ? -1 : 1; const type = col?.type || 'text'; rows.sort((a, b) => { const av = getCellContent(a, { field }, -1); const bv = getCellContent(b, { field }, -1); if (type === 'number') return (Number(av) - Number(bv)) * order; return String(av ?? '').localeCompare(String(bv ?? ''), undefined, { numeric: true, sensitivity: 'base' }) * order }); return rows })
124
- const totalRecords = computed(() => props.lazy ? (props.totalRecords || (props.value || []).length) : sortedRows.value.length)
125
- const visibleRows = computed(() => props.lazy ? (props.value || []) : (!props.paginator ? sortedRows.value : sortedRows.value.slice(internalFirst.value || 0, (internalFirst.value || 0) + (internalRows.value || 10))))
126
- const setSort = (col) => {
127
- if (!col.sortable) return
128
- const nextField = col.field
129
- let nextOrder = 1
130
- if (internalSortField.value === nextField) nextOrder = internalSortOrder.value === 1 ? -1 : 1
131
- internalSortField.value = nextField
132
- internalSortOrder.value = nextOrder
133
- internalFirst.value = 0
134
- emit('update:sortField', nextField)
135
- emit('update:sortOrder', nextOrder)
136
- emit('updateSortField', nextField)
137
- emit('updateSortOrder', nextOrder)
138
- emit('sort', { sortField: nextField, sortOrder: nextOrder })
139
- }
140
- const onSortClick = (e) => { const field = e.currentTarget?.dataset?.field; if (!field) return; const col = normalizeColumns.value.find(c => c.field === field); if (!col) return; setSort(col) }
141
- const setGlobal = (e) => {
142
- const next = e.target.value
143
- const nextFilters = { ...(effectiveFilters.value || {}), __global: next }
144
- if (props.filters && typeof props.filters === 'object') { emit('update:filters', nextFilters); emit('updateFilters', nextFilters) } else { internalFilters.value = nextFilters }
145
- internalFirst.value = 0
146
- emit('update:globalFilter', next)
147
- emit('updateGlobalFilter', next)
148
- emit('filter', { global: next, filters: nextFilters })
149
- }
150
- const setColumnFilter = (field, e) => { const next = e.target.value; const current = { ...(effectiveFilters.value || {}) }; const col = normalizeColumns.value.find(c => c.field === field); if (!next) delete current[field]; else current[field] = { value: next, matchMode: col?.filterMatchMode || current[field]?.matchMode || 'contains' }; if (props.filters && typeof props.filters === 'object') { emit('update:filters', current); emit('updateFilters', current) } else { internalFilters.value = current } internalFirst.value = 0; emit('filter', { field, value: next, filters: current }) }
151
- const onColumnFilterInput = (e) => { const field = e.target?.dataset?.field; if (!field) return; setColumnFilter(field, e) }
152
- const onPage = ({ first, rows }) => {
153
- internalFirst.value = first
154
- internalRows.value = rows
155
- emit('update:first', first)
156
- emit('update:rows', rows)
157
- emit('updateFirst', first)
158
- emit('updateRows', rows)
159
- emit('page', { first, rows })
160
- }
161
- const getWidth = (col) => columnWidths.value[col.field] || col.width || ''
162
- const startResize = (e) => { if (!props.resizableColumns) return; const field = e.currentTarget?.dataset?.field; if (!field) return; e.preventDefault(); e.stopPropagation(); const th = e.currentTarget?.parentElement; const base = th?.getBoundingClientRect?.().width || parseFloat(th?.style?.width || '') || 160; resizing.value = { field, startX: e.clientX, startW: base }; const onMove = (ev) => { if (!resizing.value) return; const delta = ev.clientX - resizing.value.startX; const next = Math.max(80, resizing.value.startW + delta); columnWidths.value = { ...columnWidths.value, [resizing.value.field]: `${Math.round(next)}px` } }; const onUp = () => { document.removeEventListener('mousemove', onMove); document.removeEventListener('mouseup', onUp); resizing.value = null }; document.addEventListener('mousemove', onMove); document.addEventListener('mouseup', onUp) }
163
- </script>
164
-
165
- <template>
166
- <div class="n-dt" :class="[`n-dt-${size}`, showGridlines ? 'is-grid' : '', scrollable ? 'is-scroll' : '']">
167
- <div class="n-dt-toolbar"><div class="n-dt-global"><input class="n-dt-global-input" :value="effectiveFilters.value.__global || ''" placeholder="Search..." @input="setGlobal" /></div></div>
168
- <div class="n-dt-wrapper">
169
- <table class="n-dt-table" :class="{ 'is-striped': stripedRows, 'is-hover': hoverRows }">
170
- <thead class="n-dt-thead">
171
- <tr class="n-dt-head-row">
172
- <th v-if="selectionMode" class="n-dt-th is-selection"><input v-if="selectionMode === 'multiple'" class="n-dt-selectbox" type="checkbox" :checked="allVisibleSelected.value" @click.stop="toggleAllVisible" /></th>
173
- <th v-for="col in normalizeColumns.value" :key="col.field" class="n-dt-th" :class="[`is-${col.align}`, col.sortable ? 'is-sortable' : '']" :style="{ width: getWidth(col) || undefined, minWidth: col.minWidth }" :data-field="col.field" @click="onSortClick">
174
- <div class="n-dt-th-content">
175
- <span class="n-dt-th-text">{{ $slots.value && $slots.value[`header-${col.field}`] ? $slots[`header-${col.field}`]({ column: col }) : getHeaderContent(col) }}</span>
176
- <span v-if="col.sortable" class="n-dt-sort" :class="{ 'is-active': internalSortField.value === col.field }">
177
- <span v-if="internalSortField.value !== col.field" class="n-dt-sort-icon">↕</span>
178
- <span v-else class="n-dt-sort-icon">{{ internalSortOrder.value === 1 ? '↑' : '↓' }}</span>
179
- </span>
180
- </div>
181
- <span v-if="resizableColumns" class="n-dt-resizer" :data-field="col.field" @mousedown="startResize"></span>
182
- </th>
183
- </tr>
184
- <tr v-if="filterDisplay === 'row'" class="n-dt-filter-row"><th v-if="selectionMode" class="n-dt-th is-selection"></th><th v-for="col in normalizeColumns.value" :key="col.field" class="n-dt-th" :class="`is-${col.align}`" :style="{ width: getWidth(col) || undefined, minWidth: col.minWidth }"><input v-if="col.filterable" class="n-dt-filter" :data-field="col.field" :value="(effectiveFilters.value[col.field]?.value) || ''" placeholder="Filter" @input="onColumnFilterInput" /></th></tr>
185
- </thead>
186
- <tbody class="n-dt-tbody">
187
- <tr v-for="(row, i) in visibleRows.value" :key="getRowKey(row, i + internalFirst.value)" class="n-dt-row" :class="{ 'is-selected': isRowSelected(row, i + internalFirst.value) }" @click="toggleRowSelection(row, i + internalFirst.value)">
188
- <td v-if="selectionMode" class="n-dt-td is-selection"><input class="n-dt-selectbox" type="checkbox" :checked="isRowSelected(row, i + internalFirst.value)" @click.stop="toggleRowSelection(row, i + internalFirst.value)" /></td>
189
- <td v-for="col in normalizeColumns.value" :key="col.field" class="n-dt-td" :class="`is-${col.align}`" :style="{ width: getWidth(col) || undefined, minWidth: col.minWidth }">
190
- <span v-if="$slots.value && $slots.value[`body-${col.field}`]">{{ $slots[`body-${col.field}`]({ data: row, column: col, index: i + internalFirst.value }) }}</span>
191
- <span v-else :innerHTML="getCellContent(row, col, i + internalFirst.value)"></span>
192
- </td>
193
- </tr>
194
- <tr v-if="visibleRows.value.length === 0" class="n-dt-empty-row"><td :colspan="normalizeColumns.value.length + (selectionMode ? 1 : 0)" class="n-dt-empty">{{ emptyMessage }}</td></tr>
195
- </tbody>
196
- </table>
197
- </div>
198
- <NPaginator v-if="paginator" :first="internalFirst.value" :rows="internalRows.value" :totalRecords="totalRecords.value" :rowsPerPageOptions="rowsPerPageOptions" @page="onPage" />
199
- </div>
200
- </template>
201
-
202
- <style scoped>
203
- .n-dt{border:1px solid var(--n-color-border);border-radius:var(--n-radius-lg);background:var(--n-color-surface);overflow:hidden;font-family:var(--n-font-sans)}.n-dt-toolbar{display:flex;align-items:center;justify-content:space-between;padding:var(--n-space-3) var(--n-space-4);border-bottom:1px solid var(--n-color-border);background:linear-gradient(180deg,rgba(255,255,255,.04),rgba(0,0,0,.08))}.n-dt-global{display:flex;align-items:center;gap:var(--n-space-2)}.n-dt-global-input{width:280px;max-width:100%;background:var(--n-color-bg);border:1px solid var(--n-color-border);border-radius:var(--n-radius-md);padding:0.55rem 0.75rem;color:var(--n-color-text);font-size:var(--n-text-sm);outline:none;box-sizing:border-box}.n-dt-global-input:focus{border-color:var(--n-color-primary);box-shadow:0 0 0 3px var(--n-color-primary-light)}.n-dt-wrapper{width:100%;overflow:auto}.n-dt-table{width:100%;border-collapse:separate;border-spacing:0;table-layout:fixed}.n-dt-thead{background:var(--n-color-surface)}.n-dt-th,.n-dt-td{padding:0.75rem 0.9rem;border-bottom:1px solid var(--n-color-border);color:var(--n-color-text);font-size:var(--n-text-sm);vertical-align:middle}.n-dt-th{position:relative;overflow:hidden;background:rgba(0,0,0,.10);color:var(--n-color-text-secondary);font-weight:var(--n-weight-semibold);user-select:none}.n-dt-th.is-sortable{cursor:pointer}.n-dt-th-content{display:flex;align-items:center;justify-content:space-between;gap:0.5rem}.n-dt-sort{display:inline-flex;align-items:center;gap:0.25rem;color:var(--n-color-text-muted)}.n-dt-sort.is-active{color:var(--n-color-primary)}.n-dt-resizer{position:absolute;right:0;top:0;bottom:0;width:8px;cursor:col-resize}.n-dt-filter-row .n-dt-th{background:rgba(0,0,0,.06)}.n-dt-filter{width:100%;max-width:100%;display:block;background:var(--n-color-bg);border:1px solid var(--n-color-border);border-radius:var(--n-radius-sm);padding:0.35rem 0.5rem;color:var(--n-color-text);font-size:var(--n-text-xs);outline:none;box-sizing:border-box}.n-dt-filter:focus{border-color:var(--n-color-primary)}.n-dt-td{background:transparent;color:var(--n-color-text)}.n-dt-row.is-selected .n-dt-td{background:rgba(59,130,246,.12)}.n-dt-table.is-striped .n-dt-row:nth-child(even) .n-dt-td{background:rgba(0,0,0,.06)}.n-dt-table.is-hover .n-dt-row:hover .n-dt-td{background:rgba(255,255,255,.06)}.n-dt-empty{text-align:center;color:var(--n-color-text-muted);padding:1.25rem}.is-left{text-align:left}.is-right{text-align:right}.is-center{text-align:center}.is-selection{width:44px;min-width:44px;max-width:44px;text-align:center}.n-dt-selectbox{width:16px;height:16px;accent-color:var(--n-color-primary)}.n-dt-check{display:inline-flex;align-items:center;justify-content:center;width:18px;height:18px;border-radius:4px;border:1px solid var(--n-color-border);color:var(--n-color-primary)}.is-grid .n-dt-td,.is-grid .n-dt-th{border-right:1px solid var(--n-color-border)}.is-grid .n-dt-td:last-child,.is-grid .n-dt-th:last-child{border-right:none}.n-dt-sm .n-dt-th,.n-dt-sm .n-dt-td{padding:0.55rem 0.7rem}.n-dt-lg .n-dt-th,.n-dt-lg .n-dt-td{padding:0.9rem 1rem}
204
- </style>
1
+ <script setup>
2
+ import { signal, computed, effect } from 'nexa-framework'
3
+ import NPaginator from './NPaginator.nexa'
4
+ const props = defineProps({ value: { type: Array, default: () => [] }, columns: { type: Array, default: () => [] }, stripedRows: { type: Boolean, default: false }, hoverRows: { type: Boolean, default: true }, size: { type: String, default: 'md' }, scrollable: { type: Boolean, default: true }, paginator: { type: Boolean, default: true }, rows: { type: Number, default: 10 }, first: { type: Number, default: 0 }, rowsPerPageOptions: { type: Array, default: () => [10, 20, 50] }, selectionMode: { type: String, default: '' }, selection: { type: null, default: null }, dataKey: { type: String, default: '' }, sortField: { type: String, default: '' }, sortOrder: { type: Number, default: 1 }, resizableColumns: { type: Boolean, default: true }, columnResizeMode: { type: String, default: 'fit' }, filterDisplay: { type: String, default: 'row' }, globalFilter: { type: String, default: '' }, globalFilterFields: { type: Array, default: null }, filters: { type: null, default: null }, lazy: { type: Boolean, default: false }, totalRecords: { type: Number, default: 0 }, emptyMessage: { type: String, default: 'No records found' }, showGridlines: { type: Boolean, default: false } })
5
+ const emit = defineEmits(['update:first', 'update:rows', 'update:selection', 'update:sortField', 'update:sortOrder', 'update:globalFilter', 'update:filters', 'updateFirst', 'updateRows', 'updateSelection', 'updateSortField', 'updateSortOrder', 'updateGlobalFilter', 'updateFilters', 'page', 'rowSelect', 'rowUnselect', 'sort', 'filter'])
6
+ const internalFirst = signal(props.first || 0)
7
+ const internalRows = signal(props.rows || 10)
8
+ const internalSortField = signal(props.sortField || '')
9
+ const internalSortOrder = signal(props.sortOrder || 1)
10
+ const internalFilters = signal((props.filters && typeof props.filters === 'object') ? props.filters : { __global: props.globalFilter || '' })
11
+ const effectiveFilters = computed(() => (props.filters && typeof props.filters === 'object') ? props.filters : internalFilters.value)
12
+ const columnWidths = signal({})
13
+ const resizing = signal(null)
14
+ const internalSelection = signal(props.selection)
15
+
16
+ effect(() => { internalFirst.value = props.first || 0 })
17
+ effect(() => { internalRows.value = props.rows || 10 })
18
+ effect(() => { internalSortField.value = props.sortField || '' })
19
+ effect(() => { internalSortOrder.value = props.sortOrder || 1 })
20
+ let lastPropGlobal = props.globalFilter || ''
21
+ effect(() => {
22
+ const next = props.globalFilter || ''
23
+ if (next === lastPropGlobal) return
24
+ lastPropGlobal = next
25
+ if (props.filters && typeof props.filters === 'object') return
26
+ internalFilters.value = { ...internalFilters.value, __global: next }
27
+ })
28
+
29
+ let lastPropSelection = props.selection
30
+ effect(() => {
31
+ const next = props.selection
32
+ if (next === lastPropSelection) return
33
+ lastPropSelection = next
34
+ internalSelection.value = next
35
+ })
36
+ const normalizeColumns = computed(() => (props.columns || []).map((c, idx) => { const field = c.field || `col_${idx}`; const header = c.header ?? field; const sortable = !!c.sortable; const filterable = c.filterable !== false; const type = c.type || 'text'; const width = c.width || ''; const minWidth = c.minWidth || '120px'; const align = c.align || (type === 'number' ? 'right' : 'left'); const filterMatchMode = c.filterMatchMode || 'contains'; return { ...c, field, header, sortable, filterable, type, width, minWidth, align, filterMatchMode } }))
37
+ const getRowKey = (row, index) => (props.dataKey && row && typeof row === 'object' && props.dataKey in row) ? String(row[props.dataKey]) : String(index)
38
+ const effectiveSelection = computed(() => internalSelection.value)
39
+ const isRowSelected = (row, index) => {
40
+ if (!props.selectionMode) return false
41
+ const selection = effectiveSelection.value
42
+ const key = getRowKey(row, index)
43
+ if (props.selectionMode === 'single') {
44
+ if (!selection) return false
45
+ if (props.dataKey && typeof selection === 'object' && selection && props.dataKey in selection) return String(selection[props.dataKey]) === key
46
+ return selection === row
47
+ }
48
+ const current = Array.isArray(selection) ? selection : []
49
+ if (props.dataKey) return current.some(s => s && typeof s === 'object' && props.dataKey in s && String(s[props.dataKey]) === key)
50
+ return current.includes(row)
51
+ }
52
+ const toggleRowSelection = (row, index) => {
53
+ if (!props.selectionMode) return
54
+ const selected = isRowSelected(row, index)
55
+ if (props.selectionMode === 'single') {
56
+ const next = selected ? null : row
57
+ internalSelection.value = next
58
+ emit('update:selection', next)
59
+ emit('updateSelection', next)
60
+ emit(selected ? 'rowUnselect' : 'rowSelect', { data: row })
61
+ return
62
+ }
63
+ const current = Array.isArray(effectiveSelection.value) ? effectiveSelection.value : []
64
+ const key = getRowKey(row, index)
65
+ const next = selected
66
+ ? (props.dataKey ? current.filter(r => String(r?.[props.dataKey]) !== key) : current.filter(r => r !== row))
67
+ : [...current, row]
68
+ internalSelection.value = next
69
+ emit('update:selection', next)
70
+ emit('updateSelection', next)
71
+ emit(selected ? 'rowUnselect' : 'rowSelect', { data: row })
72
+ }
73
+
74
+ const allVisibleSelected = computed(() => {
75
+ if (props.selectionMode !== 'multiple') return false
76
+ const rows = visibleRows.value
77
+ if (rows.length === 0) return false
78
+ for (let i = 0; i < rows.length; i++) {
79
+ if (!isRowSelected(rows[i], i + (internalFirst.value || 0))) return false
80
+ }
81
+ return true
82
+ })
83
+
84
+ const toggleAllVisible = () => {
85
+ if (props.selectionMode !== 'multiple') return
86
+ const current = Array.isArray(effectiveSelection.value) ? effectiveSelection.value : []
87
+ const rows = visibleRows.value
88
+ const startIndex = internalFirst.value || 0
89
+ if (rows.length === 0) return
90
+ if (allVisibleSelected.value) {
91
+ if (!props.dataKey) {
92
+ const next = current.filter(r => !rows.includes(r))
93
+ internalSelection.value = next
94
+ emit('update:selection', next)
95
+ emit('updateSelection', next)
96
+ return
97
+ }
98
+ const keys = rows.map((r, i) => getRowKey(r, startIndex + i))
99
+ const next = current.filter(r => !keys.includes(String(r?.[props.dataKey])))
100
+ internalSelection.value = next
101
+ emit('update:selection', next)
102
+ emit('updateSelection', next)
103
+ return
104
+ }
105
+ if (!props.dataKey) {
106
+ const next = [...current, ...rows.filter(r => !current.includes(r))]
107
+ internalSelection.value = next
108
+ emit('update:selection', next)
109
+ emit('updateSelection', next)
110
+ return
111
+ }
112
+ const existing = new Set(current.map(r => String(r?.[props.dataKey])))
113
+ const next = [...current, ...rows.filter((r) => !existing.has(String(r?.[props.dataKey])))]
114
+ internalSelection.value = next
115
+ emit('update:selection', next)
116
+ emit('updateSelection', next)
117
+ }
118
+ const getHeaderContent = (col) => (col.headerTemplate && typeof col.headerTemplate === 'function') ? col.headerTemplate(col) : col.header
119
+ const getRawValue = (row, col) => { if (!row) return ''; if (col.field && typeof row === 'object' && col.field in row) return row[col.field]; return '' }
120
+ const getCellContent = (row, col, index) => { const raw = getRawValue(row, col); if (col.body && typeof col.body === 'function') return col.body(row, { index, column: col, field: col.field, value: raw }); return raw }
121
+ const matchFilter = (value, query, mode) => { const q = String(query ?? '').toLowerCase().trim(); if (!q) return true; const v = String(value ?? '').toLowerCase(); if (mode === 'equals') return v === q; if (mode === 'startsWith') return v.startsWith(q); if (mode === 'endsWith') return v.endsWith(q); return v.includes(q) }
122
+ const filteredRows = computed(() => { const rows = props.value || []; if (props.lazy) return rows; const cols = normalizeColumns.value; const filters = effectiveFilters.value || {}; const global = String(filters.__global || '').trim(); const keys = Object.keys(filters).filter(k => k !== '__global'); if (!global && keys.length === 0) return rows; const globalFields = Array.isArray(props.globalFilterFields) && props.globalFilterFields.length ? props.globalFilterFields : cols.map(c => c.field); return rows.filter((row) => { if (global) { const ok = globalFields.some((f) => matchFilter(getRawValue(row, { field: f }), global, 'contains')); if (!ok) return false } for (const c of cols) { const f = filters[c.field]; if (!f) continue; if (!matchFilter(getRawValue(row, c), f.value, f.matchMode || c.filterMatchMode || 'contains')) return false } return true }) })
123
+ const sortedRows = computed(() => { if (props.lazy) return filteredRows.value; const rows = [...filteredRows.value]; const field = internalSortField.value; if (!field) return rows; const col = normalizeColumns.value.find(c => c.field === field); const order = internalSortOrder.value === -1 ? -1 : 1; const type = col?.type || 'text'; rows.sort((a, b) => { const av = getCellContent(a, { field }, -1); const bv = getCellContent(b, { field }, -1); if (type === 'number') return (Number(av) - Number(bv)) * order; return String(av ?? '').localeCompare(String(bv ?? ''), undefined, { numeric: true, sensitivity: 'base' }) * order }); return rows })
124
+ const totalRecords = computed(() => props.lazy ? (props.totalRecords || (props.value || []).length) : sortedRows.value.length)
125
+ const visibleRows = computed(() => props.lazy ? (props.value || []) : (!props.paginator ? sortedRows.value : sortedRows.value.slice(internalFirst.value || 0, (internalFirst.value || 0) + (internalRows.value || 10))))
126
+ const setSort = (col) => {
127
+ if (!col.sortable) return
128
+ const nextField = col.field
129
+ let nextOrder = 1
130
+ if (internalSortField.value === nextField) nextOrder = internalSortOrder.value === 1 ? -1 : 1
131
+ internalSortField.value = nextField
132
+ internalSortOrder.value = nextOrder
133
+ internalFirst.value = 0
134
+ emit('update:sortField', nextField)
135
+ emit('update:sortOrder', nextOrder)
136
+ emit('updateSortField', nextField)
137
+ emit('updateSortOrder', nextOrder)
138
+ emit('sort', { sortField: nextField, sortOrder: nextOrder })
139
+ }
140
+ const onSortClick = (e) => { const field = e.currentTarget?.dataset?.field; if (!field) return; const col = normalizeColumns.value.find(c => c.field === field); if (!col) return; setSort(col) }
141
+ const setGlobal = (e) => {
142
+ const next = e.target.value
143
+ const nextFilters = { ...(effectiveFilters.value || {}), __global: next }
144
+ if (props.filters && typeof props.filters === 'object') { emit('update:filters', nextFilters); emit('updateFilters', nextFilters) } else { internalFilters.value = nextFilters }
145
+ internalFirst.value = 0
146
+ emit('update:globalFilter', next)
147
+ emit('updateGlobalFilter', next)
148
+ emit('filter', { global: next, filters: nextFilters })
149
+ }
150
+ const setColumnFilter = (field, e) => { const next = e.target.value; const current = { ...(effectiveFilters.value || {}) }; const col = normalizeColumns.value.find(c => c.field === field); if (!next) delete current[field]; else current[field] = { value: next, matchMode: col?.filterMatchMode || current[field]?.matchMode || 'contains' }; if (props.filters && typeof props.filters === 'object') { emit('update:filters', current); emit('updateFilters', current) } else { internalFilters.value = current } internalFirst.value = 0; emit('filter', { field, value: next, filters: current }) }
151
+ const onColumnFilterInput = (e) => { const field = e.target?.dataset?.field; if (!field) return; setColumnFilter(field, e) }
152
+ const onPage = ({ first, rows }) => {
153
+ internalFirst.value = first
154
+ internalRows.value = rows
155
+ emit('update:first', first)
156
+ emit('update:rows', rows)
157
+ emit('updateFirst', first)
158
+ emit('updateRows', rows)
159
+ emit('page', { first, rows })
160
+ }
161
+ const getWidth = (col) => columnWidths.value[col.field] || col.width || ''
162
+ const startResize = (e) => { if (!props.resizableColumns) return; const field = e.currentTarget?.dataset?.field; if (!field) return; e.preventDefault(); e.stopPropagation(); const th = e.currentTarget?.parentElement; const base = th?.getBoundingClientRect?.().width || parseFloat(th?.style?.width || '') || 160; resizing.value = { field, startX: e.clientX, startW: base }; const onMove = (ev) => { if (!resizing.value) return; const delta = ev.clientX - resizing.value.startX; const next = Math.max(80, resizing.value.startW + delta); columnWidths.value = { ...columnWidths.value, [resizing.value.field]: `${Math.round(next)}px` } }; const onUp = () => { document.removeEventListener('mousemove', onMove); document.removeEventListener('mouseup', onUp); resizing.value = null }; document.addEventListener('mousemove', onMove); document.addEventListener('mouseup', onUp) }
163
+ </script>
164
+
165
+ <template>
166
+ <div class="n-dt" :class="[`n-dt-${size}`, showGridlines ? 'is-grid' : '', scrollable ? 'is-scroll' : '']">
167
+ <div class="n-dt-toolbar"><div class="n-dt-global"><input class="n-dt-global-input" :value="effectiveFilters.value.__global || ''" placeholder="Search..." @input="setGlobal" /></div></div>
168
+ <div class="n-dt-wrapper">
169
+ <table class="n-dt-table" :class="{ 'is-striped': stripedRows, 'is-hover': hoverRows }">
170
+ <thead class="n-dt-thead">
171
+ <tr class="n-dt-head-row">
172
+ <th v-if="selectionMode" class="n-dt-th is-selection"><input v-if="selectionMode === 'multiple'" class="n-dt-selectbox" type="checkbox" :checked="allVisibleSelected.value" @click.stop="toggleAllVisible" /></th>
173
+ <th v-for="col in normalizeColumns.value" :key="col.field" class="n-dt-th" :class="[`is-${col.align}`, col.sortable ? 'is-sortable' : '']" :style="{ width: getWidth(col) || undefined, minWidth: col.minWidth }" :data-field="col.field" @click="onSortClick">
174
+ <div class="n-dt-th-content">
175
+ <span class="n-dt-th-text">{{ $slots.value && $slots.value[`header-${col.field}`] ? $slots[`header-${col.field}`]({ column: col }) : getHeaderContent(col) }}</span>
176
+ <span v-if="col.sortable" class="n-dt-sort" :class="{ 'is-active': internalSortField.value === col.field }">
177
+ <span v-if="internalSortField.value !== col.field" class="n-dt-sort-icon">↕</span>
178
+ <span v-else class="n-dt-sort-icon">{{ internalSortOrder.value === 1 ? '↑' : '↓' }}</span>
179
+ </span>
180
+ </div>
181
+ <span v-if="resizableColumns" class="n-dt-resizer" :data-field="col.field" @mousedown="startResize"></span>
182
+ </th>
183
+ </tr>
184
+ <tr v-if="filterDisplay === 'row'" class="n-dt-filter-row"><th v-if="selectionMode" class="n-dt-th is-selection"></th><th v-for="col in normalizeColumns.value" :key="col.field" class="n-dt-th" :class="`is-${col.align}`" :style="{ width: getWidth(col) || undefined, minWidth: col.minWidth }"><input v-if="col.filterable" class="n-dt-filter" :data-field="col.field" :value="(effectiveFilters.value[col.field]?.value) || ''" placeholder="Filter" @input="onColumnFilterInput" /></th></tr>
185
+ </thead>
186
+ <tbody class="n-dt-tbody">
187
+ <tr v-for="(row, i) in visibleRows.value" :key="getRowKey(row, i + internalFirst.value)" class="n-dt-row" :class="{ 'is-selected': isRowSelected(row, i + internalFirst.value) }" @click="toggleRowSelection(row, i + internalFirst.value)">
188
+ <td v-if="selectionMode" class="n-dt-td is-selection"><input class="n-dt-selectbox" type="checkbox" :checked="isRowSelected(row, i + internalFirst.value)" @click.stop="toggleRowSelection(row, i + internalFirst.value)" /></td>
189
+ <td v-for="col in normalizeColumns.value" :key="col.field" class="n-dt-td" :class="`is-${col.align}`" :style="{ width: getWidth(col) || undefined, minWidth: col.minWidth }">
190
+ {{ $slots.value && $slots.value[`body-${col.field}`] ? $slots[`body-${col.field}`]({ data: row, column: col, index: i + internalFirst.value }) : getCellContent(row, col, i + internalFirst.value) }}
191
+ </td>
192
+ </tr>
193
+ <tr v-if="visibleRows.value.length === 0" class="n-dt-empty-row"><td :colspan="normalizeColumns.value.length + (selectionMode ? 1 : 0)" class="n-dt-empty">{{ emptyMessage }}</td></tr>
194
+ </tbody>
195
+ </table>
196
+ </div>
197
+ <NPaginator v-if="paginator" :first="internalFirst.value" :rows="internalRows.value" :totalRecords="totalRecords.value" :rowsPerPageOptions="rowsPerPageOptions" @page="onPage" />
198
+ </div>
199
+ </template>
200
+
201
+ <style scoped>
202
+ .n-dt{border:1px solid var(--n-color-border);border-radius:var(--n-radius-lg);background:var(--n-color-surface);overflow:hidden;font-family:var(--n-font-sans)}.n-dt-toolbar{display:flex;align-items:center;justify-content:space-between;padding:var(--n-space-3) var(--n-space-4);border-bottom:1px solid var(--n-color-border);background:linear-gradient(180deg,rgba(255,255,255,.04),rgba(0,0,0,.08))}.n-dt-global{display:flex;align-items:center;gap:var(--n-space-2)}.n-dt-global-input{width:280px;max-width:100%;background:var(--n-color-bg);border:1px solid var(--n-color-border);border-radius:var(--n-radius-md);padding:0.55rem 0.75rem;color:var(--n-color-text);font-size:var(--n-text-sm);outline:none;box-sizing:border-box}.n-dt-global-input:focus{border-color:var(--n-color-primary);box-shadow:0 0 0 3px var(--n-color-primary-light)}.n-dt-wrapper{width:100%;overflow:auto}.n-dt-table{width:100%;border-collapse:separate;border-spacing:0;table-layout:fixed}.n-dt-thead{background:var(--n-color-surface)}.n-dt-th,.n-dt-td{padding:0.75rem 0.9rem;border-bottom:1px solid var(--n-color-border);color:var(--n-color-text);font-size:var(--n-text-sm);vertical-align:middle}.n-dt-th{position:relative;overflow:hidden;background:rgba(0,0,0,.10);color:var(--n-color-text-secondary);font-weight:var(--n-weight-semibold);user-select:none}.n-dt-th.is-sortable{cursor:pointer}.n-dt-th-content{display:flex;align-items:center;justify-content:space-between;gap:0.5rem}.n-dt-sort{display:inline-flex;align-items:center;gap:0.25rem;color:var(--n-color-text-muted)}.n-dt-sort.is-active{color:var(--n-color-primary)}.n-dt-resizer{position:absolute;right:0;top:0;bottom:0;width:8px;cursor:col-resize}.n-dt-filter-row .n-dt-th{background:rgba(0,0,0,.06)}.n-dt-filter{width:100%;max-width:100%;display:block;background:var(--n-color-bg);border:1px solid var(--n-color-border);border-radius:var(--n-radius-sm);padding:0.35rem 0.5rem;color:var(--n-color-text);font-size:var(--n-text-xs);outline:none;box-sizing:border-box}.n-dt-filter:focus{border-color:var(--n-color-primary)}.n-dt-td{background:transparent;color:var(--n-color-text)}.n-dt-row.is-selected .n-dt-td{background:rgba(59,130,246,.12)}.n-dt-table.is-striped .n-dt-row:nth-child(even) .n-dt-td{background:rgba(0,0,0,.06)}.n-dt-table.is-hover .n-dt-row:hover .n-dt-td{background:rgba(255,255,255,.06)}.n-dt-empty{text-align:center;color:var(--n-color-text-muted);padding:1.25rem}.is-left{text-align:left}.is-right{text-align:right}.is-center{text-align:center}.is-selection{width:44px;min-width:44px;max-width:44px;text-align:center}.n-dt-selectbox{width:16px;height:16px;accent-color:var(--n-color-primary)}.n-dt-check{display:inline-flex;align-items:center;justify-content:center;width:18px;height:18px;border-radius:4px;border:1px solid var(--n-color-border);color:var(--n-color-primary)}.is-grid .n-dt-td,.is-grid .n-dt-th{border-right:1px solid var(--n-color-border)}.is-grid .n-dt-td:last-child,.is-grid .n-dt-th:last-child{border-right:none}.n-dt-sm .n-dt-th,.n-dt-sm .n-dt-td{padding:0.55rem 0.7rem}.n-dt-lg .n-dt-th,.n-dt-lg .n-dt-td{padding:0.9rem 1rem}
203
+ </style>
@@ -173,7 +173,7 @@ const _sfc_main = defineComponent({
173
173
  })
174
174
  // Injected render function
175
175
  _sfc_main.render = function(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
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
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
- let { fieldNames, fields, registerField, getValues, values, errors, pending, valid, validateAll, reset, submit, onSubmit, provide, $slots, emit, validateOn, disabled, Fragment: _ntc_Fragment } = ctx
114
+ const { 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
- 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
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
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
- 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
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
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
- 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
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
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-76a3e703',
4
+ __scopeId: 'data-v-39e23f1c',
5
5
  __hmrId: 'NInputNumber_nexa',
6
6
  props: {
7
7
  modelValue: { type: Number, default: 0 },
@@ -200,32 +200,32 @@ const _sfc_main = defineComponent({
200
200
  })
201
201
  // Injected render function
202
202
  _sfc_main.render = function(ctx) {
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": "" }, [
205
- "\n ",
206
- (label) ? h('label', { class: "n-inum-label", "data-v-76a3e703": "" }, [
203
+ const { 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-39e23f1c": "" }, [
205
+ "\r\n ",
206
+ (label) ? h('label', { class: "n-inum-label", "data-v-39e23f1c": "" }, [
207
207
  label
208
208
  ]) : null,
209
- h('div', { class: ["n-inum-wrap", { 'is-disabled': effectiveDisabled.value }], "data-v-76a3e703": "" }, [
210
- "\n ",
211
- h('button', { class: "n-inum-btn n-inum-dec", type: "button", disabled: effectiveDisabled.value || readonly, "aria-label": "Decrement", onClick: dec, "data-v-76a3e703": "" }, [
209
+ h('div', { class: ["n-inum-wrap", { 'is-disabled': effectiveDisabled.value }], "data-v-39e23f1c": "" }, [
210
+ "\r\n ",
211
+ h('button', { class: "n-inum-btn n-inum-dec", type: "button", disabled: effectiveDisabled.value || readonly, "aria-label": "Decrement", onClick: dec, "data-v-39e23f1c": "" }, [
212
212
  "−"
213
213
  ]),
214
- "\n ",
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": "" }),
216
- "\n ",
217
- h('button', { class: "n-inum-btn n-inum-inc", type: "button", disabled: effectiveDisabled.value || readonly, "aria-label": "Increment", onClick: inc, "data-v-76a3e703": "" }, [
214
+ "\r\n ",
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-39e23f1c": "" }),
216
+ "\r\n ",
217
+ h('button', { class: "n-inum-btn n-inum-inc", type: "button", disabled: effectiveDisabled.value || readonly, "aria-label": "Increment", onClick: inc, "data-v-39e23f1c": "" }, [
218
218
  "+"
219
219
  ]),
220
- "\n "
220
+ "\r\n "
221
221
  ]),
222
- "\n "
222
+ "\r\n "
223
223
  ])
224
224
  }
225
- _sfc_main.__scopeId = 'data-v-76a3e703'
225
+ _sfc_main.__scopeId = 'data-v-39e23f1c'
226
226
  _sfc_main.__hmrId = 'NInputNumber_nexa'
227
227
 
228
228
  export default _sfc_main
229
229
 
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)
230
+ const __style = `.n-inum[data-v-39e23f1c]{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-39e23f1c', __style)