@tokis/react 1.0.1 → 1.1.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.
Files changed (84) hide show
  1. package/README.md +8 -6
  2. package/dist/__tests__/Accordion.test.d.ts +2 -0
  3. package/dist/__tests__/Accordion.test.d.ts.map +1 -0
  4. package/dist/__tests__/Accordion.test.js +144 -0
  5. package/dist/__tests__/Accordion.test.js.map +1 -0
  6. package/dist/__tests__/Button.test.d.ts +2 -0
  7. package/dist/__tests__/Button.test.d.ts.map +1 -0
  8. package/dist/__tests__/Button.test.js +104 -0
  9. package/dist/__tests__/Button.test.js.map +1 -0
  10. package/dist/__tests__/Checkbox.test.d.ts +2 -0
  11. package/dist/__tests__/Checkbox.test.d.ts.map +1 -0
  12. package/dist/__tests__/Checkbox.test.js +90 -0
  13. package/dist/__tests__/Checkbox.test.js.map +1 -0
  14. package/dist/__tests__/Select.test.d.ts +2 -0
  15. package/dist/__tests__/Select.test.d.ts.map +1 -0
  16. package/dist/__tests__/Select.test.js +119 -0
  17. package/dist/__tests__/Select.test.js.map +1 -0
  18. package/dist/__tests__/datagrid-utils.test.d.ts +2 -0
  19. package/dist/__tests__/datagrid-utils.test.d.ts.map +1 -0
  20. package/dist/__tests__/datagrid-utils.test.js +190 -0
  21. package/dist/__tests__/datagrid-utils.test.js.map +1 -0
  22. package/dist/__tests__/date-utils.test.d.ts +2 -0
  23. package/dist/__tests__/date-utils.test.d.ts.map +1 -0
  24. package/dist/__tests__/date-utils.test.js +180 -0
  25. package/dist/__tests__/date-utils.test.js.map +1 -0
  26. package/dist/cjs/components/accordion/index.js +1 -1
  27. package/dist/cjs/components/checkbox/index.js +2 -1
  28. package/dist/cjs/components/datagrid/index.js +161 -0
  29. package/dist/cjs/components/datagrid/types.js +2 -0
  30. package/dist/cjs/components/datagrid/utils.js +87 -0
  31. package/dist/cjs/components/datepicker/Calendar.js +117 -0
  32. package/dist/cjs/components/datepicker/date-utils.js +121 -0
  33. package/dist/cjs/components/datepicker/index.js +134 -0
  34. package/dist/cjs/components/extended/index.js +39 -31
  35. package/dist/cjs/components/layout/index.js +5 -4
  36. package/dist/cjs/components/treeview/index.js +1 -1
  37. package/dist/cjs/hooks/useId.js +18 -5
  38. package/dist/cjs/index.js +2 -0
  39. package/dist/components/accordion/index.js +1 -1
  40. package/dist/components/accordion/index.js.map +1 -1
  41. package/dist/components/checkbox/index.js +2 -1
  42. package/dist/components/checkbox/index.js.map +1 -1
  43. package/dist/components/datagrid/index.d.ts +20 -0
  44. package/dist/components/datagrid/index.d.ts.map +1 -0
  45. package/dist/components/datagrid/index.js +159 -0
  46. package/dist/components/datagrid/index.js.map +1 -0
  47. package/dist/components/datagrid/types.d.ts +92 -0
  48. package/dist/components/datagrid/types.d.ts.map +1 -0
  49. package/dist/components/datagrid/types.js +2 -0
  50. package/dist/components/datagrid/types.js.map +1 -0
  51. package/dist/components/datagrid/utils.d.ts +14 -0
  52. package/dist/components/datagrid/utils.d.ts.map +1 -0
  53. package/dist/components/datagrid/utils.js +80 -0
  54. package/dist/components/datagrid/utils.js.map +1 -0
  55. package/dist/components/datepicker/Calendar.d.ts +30 -0
  56. package/dist/components/datepicker/Calendar.d.ts.map +1 -0
  57. package/dist/components/datepicker/Calendar.js +115 -0
  58. package/dist/components/datepicker/Calendar.js.map +1 -0
  59. package/dist/components/datepicker/date-utils.d.ts +34 -0
  60. package/dist/components/datepicker/date-utils.d.ts.map +1 -0
  61. package/dist/components/datepicker/date-utils.js +107 -0
  62. package/dist/components/datepicker/date-utils.js.map +1 -0
  63. package/dist/components/datepicker/index.d.ts +52 -0
  64. package/dist/components/datepicker/index.d.ts.map +1 -0
  65. package/dist/components/datepicker/index.js +128 -0
  66. package/dist/components/datepicker/index.js.map +1 -0
  67. package/dist/components/extended/index.d.ts +14 -29
  68. package/dist/components/extended/index.d.ts.map +1 -1
  69. package/dist/components/extended/index.js +40 -27
  70. package/dist/components/extended/index.js.map +1 -1
  71. package/dist/components/layout/index.d.ts.map +1 -1
  72. package/dist/components/layout/index.js +5 -4
  73. package/dist/components/layout/index.js.map +1 -1
  74. package/dist/components/treeview/index.js +1 -1
  75. package/dist/components/treeview/index.js.map +1 -1
  76. package/dist/hooks/useId.d.ts +13 -3
  77. package/dist/hooks/useId.d.ts.map +1 -1
  78. package/dist/hooks/useId.js +19 -6
  79. package/dist/hooks/useId.js.map +1 -1
  80. package/dist/index.d.ts +2 -0
  81. package/dist/index.d.ts.map +1 -1
  82. package/dist/index.js +2 -0
  83. package/dist/index.js.map +1 -1
  84. package/package.json +7 -7
