@juspay/svelte-ui-components 2.80.9 → 2.81.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.
@@ -0,0 +1,29 @@
1
+ import type { JSONValue } from 'type-decoder';
2
+ /** Comparison strategy for `sortTableRows`. */
3
+ export type TableSortType = 'date' | 'number' | 'string';
4
+ export type SortTableRowsOptions = {
5
+ /**
6
+ * Key to extract the comparable value from object-shaped cells (e.g. a
7
+ * compare cell's primary line). Scalar cells are compared directly.
8
+ */
9
+ nestedKey?: string;
10
+ /** Pins the first row (a totals/summary row) in place while the rest sort. */
11
+ hasSummaryRow?: boolean;
12
+ /**
13
+ * Forces the comparison strategy. When omitted, values that parse as
14
+ * numbers after stripping thousands separators, percent signs, and common
15
+ * currency symbols sort numerically; everything else sorts as
16
+ * case-insensitive text. Pass `'date'` explicitly for date columns —
17
+ * date detection is deliberately not inferred.
18
+ */
19
+ sortType?: TableSortType;
20
+ };
21
+ /**
22
+ * Sorts positional table rows by a column with type-aware comparison —
23
+ * currency/percent/thousands-separated numeric strings sort numerically,
24
+ * text sorts case-insensitively, dates (opt-in via `sortType: 'date'`) sort
25
+ * chronologically — with optional summary-row pinning. Pure and exported so
26
+ * consumers can pre-sort data for `sortMode: 'server'` tables or unit-test
27
+ * their sort expectations against exactly what Table would do.
28
+ */
29
+ export declare const sortTableRows: (rows: Array<JSONValue[]>, columnIndex: number, direction: "asc" | "desc" | null, options?: SortTableRowsOptions) => Array<JSONValue[]>;
@@ -0,0 +1,71 @@
1
+ const extractCellValue = (cellValue, nestedKey) => {
2
+ if (cellValue === null) {
3
+ return '';
4
+ }
5
+ if (typeof cellValue === 'object' && !Array.isArray(cellValue)) {
6
+ return cellValue[nestedKey] ?? '';
7
+ }
8
+ return cellValue;
9
+ };
10
+ const CURRENCY_AND_SEPARATORS = /[,%₹$€£]/g;
11
+ const inferSortType = (sampleValue, nestedKey) => {
12
+ const value = extractCellValue(sampleValue, nestedKey);
13
+ const cleanedValue = String(value).replace(CURRENCY_AND_SEPARATORS, '');
14
+ if (/^-?\d+(\.\d+)?%?$/.test(cleanedValue)) {
15
+ return 'number';
16
+ }
17
+ return 'string';
18
+ };
19
+ const toSortableValue = (cellValue, sortType, nestedKey) => {
20
+ const value = extractCellValue(cellValue, nestedKey);
21
+ if (sortType === 'number') {
22
+ const cleanedNumber = parseFloat(String(value).replace(CURRENCY_AND_SEPARATORS, ''));
23
+ return isNaN(cleanedNumber) ? 0 : cleanedNumber;
24
+ }
25
+ if (sortType === 'date') {
26
+ // Range cells ("1 Jun - 7 Jun") sort by their start date.
27
+ const dateString = String(value).split(' - ')[0];
28
+ const date = new Date(dateString);
29
+ return isNaN(date.getTime()) ? new Date(0) : date;
30
+ }
31
+ return String(value);
32
+ };
33
+ const compareSortableValues = (a, b) => {
34
+ if (a instanceof Date && b instanceof Date) {
35
+ return a.getTime() - b.getTime();
36
+ }
37
+ if (typeof a === 'number' && typeof b === 'number') {
38
+ return a - b;
39
+ }
40
+ return String(a).toLowerCase().localeCompare(String(b).toLowerCase());
41
+ };
42
+ /**
43
+ * Sorts positional table rows by a column with type-aware comparison —
44
+ * currency/percent/thousands-separated numeric strings sort numerically,
45
+ * text sorts case-insensitively, dates (opt-in via `sortType: 'date'`) sort
46
+ * chronologically — with optional summary-row pinning. Pure and exported so
47
+ * consumers can pre-sort data for `sortMode: 'server'` tables or unit-test
48
+ * their sort expectations against exactly what Table would do.
49
+ */
50
+ export const sortTableRows = (rows, columnIndex, direction, options = {}) => {
51
+ if (direction === null || rows.length <= 1) {
52
+ return rows;
53
+ }
54
+ const nestedKey = options.nestedKey ?? '';
55
+ let summaryRow = null;
56
+ let rowsToSort;
57
+ if (options.hasSummaryRow) {
58
+ [summaryRow, ...rowsToSort] = rows;
59
+ }
60
+ else {
61
+ rowsToSort = rows;
62
+ }
63
+ const sortType = options.sortType ?? inferSortType(rowsToSort[0]?.[columnIndex], nestedKey);
64
+ const multiplier = direction === 'desc' ? -1 : 1;
65
+ const sortedRows = [...rowsToSort].sort((rowA, rowB) => {
66
+ const valueA = toSortableValue(rowA[columnIndex], sortType, nestedKey);
67
+ const valueB = toSortableValue(rowB[columnIndex], sortType, nestedKey);
68
+ return compareSortableValues(valueA, valueB) * multiplier;
69
+ });
70
+ return options.hasSummaryRow && summaryRow ? [summaryRow, ...sortedRows] : sortedRows;
71
+ };
@@ -0,0 +1,5 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="none">
2
+ <circle cx="8" cy="3" r="1.5" fill="currentColor"/>
3
+ <circle cx="8" cy="8" r="1.5" fill="currentColor"/>
4
+ <circle cx="8" cy="13" r="1.5" fill="currentColor"/>
5
+ </svg>
@@ -0,0 +1,4 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="none">
2
+ <path d="M2 4.5L6.5 9L9 6.5L14 11.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
3
+ <path d="M9.5 11.5H14V7" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
4
+ </svg>
@@ -0,0 +1,4 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="none">
2
+ <path d="M2 11.5L6.5 7L9 9.5L14 4.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
3
+ <path d="M9.5 4.5H14V9" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
4
+ </svg>
package/dist/index.d.ts CHANGED
@@ -19,6 +19,8 @@ export { default as Toggle } from './Toggle/Toggle.svelte';
19
19
  export { default as Accordion } from './Accordion/Accordion.svelte';
