@issonujha/sdui-web 0.1.3 → 0.1.5

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 (53) hide show
  1. package/dist/cjs/DynamicComponentLoader.js +16 -0
  2. package/dist/cjs/DynamicTabRenderer.js +10 -0
  3. package/dist/cjs/DynamicTable.js +856 -0
  4. package/dist/cjs/EndpointTable.js +57 -0
  5. package/dist/cjs/NavBar.js +14 -0
  6. package/dist/cjs/SduiWebProvider.js +25 -0
  7. package/dist/cjs/index.js +22 -0
  8. package/dist/cjs/package.json +1 -0
  9. package/dist/esm/DynamicComponentLoader.d.ts.map +1 -0
  10. package/dist/esm/DynamicComponentLoader.js.map +1 -0
  11. package/dist/esm/DynamicTabRenderer.d.ts.map +1 -0
  12. package/dist/esm/DynamicTabRenderer.js.map +1 -0
  13. package/dist/esm/DynamicTable.d.ts +48 -0
  14. package/dist/esm/DynamicTable.d.ts.map +1 -0
  15. package/dist/esm/DynamicTable.js +821 -0
  16. package/dist/esm/DynamicTable.js.map +1 -0
  17. package/dist/esm/EndpointTable.d.ts.map +1 -0
  18. package/dist/esm/EndpointTable.js.map +1 -0
  19. package/dist/esm/NavBar.d.ts.map +1 -0
  20. package/dist/esm/NavBar.js.map +1 -0
  21. package/dist/esm/SduiWebProvider.d.ts.map +1 -0
  22. package/dist/esm/SduiWebProvider.js.map +1 -0
  23. package/dist/esm/index.d.ts.map +1 -0
  24. package/dist/esm/index.js.map +1 -0
  25. package/package.json +9 -7
  26. package/dist/DynamicComponentLoader.d.ts.map +0 -1
  27. package/dist/DynamicComponentLoader.js.map +0 -1
  28. package/dist/DynamicTabRenderer.d.ts.map +0 -1
  29. package/dist/DynamicTabRenderer.js.map +0 -1
  30. package/dist/DynamicTable.d.ts +0 -26
  31. package/dist/DynamicTable.d.ts.map +0 -1
  32. package/dist/DynamicTable.js +0 -418
  33. package/dist/DynamicTable.js.map +0 -1
  34. package/dist/EndpointTable.d.ts.map +0 -1
  35. package/dist/EndpointTable.js.map +0 -1
  36. package/dist/NavBar.d.ts.map +0 -1
  37. package/dist/NavBar.js.map +0 -1
  38. package/dist/SduiWebProvider.d.ts.map +0 -1
  39. package/dist/SduiWebProvider.js.map +0 -1
  40. package/dist/index.d.ts.map +0 -1
  41. package/dist/index.js.map +0 -1
  42. /package/dist/{DynamicComponentLoader.d.ts → esm/DynamicComponentLoader.d.ts} +0 -0
  43. /package/dist/{DynamicComponentLoader.js → esm/DynamicComponentLoader.js} +0 -0
  44. /package/dist/{DynamicTabRenderer.d.ts → esm/DynamicTabRenderer.d.ts} +0 -0
  45. /package/dist/{DynamicTabRenderer.js → esm/DynamicTabRenderer.js} +0 -0
  46. /package/dist/{EndpointTable.d.ts → esm/EndpointTable.d.ts} +0 -0
  47. /package/dist/{EndpointTable.js → esm/EndpointTable.js} +0 -0
  48. /package/dist/{NavBar.d.ts → esm/NavBar.d.ts} +0 -0
  49. /package/dist/{NavBar.js → esm/NavBar.js} +0 -0
  50. /package/dist/{SduiWebProvider.d.ts → esm/SduiWebProvider.d.ts} +0 -0
  51. /package/dist/{SduiWebProvider.js → esm/SduiWebProvider.js} +0 -0
  52. /package/dist/{index.d.ts → esm/index.d.ts} +0 -0
  53. /package/dist/{index.js → esm/index.js} +0 -0