@@ -0,0 +1,190 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { sortRows, filterRows, nextSortDirection, paginateRows, computeColumnWidths, } from '../components/datagrid/utils.js';
3
+ const people = [
4
+ { id: 1, name: 'Alice', age: 30, city: 'New York' },
5
+ { id: 2, name: 'Charlie', age: 25, city: 'Los Angeles' },
6
+ { id: 3, name: 'Bob', age: 35, city: 'Chicago' },
7
+ { id: 4, name: 'Diana', age: 28, city: 'New York' },
8
+ ];
9
+ const columns = [
10
+ { field: 'name', header: 'Name', sortable: true, filterable: true },
11
+ { field: 'age', header: 'Age', sortable: true, filterable: true },
12
+ { field: 'city', header: 'City', sortable: true, filterable: true },
13
+ ];
14
+ // ─── sortRows ─────────────────────────────────────────────────────────────
15
+ describe('sortRows', () => {
16
+ it('returns the original array when direction is null', () => {
17
+ const model = { field: 'name', direction: null };
18
+ const sorted = sortRows(people, model, columns);
19
+ expect(sorted.map((p) => p.id)).toEqual([1, 2, 3, 4]);
20
+ });
21
+ it('sorts strings ascending (A → Z)', () => {
22
+ const model = { field: 'name', direction: 'asc' };
23
+ const sorted = sortRows(people, model, columns);
24
+ expect(sorted.map((p) => p.name)).toEqual(['Alice', 'Bob', 'Charlie', 'Diana']);
25
+ });
26
+ it('sorts strings descending (Z → A)', () => {
27
+ const model = { field: 'name', direction: 'desc' };
28
+ const sorted = sortRows(people, model, columns);
29
+ expect(sorted.map((p) => p.name)).toEqual(['Diana', 'Charlie', 'Bob', 'Alice']);
30
+ });
31
+ it('sorts numbers ascending', () => {
32
+ const model = { field: 'age', direction: 'asc' };
33
+ const sorted = sortRows(people, model, columns);
34
+ expect(sorted.map((p) => p.age)).toEqual([25, 28, 30, 35]);
35
+ });
36
+ it('sorts numbers descending', () => {
37
+ const model = { field: 'age', direction: 'desc' };
38
+ const sorted = sortRows(people, model, columns);
39
+ expect(sorted.map((p) => p.age)).toEqual([35, 30, 28, 25]);
40
+ });
41
+ it('does not mutate the original array', () => {
42
+ const original = [...people];
43
+ const model = { field: 'name', direction: 'asc' };
44
+ sortRows(people, model, columns);
45
+ expect(people).toEqual(original);
46
+ });
47
+ it('returns original rows when field does not match any column', () => {
48
+ const model = { field: 'nonexistent', direction: 'asc' };
49
+ const sorted = sortRows(people, model, columns);
50
+ expect(sorted).toEqual(people);
51
+ });
52
+ it('uses valueGetter when provided on a column', () => {
53
+ const colsWithGetter = [
54
+ ...columns,
55
+ {
56
+ field: 'nameLen',
57
+ header: 'Name Length',
58
+ sortable: true,
59
+ valueGetter: (row) => row.name.length,
60
+ },
61
+ ];
62
+ const model = { field: 'nameLen', direction: 'asc' };
63
+ const sorted = sortRows(people, model, colsWithGetter);
64
+ // Alice=5, Bob=3, Charlie=7, Diana=5 → Bob(3), Alice(5)|Diana(5), Charlie(7)
65
+ expect(sorted[0].name).toBe('Bob');
66
+ expect(sorted[sorted.length - 1].name).toBe('Charlie');
67
+ });
68
+ });
69
+ // ─── filterRows ───────────────────────────────────────────────────────────
70
+ describe('filterRows', () => {
71
+ it('returns all rows when filterModel is empty', () => {
72
+ const model = {};
73
+ expect(filterRows(people, model, columns)).toHaveLength(4);
74
+ });
75
+ it('filters by quickFilter (case-insensitive, any filterable column)', () => {
76
+ const model = { quickFilter: 'alice' };
77
+ const result = filterRows(people, model, columns);
78
+ expect(result).toHaveLength(1);
79
+ expect(result[0].name).toBe('Alice');
80
+ });
81
+ it('quickFilter matches across multiple columns', () => {
82
+ const model = { quickFilter: 'new york' };
83
+ const result = filterRows(people, model, columns);
84
+ expect(result.map((p) => p.name)).toEqual(['Alice', 'Diana']);
85
+ });
86
+ it('returns empty array when quickFilter matches nothing', () => {
87
+ const model = { quickFilter: 'zzz-no-match' };
88
+ expect(filterRows(people, model, columns)).toHaveLength(0);
89
+ });
90
+ it('filters by columnFilters on a specific field', () => {
91
+ const model = { columnFilters: { city: 'new york' } };
92
+ const result = filterRows(people, model, columns);
93
+ expect(result.map((p) => p.name)).toEqual(['Alice', 'Diana']);
94
+ });
95
+ it('combines quickFilter AND columnFilters (both must match)', () => {
96
+ const model = {
97
+ quickFilter: 'new york',
98
+ columnFilters: { name: 'alice' },
99
+ };
100
+ const result = filterRows(people, model, columns);
101
+ expect(result).toHaveLength(1);
102
+ expect(result[0].name).toBe('Alice');
103
+ });
104
+ it('ignores empty columnFilter values', () => {
105
+ const model = { columnFilters: { name: '' } };
106
+ expect(filterRows(people, model, columns)).toHaveLength(4);
107
+ });
108
+ it('does not filter on columns with filterable=false', () => {
109
+ const noFilterCols = [
110
+ { field: 'name', header: 'Name', filterable: false },
111
+ { field: 'age', header: 'Age', filterable: true },
112
+ ];
113
+ // Filtering for "alice" should NOT match since name is not filterable
114
+ const model = { quickFilter: 'alice' };
115
+ const result = filterRows(people, model, noFilterCols);
116
+ expect(result).toHaveLength(0);
117
+ });
118
+ });
119
+ // ─── nextSortDirection ────────────────────────────────────────────────────
120
+ describe('nextSortDirection', () => {
121
+ it('first click on a column → asc', () => {
122
+ const current = { field: '', direction: null };
123
+ const next = nextSortDirection('', current, 'name');
124
+ expect(next).toEqual({ field: 'name', direction: 'asc' });
125
+ });
126
+ it('second click on same column → desc', () => {
127
+ const current = { field: 'name', direction: 'asc' };
128
+ const next = nextSortDirection('name', current, 'name');
129
+ expect(next).toEqual({ field: 'name', direction: 'desc' });
130
+ });
131
+ it('third click on same column → null (clear sort)', () => {
132
+ const current = { field: 'name', direction: 'desc' };
133
+ const next = nextSortDirection('name', current, 'name');
134
+ expect(next).toEqual({ field: 'name', direction: null });
135
+ });
136
+ it('clicking a different column resets to asc', () => {
137
+ const current = { field: 'name', direction: 'desc' };
138
+ const next = nextSortDirection('name', current, 'age');
139
+ expect(next).toEqual({ field: 'age', direction: 'asc' });
140
+ });
141
+ });
142
+ // ─── paginateRows ─────────────────────────────────────────────────────────
143
+ describe('paginateRows', () => {
144
+ const data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
145
+ it('returns first page', () => {
146
+ expect(paginateRows(data, 0, 3)).toEqual([1, 2, 3]);
147
+ });
148
+ it('returns second page', () => {
149
+ expect(paginateRows(data, 1, 3)).toEqual([4, 5, 6]);
150
+ });
151
+ it('returns partial last page', () => {
152
+ expect(paginateRows(data, 3, 3)).toEqual([10]);
153
+ });
154
+ it('returns empty array for out-of-range page', () => {
155
+ expect(paginateRows(data, 99, 3)).toEqual([]);
156
+ });
157
+ });
158
+ // ─── computeColumnWidths ──────────────────────────────────────────────────
159
+ describe('computeColumnWidths', () => {
160
+ it('uses fixed widths for columns with explicit width', () => {
161
+ const cols = [
162
+ { field: 'name', header: 'Name', width: 200 },
163
+ { field: 'age', header: 'Age', width: 100 },
164
+ ];
165
+ const widths = computeColumnWidths(cols, 500);
166
+ expect(widths[0]).toBe(200);
167
+ expect(widths[1]).toBe(100);
168
+ });
169
+ it('distributes remaining space proportionally via flex', () => {
170
+ const cols = [
171
+ { field: 'name', header: 'Name', width: 100 },
172
+ { field: 'city', header: 'City', flex: 1 },
173
+ { field: 'age', header: 'Age', flex: 2 },
174
+ ];
175
+ // totalWidth=400, fixed=100, remaining=300, totalFlex=3
176
+ // city = (1/3)*300 = 100, age = (2/3)*300 = 200
177
+ const widths = computeColumnWidths(cols, 400);
178
+ expect(widths[0]).toBe(100);
179
+ expect(widths[1]).toBe(100);
180
+ expect(widths[2]).toBe(200);
181
+ });
182
+ it('falls back to 120px when no width or flex is specified', () => {
183
+ const cols = [
184
+ { field: 'name', header: 'Name' },
185
+ ];
186
+ const widths = computeColumnWidths(cols, 500);
187
+ expect(widths[0]).toBe(120);
188
+ });
189
+ });
190
+ //# sourceMappingURL=datagrid-utils.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"datagrid-utils.test.js","sourceRoot":"","sources":["../../src/__tests__/datagrid-utils.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=date-utils.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"date-utils.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/date-utils.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,180 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { parseDate, formatDate, buildCalendarGrid, isSameDay, isBeforeDay, isAfterDay, daysInMonth, parseTime, formatTime, today, } from '../components/datepicker/date-utils.js';
3
+ // ─── parseDate ─────────────────────────────────────────────────────────────
4
+ describe('parseDate', () => {
5
+ it('parses a valid YYYY-MM-DD string into a local Date', () => {
6
+ const d = parseDate('2025-06-15');
7
+ expect(d).not.toBeNull();
8
+ expect(d.getFullYear()).toBe(2025);
9
+ expect(d.getMonth()).toBe(5); // 0-indexed
10
+ expect(d.getDate()).toBe(15);
11
+ });
12
+ it('returns null for undefined input', () => {
13
+ expect(parseDate(undefined)).toBeNull();
14
+ });
15
+ it('returns null for empty string', () => {
16
+ expect(parseDate('')).toBeNull();
17
+ });
18
+ it('returns null for invalid format', () => {
19
+ expect(parseDate('15-06-2025')).toBeNull();
20
+ expect(parseDate('2025/06/15')).toBeNull();
21
+ });
22
+ it('returns null for invalid dates that would roll over (e.g. Feb 30)', () => {
23
+ expect(parseDate('2024-02-30')).toBeNull();
24
+ });
25
+ it('handles leap year Feb 29 correctly', () => {
26
+ const d = parseDate('2024-02-29');
27
+ expect(d).not.toBeNull();
28
+ expect(d.getDate()).toBe(29);
29
+ });
30
+ it('returns null for non-leap year Feb 29', () => {
31
+ expect(parseDate('2023-02-29')).toBeNull();
32
+ });
33
+ });
34
+ // ─── formatDate ───────────────────────────────────────────────────────────
35
+ describe('formatDate', () => {
36
+ it('formats a date as YYYY-MM-DD', () => {
37
+ expect(formatDate(new Date(2025, 0, 5))).toBe('2025-01-05');
38
+ expect(formatDate(new Date(2025, 11, 31))).toBe('2025-12-31');
39
+ });
40
+ it('pads single-digit months and days with a leading zero', () => {
41
+ expect(formatDate(new Date(2025, 0, 1))).toBe('2025-01-01');
42
+ expect(formatDate(new Date(2025, 8, 9))).toBe('2025-09-09');
43
+ });
44
+ it('round-trips with parseDate', () => {
45
+ const original = '2025-03-17';
46
+ const d = parseDate(original);
47
+ expect(formatDate(d)).toBe(original);
48
+ });
49
+ });
50
+ // ─── daysInMonth ──────────────────────────────────────────────────────────
51
+ describe('daysInMonth', () => {
52
+ it('returns 31 for January', () => {
53
+ expect(daysInMonth(2025, 0)).toBe(31);
54
+ });
55
+ it('returns 28 for February in a non-leap year', () => {
56
+ expect(daysInMonth(2023, 1)).toBe(28);
57
+ });
58
+ it('returns 29 for February in a leap year', () => {
59
+ expect(daysInMonth(2024, 1)).toBe(29);
60
+ });
61
+ it('returns 30 for April', () => {
62
+ expect(daysInMonth(2025, 3)).toBe(30);
63
+ });
64
+ it('returns 31 for December', () => {
65
+ expect(daysInMonth(2025, 11)).toBe(31);
66
+ });
67
+ });
68
+ // ─── buildCalendarGrid ────────────────────────────────────────────────────
69
+ describe('buildCalendarGrid', () => {
70
+ it('always produces exactly 6 rows', () => {
71
+ const grid = buildCalendarGrid(2025, 0); // Jan 2025
72
+ expect(grid).toHaveLength(6);
73
+ });
74
+ it('each row has exactly 7 cells', () => {
75
+ const grid = buildCalendarGrid(2025, 0);
76
+ grid.forEach((row) => expect(row).toHaveLength(7));
77
+ });
78
+ it('includes all days of the target month', () => {
79
+ const grid = buildCalendarGrid(2025, 0); // 31 days
80
+ const dates = grid.flat();
81
+ const jan2025Days = dates.filter((d) => d.getFullYear() === 2025 && d.getMonth() === 0);
82
+ expect(jan2025Days).toHaveLength(31);
83
+ });
84
+ it('pads with previous-month days so the grid starts on Sunday', () => {
85
+ // Jan 1, 2025 is a Wednesday (day 3) — so first 3 cells should be Dec days
86
+ const grid = buildCalendarGrid(2025, 0);
87
+ const firstRow = grid[0];
88
+ const prevMonthCells = firstRow.filter((d) => d.getMonth() === 11); // December
89
+ expect(prevMonthCells.length).toBe(3); // Wed=3, so 3 Dec days prepend
90
+ });
91
+ it('pads with next-month days to complete 42 cells', () => {
92
+ const grid = buildCalendarGrid(2025, 0);
93
+ const dates = grid.flat();
94
+ const jan = dates.filter((d) => d.getMonth() === 0 && d.getFullYear() === 2025);
95
+ const dec = dates.filter((d) => d.getMonth() === 11 && d.getFullYear() === 2024);
96
+ const feb = dates.filter((d) => d.getMonth() === 1 && d.getFullYear() === 2025);
97
+ expect(jan.length + dec.length + feb.length).toBe(42);
98
+ });
99
+ });
100
+ // ─── isSameDay ────────────────────────────────────────────────────────────
101
+ describe('isSameDay', () => {
102
+ it('returns true for the same calendar day', () => {
103
+ const a = new Date(2025, 5, 15, 8, 0); // 8am
104
+ const b = new Date(2025, 5, 15, 23, 59); // 11pm
105
+ expect(isSameDay(a, b)).toBe(true);
106
+ });
107
+ it('returns false for different days', () => {
108
+ expect(isSameDay(new Date(2025, 5, 15), new Date(2025, 5, 16))).toBe(false);
109
+ });
110
+ it('returns false for same day but different month', () => {
111
+ expect(isSameDay(new Date(2025, 4, 15), new Date(2025, 5, 15))).toBe(false);
112
+ });
113
+ });
114
+ // ─── isBeforeDay / isAfterDay ─────────────────────────────────────────────
115
+ describe('isBeforeDay', () => {
116
+ it('returns true when date is before min', () => {
117
+ expect(isBeforeDay(new Date(2025, 0, 1), new Date(2025, 0, 5))).toBe(true);
118
+ });
119
+ it('returns false when date equals min', () => {
120
+ expect(isBeforeDay(new Date(2025, 0, 5), new Date(2025, 0, 5))).toBe(false);
121
+ });
122
+ it('returns false when date is after min', () => {
123
+ expect(isBeforeDay(new Date(2025, 0, 10), new Date(2025, 0, 5))).toBe(false);
124
+ });
125
+ });
126
+ describe('isAfterDay', () => {
127
+ it('returns true when date is after max', () => {
128
+ expect(isAfterDay(new Date(2025, 0, 10), new Date(2025, 0, 5))).toBe(true);
129
+ });
130
+ it('returns false when date equals max', () => {
131
+ expect(isAfterDay(new Date(2025, 0, 5), new Date(2025, 0, 5))).toBe(false);
132
+ });
133
+ it('returns false when date is before max', () => {
134
+ expect(isAfterDay(new Date(2025, 0, 1), new Date(2025, 0, 5))).toBe(false);
135
+ });
136
+ });
137
+ // ─── today ────────────────────────────────────────────────────────────────
138
+ describe('today', () => {
139
+ it('returns a Date with hours/minutes/seconds set to 0 (local midnight)', () => {
140
+ const t = today();
141
+ expect(t.getHours()).toBe(0);
142
+ expect(t.getMinutes()).toBe(0);
143
+ expect(t.getSeconds()).toBe(0);
144
+ expect(t.getMilliseconds()).toBe(0);
145
+ });
146
+ it('matches the current local date', () => {
147
+ const now = new Date();
148
+ const t = today();
149
+ expect(t.getFullYear()).toBe(now.getFullYear());
150
+ expect(t.getMonth()).toBe(now.getMonth());
151
+ expect(t.getDate()).toBe(now.getDate());
152
+ });
153
+ });
154
+ // ─── parseTime / formatTime ───────────────────────────────────────────────
155
+ describe('parseTime', () => {
156
+ it('parses HH:MM into hours and minutes', () => {
157
+ expect(parseTime('09:30')).toEqual({ hours: 9, minutes: 30 });
158
+ expect(parseTime('23:59')).toEqual({ hours: 23, minutes: 59 });
159
+ expect(parseTime('00:00')).toEqual({ hours: 0, minutes: 0 });
160
+ });
161
+ it('returns zero hours and minutes for undefined', () => {
162
+ expect(parseTime(undefined)).toEqual({ hours: 0, minutes: 0 });
163
+ });
164
+ it('returns zero hours and minutes for empty string', () => {
165
+ expect(parseTime('')).toEqual({ hours: 0, minutes: 0 });
166
+ });
167
+ });
168
+ describe('formatTime', () => {
169
+ it('formats as HH:MM with leading zeros', () => {
170
+ expect(formatTime(9, 5)).toBe('09:05');
171
+ expect(formatTime(0, 0)).toBe('00:00');
172
+ expect(formatTime(23, 59)).toBe('23:59');
173
+ });
174
+ it('round-trips with parseTime', () => {
175
+ const original = '14:07';
176
+ const { hours, minutes } = parseTime(original);
177
+ expect(formatTime(hours, minutes)).toBe(original);
178
+ });
179
+ });
180
+ //# sourceMappingURL=date-utils.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"date-utils.test.js","sourceRoot":"","sources":["../../src/__tests__/date-utils.test.ts"],"names":[],"mappings":"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"}
@@ -32,5 +32,5 @@ function AccordionItemComponent({ item, isOpen, onToggle }) {
32
32
  const triggerId = (0, react_1.useId)();
33
33
  const panelId = (0, react_1.useId)();
34
34
  return ((0, jsx_runtime_1.jsxs)("div", { className: "tokis-accordion-item", children: [(0, jsx_runtime_1.jsxs)("button", { id: triggerId, type: "button", "aria-expanded": isOpen, "aria-controls": panelId, "aria-disabled": item.disabled || undefined, disabled: item.disabled, className: "tokis-accordion-trigger", onClick: () => { if (!item.disabled)
35
- onToggle(item.value); }, children: [(0, jsx_runtime_1.jsx)("span", { style: { flex: 1, textAlign: 'left' }, children: item.trigger }), (0, jsx_runtime_1.jsx)("svg", { className: "tokis-accordion-trigger__icon", width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: (0, jsx_runtime_1.jsx)("path", { d: "M4 6l4 4 4-4", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) })] }), (0, jsx_runtime_1.jsx)("div", { id: panelId, role: "region", "aria-labelledby": triggerId, className: "tokis-accordion-content", "data-open": isOpen ? 'true' : 'false', "aria-hidden": !isOpen, children: (0, jsx_runtime_1.jsx)("div", { className: "tokis-accordion-content-inner", children: item.content }) })] }));
35
+ onToggle(item.value); }, children: [(0, jsx_runtime_1.jsx)("span", { style: { flex: 1, textAlign: 'start' }, children: item.trigger }), (0, jsx_runtime_1.jsx)("svg", { className: "tokis-accordion-trigger__icon", width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: (0, jsx_runtime_1.jsx)("path", { d: "M4 6l4 4 4-4", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) })] }), (0, jsx_runtime_1.jsx)("div", { id: panelId, role: "region", "aria-labelledby": triggerId, className: "tokis-accordion-content", "data-open": isOpen ? 'true' : 'false', "aria-hidden": !isOpen, children: (0, jsx_runtime_1.jsx)("div", { className: "tokis-accordion-content-inner", children: item.content }) })] }));
36
36
  }