20
20
  export { default as CheckListItem } from './CheckListItem/CheckListItem.svelte';
21
21
  export { default as Table } from './Table/Table.svelte';
22
+ export { normalizeColumns } from './Table/normalizeColumns';
23
+ export { sortTableRows } from './Table/sortEngine';
22
24
  export { default as Stepper } from './Stepper/Stepper.svelte';
23
25
  export { default as Step } from './Stepper/Step.svelte';
24
26
  export { default as Toast } from './Toast/Toast.svelte';
@@ -90,6 +92,8 @@ export type * from './Badge/properties';
90
92
  export type * from './Banner/properties';
91
93
  export type * from './Accordion/properties';
92
94
  export type * from './Table/properties';
95
+ export type { NormalizedColumns } from './Table/normalizeColumns';
96
+ export type { SortTableRowsOptions, TableSortType } from './Table/sortEngine';
93
97
  export type * from './Stepper/properties';
94
98
  export type * from './Toast/properties';
95
99
  export type * from './IconStack/properties';
package/dist/index.js CHANGED
@@ -19,6 +19,8 @@ export { default as Toggle } from './Toggle/Toggle.svelte';
19
19
  export { default as Accordion } from './Accordion/Accordion.svelte';
20
20
  export { default as CheckListItem } from './CheckListItem/CheckListItem.svelte';
21
21
  export { default as Table } from './Table/Table.svelte';
22
+ export { normalizeColumns } from './Table/normalizeColumns';
23
+ export { sortTableRows } from './Table/sortEngine';
22
24
  export { default as Stepper } from './Stepper/Stepper.svelte';
23
25
  export { default as Step } from './Stepper/Step.svelte';
24
26
  export { default as Toast } from './Toast/Toast.svelte';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@juspay/svelte-ui-components",
3
- "version": "2.80.9",
3
+ "version": "2.81.0",
4
4
  "description": "A themeable Svelte 5 UI component library with CSS custom property driven styling",
5
5
  "keywords": [
6
6
  "svelte",