ketekny-ui-kit 1.0.30 → 1.0.32
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/package.json +1 -1
- package/src/ui/kDatatable.vue +372 -187
package/package.json
CHANGED
package/src/ui/kDatatable.vue
CHANGED
|
@@ -1,31 +1,51 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div
|
|
2
|
+
<div
|
|
3
|
+
ref="tableWrapper"
|
|
4
|
+
:class="[
|
|
5
|
+
'k-datatable-wrapper rounded-lg border border-primary/15',
|
|
6
|
+
disabled ? 'pointer-events-none opacity-60' : '',
|
|
7
|
+
]"
|
|
8
|
+
>
|
|
3
9
|
<EasyDataTable
|
|
4
10
|
v-bind="$attrs"
|
|
5
|
-
:headers="
|
|
6
|
-
:items="
|
|
11
|
+
:headers="computedHeaders"
|
|
12
|
+
:items="keyedItems"
|
|
7
13
|
:search="search"
|
|
8
14
|
:theme-color="themeColor"
|
|
9
|
-
:show-select="
|
|
10
|
-
:single-select="effectiveSelectionMode === 'single'"
|
|
11
|
-
v-if="effectiveSelectionMode !== 'none'"
|
|
12
|
-
:items-selected="internalSelection"
|
|
13
|
-
@update:items-selected="handleSelectionUpdate"
|
|
14
|
-
:itemSelectable="itemSelectable"
|
|
15
|
+
:show-select="false"
|
|
15
16
|
:body-row-class-name="composeBodyRowClassName"
|
|
16
17
|
alternating
|
|
17
18
|
buttons-pagination
|
|
18
19
|
table-class-name="customize-table"
|
|
19
20
|
>
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
<template v-if="effectiveSelectionMode === 'multiple'" #header-__kdt_select>
|
|
22
|
+
<div class="k-datatable-select-cell">
|
|
23
|
+
<input
|
|
24
|
+
type="checkbox"
|
|
25
|
+
class="easy-checkbox"
|
|
26
|
+
:checked="allSelectableSelected"
|
|
27
|
+
:indeterminate.prop="partiallySelectableSelected"
|
|
28
|
+
:disabled="disabled || pageSelectableKeys.length === 0"
|
|
29
|
+
@click.stop
|
|
30
|
+
@change="handleSelectAllChange"
|
|
31
|
+
/>
|
|
32
|
+
</div>
|
|
33
|
+
</template>
|
|
34
|
+
|
|
35
|
+
<template v-if="effectiveSelectionMode !== 'none'" #item-__kdt_select="slotItem">
|
|
36
|
+
<div class="k-datatable-select-cell">
|
|
37
|
+
<input
|
|
38
|
+
type="checkbox"
|
|
39
|
+
class="easy-checkbox"
|
|
40
|
+
:checked="isItemSelected(slotItem)"
|
|
41
|
+
:disabled="disabled || !isItemSelectable(slotItem)"
|
|
42
|
+
@click.stop
|
|
43
|
+
@change="($event) => handleItemSelectionChange($event, slotItem)"
|
|
44
|
+
/>
|
|
45
|
+
</div>
|
|
23
46
|
</template>
|
|
24
|
-
</EasyDataTable>
|
|
25
47
|
|
|
26
|
-
|
|
27
|
-
<EasyDataTable v-else v-bind="$attrs" :headers="headers" :items="items" :search="search" :theme-color="themeColor" :show-select="false" :body-row-class-name="composeBodyRowClassName" alternating buttons-pagination table-class-name="customize-table">
|
|
28
|
-
<template v-for="(_, name) in $slots" :key="name" v-slot:[name]="slotProps">
|
|
48
|
+
<template v-for="name in forwardedSlotNames" :key="name" v-slot:[name]="slotProps">
|
|
29
49
|
<slot :name="name" v-bind="slotProps" />
|
|
30
50
|
</template>
|
|
31
51
|
</EasyDataTable>
|
|
@@ -39,7 +59,7 @@ import "vue3-easy-data-table/dist/style.css";
|
|
|
39
59
|
export default {
|
|
40
60
|
name: "kDatatable",
|
|
41
61
|
components: { EasyDataTable },
|
|
42
|
-
inheritAttrs: false,
|
|
62
|
+
inheritAttrs: false,
|
|
43
63
|
|
|
44
64
|
props: {
|
|
45
65
|
headers: { type: Array, required: true },
|
|
@@ -59,7 +79,12 @@ export default {
|
|
|
59
79
|
|
|
60
80
|
itemSelectable: {
|
|
61
81
|
type: Function,
|
|
62
|
-
default: () =>
|
|
82
|
+
default: () => true,
|
|
83
|
+
},
|
|
84
|
+
|
|
85
|
+
itemKey: {
|
|
86
|
+
type: [String, Function, null],
|
|
87
|
+
default: null,
|
|
63
88
|
},
|
|
64
89
|
|
|
65
90
|
modelValue: {
|
|
@@ -72,115 +97,195 @@ export default {
|
|
|
72
97
|
|
|
73
98
|
data() {
|
|
74
99
|
return {
|
|
75
|
-
internalSelection:
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
100
|
+
internalSelection: [],
|
|
101
|
+
selectedKeys: [],
|
|
102
|
+
selectedKeySet: new Set(),
|
|
103
|
+
lastSelectionAnchorKey: null,
|
|
104
|
+
currentPageRowsCache: [],
|
|
105
|
+
keyedItems: [],
|
|
106
|
+
currentItemsByKey: new Map(),
|
|
107
|
+
baseKeyToKeys: new Map(),
|
|
108
|
+
sourceItemToKey: new WeakMap(),
|
|
109
|
+
selectableKeys: [],
|
|
79
110
|
};
|
|
80
111
|
},
|
|
81
|
-
|
|
82
|
-
this.currentPageRowsCache = [];
|
|
83
|
-
},
|
|
84
|
-
mounted() {
|
|
85
|
-
this.bindSelectionInteractionListener();
|
|
86
|
-
},
|
|
87
|
-
beforeUnmount() {
|
|
88
|
-
this.unbindSelectionInteractionListener();
|
|
89
|
-
},
|
|
112
|
+
|
|
90
113
|
computed: {
|
|
91
114
|
effectiveSelectionMode() {
|
|
92
115
|
return this.disabled ? "none" : this.selectionMode;
|
|
93
116
|
},
|
|
117
|
+
computedHeaders() {
|
|
118
|
+
if (this.effectiveSelectionMode === "none") return this.headers;
|
|
119
|
+
return [{ text: "", value: "__kdt_select", width: 36 }, ...this.headers];
|
|
120
|
+
},
|
|
121
|
+
forwardedSlotNames() {
|
|
122
|
+
const reserved = new Set(["header-__kdt_select", "item-__kdt_select"]);
|
|
123
|
+
return Object.keys(this.$slots).filter((name) => !reserved.has(name));
|
|
124
|
+
},
|
|
125
|
+
pageSelectableKeys() {
|
|
126
|
+
const keys = [];
|
|
127
|
+
const seen = new Set();
|
|
128
|
+
this.currentPageRowsCache.forEach((rowItem) => {
|
|
129
|
+
const key = this.resolveIncomingItemKey(rowItem);
|
|
130
|
+
if (!key || seen.has(key)) return;
|
|
131
|
+
const sourceItem = this.currentItemsByKey.get(key);
|
|
132
|
+
if (!sourceItem || !this.isItemSelectable(sourceItem)) return;
|
|
133
|
+
seen.add(key);
|
|
134
|
+
keys.push(key);
|
|
135
|
+
});
|
|
136
|
+
return keys;
|
|
137
|
+
},
|
|
138
|
+
allSelectableSelected() {
|
|
139
|
+
if (!this.pageSelectableKeys.length) return false;
|
|
140
|
+
return this.pageSelectableKeys.every((key) => this.selectedKeySet.has(key));
|
|
141
|
+
},
|
|
142
|
+
partiallySelectableSelected() {
|
|
143
|
+
if (!this.pageSelectableKeys.length || this.allSelectableSelected) return false;
|
|
144
|
+
return this.pageSelectableKeys.some((key) => this.selectedKeySet.has(key));
|
|
145
|
+
},
|
|
146
|
+
},
|
|
147
|
+
|
|
148
|
+
created() {
|
|
149
|
+
this.rebuildItemCaches();
|
|
150
|
+
this.applyExternalModelValue(this.modelValue);
|
|
94
151
|
},
|
|
95
152
|
|
|
96
153
|
watch: {
|
|
154
|
+
items: {
|
|
155
|
+
handler() {
|
|
156
|
+
this.rebuildItemCaches();
|
|
157
|
+
this.reconcileSelectionWithItems();
|
|
158
|
+
},
|
|
159
|
+
deep: false,
|
|
160
|
+
},
|
|
161
|
+
itemSelectable: {
|
|
162
|
+
handler() {
|
|
163
|
+
this.rebuildItemCaches();
|
|
164
|
+
this.reconcileSelectionWithItems();
|
|
165
|
+
},
|
|
166
|
+
deep: false,
|
|
167
|
+
},
|
|
168
|
+
itemKey: {
|
|
169
|
+
handler() {
|
|
170
|
+
this.rebuildItemCaches();
|
|
171
|
+
this.reconcileSelectionWithItems();
|
|
172
|
+
},
|
|
173
|
+
deep: false,
|
|
174
|
+
},
|
|
97
175
|
modelValue(val) {
|
|
98
|
-
this.
|
|
176
|
+
this.applyExternalModelValue(val);
|
|
177
|
+
},
|
|
178
|
+
selectionMode() {
|
|
179
|
+
this.applyExternalModelValue(this.modelValue);
|
|
99
180
|
},
|
|
100
181
|
},
|
|
101
182
|
|
|
102
183
|
methods: {
|
|
103
|
-
|
|
104
|
-
if (this.
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
this.$emit("update:modelValue", nextSelection[0] || null);
|
|
108
|
-
return;
|
|
109
|
-
}
|
|
184
|
+
handleSelectAllChange(event) {
|
|
185
|
+
if (this.effectiveSelectionMode !== "multiple" || this.disabled) return;
|
|
186
|
+
const shouldSelect = Boolean(event?.target?.checked);
|
|
187
|
+
const nextKeySet = new Set(this.selectedKeys);
|
|
110
188
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
this
|
|
121
|
-
},
|
|
122
|
-
unbindSelectionInteractionListener() {
|
|
123
|
-
this.$refs.tableWrapper?.removeEventListener("click", this.captureSelectionInteraction, true);
|
|
189
|
+
this.pageSelectableKeys.forEach((key) => {
|
|
190
|
+
if (shouldSelect) nextKeySet.add(key);
|
|
191
|
+
else nextKeySet.delete(key);
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
const nextKeys = this.keyedItems
|
|
195
|
+
.map((item) => item.__kdt_key)
|
|
196
|
+
.filter((itemKey) => nextKeySet.has(itemKey));
|
|
197
|
+
|
|
198
|
+
this.commitSelectionByKeys(nextKeys, { emit: true, anchorKey: null });
|
|
124
199
|
},
|
|
125
|
-
|
|
126
|
-
if (this.
|
|
200
|
+
handleItemSelectionChange(event, slotItem) {
|
|
201
|
+
if (this.effectiveSelectionMode === "none" || this.disabled) return;
|
|
202
|
+
|
|
203
|
+
const key = this.resolveIncomingItemKey(slotItem);
|
|
204
|
+
if (!key) return;
|
|
205
|
+
|
|
206
|
+
const sourceItem = this.currentItemsByKey.get(key);
|
|
207
|
+
if (!sourceItem || !this.isItemSelectable(sourceItem)) return;
|
|
208
|
+
|
|
209
|
+
const shouldSelect = Boolean(event?.target?.checked);
|
|
210
|
+
|
|
211
|
+
if (this.selectionMode === "single") {
|
|
212
|
+
this.commitSelectionByKeys(shouldSelect ? [key] : [], {
|
|
213
|
+
emit: true,
|
|
214
|
+
anchorKey: shouldSelect ? key : null,
|
|
215
|
+
});
|
|
127
216
|
return;
|
|
128
217
|
}
|
|
129
218
|
|
|
130
|
-
|
|
131
|
-
|
|
219
|
+
if (event?.shiftKey && this.lastSelectionAnchorKey && key !== this.lastSelectionAnchorKey) {
|
|
220
|
+
const selectableKeySet = new Set(this.selectableKeys);
|
|
221
|
+
const rangeKeys = this.resolveRangeKeys(this.lastSelectionAnchorKey, key).filter((rangeKey) =>
|
|
222
|
+
selectableKeySet.has(rangeKey),
|
|
223
|
+
);
|
|
224
|
+
const nextKeySet = new Set(this.selectedKeys);
|
|
225
|
+
|
|
226
|
+
rangeKeys.forEach((rangeKey) => {
|
|
227
|
+
if (shouldSelect) nextKeySet.add(rangeKey);
|
|
228
|
+
else nextKeySet.delete(rangeKey);
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
const nextKeys = this.keyedItems
|
|
232
|
+
.map((item) => item.__kdt_key)
|
|
233
|
+
.filter((itemKey) => nextKeySet.has(itemKey));
|
|
132
234
|
|
|
133
|
-
|
|
134
|
-
if (!row) {
|
|
135
|
-
// Clear pending row interaction so bulk select doesn't reuse stale row state.
|
|
136
|
-
this.pendingSelectionInteraction = null;
|
|
235
|
+
this.commitSelectionByKeys(nextKeys, { emit: true });
|
|
137
236
|
return;
|
|
138
237
|
}
|
|
139
238
|
|
|
140
|
-
const
|
|
141
|
-
if (
|
|
142
|
-
|
|
239
|
+
const nextKeySet = new Set(this.selectedKeys);
|
|
240
|
+
if (shouldSelect) nextKeySet.add(key);
|
|
241
|
+
else nextKeySet.delete(key);
|
|
143
242
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
}
|
|
243
|
+
const nextKeys = this.keyedItems
|
|
244
|
+
.map((item) => item.__kdt_key)
|
|
245
|
+
.filter((itemKey) => nextKeySet.has(itemKey));
|
|
148
246
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
}
|
|
247
|
+
this.commitSelectionByKeys(nextKeys, { emit: true, anchorKey: key });
|
|
248
|
+
},
|
|
249
|
+
isItemSelected(item) {
|
|
250
|
+
const key = this.resolveIncomingItemKey(item);
|
|
251
|
+
return key != null && this.selectedKeySet.has(key);
|
|
252
|
+
},
|
|
253
|
+
isItemSelectable(item) {
|
|
254
|
+
if (typeof this.itemSelectable !== "function") return true;
|
|
255
|
+
try {
|
|
256
|
+
return this.itemSelectable(this.normalizeItem(item)) !== false;
|
|
257
|
+
} catch {
|
|
258
|
+
return false;
|
|
162
259
|
}
|
|
163
|
-
|
|
164
|
-
this.pendingSelectionInteraction = {
|
|
165
|
-
shiftKey: event.shiftKey,
|
|
166
|
-
rowNumber,
|
|
167
|
-
};
|
|
168
260
|
},
|
|
169
|
-
|
|
170
|
-
const
|
|
171
|
-
|
|
261
|
+
resolveRangeKeys(anchorKey, targetKey) {
|
|
262
|
+
const visibleKeys = this.currentPageRowsCache
|
|
263
|
+
.map((item) => this.resolveIncomingItemKey(item))
|
|
264
|
+
.filter((key) => key != null);
|
|
265
|
+
|
|
266
|
+
const fallbackKeys = this.keyedItems.map((item) => item.__kdt_key);
|
|
267
|
+
const keyOrders = visibleKeys.length ? [visibleKeys, fallbackKeys] : [fallbackKeys];
|
|
268
|
+
|
|
269
|
+
for (const orderedKeys of keyOrders) {
|
|
270
|
+
const anchorIndex = orderedKeys.indexOf(anchorKey);
|
|
271
|
+
const targetIndex = orderedKeys.indexOf(targetKey);
|
|
272
|
+
if (anchorIndex === -1 || targetIndex === -1) continue;
|
|
273
|
+
|
|
274
|
+
const [start, end] =
|
|
275
|
+
anchorIndex <= targetIndex ? [anchorIndex, targetIndex] : [targetIndex, anchorIndex];
|
|
276
|
+
return orderedKeys.slice(start, end + 1);
|
|
277
|
+
}
|
|
172
278
|
|
|
173
|
-
|
|
174
|
-
const rowIndex = selectableRows.indexOf(rowElement);
|
|
175
|
-
return rowIndex === -1 ? null : rowIndex + 1;
|
|
279
|
+
return [targetKey];
|
|
176
280
|
},
|
|
177
281
|
composeBodyRowClassName(item, rowNumber) {
|
|
178
282
|
if (rowNumber === 1) {
|
|
179
283
|
this.currentPageRowsCache = [];
|
|
180
284
|
}
|
|
181
|
-
this.currentPageRowsCache[rowNumber - 1] =
|
|
285
|
+
this.currentPageRowsCache[rowNumber - 1] = item;
|
|
182
286
|
|
|
183
|
-
const externalBodyRowClass =
|
|
287
|
+
const externalBodyRowClass =
|
|
288
|
+
this.$attrs["body-row-class-name"] ?? this.$attrs.bodyRowClassName;
|
|
184
289
|
if (typeof externalBodyRowClass === "function") {
|
|
185
290
|
return externalBodyRowClass(item, rowNumber);
|
|
186
291
|
}
|
|
@@ -189,125 +294,200 @@ export default {
|
|
|
189
294
|
}
|
|
190
295
|
return "";
|
|
191
296
|
},
|
|
192
|
-
|
|
193
|
-
|
|
297
|
+
rebuildItemCaches() {
|
|
298
|
+
const keyedItems = [];
|
|
299
|
+
const currentItemsByKey = new Map();
|
|
300
|
+
const baseKeyToKeys = new Map();
|
|
301
|
+
const sourceItemToKey = new WeakMap();
|
|
302
|
+
const selectableKeys = [];
|
|
303
|
+
|
|
304
|
+
this.items.forEach((sourceItem, index) => {
|
|
305
|
+
const baseKey = this.deriveBaseKey(sourceItem, index);
|
|
306
|
+
const uniqueKey = this.ensureUniqueKey(baseKey, currentItemsByKey);
|
|
307
|
+
const normalizedItem = this.normalizeItem(sourceItem);
|
|
308
|
+
const keyedItem =
|
|
309
|
+
normalizedItem && typeof normalizedItem === "object"
|
|
310
|
+
? { ...normalizedItem, __kdt_key: uniqueKey }
|
|
311
|
+
: { value: normalizedItem, __kdt_key: uniqueKey };
|
|
312
|
+
|
|
313
|
+
keyedItems.push(keyedItem);
|
|
314
|
+
currentItemsByKey.set(uniqueKey, sourceItem);
|
|
315
|
+
|
|
316
|
+
if (sourceItem && typeof sourceItem === "object") {
|
|
317
|
+
sourceItemToKey.set(sourceItem, uniqueKey);
|
|
318
|
+
}
|
|
194
319
|
|
|
195
|
-
|
|
196
|
-
|
|
320
|
+
const keyList = baseKeyToKeys.get(baseKey) ?? [];
|
|
321
|
+
keyList.push(uniqueKey);
|
|
322
|
+
baseKeyToKeys.set(baseKey, keyList);
|
|
197
323
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
324
|
+
if (this.isItemSelectable(sourceItem)) {
|
|
325
|
+
selectableKeys.push(uniqueKey);
|
|
326
|
+
}
|
|
327
|
+
});
|
|
328
|
+
|
|
329
|
+
this.keyedItems = keyedItems;
|
|
330
|
+
this.currentItemsByKey = currentItemsByKey;
|
|
331
|
+
this.baseKeyToKeys = baseKeyToKeys;
|
|
332
|
+
this.sourceItemToKey = sourceItemToKey;
|
|
333
|
+
this.selectableKeys = selectableKeys;
|
|
334
|
+
this.currentPageRowsCache = [];
|
|
335
|
+
},
|
|
336
|
+
ensureUniqueKey(baseKey, usedKeysMap) {
|
|
337
|
+
if (!usedKeysMap.has(baseKey)) return baseKey;
|
|
338
|
+
let suffix = 1;
|
|
339
|
+
let candidate = `${baseKey}#${suffix}`;
|
|
340
|
+
while (usedKeysMap.has(candidate)) {
|
|
341
|
+
suffix += 1;
|
|
342
|
+
candidate = `${baseKey}#${suffix}`;
|
|
343
|
+
}
|
|
344
|
+
return candidate;
|
|
345
|
+
},
|
|
346
|
+
deriveBaseKey(item, index = null) {
|
|
347
|
+
const normalized = this.normalizeItem(item);
|
|
348
|
+
const configuredKey = this.resolveConfiguredKey(normalized, index);
|
|
349
|
+
if (configuredKey != null && configuredKey !== "") {
|
|
350
|
+
return `k:${String(configuredKey)}`;
|
|
351
|
+
}
|
|
204
352
|
|
|
205
|
-
if (
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
353
|
+
if (normalized && typeof normalized === "object") {
|
|
354
|
+
if (normalized.id != null) return `id:${String(normalized.id)}`;
|
|
355
|
+
if (normalized.uuid != null) return `uuid:${String(normalized.uuid)}`;
|
|
356
|
+
if (normalized.hospIncNumber != null) {
|
|
357
|
+
return `hospIncNumber:${String(normalized.hospIncNumber)}`;
|
|
358
|
+
}
|
|
209
359
|
}
|
|
210
360
|
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
return
|
|
361
|
+
if (index != null) return `index:${index}`;
|
|
362
|
+
|
|
363
|
+
try {
|
|
364
|
+
return `json:${JSON.stringify(normalized)}`;
|
|
365
|
+
} catch {
|
|
366
|
+
return "fallback:0";
|
|
367
|
+
}
|
|
368
|
+
},
|
|
369
|
+
resolveConfiguredKey(item, index = null) {
|
|
370
|
+
if (!this.itemKey) return null;
|
|
371
|
+
|
|
372
|
+
if (typeof this.itemKey === "function") {
|
|
373
|
+
try {
|
|
374
|
+
return this.itemKey(item, index);
|
|
375
|
+
} catch {
|
|
376
|
+
return null;
|
|
377
|
+
}
|
|
217
378
|
}
|
|
218
379
|
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
const shouldSelectRange = this.containsItem(newSelection, toggledItem);
|
|
222
|
-
return this.applyRangeSelection(newSelection, anchorIndex, targetIndex, interaction.rowNumber, shouldSelectRange);
|
|
223
|
-
},
|
|
224
|
-
applyRangeSelection(baseSelection, anchorIndex, targetIndex, targetRowNumber, shouldSelectRange) {
|
|
225
|
-
const rangeItems = this.getRangeItems(anchorIndex, targetIndex, targetRowNumber);
|
|
226
|
-
if (!rangeItems.length) return baseSelection;
|
|
227
|
-
|
|
228
|
-
let nextSelection = [...baseSelection];
|
|
229
|
-
if (shouldSelectRange) {
|
|
230
|
-
rangeItems.forEach((item) => {
|
|
231
|
-
if (!this.containsItem(nextSelection, item)) {
|
|
232
|
-
nextSelection.push(this.normalizeItem(item));
|
|
233
|
-
}
|
|
234
|
-
});
|
|
235
|
-
} else {
|
|
236
|
-
nextSelection = nextSelection.filter((selectedItem) => !rangeItems.some((item) => this.areItemsEqual(selectedItem, item)));
|
|
380
|
+
if (typeof this.itemKey === "string" && item && typeof item === "object") {
|
|
381
|
+
return item[this.itemKey];
|
|
237
382
|
}
|
|
238
383
|
|
|
239
|
-
return
|
|
384
|
+
return null;
|
|
240
385
|
},
|
|
241
|
-
|
|
242
|
-
const
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
const
|
|
246
|
-
if (
|
|
247
|
-
return
|
|
386
|
+
resolveIncomingItemKey(item, index = null) {
|
|
387
|
+
const normalized = this.normalizeItem(item);
|
|
388
|
+
|
|
389
|
+
if (normalized && typeof normalized === "object") {
|
|
390
|
+
const slotKey = normalized.__kdt_key;
|
|
391
|
+
if (slotKey != null && this.currentItemsByKey.has(String(slotKey))) {
|
|
392
|
+
return String(slotKey);
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
const byReference = this.sourceItemToKey.get(normalized);
|
|
396
|
+
if (byReference && this.currentItemsByKey.has(byReference)) {
|
|
397
|
+
return byReference;
|
|
248
398
|
}
|
|
249
399
|
}
|
|
250
400
|
|
|
251
|
-
const
|
|
252
|
-
|
|
401
|
+
const baseKey = this.deriveBaseKey(normalized, index);
|
|
402
|
+
const candidates = this.baseKeyToKeys.get(baseKey) ?? [];
|
|
403
|
+
|
|
404
|
+
if (candidates.length === 1) return candidates[0];
|
|
405
|
+
if (candidates.length > 1) return candidates[0];
|
|
406
|
+
return null;
|
|
253
407
|
},
|
|
254
408
|
normalizeItem(item) {
|
|
255
409
|
if (!item || typeof item !== "object") return item;
|
|
256
410
|
const normalized = { ...item };
|
|
257
411
|
delete normalized.checkbox;
|
|
258
412
|
delete normalized.index;
|
|
413
|
+
delete normalized.__kdt_select;
|
|
259
414
|
return normalized;
|
|
260
415
|
},
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
if (normalized.uuid != null) return `uuid:${normalized.uuid}`;
|
|
266
|
-
if (normalized.hospIncNumber != null) return `hospIncNumber:${normalized.hospIncNumber}`;
|
|
267
|
-
return null;
|
|
268
|
-
},
|
|
269
|
-
areItemsEqual(left, right) {
|
|
270
|
-
const leftKey = this.extractStableKey(left);
|
|
271
|
-
const rightKey = this.extractStableKey(right);
|
|
272
|
-
if (leftKey != null || rightKey != null) {
|
|
273
|
-
return leftKey != null && leftKey === rightKey;
|
|
416
|
+
applyExternalModelValue(value) {
|
|
417
|
+
if (this.selectionMode === "none") {
|
|
418
|
+
this.commitSelectionByKeys([], { emit: false, anchorKey: null });
|
|
419
|
+
return;
|
|
274
420
|
}
|
|
275
421
|
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
return
|
|
280
|
-
} catch {
|
|
281
|
-
return normalizedLeft === normalizedRight;
|
|
422
|
+
if (this.selectionMode === "single") {
|
|
423
|
+
const key = value ? this.resolveIncomingItemKey(value) : null;
|
|
424
|
+
this.commitSelectionByKeys(key ? [key] : [], { emit: false, anchorKey: key ?? null });
|
|
425
|
+
return;
|
|
282
426
|
}
|
|
427
|
+
|
|
428
|
+
const incomingArray = Array.isArray(value) ? value : [];
|
|
429
|
+
const nextKeys = incomingArray
|
|
430
|
+
.map((item, index) => this.resolveIncomingItemKey(item, index))
|
|
431
|
+
.filter((key) => key != null);
|
|
432
|
+
this.commitSelectionByKeys(nextKeys, { emit: false });
|
|
283
433
|
},
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
434
|
+
reconcileSelectionWithItems() {
|
|
435
|
+
const changed = this.commitSelectionByKeys(this.selectedKeys, { emit: false });
|
|
436
|
+
if (changed) {
|
|
437
|
+
this.emitSelection();
|
|
438
|
+
}
|
|
289
439
|
},
|
|
290
|
-
|
|
291
|
-
const
|
|
292
|
-
|
|
440
|
+
commitSelectionByKeys(keys, { emit = true, anchorKey } = {}) {
|
|
441
|
+
const requestedKeys = Array.isArray(keys) ? keys : [];
|
|
442
|
+
const nextKeys = [];
|
|
443
|
+
const seen = new Set();
|
|
444
|
+
|
|
445
|
+
requestedKeys.forEach((key) => {
|
|
446
|
+
if (key == null || seen.has(key)) return;
|
|
447
|
+
const sourceItem = this.currentItemsByKey.get(key);
|
|
448
|
+
if (!sourceItem || !this.isItemSelectable(sourceItem)) return;
|
|
449
|
+
seen.add(key);
|
|
450
|
+
nextKeys.push(key);
|
|
451
|
+
});
|
|
452
|
+
|
|
453
|
+
if (this.selectionMode === "single" && nextKeys.length > 1) {
|
|
454
|
+
nextKeys.splice(1);
|
|
455
|
+
}
|
|
293
456
|
|
|
294
|
-
const
|
|
295
|
-
if (removed.length === 1) return this.normalizeItem(removed[0]);
|
|
457
|
+
const hasChanged = !this.areKeyArraysEqual(nextKeys, this.selectedKeys);
|
|
296
458
|
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
459
|
+
this.selectedKeys = nextKeys;
|
|
460
|
+
this.selectedKeySet = new Set(nextKeys);
|
|
461
|
+
this.internalSelection = nextKeys
|
|
462
|
+
.map((key) => this.currentItemsByKey.get(key))
|
|
463
|
+
.filter((item) => item != null);
|
|
464
|
+
|
|
465
|
+
if (anchorKey !== undefined) {
|
|
466
|
+
this.lastSelectionAnchorKey = anchorKey;
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
if (emit && hasChanged) {
|
|
470
|
+
this.emitSelection();
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
return hasChanged;
|
|
301
474
|
},
|
|
302
|
-
|
|
303
|
-
if (
|
|
304
|
-
return
|
|
475
|
+
areKeyArraysEqual(left, right) {
|
|
476
|
+
if (left.length !== right.length) return false;
|
|
477
|
+
return left.every((key, index) => key === right[index]);
|
|
305
478
|
},
|
|
306
|
-
|
|
307
|
-
if (this.selectionMode === "
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
479
|
+
emitSelection() {
|
|
480
|
+
if (this.selectionMode === "single") {
|
|
481
|
+
this.$emit("update:modelValue", this.internalSelection[0] ?? null);
|
|
482
|
+
return;
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
if (this.selectionMode === "multiple") {
|
|
486
|
+
this.$emit("update:modelValue", [...this.internalSelection]);
|
|
487
|
+
return;
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
this.$emit("update:modelValue", null);
|
|
311
491
|
},
|
|
312
492
|
},
|
|
313
493
|
};
|
|
@@ -347,12 +527,11 @@ export default {
|
|
|
347
527
|
--easy-table-footer-background-color: transparent;
|
|
348
528
|
--easy-table-footer-font-color: #1f2937;
|
|
349
529
|
--easy-table-footer-font-size: 14px;
|
|
350
|
-
--easy-table-footer-padding: 1rem;
|
|
530
|
+
--easy-table-footer-padding: 1rem;
|
|
351
531
|
--easy-table-footer-height: auto;
|
|
352
532
|
|
|
353
533
|
--easy-table-rows-per-page-selector-width: 70px;
|
|
354
534
|
--easy-table-rows-per-page-selector-option-padding: 10px;
|
|
355
|
-
--easy-table-rows-per-page-selector-z-index: 1;
|
|
356
535
|
--easy-table-rows-per-page-selector-z-index: 200;
|
|
357
536
|
--easy-table-rows-per-page-selector-font-color: #1f2937;
|
|
358
537
|
|
|
@@ -364,11 +543,17 @@ export default {
|
|
|
364
543
|
--easy-table-loading-mask-background-color: rgba(255, 255, 255, 0.6);
|
|
365
544
|
}
|
|
366
545
|
|
|
546
|
+
.k-datatable-select-cell {
|
|
547
|
+
display: flex;
|
|
548
|
+
align-items: center;
|
|
549
|
+
justify-content: center;
|
|
550
|
+
}
|
|
551
|
+
|
|
367
552
|
/* Target the rows-per-page dropdown */
|
|
368
553
|
.customize-table .easy-data-table__footer select {
|
|
369
|
-
background-color: #fff;
|
|
370
|
-
color: #1f2937;
|
|
371
|
-
padding: 0.25rem 0.5rem;
|
|
554
|
+
background-color: #fff;
|
|
555
|
+
color: #1f2937;
|
|
556
|
+
padding: 0.25rem 0.5rem;
|
|
372
557
|
border: 1px solid #bfdbfe;
|
|
373
558
|
border-radius: 0.25rem;
|
|
374
559
|
}
|