@@ -14,5 +14,6 @@ function Checkbox({ label, description, checked, defaultChecked, indeterminate =
14
14
  inputRef.current.indeterminate = indeterminate;
15
15
  }
16
16
  }, [indeterminate]);
17
- return ((0, jsx_runtime_1.jsxs)("label", { className: (0, cn_js_1.cn)('tokis-checkbox-root', className), "data-disabled": disabled || undefined, htmlFor: inputId, children: [(0, jsx_runtime_1.jsx)("input", { ref: inputRef, type: "checkbox", id: inputId, name: name, value: value, checked: checked, defaultChecked: defaultChecked, disabled: disabled, onChange: (e) => onChange?.(e.target.checked), className: "tokis-checkbox-native", "aria-label": !label ? ariaLabel : undefined, "aria-describedby": descId }), (0, jsx_runtime_1.jsx)("span", { "aria-hidden": "true", className: "tokis-checkbox-control", "data-checked": checked && !indeterminate ? 'true' : undefined, "data-indeterminate": indeterminate ? 'true' : undefined }), (label || description) && ((0, jsx_runtime_1.jsxs)("div", { children: [label && (0, jsx_runtime_1.jsx)("span", { className: "tokis-checkbox-label", children: label }), description && (0, jsx_runtime_1.jsx)("p", { id: descId, className: "tokis-checkbox-description", children: description })] }))] }));
17
+ return ((0, jsx_runtime_1.jsxs)("label", { className: (0, cn_js_1.cn)('tokis-checkbox-root', className), "data-disabled": disabled || undefined, htmlFor: inputId, children: [(0, jsx_runtime_1.jsx)("input", { ref: inputRef, type: "checkbox", id: inputId, name: name, value: value, checked: checked, defaultChecked: defaultChecked, disabled: disabled, onChange: (e) => { if (!disabled)
18
+ onChange?.(e.target.checked); }, className: "tokis-checkbox-native", "aria-label": !label ? ariaLabel : undefined, "aria-describedby": descId }), (0, jsx_runtime_1.jsx)("span", { "aria-hidden": "true", className: "tokis-checkbox-control", "data-checked": checked && !indeterminate ? 'true' : undefined, "data-indeterminate": indeterminate ? 'true' : undefined }), (label || description) && ((0, jsx_runtime_1.jsxs)("div", { children: [label && (0, jsx_runtime_1.jsx)("span", { className: "tokis-checkbox-label", children: label }), description && (0, jsx_runtime_1.jsx)("p", { id: descId, className: "tokis-checkbox-description", children: description })] }))] }));
18
19
  }
