@juspay/svelte-ui-components 2.87.0 → 2.88.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.
@@ -33,11 +33,13 @@
33
33
  let {
34
34
  column,
35
35
  value,
36
- rowIndex
36
+ rowIndex,
37
+ originalIndex
37
38
  }: {
38
39
  column: TableColumn;
39
40
  value: TableCellValue;
40
41
  rowIndex: number;
42
+ originalIndex: number;
41
43
  } = $props();
42
44
 
43
45
  let copied = $state(false);
@@ -226,7 +228,7 @@
226
228
  <Toggle
227
229
  checked={isChecked}
228
230
  text=""
229
- onclick={(newChecked) => column.onToggle?.(rowIndex, newChecked)}
231
+ onclick={(newChecked) => column.onToggle?.(rowIndex, newChecked, originalIndex)}
230
232
  />
231
233
  </span>
232
234
  {:else if column.type === 'select'}
@@ -247,7 +249,7 @@
247
249
  itemTestId={selectData.itemTestId}
248
250
  onchange={(selectedIds) => {
249
251
  if (selectedIds.length > 0) {
250
- column.onSelect?.(rowIndex, selectedIds[0]);
252
+ column.onSelect?.(rowIndex, selectedIds[0], originalIndex);
251
253
  }
252
254
  }}
253
255
  />
@@ -275,7 +277,7 @@
275
277
  : null}
276
278
  onErrorMessage={inputData.onErrorMessage ?? null}
277
279
  actionInput={false}
278
- onInput={(newValue) => column.onInput?.(rowIndex, newValue)}
280
+ onInput={(newValue) => column.onInput?.(rowIndex, newValue, originalIndex)}
279
281
  />
280
282
  </span>
281
283
  {:else}
@@ -295,7 +297,7 @@
295
297
  disabled={buttonData.disabled ?? false}
296
298
  classes={buttonData.classes ?? ''}
297
299
  testId={buttonData.testId}
298
- onclick={() => column.onButtonClick?.(rowIndex)}
300
+ onclick={() => column.onButtonClick?.(rowIndex, originalIndex)}
299
301
  />
300
302
  </span>
301
303
  {:else}
@@ -317,7 +319,7 @@
317
319
  disabled={primary.disabled ?? false}
318
320
  classes={primary.classes ?? ''}
319
321
  testId={primary.testId}
320
- onclick={() => column.onPrimaryAction?.(rowIndex)}
322
+ onclick={() => column.onPrimaryAction?.(rowIndex, originalIndex)}
321
323
  />
322
324
  {/if}
323
325
  {#if actionData.menuItems && actionData.menuItems.length > 0}
@@ -329,7 +331,7 @@
329
331
  separator: item.separator
330
332
  }))}
331
333
  testId={column.testId && `${column.testId}-menu-${rowIndex}`}
332
- onselect={(menuItem) => column.onMenuAction?.(rowIndex, menuItem.value)}
334
+ onselect={(menuItem) => column.onMenuAction?.(rowIndex, menuItem.value, originalIndex)}
333
335
  >
334
336
  {#snippet trigger()}
335
337
  <span class="builtin-icon-button">
@@ -367,7 +369,7 @@
367
369
  separator: item.separator
368
370
  }))}
369
371
  testId={column.testId && `${column.testId}-popup-${rowIndex}`}
370
- onselect={(menuItem) => column.onMenuAction?.(rowIndex, menuItem.value)}
372
+ onselect={(menuItem) => column.onMenuAction?.(rowIndex, menuItem.value, originalIndex)}
371
373
  >
