@reactorui/datagrid 1.0.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.
- package/LICENSE +21 -0
- package/README.md +778 -0
- package/dist/components/DataGrid/DataGrid.d.ts +5 -0
- package/dist/components/DataGrid/DataGrid.d.ts.map +1 -0
- package/dist/components/DataGrid/DataGrid.js +87 -0
- package/dist/components/DataGrid/index.d.ts +3 -0
- package/dist/components/DataGrid/index.d.ts.map +1 -0
- package/dist/components/DataGrid/index.js +1 -0
- package/dist/components/Filter/FilterControls.d.ts +11 -0
- package/dist/components/Filter/FilterControls.d.ts.map +1 -0
- package/dist/components/Filter/FilterControls.js +78 -0
- package/dist/components/Filter/index.d.ts +2 -0
- package/dist/components/Filter/index.d.ts.map +1 -0
- package/dist/components/Filter/index.js +1 -0
- package/dist/components/Pagination/Pagination.d.ts +17 -0
- package/dist/components/Pagination/Pagination.d.ts.map +1 -0
- package/dist/components/Pagination/Pagination.js +12 -0
- package/dist/components/Pagination/index.d.ts +2 -0
- package/dist/components/Pagination/index.d.ts.map +1 -0
- package/dist/components/Pagination/index.js +1 -0
- package/dist/components/Search/SearchInput.d.ts +11 -0
- package/dist/components/Search/SearchInput.d.ts.map +1 -0
- package/dist/components/Search/SearchInput.js +9 -0
- package/dist/components/Search/index.d.ts +2 -0
- package/dist/components/Search/index.d.ts.map +1 -0
- package/dist/components/Search/index.js +1 -0
- package/dist/components/Table/TableBody.d.ts +20 -0
- package/dist/components/Table/TableBody.d.ts.map +1 -0
- package/dist/components/Table/TableBody.js +56 -0
- package/dist/components/Table/TableHeader.d.ts +13 -0
- package/dist/components/Table/TableHeader.d.ts.map +1 -0
- package/dist/components/Table/TableHeader.js +24 -0
- package/dist/components/Table/index.d.ts +3 -0
- package/dist/components/Table/index.d.ts.map +1 -0
- package/dist/components/Table/index.js +2 -0
- package/dist/hooks/index.d.ts +2 -0
- package/dist/hooks/index.d.ts.map +1 -0
- package/dist/hooks/index.js +1 -0
- package/dist/hooks/useDataGrid.d.ts +49 -0
- package/dist/hooks/useDataGrid.d.ts.map +1 -0
- package/dist/hooks/useDataGrid.js +356 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -0
- package/dist/setupTests.d.ts +12 -0
- package/dist/setupTests.d.ts.map +1 -0
- package/dist/setupTests.js +1 -0
- package/dist/themes/index.d.ts +22 -0
- package/dist/themes/index.d.ts.map +1 -0
- package/dist/themes/index.js +31 -0
- package/dist/types/index.d.ts +108 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +1 -0
- package/dist/utils/index.d.ts +12 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +209 -0
- package/package.json +80 -0
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
// Data formatting utilities (keeping existing ones)
|
|
2
|
+
export const formatters = {
|
|
3
|
+
date: (value, includeTime = false) => {
|
|
4
|
+
if (!value)
|
|
5
|
+
return '';
|
|
6
|
+
const date = new Date(value);
|
|
7
|
+
return includeTime ? date.toLocaleString() : date.toLocaleDateString();
|
|
8
|
+
},
|
|
9
|
+
currency: (value, currency = 'USD') => {
|
|
10
|
+
return new Intl.NumberFormat('en-US', {
|
|
11
|
+
style: 'currency',
|
|
12
|
+
currency,
|
|
13
|
+
}).format(value);
|
|
14
|
+
},
|
|
15
|
+
number: (value, decimals = 0) => {
|
|
16
|
+
return new Intl.NumberFormat('en-US', {
|
|
17
|
+
minimumFractionDigits: decimals,
|
|
18
|
+
maximumFractionDigits: decimals,
|
|
19
|
+
}).format(value);
|
|
20
|
+
},
|
|
21
|
+
truncate: (text, length) => {
|
|
22
|
+
if (!text || text.length <= length)
|
|
23
|
+
return text;
|
|
24
|
+
return text.substring(0, length) + '...';
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
// Filter comparison functions (keeping existing implementation)
|
|
28
|
+
export const compareValues = (dataValue, filterValue, operator, dataType) => {
|
|
29
|
+
if (dataValue == null)
|
|
30
|
+
return false;
|
|
31
|
+
switch (dataType) {
|
|
32
|
+
case 'string':
|
|
33
|
+
const str = dataValue.toString().toLowerCase();
|
|
34
|
+
const filter = filterValue.toString().toLowerCase();
|
|
35
|
+
switch (operator) {
|
|
36
|
+
case 'eq':
|
|
37
|
+
return str === filter;
|
|
38
|
+
case 'contains':
|
|
39
|
+
return str.includes(filter);
|
|
40
|
+
case 'startsWith':
|
|
41
|
+
return str.startsWith(filter);
|
|
42
|
+
case 'endsWith':
|
|
43
|
+
return str.endsWith(filter);
|
|
44
|
+
default:
|
|
45
|
+
return str.includes(filter);
|
|
46
|
+
}
|
|
47
|
+
case 'number':
|
|
48
|
+
const num = parseFloat(dataValue);
|
|
49
|
+
const filterNum = parseFloat(filterValue);
|
|
50
|
+
switch (operator) {
|
|
51
|
+
case 'eq':
|
|
52
|
+
return num === filterNum;
|
|
53
|
+
case 'gt':
|
|
54
|
+
return num > filterNum;
|
|
55
|
+
case 'gte':
|
|
56
|
+
return num >= filterNum;
|
|
57
|
+
case 'lt':
|
|
58
|
+
return num < filterNum;
|
|
59
|
+
case 'lte':
|
|
60
|
+
return num <= filterNum;
|
|
61
|
+
default:
|
|
62
|
+
return num === filterNum;
|
|
63
|
+
}
|
|
64
|
+
case 'date':
|
|
65
|
+
case 'datetime':
|
|
66
|
+
const date = new Date(dataValue).getTime();
|
|
67
|
+
const filterDate = new Date(filterValue).getTime();
|
|
68
|
+
switch (operator) {
|
|
69
|
+
case 'eq':
|
|
70
|
+
return date === filterDate;
|
|
71
|
+
case 'gt':
|
|
72
|
+
return date > filterDate;
|
|
73
|
+
case 'gte':
|
|
74
|
+
return date >= filterDate;
|
|
75
|
+
case 'lt':
|
|
76
|
+
return date < filterDate;
|
|
77
|
+
case 'lte':
|
|
78
|
+
return date <= filterDate;
|
|
79
|
+
default:
|
|
80
|
+
return date === filterDate;
|
|
81
|
+
}
|
|
82
|
+
case 'boolean':
|
|
83
|
+
return Boolean(dataValue) === Boolean(filterValue);
|
|
84
|
+
default:
|
|
85
|
+
return String(dataValue).toLowerCase().includes(String(filterValue).toLowerCase());
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
// Simplified API utilities
|
|
89
|
+
export const createApiRequest = async (endpoint, request, config = {}) => {
|
|
90
|
+
const { method = 'GET', bearerToken, apiKey, customHeaders = {}, withCredentials = false, timeout = 30000, } = config;
|
|
91
|
+
// Build headers
|
|
92
|
+
const headers = {
|
|
93
|
+
'Content-Type': 'application/json',
|
|
94
|
+
...customHeaders,
|
|
95
|
+
};
|
|
96
|
+
if (bearerToken) {
|
|
97
|
+
headers.Authorization = `Bearer ${bearerToken}`;
|
|
98
|
+
}
|
|
99
|
+
if (apiKey) {
|
|
100
|
+
headers['X-API-Key'] = apiKey;
|
|
101
|
+
}
|
|
102
|
+
// Build request
|
|
103
|
+
const requestOptions = {
|
|
104
|
+
method,
|
|
105
|
+
headers,
|
|
106
|
+
credentials: withCredentials ? 'include' : 'same-origin',
|
|
107
|
+
};
|
|
108
|
+
let url = endpoint;
|
|
109
|
+
if (method === 'POST') {
|
|
110
|
+
requestOptions.body = JSON.stringify({ request });
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
const params = new URLSearchParams({ request: JSON.stringify(request) });
|
|
114
|
+
url = `${endpoint}?${params.toString()}`;
|
|
115
|
+
}
|
|
116
|
+
// Create timeout
|
|
117
|
+
const controller = new AbortController();
|
|
118
|
+
const timeoutId = setTimeout(() => controller.abort(), timeout);
|
|
119
|
+
requestOptions.signal = controller.signal;
|
|
120
|
+
try {
|
|
121
|
+
const response = await fetch(url, requestOptions);
|
|
122
|
+
clearTimeout(timeoutId);
|
|
123
|
+
if (!response.ok) {
|
|
124
|
+
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
125
|
+
}
|
|
126
|
+
const data = await response.json();
|
|
127
|
+
return mapServerResponse(data);
|
|
128
|
+
}
|
|
129
|
+
catch (error) {
|
|
130
|
+
clearTimeout(timeoutId);
|
|
131
|
+
throw error;
|
|
132
|
+
}
|
|
133
|
+
};
|
|
134
|
+
// Simplified server response mapping with flexible casing
|
|
135
|
+
export const mapServerResponse = (data) => {
|
|
136
|
+
// Helper to get value with flexible casing
|
|
137
|
+
const getValue = (obj, keys) => {
|
|
138
|
+
for (const key of keys) {
|
|
139
|
+
if (obj[key] !== undefined)
|
|
140
|
+
return obj[key];
|
|
141
|
+
}
|
|
142
|
+
return undefined;
|
|
143
|
+
};
|
|
144
|
+
// Get items with flexible casing
|
|
145
|
+
const items = getValue(data, ['Items', 'items', 'data', 'Data']);
|
|
146
|
+
// Get continuation token with flexible casing
|
|
147
|
+
const continuationToken = getValue(data, [
|
|
148
|
+
'ContinuationToken',
|
|
149
|
+
'continuationToken',
|
|
150
|
+
'continuationtoken',
|
|
151
|
+
'nextToken',
|
|
152
|
+
'next_token',
|
|
153
|
+
'NextToken',
|
|
154
|
+
]);
|
|
155
|
+
// Get hasMore with flexible casing
|
|
156
|
+
const hasMore = getValue(data, [
|
|
157
|
+
'HasMore',
|
|
158
|
+
'hasMore',
|
|
159
|
+
'hasmore',
|
|
160
|
+
'has_more',
|
|
161
|
+
'hasNextPage',
|
|
162
|
+
'has_next_page',
|
|
163
|
+
]);
|
|
164
|
+
// Get count with flexible casing
|
|
165
|
+
const count = getValue(data, ['Count', 'count', 'COUNT', 'total', 'Total', 'length', 'size']);
|
|
166
|
+
// Direct mapping for arrays
|
|
167
|
+
if (Array.isArray(data)) {
|
|
168
|
+
return {
|
|
169
|
+
Items: data,
|
|
170
|
+
HasMore: false,
|
|
171
|
+
Count: data.length,
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
// AWS DynamoDB style response (special case)
|
|
175
|
+
if (data.Items && data.LastEvaluatedKey) {
|
|
176
|
+
return {
|
|
177
|
+
Items: data.Items,
|
|
178
|
+
ContinuationToken: JSON.stringify(data.LastEvaluatedKey),
|
|
179
|
+
HasMore: !!data.LastEvaluatedKey,
|
|
180
|
+
Count: data.Count || data.Items.length,
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
// Standard response mapping
|
|
184
|
+
return {
|
|
185
|
+
Items: Array.isArray(items) ? items : [],
|
|
186
|
+
ContinuationToken: continuationToken,
|
|
187
|
+
HasMore: Boolean(hasMore),
|
|
188
|
+
Count: Number(count) || 0,
|
|
189
|
+
};
|
|
190
|
+
};
|
|
191
|
+
// Sorting utilities (keeping existing implementation)
|
|
192
|
+
export const sortData = (data, sortColumn, direction) => {
|
|
193
|
+
if (!sortColumn)
|
|
194
|
+
return data;
|
|
195
|
+
return [...data].sort((a, b) => {
|
|
196
|
+
const aVal = a[sortColumn];
|
|
197
|
+
const bVal = b[sortColumn];
|
|
198
|
+
if (aVal == null && bVal == null)
|
|
199
|
+
return 0;
|
|
200
|
+
if (aVal == null)
|
|
201
|
+
return 1;
|
|
202
|
+
if (bVal == null)
|
|
203
|
+
return -1;
|
|
204
|
+
const aStr = String(aVal).toLowerCase();
|
|
205
|
+
const bStr = String(bVal).toLowerCase();
|
|
206
|
+
const result = aStr.localeCompare(bStr, undefined, { numeric: true });
|
|
207
|
+
return direction === 'desc' ? -result : result;
|
|
208
|
+
});
|
|
209
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@reactorui/datagrid",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "High-performance React data grid with TypeScript support, server-side integration, and continuation token pagination",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"module": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"files": [
|
|
9
|
+
"dist",
|
|
10
|
+
"README.md",
|
|
11
|
+
"LICENSE"
|
|
12
|
+
],
|
|
13
|
+
"scripts": {
|
|
14
|
+
"build": "npm run clean && tsc",
|
|
15
|
+
"build:rollup": "npm run clean && rollup -c",
|
|
16
|
+
"clean": "rm -rf dist",
|
|
17
|
+
"test": "jest",
|
|
18
|
+
"test:watch": "jest --watch",
|
|
19
|
+
"test:coverage": "jest --coverage",
|
|
20
|
+
"lint": "echo 'Linting skipped for now'",
|
|
21
|
+
"format": "prettier --write \"src/**/*.{ts,tsx,json,md}\"",
|
|
22
|
+
"typecheck": "tsc --noEmit",
|
|
23
|
+
"prepublishOnly": "npm run build && npm run test"
|
|
24
|
+
},
|
|
25
|
+
"keywords": [
|
|
26
|
+
"react",
|
|
27
|
+
"datagrid",
|
|
28
|
+
"table",
|
|
29
|
+
"data-table",
|
|
30
|
+
"grid",
|
|
31
|
+
"reactor",
|
|
32
|
+
"typescript",
|
|
33
|
+
"performance",
|
|
34
|
+
"pagination",
|
|
35
|
+
"continuation-token",
|
|
36
|
+
"server-side",
|
|
37
|
+
"filtering",
|
|
38
|
+
"sorting"
|
|
39
|
+
],
|
|
40
|
+
"author": "ReactorUI",
|
|
41
|
+
"license": "MIT",
|
|
42
|
+
"repository": {
|
|
43
|
+
"type": "git",
|
|
44
|
+
"url": "https://github.com/reactorui/datagrid.git"
|
|
45
|
+
},
|
|
46
|
+
"bugs": {
|
|
47
|
+
"url": "https://github.com/reactorui/datagrid/issues"
|
|
48
|
+
},
|
|
49
|
+
"homepage": "https://reactorui.dev",
|
|
50
|
+
"peerDependencies": {
|
|
51
|
+
"react": ">=16.8.0",
|
|
52
|
+
"react-dom": ">=16.8.0"
|
|
53
|
+
},
|
|
54
|
+
"devDependencies": {
|
|
55
|
+
"@rollup/plugin-commonjs": "^25.0.7",
|
|
56
|
+
"@rollup/plugin-node-resolve": "^15.2.3",
|
|
57
|
+
"@rollup/plugin-terser": "^0.4.4",
|
|
58
|
+
"@rollup/plugin-typescript": "^11.1.5",
|
|
59
|
+
"@testing-library/jest-dom": "^6.1.5",
|
|
60
|
+
"@testing-library/react": "^13.4.0",
|
|
61
|
+
"@testing-library/user-event": "^14.5.1",
|
|
62
|
+
"@types/jest": "^29.5.8",
|
|
63
|
+
"@types/node": "^20.10.5",
|
|
64
|
+
"@types/react": "^18.2.45",
|
|
65
|
+
"@types/react-dom": "^18.2.18",
|
|
66
|
+
"jest": "^29.7.0",
|
|
67
|
+
"jest-environment-jsdom": "^29.7.0",
|
|
68
|
+
"prettier": "^3.1.1",
|
|
69
|
+
"react": "^18.2.0",
|
|
70
|
+
"react-dom": "^18.2.0",
|
|
71
|
+
"rollup": "^4.9.1",
|
|
72
|
+
"rollup-plugin-dts": "^6.1.0",
|
|
73
|
+
"rollup-plugin-peer-deps-external": "^2.2.4",
|
|
74
|
+
"ts-jest": "^29.1.1",
|
|
75
|
+
"typescript": "^5.3.3"
|
|
76
|
+
},
|
|
77
|
+
"publishConfig": {
|
|
78
|
+
"access": "public"
|
|
79
|
+
}
|
|
80
|
+
}
|