@@ -0,0 +1,161 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DataGrid = DataGrid;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ /**
6
+ * DataGrid — feature-complete data table for Tokis.
7
+ *
8
+ * Features:
9
+ * - Column sorting (asc/desc/none cycle, click header)
10
+ * - Quick filter toolbar
11
+ * - Per-column text filtering
12
+ * - Client-side pagination with page-size selector
13
+ * - Row selection (single / multi-select checkboxes)
14
+ * - Custom cell rendering (renderCell)
15
+ * - Loading skeleton state
16
+ * - Empty state
17
+ * - Windowed virtual scrolling (fixed height + rowHeight)
18
+ * - Controlled & uncontrolled patterns for sort, filter, page
19
+ * - ARIA: role="grid", aria-sort, aria-rowcount, aria-colcount
20
+ */
21
+ const react_1 = require("react");
22
+ const cn_js_1 = require("../../utils/cn");
23
+ const utils_js_1 = require("./utils");
24
+ // ─── Sort icon ────────────────────────────────────────────────────────────────
25
+ function SortIcon({ direction }) {
26
+ if (!direction)
27
+ return (0, jsx_runtime_1.jsx)("span", { className: "tokis-dg-sort-icon tokis-dg-sort-icon--none", "aria-hidden": "true", children: "\u21C5" });
28
+ if (direction === 'asc')
29
+ return (0, jsx_runtime_1.jsx)("span", { className: "tokis-dg-sort-icon", "aria-hidden": "true", children: "\u2191" });
30
+ return (0, jsx_runtime_1.jsx)("span", { className: "tokis-dg-sort-icon", "aria-hidden": "true", children: "\u2193" });
31
+ }
32
+ function DataGridToolbar({ quickFilter, onQuickFilter }) {
33
+ return ((0, jsx_runtime_1.jsx)("div", { className: "tokis-dg-toolbar", children: (0, jsx_runtime_1.jsx)("input", { type: "search", className: "tokis-dg-search", placeholder: "Search\u2026", value: quickFilter, "aria-label": "Quick filter", onChange: (e) => onQuickFilter(e.target.value) }) }));
34
+ }
35
+ function DataGridHeader({ columns, sortModel, onSort, checkboxSelection, allSelected, someSelected, onSelectAll, columnFilters, onColumnFilter, }) {
36
+ return ((0, jsx_runtime_1.jsxs)("div", { className: "tokis-dg-header", role: "rowgroup", children: [(0, jsx_runtime_1.jsxs)("div", { className: "tokis-dg-row tokis-dg-row--header", role: "row", children: [checkboxSelection && ((0, jsx_runtime_1.jsx)("div", { className: "tokis-dg-cell tokis-dg-cell--checkbox", role: "columnheader", "aria-label": "Select all", children: (0, jsx_runtime_1.jsx)("input", { type: "checkbox", checked: allSelected, ref: (el) => { if (el)
37
+ el.indeterminate = someSelected && !allSelected; }, onChange: (e) => onSelectAll(e.target.checked), "aria-label": "Select all rows" }) })), columns.map((col) => {
38
+ const isSorted = sortModel.field === col.field && sortModel.direction != null;
39
+ return ((0, jsx_runtime_1.jsxs)("div", { className: (0, cn_js_1.cn)('tokis-dg-cell', 'tokis-dg-cell--header', col.sortable !== false && 'tokis-dg-cell--sortable'), role: "columnheader", "aria-sort": isSorted ? (sortModel.direction === 'asc' ? 'ascending' : 'descending') : 'none', style: { '--dg-align': col.headerAlign ?? col.align ?? 'start' }, onClick: () => col.sortable !== false && onSort(col.field), children: [col.renderHeader ? col.renderHeader(col) : (col.headerName ?? col.field), col.sortable !== false && ((0, jsx_runtime_1.jsx)(SortIcon, { direction: isSorted ? sortModel.direction : null }))] }, col.field));
40
+ })] }), columns.some((c) => c.filterable) && ((0, jsx_runtime_1.jsxs)("div", { className: "tokis-dg-row tokis-dg-row--filter-row", role: "row", "aria-label": "Column filters", children: [checkboxSelection && (0, jsx_runtime_1.jsx)("div", { className: "tokis-dg-cell tokis-dg-cell--checkbox", role: "cell" }), columns.map((col) => ((0, jsx_runtime_1.jsx)("div", { className: "tokis-dg-cell tokis-dg-cell--filter", role: "cell", children: col.filterable && ((0, jsx_runtime_1.jsx)("input", { type: "search", className: "tokis-dg-col-filter", placeholder: `Filter ${col.headerName ?? col.field}…`, value: columnFilters[col.field] ?? '', "aria-label": `Filter by ${col.headerName ?? col.field}`, onChange: (e) => onColumnFilter(col.field, e.target.value) })) }, col.field)))] }))] }));
41
+ }
42
+ function DataGridPagination({ page, pageSize, pageSizeOptions, total, onPageChange, onPageSizeChange }) {
43
+ const totalPages = Math.max(1, Math.ceil(total / pageSize));
44
+ const start = page * pageSize + 1;
45
+ const end = Math.min((page + 1) * pageSize, total);
46
+ return ((0, jsx_runtime_1.jsxs)("div", { className: "tokis-dg-pagination", role: "navigation", "aria-label": "Pagination", children: [(0, jsx_runtime_1.jsx)("span", { className: "tokis-dg-pagination-info", children: total === 0 ? '0 rows' : `${start}–${end} of ${total}` }), (0, jsx_runtime_1.jsx)("select", { className: "tokis-dg-page-size", value: pageSize, "aria-label": "Rows per page", onChange: (e) => { onPageSizeChange(Number(e.target.value)); onPageChange(0); }, children: pageSizeOptions.map((s) => (0, jsx_runtime_1.jsxs)("option", { value: s, children: [s, " / page"] }, s)) }), (0, jsx_runtime_1.jsx)("button", { className: "tokis-dg-page-btn", disabled: page === 0, onClick: () => onPageChange(0), "aria-label": "First page", children: "\u00AB" }), (0, jsx_runtime_1.jsx)("button", { className: "tokis-dg-page-btn", disabled: page === 0, onClick: () => onPageChange(page - 1), "aria-label": "Previous page", children: "\u2039" }), (0, jsx_runtime_1.jsx)("button", { className: "tokis-dg-page-btn", disabled: page >= totalPages - 1, onClick: () => onPageChange(page + 1), "aria-label": "Next page", children: "\u203A" }), (0, jsx_runtime_1.jsx)("button", { className: "tokis-dg-page-btn", disabled: page >= totalPages - 1, onClick: () => onPageChange(totalPages - 1), "aria-label": "Last page", children: "\u00BB" })] }));
47
+ }
48
+ // ─── Skeleton loader ──────────────────────────────────────────────────────────
49
+ function DataGridSkeleton({ rows, columns }) {
50
+ return ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: Array.from({ length: rows }).map((_, r) => ((0, jsx_runtime_1.jsx)("div", { className: "tokis-dg-row tokis-dg-row--skeleton", role: "row", "aria-hidden": "true", children: Array.from({ length: columns }).map((__, c) => ((0, jsx_runtime_1.jsx)("div", { className: "tokis-dg-cell", children: (0, jsx_runtime_1.jsx)("span", { className: "tokis-dg-skeleton-bar" }) }, c))) }, r))) }));
51
+ }
52
+ // ─── Main DataGrid ────────────────────────────────────────────────────────────
53
+ function DataGrid({ columns, rows, rowIdField = 'id', loading = false, emptyText = 'No rows', checkboxSelection = false, selectionModel: selectionProp, onSelectionChange, onRowClick, sortModel: sortProp, onSortModelChange, filterModel: filterProp, onFilterModelChange, showToolbar = false, pageSize: pageSizeProp = 25, pageSizeOptions = [10, 25, 50, 100], page: pageProp, onPageChange, height, rowHeight = 48, className, }) {
54
+ // ── Internal state (uncontrolled fallbacks) ──
55
+ const [sortInternal, setSortInternal] = (0, react_1.useState)({ field: '', direction: null });
56
+ const [filterInternal, setFilterInternal] = (0, react_1.useState)({ quickFilter: '', columnFilters: {} });
57
+ const [pageInternal, setPageInternal] = (0, react_1.useState)(0);
58
+ const [pageSizeInternal, setPageSizeInternal] = (0, react_1.useState)(pageSizeProp);
59
+ const [selectionInternal, setSelectionInternal] = (0, react_1.useState)([]);
60
+ const sort = sortProp ?? sortInternal;
61
+ const filterModel = filterProp ?? filterInternal;
62
+ const page = pageProp ?? pageInternal;
63
+ const pageSize = pageSizeInternal;
64
+ const selection = selectionProp ?? selectionInternal;
65
+ const setSort = (0, react_1.useCallback)((model) => {
66
+ if (onSortModelChange)
67
+ onSortModelChange(model);
68
+ else
69
+ setSortInternal(model);
70
+ }, [onSortModelChange]);
71
+ const setFilter = (0, react_1.useCallback)((model) => {
72
+ if (onFilterModelChange)
73
+ onFilterModelChange(model);
74
+ else
75
+ setFilterInternal(model);
76
+ // Reset to page 0 on filter change
77
+ if (onPageChange)
78
+ onPageChange(0);
79
+ else
80
+ setPageInternal(0);
81
+ }, [onFilterModelChange, onPageChange]);
82
+ const setPage = (0, react_1.useCallback)((p) => {
83
+ if (onPageChange)
84
+ onPageChange(p);
85
+ else
86
+ setPageInternal(p);
87
+ }, [onPageChange]);
88
+ const setSelection = (0, react_1.useCallback)((ids) => {
89
+ if (onSelectionChange)
90
+ onSelectionChange(ids);
91
+ else
92
+ setSelectionInternal(ids);
93
+ }, [onSelectionChange]);
94
+ // ── Process rows ──
95
+ const processed = (0, react_1.useMemo)(() => {
96
+ let r = (0, utils_js_1.filterRows)(rows, filterModel, columns);
97
+ r = (0, utils_js_1.sortRows)(r, sort, columns);
98
+ return r;
99
+ }, [rows, filterModel, sort, columns]);
100
+ const paginated = (0, react_1.useMemo)(() => (0, utils_js_1.paginateRows)(processed, page, pageSize), [processed, page, pageSize]);
101
+ // ── Virtualization ──
102
+ const bodyRef = (0, react_1.useRef)(null);
103
+ const [scrollTop, setScrollTop] = (0, react_1.useState)(0);
104
+ const isVirtualized = typeof height === 'number';
105
+ (0, react_1.useEffect)(() => {
106
+ const el = bodyRef.current;
107
+ if (!el || !isVirtualized)
108
+ return;
109
+ const handler = () => setScrollTop(el.scrollTop);
110
+ el.addEventListener('scroll', handler, { passive: true });
111
+ return () => el.removeEventListener('scroll', handler);
112
+ }, [isVirtualized]);
113
+ const OVERSCAN = 5;
114
+ const visibleStart = isVirtualized ? Math.max(0, Math.floor(scrollTop / rowHeight) - OVERSCAN) : 0;
115
+ const visibleCount = isVirtualized ? Math.ceil((Number(height) / rowHeight) + OVERSCAN * 2) : paginated.length;
116
+ const visibleEnd = Math.min(paginated.length, visibleStart + visibleCount);
117
+ const visibleRows = isVirtualized ? paginated.slice(visibleStart, visibleEnd) : paginated;
118
+ const paddingTop = isVirtualized ? visibleStart * rowHeight : 0;
119
+ const paddingBottom = isVirtualized ? Math.max(0, (paginated.length - visibleEnd) * rowHeight) : 0;
120
+ // ── Selection helpers ──
121
+ const allOnPageSelected = paginated.length > 0 && paginated.every((r) => selection.includes(r[rowIdField]));
122
+ const someOnPageSelected = paginated.some((r) => selection.includes(r[rowIdField]));
123
+ const handleSelectAll = (checked) => {
124
+ if (checked) {
125
+ const newIds = paginated.map((r) => r[rowIdField]);
126
+ const merged = Array.from(new Set([...selection, ...newIds]));
127
+ setSelection(merged);
128
+ }
129
+ else {
130
+ const pageIds = new Set(paginated.map((r) => r[rowIdField]));
131
+ setSelection(selection.filter((id) => !pageIds.has(id)));
132
+ }
133
+ };
134
+ const handleRowSelect = (rowId, checked) => {
135
+ if (checked)
136
+ setSelection([...selection, rowId]);
137
+ else
138
+ setSelection(selection.filter((id) => id !== rowId));
139
+ };
140
+ // ── Sort handler ──
141
+ const handleSort = (field) => {
142
+ setSort((0, utils_js_1.nextSortDirection)(sort.field, sort, field));
143
+ };
144
+ // ── Filter handlers ──
145
+ const handleQuickFilter = (v) => setFilter({ ...filterModel, quickFilter: v });
146
+ const handleColumnFilter = (field, v) => {
147
+ setFilter({ ...filterModel, columnFilters: { ...(filterModel.columnFilters ?? {}), [field]: v } });
148
+ };
149
+ // ── Render ──
150
+ const bodyStyle = height
151
+ ? { height: typeof height === 'number' ? `${height}px` : height, overflowY: 'auto' }
152
+ : {};
153
+ return ((0, jsx_runtime_1.jsxs)("div", { className: (0, cn_js_1.cn)('tokis-datagrid', className), role: "grid", "aria-rowcount": processed.length, "aria-colcount": columns.length, "aria-busy": loading, children: [showToolbar && ((0, jsx_runtime_1.jsx)(DataGridToolbar, { quickFilter: filterModel.quickFilter ?? '', onQuickFilter: handleQuickFilter })), (0, jsx_runtime_1.jsx)(DataGridHeader, { columns: columns, sortModel: sort, onSort: handleSort, checkboxSelection: checkboxSelection, allSelected: allOnPageSelected, someSelected: someOnPageSelected, onSelectAll: handleSelectAll, columnFilters: filterModel.columnFilters ?? {}, onColumnFilter: handleColumnFilter }), (0, jsx_runtime_1.jsx)("div", { className: "tokis-dg-body", ref: bodyRef, style: bodyStyle, role: "rowgroup", children: loading ? ((0, jsx_runtime_1.jsx)(DataGridSkeleton, { rows: Math.min(pageSize, 8), columns: columns.length + (checkboxSelection ? 1 : 0) })) : processed.length === 0 ? ((0, jsx_runtime_1.jsx)("div", { className: "tokis-dg-empty", role: "row", children: (0, jsx_runtime_1.jsx)("div", { className: "tokis-dg-cell", role: "cell", style: { gridColumn: '1 / -1' }, children: emptyText }) })) : ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [paddingTop > 0 && (0, jsx_runtime_1.jsx)("div", { style: { height: paddingTop }, "aria-hidden": "true" }), visibleRows.map((row, idx) => {
154
+ const rowId = row[rowIdField];
155
+ const isSelected = selection.includes(rowId);
156
+ return ((0, jsx_runtime_1.jsxs)("div", { className: (0, cn_js_1.cn)('tokis-dg-row', isSelected && 'tokis-dg-row--selected'), role: "row", "aria-rowindex": visibleStart + idx + 2, "aria-selected": checkboxSelection ? isSelected : undefined, style: { height: `${rowHeight}px` }, onClick: (e) => onRowClick?.(row, e), children: [checkboxSelection && ((0, jsx_runtime_1.jsx)("div", { className: "tokis-dg-cell tokis-dg-cell--checkbox", role: "gridcell", children: (0, jsx_runtime_1.jsx)("input", { type: "checkbox", checked: isSelected, "aria-label": `Select row ${rowId}`, onChange: (e) => handleRowSelect(rowId, e.target.checked), onClick: (e) => e.stopPropagation() }) })), columns.map((col) => {
157
+ const value = col.valueGetter ? col.valueGetter(row) : row[col.field];
158
+ return ((0, jsx_runtime_1.jsx)("div", { className: "tokis-dg-cell", role: "gridcell", style: { '--dg-align': col.align ?? 'start', ...col.cellStyle }, children: col.renderCell ? col.renderCell({ value, row, field: col.field }) : value }, col.field));
159
+ })] }, rowId ?? visibleStart + idx));
160
+ }), paddingBottom > 0 && (0, jsx_runtime_1.jsx)("div", { style: { height: paddingBottom }, "aria-hidden": "true" })] })) }), (0, jsx_runtime_1.jsx)(DataGridPagination, { page: page, pageSize: pageSize, pageSizeOptions: pageSizeOptions, total: processed.length, onPageChange: setPage, onPageSizeChange: setPageSizeInternal })] }));
161
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });