ketekny-ui-kit 1.0.31 → 1.0.33
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 +385 -188
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
|
+
_pageSelectableKeys: [],
|
|
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
|
+
return this._pageSelectableKeys;
|
|
127
|
+
},
|
|
128
|
+
allSelectableSelected() {
|
|
129
|
+
if (!this.pageSelectableKeys.length) return false;
|
|
130
|
+
return this.pageSelectableKeys.every((key) => this.selectedKeySet.has(key));
|
|
131
|
+
},
|
|
132
|
+
partiallySelectableSelected() {
|
|
133
|
+
if (!this.pageSelectableKeys.length || this.allSelectableSelected) return false;
|
|
134
|
+
return this.pageSelectableKeys.some((key) => this.selectedKeySet.has(key));
|
|
135
|
+
},
|
|
136
|
+
},
|
|
137
|
+
|
|
138
|
+
created() {
|
|
139
|
+
this.currentPageRowsCache = []; // non-reactive — mutated during EasyDataTable render
|
|
140
|
+
this._pageRenderScheduled = false; // non-reactive flag
|
|
141
|
+
this.rebuildItemCaches();
|
|
142
|
+
this.applyExternalModelValue(this.modelValue);
|
|
94
143
|
},
|
|
95
144
|
|
|
96
145
|
watch: {
|
|
146
|
+
items: {
|
|
147
|
+
handler() {
|
|
148
|
+
this.rebuildItemCaches();
|
|
149
|
+
this.reconcileSelectionWithItems();
|
|
150
|
+
},
|
|
151
|
+
deep: false,
|
|
152
|
+
},
|
|
153
|
+
itemSelectable: {
|
|
154
|
+
handler() {
|
|
155
|
+
this.rebuildItemCaches();
|
|
156
|
+
this.reconcileSelectionWithItems();
|
|
157
|
+
},
|
|
158
|
+
deep: false,
|
|
159
|
+
},
|
|
160
|
+
itemKey: {
|
|
161
|
+
handler() {
|
|
162
|
+
this.rebuildItemCaches();
|
|
163
|
+
this.reconcileSelectionWithItems();
|
|
164
|
+
},
|
|
165
|
+
deep: false,
|
|
166
|
+
},
|
|
97
167
|
modelValue(val) {
|
|
98
|
-
this.
|
|
168
|
+
this.applyExternalModelValue(val);
|
|
169
|
+
},
|
|
170
|
+
selectionMode() {
|
|
171
|
+
this.applyExternalModelValue(this.modelValue);
|
|
99
172
|
},
|
|
100
173
|
},
|
|
101
174
|
|
|
102
175
|
methods: {
|
|
103
|
-
|
|
104
|
-
if (this.
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
this.$emit("update:modelValue", nextSelection[0] || null);
|
|
108
|
-
return;
|
|
109
|
-
}
|
|
176
|
+
handleSelectAllChange(event) {
|
|
177
|
+
if (this.effectiveSelectionMode !== "multiple" || this.disabled) return;
|
|
178
|
+
const shouldSelect = Boolean(event?.target?.checked);
|
|
179
|
+
const nextKeySet = new Set(this.selectedKeys);
|
|
110
180
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
this
|
|
121
|
-
},
|
|
122
|
-
unbindSelectionInteractionListener() {
|
|
123
|
-
this.$refs.tableWrapper?.removeEventListener("click", this.captureSelectionInteraction, true);
|
|
181
|
+
this.pageSelectableKeys.forEach((key) => {
|
|
182
|
+
if (shouldSelect) nextKeySet.add(key);
|
|
183
|
+
else nextKeySet.delete(key);
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
const nextKeys = this.keyedItems
|
|
187
|
+
.map((item) => item.__kdt_key)
|
|
188
|
+
.filter((itemKey) => nextKeySet.has(itemKey));
|
|
189
|
+
|
|
190
|
+
this.commitSelectionByKeys(nextKeys, { emit: true, anchorKey: null });
|
|
124
191
|
},
|
|
125
|
-
|
|
126
|
-
if (this.
|
|
192
|
+
handleItemSelectionChange(event, slotItem) {
|
|
193
|
+
if (this.effectiveSelectionMode === "none" || this.disabled) return;
|
|
194
|
+
|
|
195
|
+
const key = this.resolveIncomingItemKey(slotItem);
|
|
196
|
+
if (!key) return;
|
|
197
|
+
|
|
198
|
+
const sourceItem = this.currentItemsByKey.get(key);
|
|
199
|
+
if (!sourceItem || !this.isItemSelectable(sourceItem)) return;
|
|
200
|
+
|
|
201
|
+
const shouldSelect = Boolean(event?.target?.checked);
|
|
202
|
+
|
|
203
|
+
if (this.selectionMode === "single") {
|
|
204
|
+
this.commitSelectionByKeys(shouldSelect ? [key] : [], {
|
|
205
|
+
emit: true,
|
|
206
|
+
anchorKey: shouldSelect ? key : null,
|
|
207
|
+
});
|
|
127
208
|
return;
|
|
128
209
|
}
|
|
129
210
|
|
|
130
|
-
|
|
131
|
-
|
|
211
|
+
if (event?.shiftKey && this.lastSelectionAnchorKey && key !== this.lastSelectionAnchorKey) {
|
|
212
|
+
const selectableKeySet = new Set(this.selectableKeys);
|
|
213
|
+
const rangeKeys = this.resolveRangeKeys(this.lastSelectionAnchorKey, key).filter((rangeKey) =>
|
|
214
|
+
selectableKeySet.has(rangeKey),
|
|
215
|
+
);
|
|
216
|
+
const nextKeySet = new Set(this.selectedKeys);
|
|
132
217
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
218
|
+
rangeKeys.forEach((rangeKey) => {
|
|
219
|
+
if (shouldSelect) nextKeySet.add(rangeKey);
|
|
220
|
+
else nextKeySet.delete(rangeKey);
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
const nextKeys = this.keyedItems
|
|
224
|
+
.map((item) => item.__kdt_key)
|
|
225
|
+
.filter((itemKey) => nextKeySet.has(itemKey));
|
|
226
|
+
|
|
227
|
+
this.commitSelectionByKeys(nextKeys, { emit: true });
|
|
137
228
|
return;
|
|
138
229
|
}
|
|
139
230
|
|
|
140
|
-
const
|
|
141
|
-
if (
|
|
142
|
-
|
|
231
|
+
const nextKeySet = new Set(this.selectedKeys);
|
|
232
|
+
if (shouldSelect) nextKeySet.add(key);
|
|
233
|
+
else nextKeySet.delete(key);
|
|
143
234
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
}
|
|
235
|
+
const nextKeys = this.keyedItems
|
|
236
|
+
.map((item) => item.__kdt_key)
|
|
237
|
+
.filter((itemKey) => nextKeySet.has(itemKey));
|
|
148
238
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
}
|
|
239
|
+
this.commitSelectionByKeys(nextKeys, { emit: true, anchorKey: key });
|
|
240
|
+
},
|
|
241
|
+
isItemSelected(item) {
|
|
242
|
+
const key = this.resolveIncomingItemKey(item);
|
|
243
|
+
return key != null && this.selectedKeySet.has(key);
|
|
244
|
+
},
|
|
245
|
+
isItemSelectable(item) {
|
|
246
|
+
if (typeof this.itemSelectable !== "function") return true;
|
|
247
|
+
try {
|
|
248
|
+
return this.itemSelectable(this.normalizeItem(item)) !== false;
|
|
249
|
+
} catch {
|
|
250
|
+
return false;
|
|
162
251
|
}
|
|
163
|
-
|
|
164
|
-
this.pendingSelectionInteraction = {
|
|
165
|
-
shiftKey: event.shiftKey,
|
|
166
|
-
rowNumber,
|
|
167
|
-
};
|
|
168
252
|
},
|
|
169
|
-
|
|
170
|
-
const
|
|
171
|
-
|
|
253
|
+
resolveRangeKeys(anchorKey, targetKey) {
|
|
254
|
+
const visibleKeys = this.currentPageRowsCache
|
|
255
|
+
.map((item) => this.resolveIncomingItemKey(item))
|
|
256
|
+
.filter((key) => key != null);
|
|
257
|
+
|
|
258
|
+
const fallbackKeys = this.keyedItems.map((item) => item.__kdt_key);
|
|
259
|
+
const keyOrders = visibleKeys.length ? [visibleKeys, fallbackKeys] : [fallbackKeys];
|
|
260
|
+
|
|
261
|
+
for (const orderedKeys of keyOrders) {
|
|
262
|
+
const anchorIndex = orderedKeys.indexOf(anchorKey);
|
|
263
|
+
const targetIndex = orderedKeys.indexOf(targetKey);
|
|
264
|
+
if (anchorIndex === -1 || targetIndex === -1) continue;
|
|
265
|
+
|
|
266
|
+
const [start, end] =
|
|
267
|
+
anchorIndex <= targetIndex ? [anchorIndex, targetIndex] : [targetIndex, anchorIndex];
|
|
268
|
+
return orderedKeys.slice(start, end + 1);
|
|
269
|
+
}
|
|
172
270
|
|
|
173
|
-
|
|
174
|
-
const rowIndex = selectableRows.indexOf(rowElement);
|
|
175
|
-
return rowIndex === -1 ? null : rowIndex + 1;
|
|
271
|
+
return [targetKey];
|
|
176
272
|
},
|
|
177
273
|
composeBodyRowClassName(item, rowNumber) {
|
|
178
274
|
if (rowNumber === 1) {
|
|
179
275
|
this.currentPageRowsCache = [];
|
|
180
276
|
}
|
|
181
|
-
this.currentPageRowsCache[rowNumber - 1] =
|
|
277
|
+
this.currentPageRowsCache[rowNumber - 1] = item;
|
|
278
|
+
|
|
279
|
+
if (!this._pageRenderScheduled) {
|
|
280
|
+
this._pageRenderScheduled = true;
|
|
281
|
+
this.$nextTick(() => {
|
|
282
|
+
this._pageRenderScheduled = false;
|
|
283
|
+
this._pageSelectableKeys = this._computePageSelectableKeys();
|
|
284
|
+
});
|
|
285
|
+
}
|
|
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,126 +294,213 @@ export default {
|
|
|
189
294
|
}
|
|
190
295
|
return "";
|
|
191
296
|
},
|
|
192
|
-
|
|
193
|
-
|
|
297
|
+
_computePageSelectableKeys() {
|
|
298
|
+
const keys = [];
|
|
299
|
+
const seen = new Set();
|
|
300
|
+
this.currentPageRowsCache.forEach((rowItem) => {
|
|
301
|
+
const key = this.resolveIncomingItemKey(rowItem);
|
|
302
|
+
if (!key || seen.has(key)) return;
|
|
303
|
+
const sourceItem = this.currentItemsByKey.get(key);
|
|
304
|
+
if (!sourceItem || !this.isItemSelectable(sourceItem)) return;
|
|
305
|
+
seen.add(key);
|
|
306
|
+
keys.push(key);
|
|
307
|
+
});
|
|
308
|
+
return keys;
|
|
309
|
+
},
|
|
310
|
+
rebuildItemCaches() {
|
|
311
|
+
const keyedItems = [];
|
|
312
|
+
const currentItemsByKey = new Map();
|
|
313
|
+
const baseKeyToKeys = new Map();
|
|
314
|
+
const sourceItemToKey = new WeakMap();
|
|
315
|
+
const selectableKeys = [];
|
|
316
|
+
|
|
317
|
+
this.items.forEach((sourceItem, index) => {
|
|
318
|
+
const baseKey = this.deriveBaseKey(sourceItem, index);
|
|
319
|
+
const uniqueKey = this.ensureUniqueKey(baseKey, currentItemsByKey);
|
|
320
|
+
const normalizedItem = this.normalizeItem(sourceItem);
|
|
321
|
+
const keyedItem =
|
|
322
|
+
normalizedItem && typeof normalizedItem === "object"
|
|
323
|
+
? { ...normalizedItem, __kdt_key: uniqueKey }
|
|
324
|
+
: { value: normalizedItem, __kdt_key: uniqueKey };
|
|
325
|
+
|
|
326
|
+
keyedItems.push(keyedItem);
|
|
327
|
+
currentItemsByKey.set(uniqueKey, sourceItem);
|
|
328
|
+
|
|
329
|
+
if (sourceItem && typeof sourceItem === "object") {
|
|
330
|
+
sourceItemToKey.set(sourceItem, uniqueKey);
|
|
331
|
+
}
|
|
194
332
|
|
|
195
|
-
|
|
196
|
-
|
|
333
|
+
const keyList = baseKeyToKeys.get(baseKey) ?? [];
|
|
334
|
+
keyList.push(uniqueKey);
|
|
335
|
+
baseKeyToKeys.set(baseKey, keyList);
|
|
197
336
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
337
|
+
if (this.isItemSelectable(sourceItem)) {
|
|
338
|
+
selectableKeys.push(uniqueKey);
|
|
339
|
+
}
|
|
340
|
+
});
|
|
341
|
+
|
|
342
|
+
this.keyedItems = keyedItems;
|
|
343
|
+
this.currentItemsByKey = currentItemsByKey;
|
|
344
|
+
this.baseKeyToKeys = baseKeyToKeys;
|
|
345
|
+
this.sourceItemToKey = sourceItemToKey;
|
|
346
|
+
this.selectableKeys = selectableKeys;
|
|
347
|
+
this.currentPageRowsCache = [];
|
|
348
|
+
},
|
|
349
|
+
ensureUniqueKey(baseKey, usedKeysMap) {
|
|
350
|
+
if (!usedKeysMap.has(baseKey)) return baseKey;
|
|
351
|
+
let suffix = 1;
|
|
352
|
+
let candidate = `${baseKey}#${suffix}`;
|
|
353
|
+
while (usedKeysMap.has(candidate)) {
|
|
354
|
+
suffix += 1;
|
|
355
|
+
candidate = `${baseKey}#${suffix}`;
|
|
356
|
+
}
|
|
357
|
+
return candidate;
|
|
358
|
+
},
|
|
359
|
+
deriveBaseKey(item, index = null) {
|
|
360
|
+
const normalized = this.normalizeItem(item);
|
|
361
|
+
const configuredKey = this.resolveConfiguredKey(normalized, index);
|
|
362
|
+
if (configuredKey != null && configuredKey !== "") {
|
|
363
|
+
return `k:${String(configuredKey)}`;
|
|
364
|
+
}
|
|
204
365
|
|
|
205
|
-
if (
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
366
|
+
if (normalized && typeof normalized === "object") {
|
|
367
|
+
if (normalized.id != null) return `id:${String(normalized.id)}`;
|
|
368
|
+
if (normalized.uuid != null) return `uuid:${String(normalized.uuid)}`;
|
|
369
|
+
if (normalized.hospIncNumber != null) {
|
|
370
|
+
return `hospIncNumber:${String(normalized.hospIncNumber)}`;
|
|
371
|
+
}
|
|
209
372
|
}
|
|
210
373
|
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
return
|
|
374
|
+
if (index != null) return `index:${index}`;
|
|
375
|
+
|
|
376
|
+
try {
|
|
377
|
+
return `json:${JSON.stringify(normalized)}`;
|
|
378
|
+
} catch {
|
|
379
|
+
return "fallback:0";
|
|
380
|
+
}
|
|
381
|
+
},
|
|
382
|
+
resolveConfiguredKey(item, index = null) {
|
|
383
|
+
if (!this.itemKey) return null;
|
|
384
|
+
|
|
385
|
+
if (typeof this.itemKey === "function") {
|
|
386
|
+
try {
|
|
387
|
+
return this.itemKey(item, index);
|
|
388
|
+
} catch {
|
|
389
|
+
return null;
|
|
390
|
+
}
|
|
217
391
|
}
|
|
218
392
|
|
|
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)));
|
|
393
|
+
if (typeof this.itemKey === "string" && item && typeof item === "object") {
|
|
394
|
+
return item[this.itemKey];
|
|
237
395
|
}
|
|
238
396
|
|
|
239
|
-
return
|
|
397
|
+
return null;
|
|
240
398
|
},
|
|
241
|
-
|
|
242
|
-
const
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
const
|
|
246
|
-
if (
|
|
247
|
-
return
|
|
399
|
+
resolveIncomingItemKey(item, index = null) {
|
|
400
|
+
const normalized = this.normalizeItem(item);
|
|
401
|
+
|
|
402
|
+
if (normalized && typeof normalized === "object") {
|
|
403
|
+
const slotKey = normalized.__kdt_key;
|
|
404
|
+
if (slotKey != null && this.currentItemsByKey.has(String(slotKey))) {
|
|
405
|
+
return String(slotKey);
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
const byReference = this.sourceItemToKey.get(normalized);
|
|
409
|
+
if (byReference && this.currentItemsByKey.has(byReference)) {
|
|
410
|
+
return byReference;
|
|
248
411
|
}
|
|
249
412
|
}
|
|
250
413
|
|
|
251
|
-
const
|
|
252
|
-
|
|
414
|
+
const baseKey = this.deriveBaseKey(normalized, index);
|
|
415
|
+
const candidates = this.baseKeyToKeys.get(baseKey) ?? [];
|
|
416
|
+
|
|
417
|
+
if (candidates.length === 1) return candidates[0];
|
|
418
|
+
if (candidates.length > 1) return candidates[0];
|
|
419
|
+
return null;
|
|
253
420
|
},
|
|
254
421
|
normalizeItem(item) {
|
|
255
422
|
if (!item || typeof item !== "object") return item;
|
|
256
423
|
const normalized = { ...item };
|
|
257
424
|
delete normalized.checkbox;
|
|
258
425
|
delete normalized.index;
|
|
426
|
+
delete normalized.__kdt_select;
|
|
259
427
|
return normalized;
|
|
260
428
|
},
|
|
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;
|
|
429
|
+
applyExternalModelValue(value) {
|
|
430
|
+
if (this.selectionMode === "none") {
|
|
431
|
+
this.commitSelectionByKeys([], { emit: false, anchorKey: null });
|
|
432
|
+
return;
|
|
274
433
|
}
|
|
275
434
|
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
return
|
|
280
|
-
} catch {
|
|
281
|
-
return normalizedLeft === normalizedRight;
|
|
435
|
+
if (this.selectionMode === "single") {
|
|
436
|
+
const key = value ? this.resolveIncomingItemKey(value) : null;
|
|
437
|
+
this.commitSelectionByKeys(key ? [key] : [], { emit: false, anchorKey: key ?? null });
|
|
438
|
+
return;
|
|
282
439
|
}
|
|
440
|
+
|
|
441
|
+
const incomingArray = Array.isArray(value) ? value : [];
|
|
442
|
+
const nextKeys = incomingArray
|
|
443
|
+
.map((item, index) => this.resolveIncomingItemKey(item, index))
|
|
444
|
+
.filter((key) => key != null);
|
|
445
|
+
this.commitSelectionByKeys(nextKeys, { emit: false });
|
|
283
446
|
},
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
447
|
+
reconcileSelectionWithItems() {
|
|
448
|
+
const changed = this.commitSelectionByKeys(this.selectedKeys, { emit: false });
|
|
449
|
+
if (changed) {
|
|
450
|
+
this.emitSelection();
|
|
451
|
+
}
|
|
289
452
|
},
|
|
290
|
-
|
|
291
|
-
const
|
|
292
|
-
|
|
293
|
-
|
|
453
|
+
commitSelectionByKeys(keys, { emit = true, anchorKey } = {}) {
|
|
454
|
+
const requestedKeys = Array.isArray(keys) ? keys : [];
|
|
455
|
+
const nextKeys = [];
|
|
456
|
+
const seen = new Set();
|
|
457
|
+
|
|
458
|
+
requestedKeys.forEach((key) => {
|
|
459
|
+
if (key == null || seen.has(key)) return;
|
|
460
|
+
const sourceItem = this.currentItemsByKey.get(key);
|
|
461
|
+
if (!sourceItem || !this.isItemSelectable(sourceItem)) return;
|
|
462
|
+
seen.add(key);
|
|
463
|
+
nextKeys.push(key);
|
|
464
|
+
});
|
|
465
|
+
|
|
466
|
+
if (this.selectionMode === "single" && nextKeys.length > 1) {
|
|
467
|
+
nextKeys.splice(1);
|
|
468
|
+
}
|
|
294
469
|
|
|
295
|
-
const
|
|
296
|
-
if (removed.length === 1) return this.normalizeItem(removed[0]);
|
|
470
|
+
const hasChanged = !this.areKeyArraysEqual(nextKeys, this.selectedKeys);
|
|
297
471
|
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
472
|
+
this.selectedKeys = nextKeys;
|
|
473
|
+
this.selectedKeySet = new Set(nextKeys);
|
|
474
|
+
this.internalSelection = nextKeys
|
|
475
|
+
.map((key) => this.currentItemsByKey.get(key))
|
|
476
|
+
.filter((item) => item != null);
|
|
477
|
+
|
|
478
|
+
if (anchorKey !== undefined) {
|
|
479
|
+
this.lastSelectionAnchorKey = anchorKey;
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
if (emit && hasChanged) {
|
|
483
|
+
this.emitSelection();
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
return hasChanged;
|
|
302
487
|
},
|
|
303
|
-
|
|
304
|
-
if (
|
|
305
|
-
return
|
|
488
|
+
areKeyArraysEqual(left, right) {
|
|
489
|
+
if (left.length !== right.length) return false;
|
|
490
|
+
return left.every((key, index) => key === right[index]);
|
|
306
491
|
},
|
|
307
|
-
|
|
308
|
-
if (this.selectionMode === "
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
492
|
+
emitSelection() {
|
|
493
|
+
if (this.selectionMode === "single") {
|
|
494
|
+
this.$emit("update:modelValue", this.internalSelection[0] ?? null);
|
|
495
|
+
return;
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
if (this.selectionMode === "multiple") {
|
|
499
|
+
this.$emit("update:modelValue", [...this.internalSelection]);
|
|
500
|
+
return;
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
this.$emit("update:modelValue", null);
|
|
312
504
|
},
|
|
313
505
|
},
|
|
314
506
|
};
|
|
@@ -348,12 +540,11 @@ export default {
|
|
|
348
540
|
--easy-table-footer-background-color: transparent;
|
|
349
541
|
--easy-table-footer-font-color: #1f2937;
|
|
350
542
|
--easy-table-footer-font-size: 14px;
|
|
351
|
-
--easy-table-footer-padding: 1rem;
|
|
543
|
+
--easy-table-footer-padding: 1rem;
|
|
352
544
|
--easy-table-footer-height: auto;
|
|
353
545
|
|
|
354
546
|
--easy-table-rows-per-page-selector-width: 70px;
|
|
355
547
|
--easy-table-rows-per-page-selector-option-padding: 10px;
|
|
356
|
-
--easy-table-rows-per-page-selector-z-index: 1;
|
|
357
548
|
--easy-table-rows-per-page-selector-z-index: 200;
|
|
358
549
|
--easy-table-rows-per-page-selector-font-color: #1f2937;
|
|
359
550
|
|
|
@@ -365,11 +556,17 @@ export default {
|
|
|
365
556
|
--easy-table-loading-mask-background-color: rgba(255, 255, 255, 0.6);
|
|
366
557
|
}
|
|
367
558
|
|
|
559
|
+
.k-datatable-select-cell {
|
|
560
|
+
display: flex;
|
|
561
|
+
align-items: center;
|
|
562
|
+
justify-content: center;
|
|
563
|
+
}
|
|
564
|
+
|
|
368
565
|
/* Target the rows-per-page dropdown */
|
|
369
566
|
.customize-table .easy-data-table__footer select {
|
|
370
|
-
background-color: #fff;
|
|
371
|
-
color: #1f2937;
|
|
372
|
-
padding: 0.25rem 0.5rem;
|
|
567
|
+
background-color: #fff;
|
|
568
|
+
color: #1f2937;
|
|
569
|
+
padding: 0.25rem 0.5rem;
|
|
373
570
|
border: 1px solid #bfdbfe;
|
|
374
571
|
border-radius: 0.25rem;
|
|
375
572
|
}
|