372
374
  {#snippet trigger()}
373
375
  <span class="builtin-icon-button">
@@ -3,6 +3,7 @@ type $$ComponentProps = {
3
3
  column: TableColumn;
4
4
  value: TableCellValue;
5
5
  rowIndex: number;
6
+ originalIndex: number;
6
7
  };
7
8
  declare const BuiltinCell: import("svelte").Component<$$ComponentProps, {}, "">;
8
9
  type BuiltinCell = ReturnType<typeof BuiltinCell>;
@@ -59,6 +59,10 @@
59
59
  let normalized = $derived(columns ? normalizeColumns(columns, rows ?? []) : null);
60
60
  let effectiveHeaders = $derived(normalized ? normalized.tableHeaders : tableHeaders);
61
61
  let effectiveData = $derived(normalized ? normalized.tableData : tableData);
62
+ // Maps each row reference back to its index in the consumer-supplied `rows`
63
+ // (pre-sort/pre-filter). Row refs are preserved through sort/filter/paginate,
64
+ // so cell callbacks can hand consumers a sort-stable `originalIndex`.
65
+ let originalIndexByRow = $derived(new Map(effectiveData.map((row, index) => [row, index])));
62
66
  let effectiveSortableColumns = $derived(
63
67
  normalized ? normalized.sortableColumns : sortableColumns
64
68
  );
@@ -712,6 +716,7 @@
712
716
  {:else}
713
717
  {#each paginatedTableData as row, pageRowIndex (rowIdByRow.get(row) ?? pageRowIndex)}
714
718
  {@const rowIndex = pageRowIndex + rowIndexOffset}
719
+ {@const originalIndex = originalIndexByRow.get(row) ?? rowIndex}
715
720
  {@const rowId = rowIdByRow.get(row) ?? String(rowIndex)}
716
721
  {@const rowDisabled = isCheckboxMode && isRowDisabled(rowId)}
717
722
  {@const rowSelected = isCheckboxMode && isRowSelected(rowId)}
@@ -781,9 +786,14 @@
781
786
  class:table-cell-clamp={keyedColumn?.maxWidth && isScalarCell}
782
787
  >
783
788
  {#if keyedColumn && typeof keyedColumn.cell === 'function' && keyedRow}
784
- {@render keyedColumn.cell(keyedRow, rowIndex)}
789
+ {@render keyedColumn.cell(keyedRow, rowIndex, originalIndex)}
785
790
  {:else if keyedColumn?.type && keyedColumn.type !== 'text' && keyedColumn.type !== 'custom'}
786
- <BuiltinCell column={keyedColumn} value={cellValue} {rowIndex} />
791
+ <BuiltinCell
792
+ column={keyedColumn}
793
+ value={cellValue}
794
+ {rowIndex}
795
+ {originalIndex}
796
+ />
787
797
  {:else if typeof cell === 'function'}
788
798
  {@render cell(cellValue, rowIndex, colIndex)}
789
799
  {:else}
@@ -172,9 +172,9 @@ export type TableRow = Record<string, TableCellValue>;
172
172
  * `sortable` prop. Equivalent to listing/omitting the column's index in
173
173
  * `sortableColumns`.
174
174
  * - `testId` — `data-pw` attribute emitted on this column's header cell.
175
- * - `cell` — column-scoped renderer snippet receiving the full keyed row and
176
- * the row index. Takes precedence over the table-wide `cell` snippet for
177
- * this column; required when `type` is `'custom'`.
175
+ * - `cell` — column-scoped renderer snippet receiving the full keyed row, the
176
+ * display row index, and the original (pre-sort) row index. Takes precedence
177
+ * over the table-wide `cell` snippet for this column; required when `type` is `'custom'`.
178
178
  * - `onToggle`/`onSelect`/`onInput`/`onButtonClick`/`onPrimaryAction`/`onMenuAction`
179
179
  * — change/action handlers for the matching interactive cell types. Behavior
180
180
  * lives on the column so row data stays plain JSON.
@@ -185,7 +185,7 @@ export type TableColumn = {
185
185
  type?: TableColumnType;
186
186
  sortable?: boolean;
187
187
  testId?: string;
188
- cell?: Snippet<[TableRow, number]>;
188
+ cell?: Snippet<[TableRow, number, number]>;
189
189
  /** Header tooltip text, shown on hover over the column label. */
190
190
  tooltip?: string;
191
191
  /**
@@ -207,13 +207,19 @@ export type TableColumn = {
207
207
  * the cell value itself.
208
208
  */
209
209
  getSortValue?: (row: TableRow, rowIndex: number) => string | number | boolean;
210
- /** `checked` is the NEW state after the flip, not the pre-click value. */
211
- onToggle?: (rowIndex: number, checked: boolean) => void;
212
- onSelect?: (rowIndex: number, selectedId: string) => void;
213
- onInput?: (rowIndex: number, value: string) => void;
214
- onButtonClick?: (rowIndex: number) => void;
215
- onPrimaryAction?: (rowIndex: number) => void;
216
- onMenuAction?: (rowIndex: number, itemId: string) => void;
210
+ /**
211
+ * Row-action handlers. `rowIndex` is the row's position in the CURRENT
212
+ * (sorted/filtered/paginated) view; `originalIndex` is its position in the
213
+ * consumer-supplied `rows` array, stable under sort/filter — index your own
214
+ * source array with `originalIndex` so actions hit the correct row when the
215
+ * table is sorted. `checked` is the NEW state after the flip, not the pre-click value.
216
+ */
217
+ onToggle?: (rowIndex: number, checked: boolean, originalIndex: number) => void;
218
+ onSelect?: (rowIndex: number, selectedId: string, originalIndex: number) => void;
219
+ onInput?: (rowIndex: number, value: string, originalIndex: number) => void;
220
+ onButtonClick?: (rowIndex: number, originalIndex: number) => void;
221
+ onPrimaryAction?: (rowIndex: number, originalIndex: number) => void;
222
+ onMenuAction?: (rowIndex: number, itemId: string, originalIndex: number) => void;
217
223
  };
218
224
  /**
219
225
  * Configuration for row checkbox selection (C2-1).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@juspay/svelte-ui-components",
3
- "version": "2.87.0",
3
+ "version": "2.88.0",
4
4
  "description": "A themeable Svelte 5 UI component library with CSS custom property driven styling",
5
5
  "keywords": [
6
6
  "svelte",