ketekny-ui-kit 1.0.29 → 1.0.30

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "ketekny-ui-kit",
3
3
  "type": "module",
4
- "version": "1.0.29",
4
+ "version": "1.0.30",
5
5
  "description": "A Vue 3 UI component library with Tailwind CSS styling",
6
6
  "main": "index.js",
7
7
  "files": [
@@ -130,9 +130,12 @@ export default {
130
130
  const checkbox = event.target.closest(".easy-checkbox");
131
131
  if (!checkbox) return;
132
132
 
133
- // Ignore the header "select all" checkbox.
134
133
  const row = checkbox.closest("tbody tr");
135
- if (!row) return;
134
+ if (!row) {
135
+ // Clear pending row interaction so bulk select doesn't reuse stale row state.
136
+ this.pendingSelectionInteraction = null;
137
+ return;
138
+ }
136
139
 
137
140
  const rowNumber = this.resolveClickedRowNumber(row);
138
141
  if (!rowNumber) return;
@@ -193,12 +196,15 @@ export default {
193
196
  this.pendingSelectionInteraction = null;
194
197
 
195
198
  const toggledItemFromInteraction = interaction?.rowNumber ? this.currentPageRowsCache[interaction.rowNumber - 1] : null;
196
- const toggledItem = toggledItemFromInteraction ?? this.getToggledItem(oldSelection, newSelection);
199
+ const hasInteractionToggle = toggledItemFromInteraction
200
+ ? this.didItemSelectionChange(toggledItemFromInteraction, oldSelection, newSelection)
201
+ : false;
202
+ const toggledItem = hasInteractionToggle ? toggledItemFromInteraction : this.getToggledItem(oldSelection, newSelection);
197
203
  if (!toggledItem) return newSelection;
198
204
 
199
- if (!interaction?.shiftKey || !this.lastSelectionAnchor) {
205
+ if (!interaction?.shiftKey || !hasInteractionToggle || !this.lastSelectionAnchor) {
200
206
  this.lastSelectionAnchor = toggledItem;
201
- this.lastSelectionAnchorRowNumber = interaction?.rowNumber ?? null;
207
+ this.lastSelectionAnchorRowNumber = hasInteractionToggle ? interaction?.rowNumber ?? null : null;
202
208
  return newSelection;
203
209
  }
204
210
 
@@ -252,12 +258,35 @@ export default {
252
258
  delete normalized.index;
253
259
  return normalized;
254
260
  },
261
+ extractStableKey(item) {
262
+ const normalized = this.normalizeItem(item);
263
+ if (!normalized || typeof normalized !== "object") return null;
264
+ if (normalized.id != null) return `id:${normalized.id}`;
265
+ if (normalized.uuid != null) return `uuid:${normalized.uuid}`;
266
+ if (normalized.hospIncNumber != null) return `hospIncNumber:${normalized.hospIncNumber}`;
267
+ return null;
268
+ },
255
269
  areItemsEqual(left, right) {
256
- return JSON.stringify(this.normalizeItem(left)) === JSON.stringify(this.normalizeItem(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;
274
+ }
275
+
276
+ const normalizedLeft = this.normalizeItem(left);
277
+ const normalizedRight = this.normalizeItem(right);
278
+ try {
279
+ return JSON.stringify(normalizedLeft) === JSON.stringify(normalizedRight);
280
+ } catch {
281
+ return normalizedLeft === normalizedRight;
282
+ }
257
283
  },
258
284
  containsItem(collection, item) {
259
285
  return collection.some((current) => this.areItemsEqual(current, item));
260
286
  },
287
+ didItemSelectionChange(item, previousSelection, nextSelection) {
288
+ return this.containsItem(previousSelection, item) !== this.containsItem(nextSelection, item);
289
+ },
261
290
  getToggledItem(previousSelection, nextSelection) {
262
291
  const added = nextSelection.filter((item) => !this.containsItem(previousSelection, item));
263
292
  if (added.length === 1) return this.normalizeItem(added[0]);