@@ -0,0 +1,856 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.DynamicTable = DynamicTable;
37
+ const jsx_runtime_1 = require("react/jsx-runtime");
38
+ const react_1 = __importStar(require("react"));
39
+ const STAGE_PALETTES = [
40
+ { color: '#6366F1', bg: '#EEF2FF', text: '#4338CA', border: '#C7D2FE' }, // Indigo
41
+ { color: '#F59E0B', bg: '#FEF3C7', text: '#B45309', border: '#FDE68A' }, // Amber
42
+ { color: '#3B82F6', bg: '#EFF6FF', text: '#1D4ED8', border: '#BFDBFE' }, // Blue
43
+ { color: '#10B981', bg: '#D1FAE5', text: '#047857', border: '#A7F3D0' }, // Emerald
44
+ { color: '#EF4444', bg: '#FEE2E2', text: '#B91C1C', border: '#FECACA' }, // Red
45
+ { color: '#8B5CF6', bg: '#EDE9FE', text: '#6D28D9', border: '#DDD6FE' }, // Purple
46
+ { color: '#EC4899', bg: '#FCE7F3', text: '#BE185D', border: '#FBCFE8' }, // Pink
47
+ { color: '#14B8A6', bg: '#CCFBF1', text: '#0F766E', border: '#99F6E4' }, // Teal
48
+ ];
49
+ function formatStageLabel(code) {
50
+ if (!code)
51
+ return '';
52
+ return code
53
+ .replace(/[_-]+/g, ' ')
54
+ .toLowerCase()
55
+ .replace(/\b\w/g, (c) => c.toUpperCase());
56
+ }
57
+ function normalizeStageDef(raw, index = 0) {
58
+ const key = String(raw.key || raw.code || raw.id || '').toUpperCase();
59
+ const label = raw.label || raw.name || formatStageLabel(key);
60
+ const palette = STAGE_PALETTES[index % STAGE_PALETTES.length];
61
+ return {
62
+ key,
63
+ label,
64
+ color: raw.color || palette.color,
65
+ textColor: raw.textColor || palette.text,
66
+ borderColor: raw.borderColor || palette.border,
67
+ statuses: Array.isArray(raw.statuses) && raw.statuses.length > 0 ? raw.statuses : [key],
68
+ };
69
+ }
70
+ function getRowStage(row, stageKey) {
71
+ if (!row)
72
+ return '';
73
+ const r = row;
74
+ const val = (stageKey && r[stageKey]) || r.deliveryStatus || r.stageCode || r.stageName || r.status || r.stage || '';
75
+ return String(val).toUpperCase();
76
+ }
77
+ function getBadgeStyle(val) {
78
+ const s = String(val || '').toUpperCase();
79
+ if (['ACTIVE', 'APPROVED', 'SUCCESS', 'DELIVERED', 'PAID', 'COMPLETED', 'OPEN', 'TRUE'].includes(s)) {
80
+ return { bg: '#ECFDF5', text: '#065F46', border: '#A7F3D0' };
81
+ }
82
+ if (['PENDING', 'PROCESSING', 'IN_TRANSIT', 'PLACED', 'ACCEPTED', 'PACKED', 'DISPATCHED', 'WARN', 'WARNING'].includes(s)) {
83
+ return { bg: '#FFFBEB', text: '#92400E', border: '#FDE68A' };
84
+ }
85
+ if (['CANCELLED', 'REJECTED', 'FAILED', 'SUSPENDED', 'BLOCKED', 'BANNED', 'ERROR', 'FALSE'].includes(s)) {
86
+ return { bg: '#FEF2F2', text: '#991B1B', border: '#FECACA' };
87
+ }
88
+ if (['SIMULATED', 'INFO', 'SELLER', 'WEB', 'EMAIL', 'SMS', 'IN_APP'].includes(s)) {
89
+ return { bg: '#EFF6FF', text: '#1E40AF', border: '#BFDBFE' };
90
+ }
91
+ if (s.includes('OTP') || s.includes('SECURITY')) {
92
+ return { bg: '#FAF5FF', text: '#6B21A8', border: '#E9D5FF' };
93
+ }
94
+ return { bg: '#F1F5F9', text: '#334155', border: '#E2E8F0' };
95
+ }
96
+ function DynamicTable({ data: rawData, columns: customColumns, filters: customFilters, loading = false, error = null, userRoles = [], viewMode: controlledViewMode, onViewModeChange, availableViews: propAvailableViews, kanbanStages: explicitKanbanStages, stageKey, canDragRecord = true, onTransitionStage, onPageChange, onRowsPerPageChange, onSortChange, onFilterChange, onSearchChange, onSearch, searchValue: controlledSearchValue, onRowClick, onExportCsv, onRefresh, title, subtitle, pageSizeOptions = [10, 15, 25, 50, 100], defaultRowsPerPage = 10, renderCustomCard, actions, rowActions, renderExpandedRow, activeFilters, emptyMessage, exportFilename, tableActions, extraHeaderActions, compact = false, enableExport, enableLiveReload, defaultLiveReload, showGlobalFilters, }) {
97
+ // Normalize incoming data (can be DataTableResponse or Array)
98
+ const isResponseObject = Boolean(rawData && typeof rawData === 'object' && !Array.isArray(rawData));
99
+ const normalizedData = (0, react_1.useMemo)(() => {
100
+ if (isResponseObject) {
101
+ const resp = rawData;
102
+ return {
103
+ content: Array.isArray(resp.content) ? resp.content : [],
104
+ totalElements: typeof resp.totalElements === 'number' ? resp.totalElements : (resp.content?.length || 0),
105
+ totalPages: typeof resp.totalPages === 'number' ? resp.totalPages : 1,
106
+ pageNumber: typeof resp.pageNumber === 'number' ? resp.pageNumber : 0,
107
+ pageSize: typeof resp.pageSize === 'number' ? resp.pageSize : defaultRowsPerPage,
108
+ last: typeof resp.last === 'boolean' ? resp.last : true,
109
+ columns: Array.isArray(resp.columns) ? resp.columns : [],
110
+ filters: Array.isArray(resp.filters) ? resp.filters : [],
111
+ sortBy: resp.sortBy,
112
+ sortDir: resp.sortDir,
113
+ stages: resp.stages,
114
+ enableExport: typeof enableExport === 'boolean' ? enableExport : resp.enableExport,
115
+ enableLiveReload: typeof enableLiveReload === 'boolean' ? enableLiveReload : resp.enableLiveReload,
116
+ enableColumnVisibility: resp.enableColumnVisibility,
117
+ };
118
+ }
119
+ const arr = Array.isArray(rawData) ? rawData : [];
120
+ return {
121
+ content: arr,
122
+ totalElements: arr.length,
123
+ totalPages: 1,
124
+ pageNumber: 0,
125
+ pageSize: arr.length || defaultRowsPerPage,
126
+ last: true,
127
+ columns: [],
128
+ filters: [],
129
+ enableExport: typeof enableExport === 'boolean' ? enableExport : true,
130
+ enableLiveReload: typeof enableLiveReload === 'boolean' ? enableLiveReload : true,
131
+ };
132
+ }, [rawData, isResponseObject, defaultRowsPerPage, enableExport, enableLiveReload]);
133
+ // Dynamic View Mode
134
+ const [internalViewMode, setInternalViewMode] = (0, react_1.useState)('table');
135
+ const activeView = controlledViewMode ?? internalViewMode;
136
+ const setViewMode = (mode) => {
137
+ setInternalViewMode(mode);
138
+ onViewModeChange?.(mode);
139
+ };
140
+ // Search state
141
+ const [internalSearch, setInternalSearch] = (0, react_1.useState)('');
142
+ const activeSearch = controlledSearchValue !== undefined ? controlledSearchValue : internalSearch;
143
+ const handleSearchInput = (val) => {
144
+ setInternalSearch(val);
145
+ onSearchChange?.(val);
146
+ onSearch?.(val);
147
+ };
148
+ // Filter drawer / panel state
149
+ const [filterDrawerOpen, setFilterDrawerOpen] = (0, react_1.useState)(false);
150
+ const [filterDrawerSearch, setFilterDrawerSearch] = (0, react_1.useState)('');
151
+ const [internalFilters, setInternalFilters] = (0, react_1.useState)({});
152
+ const effectiveFilters = (0, react_1.useMemo)(() => {
153
+ return activeFilters !== undefined ? activeFilters : internalFilters;
154
+ }, [activeFilters, internalFilters]);
155
+ const [hiddenColumns, setHiddenColumns] = (0, react_1.useState)(new Set());
156
+ // Columns resolution
157
+ const columns = (0, react_1.useMemo)(() => {
158
+ let base = customColumns && customColumns.length > 0
159
+ ? customColumns
160
+ : normalizedData.columns && normalizedData.columns.length > 0
161
+ ? normalizedData.columns
162
+ : [];
163
+ if (base.length === 0 && normalizedData.content.length > 0) {
164
+ const sample = normalizedData.content[0];
165
+ base = Object.keys(sample).slice(0, 8).map((k) => ({
166
+ key: k,
167
+ label: formatStageLabel(k),
168
+ type: typeof sample[k] === 'number' ? 'number' : 'text',
169
+ sortable: true,
170
+ }));
171
+ }
172
+ return base.filter((c) => !c.rolesAllowed || c.rolesAllowed.length === 0 || c.rolesAllowed.some((r) => userRoles.includes(r)));
173
+ }, [customColumns, normalizedData.columns, normalizedData.content, userRoles]);
174
+ const visibleColumns = (0, react_1.useMemo)(() => {
175
+ return columns.filter((c) => !hiddenColumns.has(c.key));
176
+ }, [columns, hiddenColumns]);
177
+ // Filters resolution
178
+ const filters = (0, react_1.useMemo)(() => {
179
+ const base = customFilters && customFilters.length > 0 ? customFilters : normalizedData.filters || [];
180
+ return base.filter((f) => !f.rolesAllowed || f.rolesAllowed.length === 0 || f.rolesAllowed.some((r) => userRoles.includes(r)));
181
+ }, [customFilters, normalizedData.filters, userRoles]);
182
+ // Dynamic Kanban Stages
183
+ const kanbanStages = (0, react_1.useMemo)(() => {
184
+ if (explicitKanbanStages && explicitKanbanStages.length > 0) {
185
+ return explicitKanbanStages.map((s, i) => normalizeStageDef(s, i));
186
+ }
187
+ if (Array.isArray(normalizedData.stages) && normalizedData.stages.length > 0) {
188
+ return normalizedData.stages.map((s, i) => normalizeStageDef(s, i));
189
+ }
190
+ // Derive dynamically from content
191
+ const stageMap = new Map();
192
+ const ordered = [];
193
+ normalizedData.content.forEach((item) => {
194
+ const key = getRowStage(item, stageKey);
195
+ if (key && !stageMap.has(key)) {
196
+ const label = item.stageName || formatStageLabel(key);
197
+ stageMap.set(key, { label });
198
+ ordered.push(key);
199
+ }
200
+ });
201
+ if (ordered.length === 0) {
202
+ return [normalizeStageDef({ key: 'DEFAULT', label: 'All Records' }, 0)];
203
+ }
204
+ return ordered.map((k, idx) => {
205
+ const info = stageMap.get(k);
206
+ return normalizeStageDef({ key: k, label: info.label }, idx);
207
+ });
208
+ }, [explicitKanbanStages, normalizedData.stages, normalizedData.content, stageKey]);
209
+ // Available Views
210
+ const availableViews = (0, react_1.useMemo)(() => {
211
+ if (propAvailableViews && propAvailableViews.length > 0) {
212
+ return propAvailableViews;
213
+ }
214
+ return ['table', 'kanban', 'cards'];
215
+ }, [propAvailableViews]);
216
+ // Drag and drop state for Kanban
217
+ const [draggedItem, setDraggedItem] = (0, react_1.useState)(null);
218
+ const [dragOverCol, setDragOverCol] = (0, react_1.useState)(null);
219
+ const isDraggable = (row) => {
220
+ if (typeof canDragRecord === 'function')
221
+ return canDragRecord(row);
222
+ return Boolean(canDragRecord);
223
+ };
224
+ const handleDragStart = (e, item) => {
225
+ setDraggedItem(item);
226
+ e.dataTransfer.setData('text/plain', String(item.id ?? ''));
227
+ e.dataTransfer.effectAllowed = 'move';
228
+ };
229
+ const handleDragOver = (e, colKey) => {
230
+ e.preventDefault();
231
+ e.dataTransfer.dropEffect = 'move';
232
+ if (dragOverCol !== colKey)
233
+ setDragOverCol(colKey);
234
+ };
235
+ const handleDrop = async (e, colKey) => {
236
+ e.preventDefault();
237
+ setDragOverCol(null);
238
+ if (!draggedItem)
239
+ return;
240
+ const currentStage = getRowStage(draggedItem, stageKey);
241
+ if (currentStage !== colKey && onTransitionStage) {
242
+ await onTransitionStage(draggedItem, colKey);
243
+ }
244
+ setDraggedItem(null);
245
+ };
246
+ // Export CSV
247
+ const handleExport = () => {
248
+ if (onExportCsv) {
249
+ onExportCsv();
250
+ return;
251
+ }
252
+ if (!normalizedData.content || normalizedData.content.length === 0)
253
+ return;
254
+ const headers = visibleColumns.map((c) => c.label || c.header || c.key);
255
+ const rows = normalizedData.content.map((row) => visibleColumns.map((c) => {
256
+ const v = typeof c.accessor === 'function'
257
+ ? c.accessor(row)
258
+ : row[c.key];
259
+ return typeof v === 'object' ? JSON.stringify(v) : String(v ?? '');
260
+ }));
261
+ const csvContent = 'data:text/csv;charset=utf-8,' +
262
+ [headers.join(','), ...rows.map((r) => r.map((cell) => `"${cell.replace(/"/g, '""')}"`).join(','))].join('\n');
263
+ const encodedUri = encodeURI(csvContent);
264
+ const link = document.createElement('a');
265
+ link.setAttribute('href', encodedUri);
266
+ link.setAttribute('download', `${exportFilename || title || 'export'}_${Date.now()}.csv`);
267
+ document.body.appendChild(link);
268
+ link.click();
269
+ document.body.removeChild(link);
270
+ };
271
+ // Active filter count
272
+ const activeFiltersCount = Object.keys(effectiveFilters).filter((k) => effectiveFilters[k] !== '' && effectiveFilters[k] !== null && effectiveFilters[k] !== undefined).length;
273
+ // Filter drawer toggle column
274
+ const toggleColumnVisibility = (key) => {
275
+ setHiddenColumns((prev) => {
276
+ const next = new Set(prev);
277
+ if (next.has(key))
278
+ next.delete(key);
279
+ else
280
+ next.add(key);
281
+ return next;
282
+ });
283
+ };
284
+ // Render cell content based on ColumnDef
285
+ const renderCellContent = (row, column) => {
286
+ if (typeof column.render === 'function') {
287
+ const cellVal = typeof column.accessor === 'function'
288
+ ? column.accessor(row)
289
+ : row[column.key];
290
+ return column.render(cellVal, row);
291
+ }
292
+ const val = typeof column.accessor === 'function'
293
+ ? column.accessor(row)
294
+ : row[column.key];
295
+ const type = String(column.type || '').toLowerCase();
296
+ const keyLower = String(column.key || '').toLowerCase();
297
+ if (val === null || val === undefined || val === '') {
298
+ return (0, jsx_runtime_1.jsx)("span", { style: { color: '#94A3B8' }, children: "\u2014" });
299
+ }
300
+ if (type === 'badge' || keyLower === 'status' || keyLower === 'role' || keyLower.includes('stage')) {
301
+ const badgeStyle = getBadgeStyle(String(val));
302
+ return ((0, jsx_runtime_1.jsx)("span", { style: {
303
+ display: 'inline-flex',
304
+ alignItems: 'center',
305
+ padding: '3px 9px',
306
+ borderRadius: 9999,
307
+ fontSize: '0.72rem',
308
+ fontWeight: 700,
309
+ backgroundColor: badgeStyle.bg,
310
+ color: badgeStyle.text,
311
+ border: `1px solid ${badgeStyle.border}`,
312
+ letterSpacing: '0.01em',
313
+ textTransform: 'capitalize',
314
+ }, children: String(val).replace(/_/g, ' ') }));
315
+ }
316
+ if (type === 'money' || keyLower.includes('amount') || keyLower.includes('price') || keyLower.includes('total')) {
317
+ const num = Number(val);
318
+ const symbol = column.currency === 'USD' ? '$' : '₹';
319
+ return ((0, jsx_runtime_1.jsxs)("span", { style: { fontFamily: 'ui-monospace, SFMono-Regular, Menlo, Monaco, monospace', fontWeight: 800, color: '#0F172A' }, children: [symbol, isNaN(num) ? String(val) : num.toLocaleString('en-IN')] }));
320
+ }
321
+ if (type === 'date' || keyLower.includes('date') || keyLower.includes('at') || keyLower === 'timestamp') {
322
+ const d = new Date(val);
323
+ if (!isNaN(d.getTime())) {
324
+ return ((0, jsx_runtime_1.jsx)("span", { style: { fontSize: '0.78rem', color: '#475569' }, children: d.toLocaleDateString('en-IN', { day: '2-digit', month: 'short', year: 'numeric' }) }));
325
+ }
326
+ }
327
+ if (type === 'image' || keyLower.includes('avatar') || keyLower.includes('logo')) {
328
+ const src = String(val);
329
+ if (src.startsWith('http') || src.startsWith('/')) {
330
+ return ((0, jsx_runtime_1.jsx)("img", { src: src, alt: "thumbnail", style: { width: 32, height: 32, borderRadius: 8, objectFit: 'cover', border: '1px solid #E2E8F0' } }));
331
+ }
332
+ }
333
+ return ((0, jsx_runtime_1.jsx)("span", { style: { fontSize: '0.82rem', color: '#1E293B', fontWeight: 500 }, children: String(val) }));
334
+ };
335
+ return ((0, jsx_runtime_1.jsxs)("div", { className: "sdui-dynamic-table-root", style: {
336
+ width: '100%',
337
+ boxSizing: 'border-box',
338
+ display: 'flex',
339
+ flexDirection: 'column',
340
+ gap: 12,
341
+ fontFamily: 'Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
342
+ }, children: [(0, jsx_runtime_1.jsxs)("div", { className: "sdui-dt-header", style: {
343
+ display: 'flex',
344
+ justifyContent: 'space-between',
345
+ alignItems: 'center',
346
+ flexWrap: 'wrap',
347
+ gap: 12,
348
+ padding: '14px 18px',
349
+ background: 'var(--surface-card, #FFFFFF)',
350
+ borderRadius: 16,
351
+ border: '1px solid var(--border-subtle, #E2E8F0)',
352
+ boxShadow: '0 1px 3px rgba(15, 23, 42, 0.04), 0 6px 20px rgba(15, 23, 42, 0.02)',
353
+ }, children: [(0, jsx_runtime_1.jsxs)("div", { style: { minWidth: 200 }, children: [title && ((0, jsx_runtime_1.jsx)("h2", { style: { margin: 0, fontSize: '1.18rem', fontWeight: 800, color: 'var(--text-main, #0F172A)', letterSpacing: '-0.02em' }, children: title })), subtitle && ((0, jsx_runtime_1.jsxs)("div", { style: { marginTop: 3, fontSize: '0.78rem', color: 'var(--text-muted, #64748B)', fontWeight: 500 }, children: [subtitle, normalizedData.totalElements > 0 && ((0, jsx_runtime_1.jsxs)("span", { children: [" \u00B7 ", (0, jsx_runtime_1.jsx)("strong", { style: { color: 'var(--color-primary, #6366F1)' }, children: normalizedData.totalElements.toLocaleString() }), " records"] }))] }))] }), (0, jsx_runtime_1.jsxs)("div", { style: { display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap', marginLeft: 'auto' }, children: [(0, jsx_runtime_1.jsxs)("div", { style: {
354
+ display: 'flex',
355
+ alignItems: 'center',
356
+ background: 'var(--surface-subtle, #F8FAFC)',
357
+ border: '1px solid var(--border-subtle, #E2E8F0)',
358
+ borderRadius: 10,
359
+ padding: '4px 10px',
360
+ gap: 6,
361
+ minWidth: 180,
362
+ }, children: [(0, jsx_runtime_1.jsx)("span", { style: { fontSize: '0.82rem', color: '#94A3B8' }, children: "\uD83D\uDD0D" }), (0, jsx_runtime_1.jsx)("input", { type: "text", placeholder: "Search records\u2026", value: activeSearch, onChange: (e) => handleSearchInput(e.target.value), style: {
363
+ border: 'none',
364
+ background: 'transparent',
365
+ outline: 'none',
366
+ fontSize: '0.8rem',
367
+ color: '#0F172A',
368
+ width: '100%',
369
+ } }), activeSearch && ((0, jsx_runtime_1.jsx)("button", { type: "button", onClick: () => handleSearchInput(''), style: {
370
+ border: 'none',
371
+ background: 'transparent',
372
+ cursor: 'pointer',
373
+ color: '#94A3B8',
374
+ fontSize: '0.82rem',
375
+ padding: 0,
376
+ }, children: "\u2715" }))] }), availableViews.length > 1 && ((0, jsx_runtime_1.jsxs)("div", { style: {
377
+ display: 'inline-flex',
378
+ background: 'var(--surface-subtle, #F8FAFC)',
379
+ border: '1px solid var(--border-subtle, #E2E8F0)',
380
+ borderRadius: 10,
381
+ padding: 3,
382
+ gap: 2,
383
+ }, children: [availableViews.includes('table') && ((0, jsx_runtime_1.jsxs)("button", { type: "button", title: "Table View", onClick: () => setViewMode('table'), style: {
384
+ padding: '5px 11px',
385
+ borderRadius: 7,
386
+ border: 'none',
387
+ fontSize: '0.78rem',
388
+ fontWeight: 700,
389
+ cursor: 'pointer',
390
+ display: 'flex',
391
+ alignItems: 'center',
392
+ gap: 5,
393
+ backgroundColor: activeView === 'table' ? 'var(--surface-card, #FFFFFF)' : 'transparent',
394
+ color: activeView === 'table' ? 'var(--color-primary, #6366F1)' : '#64748B',
395
+ boxShadow: activeView === 'table' ? '0 1px 3px rgba(15, 23, 42, 0.08)' : 'none',
396
+ transition: 'all 0.15s ease',
397
+ }, children: [(0, jsx_runtime_1.jsx)("span", { children: "\u2630" }), (0, jsx_runtime_1.jsx)("span", { children: "Table" })] })), availableViews.includes('kanban') && ((0, jsx_runtime_1.jsxs)("button", { type: "button", title: "Kanban Board", onClick: () => setViewMode('kanban'), style: {
398
+ padding: '5px 11px',
399
+ borderRadius: 7,
400
+ border: 'none',
401
+ fontSize: '0.78rem',
402
+ fontWeight: 700,
403
+ cursor: 'pointer',
404
+ display: 'flex',
405
+ alignItems: 'center',
406
+ gap: 5,
407
+ backgroundColor: activeView === 'kanban' ? 'var(--surface-card, #FFFFFF)' : 'transparent',
408
+ color: activeView === 'kanban' ? 'var(--color-primary, #6366F1)' : '#64748B',
409
+ boxShadow: activeView === 'kanban' ? '0 1px 3px rgba(15, 23, 42, 0.08)' : 'none',
410
+ transition: 'all 0.15s ease',
411
+ }, children: [(0, jsx_runtime_1.jsx)("span", { children: "\u229E" }), (0, jsx_runtime_1.jsx)("span", { children: "Kanban" })] })), availableViews.includes('cards') && ((0, jsx_runtime_1.jsxs)("button", { type: "button", title: "Cards Grid", onClick: () => setViewMode('cards'), style: {
412
+ padding: '5px 11px',
413
+ borderRadius: 7,
414
+ border: 'none',
415
+ fontSize: '0.78rem',
416
+ fontWeight: 700,
417
+ cursor: 'pointer',
418
+ display: 'flex',
419
+ alignItems: 'center',
420
+ gap: 5,
421
+ backgroundColor: activeView === 'cards' ? 'var(--surface-card, #FFFFFF)' : 'transparent',
422
+ color: activeView === 'cards' ? 'var(--color-primary, #6366F1)' : '#64748B',
423
+ boxShadow: activeView === 'cards' ? '0 1px 3px rgba(15, 23, 42, 0.08)' : 'none',
424
+ transition: 'all 0.15s ease',
425
+ }, children: [(0, jsx_runtime_1.jsx)("span", { children: "\u25A6" }), (0, jsx_runtime_1.jsx)("span", { children: "Cards" })] }))] })), onRefresh && ((0, jsx_runtime_1.jsxs)("button", { type: "button", onClick: onRefresh, title: "Refresh Records", style: {
426
+ padding: '6px 12px',
427
+ borderRadius: 10,
428
+ border: '1px solid var(--border-subtle, #E2E8F0)',
429
+ background: 'var(--surface-card, #FFFFFF)',
430
+ fontSize: '0.78rem',
431
+ fontWeight: 700,
432
+ color: '#475569',
433
+ cursor: 'pointer',
434
+ display: 'flex',
435
+ alignItems: 'center',
436
+ gap: 5,
437
+ }, children: [(0, jsx_runtime_1.jsx)("span", { children: "\u21BB" }), (0, jsx_runtime_1.jsx)("span", { children: "Refresh" })] })), normalizedData.enableExport !== false && ((0, jsx_runtime_1.jsxs)("button", { type: "button", onClick: handleExport, title: "Export Records CSV", style: {
438
+ padding: '6px 12px',
439
+ borderRadius: 10,
440
+ border: '1px solid var(--border-subtle, #E2E8F0)',
441
+ background: 'var(--surface-card, #FFFFFF)',
442
+ fontSize: '0.78rem',
443
+ fontWeight: 700,
444
+ color: '#475569',
445
+ cursor: 'pointer',
446
+ display: 'flex',
447
+ alignItems: 'center',
448
+ gap: 5,
449
+ }, children: [(0, jsx_runtime_1.jsx)("span", { children: "\u2B73" }), (0, jsx_runtime_1.jsx)("span", { children: "Export" })] })), (0, jsx_runtime_1.jsxs)("button", { type: "button", onClick: () => setFilterDrawerOpen(true), style: {
450
+ padding: '6px 14px',
451
+ borderRadius: 10,
452
+ border: `1px solid ${activeFiltersCount > 0 ? 'var(--color-primary, #6366F1)' : 'var(--border-subtle, #E2E8F0)'}`,
453
+ background: activeFiltersCount > 0 ? 'rgba(99, 102, 241, 0.08)' : 'var(--surface-card, #FFFFFF)',
454
+ color: activeFiltersCount > 0 ? 'var(--color-primary, #6366F1)' : '#0F172A',
455
+ fontSize: '0.78rem',
456
+ fontWeight: 700,
457
+ cursor: 'pointer',
458
+ display: 'flex',
459
+ alignItems: 'center',
460
+ gap: 6,
461
+ }, children: [(0, jsx_runtime_1.jsx)("span", { children: "\u2699" }), (0, jsx_runtime_1.jsx)("span", { children: "Filters & Columns" }), activeFiltersCount > 0 && ((0, jsx_runtime_1.jsx)("span", { style: {
462
+ background: 'var(--color-primary, #6366F1)',
463
+ color: '#FFFFFF',
464
+ borderRadius: 9999,
465
+ fontSize: '0.65rem',
466
+ fontWeight: 800,
467
+ padding: '1px 6px',
468
+ }, children: activeFiltersCount }))] }), extraHeaderActions, tableActions] })] }), filterDrawerOpen && ((0, jsx_runtime_1.jsx)("div", { style: {
469
+ position: 'fixed',
470
+ top: 0,
471
+ left: 0,
472
+ right: 0,
473
+ bottom: 0,
474
+ backgroundColor: 'rgba(15, 23, 42, 0.3)',
475
+ backdropFilter: 'blur(3px)',
476
+ zIndex: 9999,
477
+ display: 'flex',
478
+ justifyContent: 'flex-end',
479
+ }, onClick: () => setFilterDrawerOpen(false), children: (0, jsx_runtime_1.jsxs)("div", { style: {
480
+ width: 380,
481
+ maxWidth: '90vw',
482
+ height: '100%',
483
+ backgroundColor: '#FFFFFF',
484
+ boxShadow: '-8px 0 32px rgba(15, 23, 42, 0.16)',
485
+ display: 'flex',
486
+ flexDirection: 'column',
487
+ boxSizing: 'border-box',
488
+ }, onClick: (e) => e.stopPropagation(), children: [(0, jsx_runtime_1.jsxs)("div", { style: {
489
+ padding: '16px 20px',
490
+ borderBottom: '1px solid #E2E8F0',
491
+ display: 'flex',
492
+ justifyContent: 'space-between',
493
+ alignItems: 'center',
494
+ }, children: [(0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("h3", { style: { margin: 0, fontSize: '1rem', fontWeight: 800, color: '#0F172A' }, children: "Filters & Columns" }), (0, jsx_runtime_1.jsxs)("div", { style: { fontSize: '0.74rem', color: '#64748B', marginTop: 2 }, children: [visibleColumns.length, " of ", columns.length, " columns visible"] })] }), (0, jsx_runtime_1.jsx)("button", { type: "button", onClick: () => setFilterDrawerOpen(false), style: {
495
+ border: 'none',
496
+ background: 'transparent',
497
+ cursor: 'pointer',
498
+ fontSize: '1.2rem',
499
+ color: '#64748B',
500
+ }, children: "\u2715" })] }), (0, jsx_runtime_1.jsx)("div", { style: { padding: '12px 20px', borderBottom: '1px solid #E2E8F0' }, children: (0, jsx_runtime_1.jsx)("input", { type: "text", placeholder: "Find a column or filter\u2026", value: filterDrawerSearch, onChange: (e) => setFilterDrawerSearch(e.target.value), style: {
501
+ width: '100%',
502
+ padding: '8px 12px',
503
+ borderRadius: 8,
504
+ border: '1px solid #CBD5E1',
505
+ fontSize: '0.8rem',
506
+ outline: 'none',
507
+ boxSizing: 'border-box',
508
+ } }) }), (0, jsx_runtime_1.jsxs)("div", { style: { padding: '16px 20px', flex: 1, overflowY: 'auto', display: 'flex', flexDirection: 'column', gap: 14 }, children: [(0, jsx_runtime_1.jsx)("div", { style: { fontSize: '0.7rem', fontWeight: 800, color: '#94A3B8', letterSpacing: '0.06em', textTransform: 'uppercase' }, children: "Columns & Active Dimensions" }), columns
509
+ .filter((c) => !filterDrawerSearch || c.label.toLowerCase().includes(filterDrawerSearch.toLowerCase()))
510
+ .map((col) => {
511
+ const isVisible = !hiddenColumns.has(col.key);
512
+ const boundFilter = filters.find((f) => f.key === col.key || f.columnKey === col.key);
513
+ return ((0, jsx_runtime_1.jsxs)("div", { style: {
514
+ padding: '10px 12px',
515
+ borderRadius: 10,
516
+ border: '1px solid #E2E8F0',
517
+ backgroundColor: isVisible ? '#FFFFFF' : '#F8FAFC',
518
+ }, children: [(0, jsx_runtime_1.jsxs)("div", { style: { display: 'flex', alignItems: 'center', justifyContent: 'space-between' }, children: [(0, jsx_runtime_1.jsxs)("label", { style: { display: 'flex', alignItems: 'center', gap: 8, cursor: 'pointer', fontSize: '0.82rem', fontWeight: 700, color: isVisible ? '#0F172A' : '#94A3B8' }, children: [(0, jsx_runtime_1.jsx)("input", { type: "checkbox", checked: isVisible, onChange: () => toggleColumnVisibility(col.key), style: { cursor: 'pointer' } }), (0, jsx_runtime_1.jsx)("span", { children: col.label })] }), (0, jsx_runtime_1.jsx)("span", { style: { fontSize: '0.68rem', fontWeight: 600, color: '#94A3B8', textTransform: 'uppercase' }, children: col.type || 'text' })] }), boundFilter && isVisible && ((0, jsx_runtime_1.jsx)("div", { style: { marginTop: 8, paddingTop: 8, borderTop: '1px dashed #E2E8F0' }, children: boundFilter.type === 'SELECT' ? ((0, jsx_runtime_1.jsxs)("select", { value: String(effectiveFilters[boundFilter.key] || ''), onChange: (e) => {
519
+ const next = { ...effectiveFilters, [boundFilter.key]: e.target.value };
520
+ if (!e.target.value)
521
+ delete next[boundFilter.key];
522
+ setInternalFilters(next);
523
+ onFilterChange?.(next);
524
+ }, style: {
525
+ width: '100%',
526
+ padding: '6px 8px',
527
+ borderRadius: 6,
528
+ border: '1px solid #CBD5E1',
529
+ fontSize: '0.78rem',
530
+ color: '#0F172A',
531
+ backgroundColor: '#FFFFFF',
532
+ }, children: [(0, jsx_runtime_1.jsxs)("option", { value: "", children: ["All ", boundFilter.label] }), (boundFilter.options || []).map((opt) => ((0, jsx_runtime_1.jsx)("option", { value: String(opt.value), children: opt.label }, String(opt.value))))] })) : ((0, jsx_runtime_1.jsx)("input", { type: "text", placeholder: `Filter by ${boundFilter.label}…`, value: String(effectiveFilters[boundFilter.key] || ''), onChange: (e) => {
533
+ const next = { ...effectiveFilters, [boundFilter.key]: e.target.value };
534
+ if (!e.target.value)
535
+ delete next[boundFilter.key];
536
+ setInternalFilters(next);
537
+ onFilterChange?.(next);
538
+ }, style: {
539
+ width: '100%',
540
+ padding: '6px 8px',
541
+ borderRadius: 6,
542
+ border: '1px solid #CBD5E1',
543
+ fontSize: '0.78rem',
544
+ boxSizing: 'border-box',
545
+ } })) }))] }, col.key));
546
+ })] }), (0, jsx_runtime_1.jsxs)("div", { style: {
547
+ padding: '14px 20px',
548
+ borderTop: '1px solid #E2E8F0',
549
+ display: 'flex',
550
+ justifyContent: 'space-between',
551
+ alignItems: 'center',
552
+ backgroundColor: '#F8FAFC',
553
+ }, children: [(0, jsx_runtime_1.jsx)("button", { type: "button", onClick: () => {
554
+ setInternalFilters({});
555
+ setHiddenColumns(new Set());
556
+ onFilterChange?.({});
557
+ }, style: {
558
+ border: 'none',
559
+ background: 'transparent',
560
+ color: '#EF4444',
561
+ fontSize: '0.78rem',
562
+ fontWeight: 700,
563
+ cursor: 'pointer',
564
+ }, children: "Clear all filters" }), (0, jsx_runtime_1.jsx)("button", { type: "button", onClick: () => setFilterDrawerOpen(false), style: {
565
+ padding: '7px 18px',
566
+ borderRadius: 8,
567
+ border: 'none',
568
+ background: 'var(--color-primary, #6366F1)',
569
+ color: '#FFFFFF',
570
+ fontSize: '0.8rem',
571
+ fontWeight: 700,
572
+ cursor: 'pointer',
573
+ }, children: "Done" })] })] }) })), error && ((0, jsx_runtime_1.jsx)("div", { style: {
574
+ padding: '12px 16px',
575
+ borderRadius: 12,
576
+ backgroundColor: '#FEF2F2',
577
+ border: '1px solid #FECACA',
578
+ color: '#B91C1C',
579
+ fontSize: '0.84rem',
580
+ fontWeight: 600,
581
+ }, children: error })), activeView === 'table' && ((0, jsx_runtime_1.jsx)("div", { className: "sdui-dt-surface", style: {
582
+ width: '100%',
583
+ overflowX: 'auto',
584
+ background: 'var(--surface-card, #FFFFFF)',
585
+ borderRadius: 16,
586
+ border: '1px solid var(--border-subtle, #E2E8F0)',
587
+ boxShadow: '0 1px 3px rgba(15, 23, 42, 0.04), 0 6px 20px rgba(15, 23, 42, 0.02)',
588
+ }, children: (0, jsx_runtime_1.jsxs)("table", { style: { width: '100%', borderCollapse: 'collapse', textAlign: 'left', fontSize: '0.82rem' }, children: [(0, jsx_runtime_1.jsx)("thead", { children: (0, jsx_runtime_1.jsxs)("tr", { style: { background: 'var(--surface-subtle, #F8FAFC)', borderBottom: '1px solid var(--border-subtle, #E2E8F0)' }, children: [visibleColumns.map((col) => {
589
+ const isSorted = normalizedData.sortBy === col.key;
590
+ const sortDir = normalizedData.sortDir?.toLowerCase();
591
+ return ((0, jsx_runtime_1.jsx)("th", { style: {
592
+ padding: compact ? '8px 12px' : '12px 16px',
593
+ fontWeight: 700,
594
+ color: '#475569',
595
+ fontSize: '0.74rem',
596
+ letterSpacing: '0.04em',
597
+ textTransform: 'uppercase',
598
+ textAlign: col.align || 'left',
599
+ cursor: col.sortable !== false ? 'pointer' : 'default',
600
+ userSelect: 'none',
601
+ whiteSpace: 'nowrap',
602
+ }, onClick: () => col.sortable !== false && onSortChange?.(col.key, sortDir === 'asc' ? 'desc' : 'asc'), children: (0, jsx_runtime_1.jsxs)("div", { style: { display: 'inline-flex', alignItems: 'center', gap: 6 }, children: [(0, jsx_runtime_1.jsx)("span", { children: col.label || col.header || col.key }), col.sortable !== false && ((0, jsx_runtime_1.jsx)("span", { style: { fontSize: '0.7rem', color: isSorted ? 'var(--color-primary, #6366F1)' : '#CBD5E1' }, children: isSorted ? (sortDir === 'desc' ? '▼' : '▲') : '⇅' }))] }) }, col.key));
603
+ }), Boolean(actions || rowActions) && ((0, jsx_runtime_1.jsx)("th", { style: {
604
+ padding: compact ? '8px 12px' : '12px 16px',
605
+ fontWeight: 800,
606
+ color: '#475569',
607
+ fontSize: '0.74rem',
608
+ letterSpacing: '0.04em',
609
+ textTransform: 'uppercase',
610
+ textAlign: 'right',
611
+ }, children: "Actions" }))] }) }), (0, jsx_runtime_1.jsx)("tbody", { children: loading ? ((0, jsx_runtime_1.jsx)("tr", { children: (0, jsx_runtime_1.jsxs)("td", { colSpan: visibleColumns.length + (actions || rowActions ? 1 : 0), style: { padding: 48, textAlign: 'center', color: '#64748B' }, children: [(0, jsx_runtime_1.jsx)("div", { style: { fontSize: '1.2rem', marginBottom: 6 }, children: "\u23F3" }), (0, jsx_runtime_1.jsx)("div", { style: { fontWeight: 600 }, children: "Loading records\u2026" })] }) })) : normalizedData.content.length === 0 ? ((0, jsx_runtime_1.jsx)("tr", { children: (0, jsx_runtime_1.jsxs)("td", { colSpan: visibleColumns.length + (actions || rowActions ? 1 : 0), style: { padding: 48, textAlign: 'center', color: '#64748B' }, children: [(0, jsx_runtime_1.jsx)("div", { style: { fontSize: '1.4rem', marginBottom: 6 }, children: "\uD83D\uDCED" }), (0, jsx_runtime_1.jsx)("div", { style: { fontWeight: 700, color: '#0F172A', marginBottom: 2 }, children: emptyMessage || 'No records found' }), (0, jsx_runtime_1.jsx)("div", { style: { fontSize: '0.76rem' }, children: "Try clearing filters or search terms" })] }) })) : (normalizedData.content.map((row, idx) => {
612
+ const rowId = row.id || idx;
613
+ return ((0, jsx_runtime_1.jsxs)(react_1.default.Fragment, { children: [(0, jsx_runtime_1.jsxs)("tr", { onClick: (e) => {
614
+ const target = e.target;
615
+ if (target.closest('button') || target.closest('a') || target.closest('select'))
616
+ return;
617
+ onRowClick?.(row);
618
+ }, style: {
619
+ borderBottom: '1px solid #F1F5F9',
620
+ cursor: onRowClick ? 'pointer' : 'default',
621
+ transition: 'background-color 0.15s ease',
622
+ }, onMouseEnter: (e) => (e.currentTarget.style.backgroundColor = 'rgba(99, 102, 241, 0.04)'), onMouseLeave: (e) => (e.currentTarget.style.backgroundColor = 'transparent'), children: [visibleColumns.map((col) => ((0, jsx_runtime_1.jsx)("td", { style: {
623
+ padding: compact ? '8px 12px' : '12px 16px',
624
+ textAlign: col.align || 'left',
625
+ verticalAlign: 'middle',
626
+ }, children: renderCellContent(row, col) }, col.key))), Boolean(actions || rowActions) && ((0, jsx_runtime_1.jsx)("td", { style: {
627
+ padding: compact ? '8px 12px' : '12px 16px',
628
+ textAlign: 'right',
629
+ verticalAlign: 'middle',
630
+ }, onClick: (e) => e.stopPropagation(), children: (actions || rowActions)(row) }))] }), renderExpandedRow && ((0, jsx_runtime_1.jsx)("tr", { children: (0, jsx_runtime_1.jsx)("td", { colSpan: visibleColumns.length + (actions || rowActions ? 1 : 0), style: {
631
+ padding: compact ? '8px 12px' : '12px 16px',
632
+ backgroundColor: 'rgba(99, 102, 241, 0.02)',
633
+ borderBottom: '1px solid #E2E8F0',
634
+ }, children: renderExpandedRow(row) }) }))] }, rowId));
635
+ })) })] }) })), activeView === 'kanban' && ((0, jsx_runtime_1.jsx)("div", { className: "sdui-kanban-board", style: {
636
+ display: 'flex',
637
+ gap: 16,
638
+ overflowX: 'auto',
639
+ paddingBottom: 14,
640
+ minHeight: 520,
641
+ alignItems: 'stretch',
642
+ }, children: kanbanStages.map((stage) => {
643
+ const isColOver = dragOverCol === stage.key;
644
+ const stageRecords = normalizedData.content.filter((item) => {
645
+ const itemStage = getRowStage(item, stageKey);
646
+ if (stage.statuses && stage.statuses.length > 0) {
647
+ return stage.statuses.includes(itemStage) || itemStage === stage.key;
648
+ }
649
+ return itemStage === stage.key;
650
+ });
651
+ return ((0, jsx_runtime_1.jsxs)("div", { onDragOver: (e) => handleDragOver(e, stage.key), onDragLeave: () => setDragOverCol(null), onDrop: (e) => handleDrop(e, stage.key), style: {
652
+ flex: '0 0 310px',
653
+ background: isColOver ? 'rgba(99, 102, 241, 0.08)' : 'var(--surface-subtle, #F8FAFC)',
654
+ border: `1px ${isColOver ? 'dashed var(--color-primary, #6366F1)' : 'solid var(--border-subtle, #E2E8F0)'}`,
655
+ borderRadius: 16,
656
+ display: 'flex',
657
+ flexDirection: 'column',
658
+ maxHeight: 'calc(100vh - 280px)',
659
+ transition: 'all 0.15s ease',
660
+ boxShadow: '0 1px 3px rgba(15, 23, 42, 0.04)',
661
+ }, children: [(0, jsx_runtime_1.jsxs)("div", { style: {
662
+ padding: '12px 14px',
663
+ display: 'flex',
664
+ alignItems: 'center',
665
+ justifyContent: 'space-between',
666
+ borderBottom: '1px solid var(--border-subtle, #E2E8F0)',
667
+ background: 'var(--surface-card, #FFFFFF)',
668
+ borderTopLeftRadius: 16,
669
+ borderTopRightRadius: 16,
670
+ borderTop: `3px solid ${stage.color || '#6366F1'}`,
671
+ }, children: [(0, jsx_runtime_1.jsxs)("div", { style: { display: 'flex', alignItems: 'center', gap: 7 }, children: [(0, jsx_runtime_1.jsx)("span", { style: {
672
+ width: 8,
673
+ height: 8,
674
+ borderRadius: '50%',
675
+ backgroundColor: stage.color || '#6366F1',
676
+ } }), (0, jsx_runtime_1.jsx)("span", { style: { fontWeight: 800, fontSize: '0.82rem', color: '#0F172A' }, children: stage.label })] }), (0, jsx_runtime_1.jsx)("span", { style: {
677
+ fontSize: '0.72rem',
678
+ fontWeight: 800,
679
+ padding: '2px 8px',
680
+ borderRadius: 9999,
681
+ background: 'var(--surface-subtle, #F8FAFC)',
682
+ color: '#64748B',
683
+ border: '1px solid var(--border-subtle, #E2E8F0)',
684
+ }, children: stageRecords.length })] }), (0, jsx_runtime_1.jsx)("div", { style: {
685
+ padding: 10,
686
+ display: 'flex',
687
+ flexDirection: 'column',
688
+ gap: 10,
689
+ overflowY: 'auto',
690
+ flex: 1,
691
+ }, children: stageRecords.length === 0 ? ((0, jsx_runtime_1.jsx)("div", { style: { padding: '36px 16px', textAlign: 'center', color: '#94A3B8', fontSize: '0.78rem', fontStyle: 'italic' }, children: "No records in this stage" })) : (stageRecords.map((item, i) => {
692
+ const draggable = isDraggable(item);
693
+ const isDragged = draggedItem && draggedItem.id === item.id;
694
+ const allowedNext = item.allowedNextTransitions || [];
695
+ if (renderCustomCard) {
696
+ return ((0, jsx_runtime_1.jsx)("div", { draggable: draggable, onDragStart: (e) => handleDragStart(e, item), onDragEnd: () => setDraggedItem(null), onClick: () => onRowClick?.(item), children: renderCustomCard(item, (target) => onTransitionStage?.(item, target)) }, item.id ?? i));
697
+ }
698
+ return ((0, jsx_runtime_1.jsxs)("div", { draggable: draggable, onDragStart: (e) => handleDragStart(e, item), onDragEnd: () => setDraggedItem(null), onClick: (e) => {
699
+ const target = e.target;
700
+ if (target.closest('button') || target.closest('select'))
701
+ return;
702
+ onRowClick?.(item);
703
+ }, style: {
704
+ background: 'var(--surface-card, #FFFFFF)',
705
+ border: '1px solid var(--border-subtle, #E2E8F0)',
706
+ borderRadius: 12,
707
+ padding: '12px 14px',
708
+ cursor: draggable ? 'grab' : onRowClick ? 'pointer' : 'default',
709
+ opacity: isDragged ? 0.4 : 1,
710
+ boxShadow: '0 1px 3px rgba(15, 23, 42, 0.04)',
711
+ transition: 'all 0.15s ease',
712
+ }, onMouseEnter: (e) => {
713
+ e.currentTarget.style.transform = 'translateY(-2px)';
714
+ e.currentTarget.style.boxShadow = '0 8px 20px rgba(15, 23, 42, 0.08)';
715
+ }, onMouseLeave: (e) => {
716
+ e.currentTarget.style.transform = 'none';
717
+ e.currentTarget.style.boxShadow = '0 1px 3px rgba(15, 23, 42, 0.04)';
718
+ }, children: [(0, jsx_runtime_1.jsxs)("div", { style: { display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', gap: 6, marginBottom: 6 }, children: [(0, jsx_runtime_1.jsx)("span", { style: { fontWeight: 800, fontSize: '0.82rem', color: '#0F172A', letterSpacing: '-0.01em' }, children: item.code || `#${String(item.id || i + 1).slice(0, 8)}` }), (item.stageCode || item.deliveryStatus || item.status) && ((0, jsx_runtime_1.jsx)("span", { style: {
719
+ fontSize: '0.66rem',
720
+ fontWeight: 700,
721
+ padding: '2px 7px',
722
+ borderRadius: 9999,
723
+ backgroundColor: getBadgeStyle(item.stageCode || item.deliveryStatus || item.status).bg,
724
+ color: getBadgeStyle(item.stageCode || item.deliveryStatus || item.status).text,
725
+ border: `1px solid ${getBadgeStyle(item.stageCode || item.deliveryStatus || item.status).border}`,
726
+ }, children: String(item.stageName || item.stageCode || item.deliveryStatus || item.status).replace(/_/g, ' ') }))] }), (item.customerName || item.storeName) && ((0, jsx_runtime_1.jsx)("div", { style: { fontSize: '0.78rem', fontWeight: 600, color: '#1E293B', marginBottom: 2 }, children: item.customerName || item.storeName })), item.itemsSummary && ((0, jsx_runtime_1.jsx)("div", { style: { fontSize: '0.72rem', color: '#64748B', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis', marginBottom: 6 }, children: item.itemsSummary })), (0, jsx_runtime_1.jsxs)("div", { style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginTop: 4 }, children: [item.totalAmount !== undefined && ((0, jsx_runtime_1.jsxs)("span", { style: { fontWeight: 800, fontSize: '0.84rem', color: 'var(--color-primary, #6366F1)', fontFamily: 'ui-monospace, monospace' }, children: ["\u20B9", Number(item.totalAmount || 0).toLocaleString('en-IN')] })), item.createdAt && ((0, jsx_runtime_1.jsx)("span", { style: { fontSize: '0.68rem', color: '#94A3B8' }, children: new Date(item.createdAt).toLocaleDateString() }))] }), allowedNext.length > 0 && onTransitionStage && ((0, jsx_runtime_1.jsx)("div", { style: {
727
+ marginTop: 8,
728
+ paddingTop: 8,
729
+ borderTop: '1px solid #F1F5F9',
730
+ display: 'flex',
731
+ gap: 4,
732
+ flexWrap: 'wrap',
733
+ }, onClick: (e) => e.stopPropagation(), children: allowedNext.map((opt) => ((0, jsx_runtime_1.jsxs)("button", { type: "button", onClick: () => onTransitionStage(item, opt.code || opt.id, opt), style: {
734
+ fontSize: '0.66rem',
735
+ fontWeight: 700,
736
+ padding: '2px 8px',
737
+ borderRadius: 9999,
738
+ border: '1px solid #BFDBFE',
739
+ backgroundColor: '#EFF6FF',
740
+ color: '#1D4ED8',
741
+ cursor: 'pointer',
742
+ }, children: ["\u2192 ", opt.name || opt.code?.replace(/_/g, ' ')] }, opt.id || opt.code))) })), Boolean(actions || rowActions) && ((0, jsx_runtime_1.jsx)("div", { style: {
743
+ marginTop: 6,
744
+ paddingTop: 6,
745
+ borderTop: '1px solid #F1F5F9',
746
+ display: 'flex',
747
+ justifyContent: 'flex-end',
748
+ gap: 4,
749
+ }, onClick: (e) => e.stopPropagation(), children: (actions || rowActions)(item) }))] }, item.id ?? i));
750
+ })) })] }, stage.key));
751
+ }) })), activeView === 'cards' && ((0, jsx_runtime_1.jsx)("div", { className: "sdui-cards-grid", style: {
752
+ display: 'grid',
753
+ gridTemplateColumns: 'repeat(auto-fill, minmax(290px, 1fr))',
754
+ gap: 12,
755
+ }, children: loading ? ((0, jsx_runtime_1.jsx)("div", { style: { gridColumn: '1 / -1', padding: 48, textAlign: 'center', color: '#64748B' }, children: "Loading cards\u2026" })) : normalizedData.content.length === 0 ? ((0, jsx_runtime_1.jsxs)("div", { style: { gridColumn: '1 / -1', padding: 48, textAlign: 'center', color: '#64748B' }, children: [(0, jsx_runtime_1.jsx)("div", { style: { fontSize: '1.4rem', marginBottom: 6 }, children: "\uD83D\uDCED" }), (0, jsx_runtime_1.jsx)("div", { style: { fontWeight: 700, color: '#0F172A', marginBottom: 2 }, children: emptyMessage || 'No records found' }), (0, jsx_runtime_1.jsx)("div", { style: { fontSize: '0.76rem' }, children: "Try clearing filters or search terms" })] })) : (normalizedData.content.map((item, idx) => {
756
+ const currentStage = getRowStage(item, stageKey);
757
+ const allowedNext = item.allowedNextTransitions || [];
758
+ if (renderCustomCard) {
759
+ return ((0, jsx_runtime_1.jsx)("div", { onClick: () => onRowClick?.(item), children: renderCustomCard(item, (target) => onTransitionStage?.(item, target)) }, item.id ?? idx));
760
+ }
761
+ return ((0, jsx_runtime_1.jsxs)("div", { onClick: (e) => {
762
+ const target = e.target;
763
+ if (target.closest('button'))
764
+ return;
765
+ onRowClick?.(item);
766
+ }, style: {
767
+ background: 'var(--surface-card, #FFFFFF)',
768
+ border: '1px solid var(--border-subtle, #E2E8F0)',
769
+ borderRadius: 14,
770
+ padding: 16,
771
+ display: 'flex',
772
+ flexDirection: 'column',
773
+ gap: 8,
774
+ cursor: onRowClick ? 'pointer' : 'default',
775
+ boxShadow: '0 1px 3px rgba(15, 23, 42, 0.04)',
776
+ transition: 'all 0.15s ease',
777
+ }, onMouseEnter: (e) => {
778
+ e.currentTarget.style.transform = 'translateY(-2px)';
779
+ e.currentTarget.style.boxShadow = '0 8px 24px rgba(15, 23, 42, 0.08)';
780
+ }, onMouseLeave: (e) => {
781
+ e.currentTarget.style.transform = 'none';
782
+ e.currentTarget.style.boxShadow = '0 1px 3px rgba(15, 23, 42, 0.04)';
783
+ }, children: [(0, jsx_runtime_1.jsxs)("div", { style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center' }, children: [(0, jsx_runtime_1.jsx)("span", { style: { fontWeight: 800, fontSize: '0.85rem', color: '#0F172A' }, children: item.code || `#${String(item.id || idx + 1).slice(0, 8)}` }), currentStage && ((0, jsx_runtime_1.jsx)("span", { style: {
784
+ fontSize: '0.68rem',
785
+ fontWeight: 700,
786
+ padding: '2px 8px',
787
+ borderRadius: 9999,
788
+ backgroundColor: getBadgeStyle(currentStage).bg,
789
+ color: getBadgeStyle(currentStage).text,
790
+ border: `1px solid ${getBadgeStyle(currentStage).border}`,
791
+ }, children: currentStage.replace(/_/g, ' ') }))] }), (item.customerName || item.storeName) && ((0, jsx_runtime_1.jsx)("div", { style: { fontSize: '0.8rem', fontWeight: 600, color: '#1E293B' }, children: item.customerName || item.storeName })), item.itemsSummary && ((0, jsx_runtime_1.jsx)("div", { style: { fontSize: '0.74rem', color: '#64748B' }, children: item.itemsSummary })), (0, jsx_runtime_1.jsxs)("div", { style: {
792
+ display: 'flex',
793
+ justifyContent: 'space-between',
794
+ alignItems: 'center',
795
+ marginTop: 'auto',
796
+ paddingTop: 10,
797
+ borderTop: '1px solid #F1F5F9',
798
+ }, children: [item.totalAmount !== undefined && ((0, jsx_runtime_1.jsxs)("span", { style: { fontWeight: 800, fontSize: '0.88rem', color: 'var(--color-primary, #6366F1)', fontFamily: 'ui-monospace, monospace' }, children: ["\u20B9", Number(item.totalAmount || 0).toLocaleString('en-IN')] })), allowedNext.length > 0 && onTransitionStage && ((0, jsx_runtime_1.jsxs)("button", { type: "button", onClick: () => onTransitionStage(item, allowedNext[0].code || allowedNext[0].id, allowedNext[0]), style: {
799
+ fontSize: '0.68rem',
800
+ fontWeight: 700,
801
+ padding: '3px 10px',
802
+ borderRadius: 9999,
803
+ border: '1px solid #BFDBFE',
804
+ backgroundColor: '#EFF6FF',
805
+ color: '#1D4ED8',
806
+ cursor: 'pointer',
807
+ }, children: ["\u2192 ", allowedNext[0].name || allowedNext[0].code?.replace(/_/g, ' ')] }))] }), Boolean(actions || rowActions) && ((0, jsx_runtime_1.jsx)("div", { style: {
808
+ marginTop: 6,
809
+ paddingTop: 8,
810
+ borderTop: '1px solid #F1F5F9',
811
+ display: 'flex',
812
+ justifyContent: 'flex-end',
813
+ gap: 6,
814
+ }, onClick: (e) => e.stopPropagation(), children: (actions || rowActions)(item) }))] }, item.id ?? idx));
815
+ })) })), (0, jsx_runtime_1.jsxs)("div", { className: "sdui-dt-footer", style: {
816
+ display: 'flex',
817
+ justifyContent: 'space-between',
818
+ alignItems: 'center',
819
+ flexWrap: 'wrap',
820
+ gap: 12,
821
+ padding: '10px 16px',
822
+ background: 'var(--surface-card, #FFFFFF)',
823
+ borderRadius: 14,
824
+ border: '1px solid var(--border-subtle, #E2E8F0)',
825
+ fontSize: '0.78rem',
826
+ color: '#64748B',
827
+ }, children: [(0, jsx_runtime_1.jsxs)("div", { style: { display: 'flex', alignItems: 'center', gap: 10 }, children: [(0, jsx_runtime_1.jsx)("span", { children: "Rows per page:" }), (0, jsx_runtime_1.jsx)("select", { value: normalizedData.pageSize, onChange: (e) => onRowsPerPageChange?.(Number(e.target.value)), style: {
828
+ padding: '3px 6px',
829
+ borderRadius: 6,
830
+ border: '1px solid #CBD5E1',
831
+ fontSize: '0.78rem',
832
+ backgroundColor: '#FFFFFF',
833
+ color: '#0F172A',
834
+ }, children: pageSizeOptions.map((sz) => ((0, jsx_runtime_1.jsx)("option", { value: sz, children: sz }, sz))) }), (0, jsx_runtime_1.jsx)("span", { children: normalizedData.totalElements > 0
835
+ ? `${normalizedData.pageNumber * normalizedData.pageSize + 1}–${Math.min((normalizedData.pageNumber + 1) * normalizedData.pageSize, normalizedData.totalElements)} of ${normalizedData.totalElements}`
836
+ : '0 records' })] }), (0, jsx_runtime_1.jsxs)("div", { style: { display: 'flex', gap: 6, alignItems: 'center' }, children: [(0, jsx_runtime_1.jsx)("button", { type: "button", disabled: normalizedData.pageNumber <= 0, onClick: () => onPageChange?.(normalizedData.pageNumber - 1), style: {
837
+ padding: '4px 10px',
838
+ borderRadius: 6,
839
+ border: '1px solid #CBD5E1',
840
+ backgroundColor: '#FFFFFF',
841
+ fontSize: '0.78rem',
842
+ fontWeight: 600,
843
+ cursor: normalizedData.pageNumber <= 0 ? 'not-allowed' : 'pointer',
844
+ opacity: normalizedData.pageNumber <= 0 ? 0.4 : 1,
845
+ }, children: "\u2039 Prev" }), (0, jsx_runtime_1.jsxs)("span", { style: { fontSize: '0.78rem', color: '#0F172A', fontWeight: 600 }, children: ["Page ", normalizedData.pageNumber + 1, " of ", Math.max(1, normalizedData.totalPages)] }), (0, jsx_runtime_1.jsx)("button", { type: "button", disabled: normalizedData.last, onClick: () => onPageChange?.(normalizedData.pageNumber + 1), style: {
846
+ padding: '4px 10px',
847
+ borderRadius: 6,
848
+ border: '1px solid #CBD5E1',
849
+ backgroundColor: '#FFFFFF',
850
+ fontSize: '0.78rem',
851
+ fontWeight: 600,
852
+ cursor: normalizedData.last ? 'not-allowed' : 'pointer',
853
+ opacity: normalizedData.last ? 0.4 : 1,
854
+ }, children: "Next \u203A" })] })] })] }));
855
+ }
856
+ exports.default = DynamicTable;