nexa-ui-kit 0.7.11 → 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.
- package/dist/components/NAlert.js +1 -1
- package/dist/components/NAutocomplete.js +1 -1
- package/dist/components/NAvatar.js +1 -1
- package/dist/components/NBadge.js +1 -1
- package/dist/components/NBottomSheet.js +1 -1
- package/dist/components/NButton.js +225 -225
- package/dist/components/NButton.nexa +274 -274
- package/dist/components/NCard.js +3 -3
- package/dist/components/NCheckbox.js +1 -1
- package/dist/components/NChips.js +1 -1
- package/dist/components/NDataTable.js +59 -61
- package/dist/components/NDataTable.nexa +203 -204
- package/dist/components/NDatepicker.js +1 -1
- package/dist/components/NForm.js +1 -1
- package/dist/components/NFormField.js +1 -1
- package/dist/components/NImage.js +1 -1
- package/dist/components/NInput.js +1 -1
- package/dist/components/NInputNumber.js +17 -17
- package/dist/components/NInputNumber.nexa +232 -232
- package/dist/components/NModal.js +131 -131
- package/dist/components/NModal.nexa +226 -226
- package/dist/components/NMultiSelect.js +1 -1
- package/dist/components/NPaginator.js +1 -1
- package/dist/components/NPassword.js +1 -1
- package/dist/components/NProgressBar.js +1 -1
- package/dist/components/NRadio.js +1 -1
- package/dist/components/NScrollView.js +1 -1
- package/dist/components/NSelect.js +1 -1
- package/dist/components/NSkeleton.js +1 -1
- package/dist/components/NSwitch.js +1 -1
- package/dist/components/NTabs.js +1 -1
- package/dist/components/NTag.js +1 -1
- package/dist/components/NToastContainer.js +1 -1
- package/dist/components/NTooltip.js +1 -1
- package/dist/components/NTreeMenu.js +1 -1
- package/dist/components/NVirtualList.js +1 -1
- package/package.json +4 -4
- package/src/components/NButton.nexa +274 -274
- package/src/components/NDataTable.nexa +203 -204
- package/src/components/NInputNumber.nexa +232 -232
- 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
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
</tr>
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
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
|
-
|
|
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": "" }, [
|
package/dist/components/NForm.js
CHANGED
|
@@ -111,7 +111,7 @@ const _sfc_main = defineComponent({
|
|
|
111
111
|
})
|
|
112
112
|
// Injected render function
|
|
113
113
|
_sfc_main.render = function(ctx) {
|
|
114
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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-
|
|
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
|
-
|
|
204
|
-
return h('div', { class: "n-inum", "data-v-
|
|
205
|
-
"\n ",
|
|
206
|
-
(label) ? h('label', { class: "n-inum-label", "data-v-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
231
|
-
injectStyle('data-v-
|
|
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)
|