@gridcore/react-smart-table 0.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.
- package/README.md +139 -0
- package/dist/index.d.mts +149 -0
- package/dist/index.d.ts +149 -0
- package/dist/index.js +864 -0
- package/dist/index.mjs +822 -0
- package/package.json +33 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,864 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// src/index.ts
|
|
31
|
+
var index_exports = {};
|
|
32
|
+
__export(index_exports, {
|
|
33
|
+
ColumnSelector: () => ColumnSelector,
|
|
34
|
+
Icon: () => Icon,
|
|
35
|
+
Pagination: () => Pagination,
|
|
36
|
+
SmartTable: () => SmartTable,
|
|
37
|
+
Tooltip: () => Tooltip,
|
|
38
|
+
getIcon: () => getIcon
|
|
39
|
+
});
|
|
40
|
+
module.exports = __toCommonJS(index_exports);
|
|
41
|
+
|
|
42
|
+
// src/components/SmartTable.tsx
|
|
43
|
+
var import_react4 = require("react");
|
|
44
|
+
|
|
45
|
+
// src/components/SearchBar.tsx
|
|
46
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
47
|
+
var SearchBar = ({ value, onChange, placeholder = "Search...", primaryColor = "purple" }) => {
|
|
48
|
+
const focusRingColor = primaryColor === "purple" ? "focus:ring-purple-600 focus:border-purple-600" : `focus:ring-${primaryColor}-600 focus:border-${primaryColor}-600`;
|
|
49
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "relative flex-1", children: [
|
|
50
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
51
|
+
"input",
|
|
52
|
+
{
|
|
53
|
+
type: "text",
|
|
54
|
+
placeholder,
|
|
55
|
+
value,
|
|
56
|
+
onChange: (e) => onChange(e.target.value),
|
|
57
|
+
className: `w-full h-[41px] pl-10 pr-10 border border-gray-300 rounded-md focus:outline-none focus:ring-1 ${focusRingColor}`
|
|
58
|
+
}
|
|
59
|
+
),
|
|
60
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { className: "absolute left-3 top-3 w-5 h-5 text-gray-400", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" }) }),
|
|
61
|
+
value && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
62
|
+
"button",
|
|
63
|
+
{
|
|
64
|
+
onClick: () => onChange(""),
|
|
65
|
+
className: "absolute right-3 top-3 text-gray-400 hover:text-gray-600",
|
|
66
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { className: "w-5 h-5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) })
|
|
67
|
+
}
|
|
68
|
+
)
|
|
69
|
+
] });
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
// src/components/BulkActionsDropdown.tsx
|
|
73
|
+
var import_react = require("react");
|
|
74
|
+
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
75
|
+
var colorClasses = {
|
|
76
|
+
red: "text-red-600",
|
|
77
|
+
green: "text-green-600",
|
|
78
|
+
yellow: "text-yellow-600",
|
|
79
|
+
blue: "text-blue-600"
|
|
80
|
+
};
|
|
81
|
+
var BulkActionsDropdown = ({
|
|
82
|
+
selectedCount,
|
|
83
|
+
isOpen,
|
|
84
|
+
onToggle,
|
|
85
|
+
actions,
|
|
86
|
+
onClose
|
|
87
|
+
}) => {
|
|
88
|
+
const dropdownRef = (0, import_react.useRef)(null);
|
|
89
|
+
(0, import_react.useEffect)(() => {
|
|
90
|
+
const handleClickOutside = (event) => {
|
|
91
|
+
if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {
|
|
92
|
+
onClose();
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
if (isOpen) {
|
|
96
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
97
|
+
}
|
|
98
|
+
return () => {
|
|
99
|
+
document.removeEventListener("mousedown", handleClickOutside);
|
|
100
|
+
};
|
|
101
|
+
}, [isOpen, onClose]);
|
|
102
|
+
if (selectedCount === 0) return null;
|
|
103
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "relative", ref: dropdownRef, children: [
|
|
104
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
105
|
+
"button",
|
|
106
|
+
{
|
|
107
|
+
onClick: onToggle,
|
|
108
|
+
className: "h-[41px] px-3 border border-purple-600 rounded-md hover:bg-gray-50 transition-colors flex items-center gap-2 text-purple-600",
|
|
109
|
+
children: [
|
|
110
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "text-sm font-medium", children: [
|
|
111
|
+
"Actions (",
|
|
112
|
+
selectedCount,
|
|
113
|
+
")"
|
|
114
|
+
] }),
|
|
115
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { className: "w-4 h-4", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M19 9l-7 7-7-7" }) })
|
|
116
|
+
]
|
|
117
|
+
}
|
|
118
|
+
),
|
|
119
|
+
isOpen && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "absolute top-full mt-2 right-0 w-40 bg-white border border-gray-200 rounded-lg shadow-xl z-50 py-2", children: actions.map((action, idx) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
120
|
+
"button",
|
|
121
|
+
{
|
|
122
|
+
onClick: () => {
|
|
123
|
+
action.onClick([]);
|
|
124
|
+
onClose();
|
|
125
|
+
},
|
|
126
|
+
className: `w-full px-4 py-2 text-left text-sm hover:bg-gray-50 flex items-center gap-3 ${colorClasses[action.color || "blue"]}`,
|
|
127
|
+
children: [
|
|
128
|
+
action.icon,
|
|
129
|
+
action.label
|
|
130
|
+
]
|
|
131
|
+
},
|
|
132
|
+
idx
|
|
133
|
+
)) })
|
|
134
|
+
] });
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
// src/components/Tooltip.tsx
|
|
138
|
+
var import_react2 = require("react");
|
|
139
|
+
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
140
|
+
var Tooltip = ({ children, text, position = "left" }) => {
|
|
141
|
+
const [isVisible, setIsVisible] = (0, import_react2.useState)(false);
|
|
142
|
+
const [isTruncated, setIsTruncated] = (0, import_react2.useState)(false);
|
|
143
|
+
const contentRef = (0, import_react2.useRef)(null);
|
|
144
|
+
(0, import_react2.useEffect)(() => {
|
|
145
|
+
const checkTruncation = () => {
|
|
146
|
+
if (contentRef.current) {
|
|
147
|
+
const element = contentRef.current.querySelector("[data-truncate]");
|
|
148
|
+
if (element) {
|
|
149
|
+
setIsTruncated(element.scrollWidth > element.clientWidth || element.scrollHeight > element.clientHeight);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
};
|
|
153
|
+
checkTruncation();
|
|
154
|
+
window.addEventListener("resize", checkTruncation);
|
|
155
|
+
return () => window.removeEventListener("resize", checkTruncation);
|
|
156
|
+
}, [children]);
|
|
157
|
+
const positionClasses = {
|
|
158
|
+
left: "right-full mr-2 top-1/2 -translate-y-1/2",
|
|
159
|
+
right: "left-full ml-2 top-1/2 -translate-y-1/2",
|
|
160
|
+
top: "bottom-full mb-2 left-1/2 -translate-x-1/2",
|
|
161
|
+
bottom: "top-full mt-2 left-1/2 -translate-x-1/2"
|
|
162
|
+
};
|
|
163
|
+
const arrowClasses = {
|
|
164
|
+
left: "absolute left-full top-1/2 -translate-y-1/2 border-l-gray-800 border-l-4 border-y-transparent border-y-4 border-r-0",
|
|
165
|
+
right: "absolute right-full top-1/2 -translate-y-1/2 border-r-gray-800 border-r-4 border-y-transparent border-y-4 border-l-0",
|
|
166
|
+
top: "absolute top-full left-1/2 -translate-x-1/2 border-t-gray-800 border-t-4 border-x-transparent border-x-4 border-b-0",
|
|
167
|
+
bottom: "absolute bottom-full left-1/2 -translate-x-1/2 border-b-gray-800 border-b-4 border-x-transparent border-x-4 border-t-0"
|
|
168
|
+
};
|
|
169
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
170
|
+
"div",
|
|
171
|
+
{
|
|
172
|
+
ref: contentRef,
|
|
173
|
+
className: "relative inline-block",
|
|
174
|
+
onMouseEnter: () => isTruncated && setIsVisible(true),
|
|
175
|
+
onMouseLeave: () => setIsVisible(false),
|
|
176
|
+
children: [
|
|
177
|
+
children,
|
|
178
|
+
isVisible && isTruncated && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: `absolute z-50 ${positionClasses[position]}`, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "bg-gray-800 text-white text-xs px-2 py-1 rounded whitespace-nowrap", children: [
|
|
179
|
+
text,
|
|
180
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: arrowClasses[position] })
|
|
181
|
+
] }) })
|
|
182
|
+
]
|
|
183
|
+
}
|
|
184
|
+
);
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
// src/utils/icons.tsx
|
|
188
|
+
var LucideIcons = __toESM(require("lucide-react"));
|
|
189
|
+
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
190
|
+
var Icon = ({ name, className, size, strokeWidth, style }) => {
|
|
191
|
+
const LucideIcon = LucideIcons[name];
|
|
192
|
+
if (!LucideIcon) {
|
|
193
|
+
console.warn(`Icon "${name}" not found in lucide-react`);
|
|
194
|
+
return null;
|
|
195
|
+
}
|
|
196
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(LucideIcon, { className, size, strokeWidth, style });
|
|
197
|
+
};
|
|
198
|
+
var getIcon = (name, props) => {
|
|
199
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Icon, { name, ...props });
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
// src/components/TableHeader.tsx
|
|
203
|
+
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
204
|
+
function TableHeader({
|
|
205
|
+
columns,
|
|
206
|
+
showCheckbox,
|
|
207
|
+
showActions,
|
|
208
|
+
selectAll,
|
|
209
|
+
onSelectAll,
|
|
210
|
+
sortConfig,
|
|
211
|
+
onSort,
|
|
212
|
+
styles = {},
|
|
213
|
+
primaryColor = "purple"
|
|
214
|
+
}) {
|
|
215
|
+
const checkboxBg = primaryColor === "purple" ? "rgb(147 51 234)" : `var(--${primaryColor}-600)`;
|
|
216
|
+
const checkboxBorder = primaryColor === "purple" ? "rgb(147 51 234)" : `var(--${primaryColor}-600)`;
|
|
217
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("tr", { className: styles.headerRow || "border-b border-gray-200", children: [
|
|
218
|
+
showCheckbox && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("th", { className: styles.headerCell || "w-15 pl-4 py-3 text-left", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "relative group", children: [
|
|
219
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("input", { type: "checkbox", checked: selectAll, onChange: onSelectAll, className: "sr-only" }),
|
|
220
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
221
|
+
"div",
|
|
222
|
+
{
|
|
223
|
+
className: styles.checkbox || `w-5 h-5 border-2 rounded-lg cursor-pointer transition-all duration-300 flex items-center justify-center transform hover:scale-105 active:scale-95`,
|
|
224
|
+
style: {
|
|
225
|
+
borderColor: selectAll ? checkboxBorder : "rgb(209 213 219)",
|
|
226
|
+
backgroundColor: selectAll ? checkboxBg : "white"
|
|
227
|
+
},
|
|
228
|
+
onClick: onSelectAll,
|
|
229
|
+
children: selectAll && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Icon, { name: "Check", className: "w-3 h-3 text-white", strokeWidth: 2.5 })
|
|
230
|
+
}
|
|
231
|
+
)
|
|
232
|
+
] }) }),
|
|
233
|
+
columns.map((col) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
234
|
+
"th",
|
|
235
|
+
{
|
|
236
|
+
className: styles.headerCell || `px-4 py-3 text-xs font-medium uppercase tracking-wider text-left ${col.sortable ? "cursor-pointer hover:bg-gray-50" : ""}`,
|
|
237
|
+
onClick: () => col.sortable && onSort(col.key),
|
|
238
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex items-center space-x-2", children: [
|
|
239
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Tooltip, { text: col.title, position: "top", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "truncate", "data-truncate": true, children: col.title }) }),
|
|
240
|
+
col.sortable && (sortConfig == null ? void 0 : sortConfig.key) === col.key && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: sortConfig.direction === "asc" ? "\u2191" : "\u2193" })
|
|
241
|
+
] })
|
|
242
|
+
},
|
|
243
|
+
String(col.key)
|
|
244
|
+
)),
|
|
245
|
+
showActions && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("th", { className: styles.headerCell || "px-4 py-3 text-left text-xs font-medium uppercase tracking-wider", children: "Action" })
|
|
246
|
+
] });
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// src/components/TableRow.tsx
|
|
250
|
+
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
251
|
+
function TableRow({
|
|
252
|
+
row,
|
|
253
|
+
columns,
|
|
254
|
+
showCheckbox,
|
|
255
|
+
showActions,
|
|
256
|
+
isSelected,
|
|
257
|
+
onSelect,
|
|
258
|
+
onRowClick,
|
|
259
|
+
onEdit,
|
|
260
|
+
onDelete,
|
|
261
|
+
styles = {},
|
|
262
|
+
primaryColor = "purple"
|
|
263
|
+
}) {
|
|
264
|
+
const checkboxBg = primaryColor === "purple" ? "rgb(147 51 234)" : `var(--${primaryColor}-600)`;
|
|
265
|
+
const checkboxBorder = primaryColor === "purple" ? "rgb(147 51 234)" : `var(--${primaryColor}-600)`;
|
|
266
|
+
const actionColor = primaryColor === "purple" ? "rgb(147 51 234)" : `var(--${primaryColor}-600)`;
|
|
267
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("tr", { className: styles.row || "hover:bg-gray-50 cursor-pointer border-b border-gray-100", onClick: onRowClick, children: [
|
|
268
|
+
showCheckbox && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("td", { className: "pl-4 py-4", onClick: (e) => e.stopPropagation(), children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "relative group", children: [
|
|
269
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("input", { type: "checkbox", checked: isSelected, onChange: onSelect, className: "sr-only" }),
|
|
270
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
271
|
+
"div",
|
|
272
|
+
{
|
|
273
|
+
className: styles.checkbox || `w-5 h-5 border-2 rounded-lg cursor-pointer transition-all duration-300 flex items-center justify-center transform hover:scale-105 active:scale-95`,
|
|
274
|
+
style: {
|
|
275
|
+
borderColor: isSelected ? checkboxBorder : "rgb(209 213 219)",
|
|
276
|
+
backgroundColor: isSelected ? checkboxBg : "white"
|
|
277
|
+
},
|
|
278
|
+
onClick: onSelect,
|
|
279
|
+
children: isSelected && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Icon, { name: "Check", className: "w-3 h-3 text-white", strokeWidth: 2.5 })
|
|
280
|
+
}
|
|
281
|
+
)
|
|
282
|
+
] }) }),
|
|
283
|
+
columns.map((col) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("td", { className: styles.cell || "px-4 py-4 text-sm text-gray-900", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Tooltip, { text: String(col.render ? col.render(row[col.key], row) : row[col.key] || "-"), position: "top", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "block truncate", "data-truncate": true, children: col.render ? col.render(row[col.key], row) : row[col.key] || "-" }) }) }, String(col.key))),
|
|
284
|
+
showActions && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("td", { className: styles.cell || "px-2 py-4 text-sm", onClick: (e) => e.stopPropagation(), children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex space-x-2", children: [
|
|
285
|
+
onEdit && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { onClick: onEdit, className: "p-1 rounded hover:bg-gray-100", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Icon, { name: "Edit2", className: "w-4 h-4", style: { color: actionColor } }) }),
|
|
286
|
+
onDelete && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { onClick: onDelete, className: "p-1 rounded hover:bg-gray-100", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Icon, { name: "Trash2", className: "w-4 h-4", style: { color: actionColor } }) })
|
|
287
|
+
] }) })
|
|
288
|
+
] });
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
// src/components/TableSkeleton.tsx
|
|
292
|
+
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
293
|
+
function TableSkeleton({ columns, showCheckbox, showActions, rows = 5 }) {
|
|
294
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_jsx_runtime7.Fragment, { children: Array.from({ length: rows }).map((_, idx) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("tr", { className: "animate-pulse", children: [
|
|
295
|
+
showCheckbox && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("td", { className: "pl-4 py-4", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "w-5 h-5 bg-gray-200 rounded" }) }),
|
|
296
|
+
columns.map((col) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("td", { className: "px-4 py-4", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "h-4 bg-gray-200 rounded w-3/4" }) }, String(col.key))),
|
|
297
|
+
showActions && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("td", { className: "px-4 py-4", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex space-x-2", children: [
|
|
298
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "w-4 h-4 bg-gray-200 rounded" }),
|
|
299
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "w-4 h-4 bg-gray-200 rounded" })
|
|
300
|
+
] }) })
|
|
301
|
+
] }, idx)) });
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
// src/components/Pagination.tsx
|
|
305
|
+
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
306
|
+
var Pagination = ({
|
|
307
|
+
currentPage,
|
|
308
|
+
totalPages,
|
|
309
|
+
onPageChange,
|
|
310
|
+
pageSize,
|
|
311
|
+
totalItems,
|
|
312
|
+
onPageSizeChange,
|
|
313
|
+
pageSizeOptions = [10, 25, 50, 100],
|
|
314
|
+
primaryColor = "purple"
|
|
315
|
+
}) => {
|
|
316
|
+
const startItem = (currentPage - 1) * pageSize + 1;
|
|
317
|
+
const endItem = Math.min(currentPage * pageSize, totalItems);
|
|
318
|
+
const activeColor = primaryColor === "purple" ? "bg-purple-600 text-white" : `bg-${primaryColor}-600 text-white`;
|
|
319
|
+
const hoverColor = primaryColor === "purple" ? "hover:bg-purple-50" : `hover:bg-${primaryColor}-50`;
|
|
320
|
+
const hoverBorderColor = primaryColor === "purple" ? "hover:border-purple-500" : `hover:border-${primaryColor}-500`;
|
|
321
|
+
const getPageNumbers = () => {
|
|
322
|
+
const pages = [];
|
|
323
|
+
const maxVisible = 5;
|
|
324
|
+
if (totalPages <= maxVisible) {
|
|
325
|
+
for (let i = 1; i <= totalPages; i++) {
|
|
326
|
+
pages.push(i);
|
|
327
|
+
}
|
|
328
|
+
} else {
|
|
329
|
+
if (currentPage <= 3) {
|
|
330
|
+
for (let i = 1; i <= 4; i++) pages.push(i);
|
|
331
|
+
pages.push("...");
|
|
332
|
+
pages.push(totalPages);
|
|
333
|
+
} else if (currentPage >= totalPages - 2) {
|
|
334
|
+
pages.push(1);
|
|
335
|
+
pages.push("...");
|
|
336
|
+
for (let i = totalPages - 3; i <= totalPages; i++) pages.push(i);
|
|
337
|
+
} else {
|
|
338
|
+
pages.push(1);
|
|
339
|
+
pages.push("...");
|
|
340
|
+
for (let i = currentPage - 1; i <= currentPage + 1; i++) pages.push(i);
|
|
341
|
+
pages.push("...");
|
|
342
|
+
pages.push(totalPages);
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
return pages;
|
|
346
|
+
};
|
|
347
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "flex items-center justify-between px-4 py-3 border-t border-gray-200 bg-white", children: [
|
|
348
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "flex items-center gap-4", children: [
|
|
349
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("span", { className: "text-xs text-gray-700", children: [
|
|
350
|
+
"Showing ",
|
|
351
|
+
startItem,
|
|
352
|
+
" to ",
|
|
353
|
+
endItem,
|
|
354
|
+
" of ",
|
|
355
|
+
totalItems,
|
|
356
|
+
" results"
|
|
357
|
+
] }),
|
|
358
|
+
onPageSizeChange && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "flex items-center gap-2 relative", children: [
|
|
359
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("label", { className: "text-xs text-gray-700", children: "Rows per page:" }),
|
|
360
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "relative", children: [
|
|
361
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
362
|
+
"select",
|
|
363
|
+
{
|
|
364
|
+
value: pageSize,
|
|
365
|
+
onChange: (e) => onPageSizeChange(Number(e.target.value)),
|
|
366
|
+
className: `appearance-none bg-white border border-gray-300 rounded-md pl-2 pr-6 py-1 text-xs text-gray-700 cursor-pointer ${hoverBorderColor} focus:outline-none transition-all duration-200`,
|
|
367
|
+
children: pageSizeOptions.map((size) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("option", { value: size, children: size }, size))
|
|
368
|
+
}
|
|
369
|
+
),
|
|
370
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "absolute inset-y-0 right-0 flex items-center pr-1.5 pointer-events-none", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Icon, { name: "ChevronDown", className: "w-3 h-3 text-gray-500" }) })
|
|
371
|
+
] })
|
|
372
|
+
] })
|
|
373
|
+
] }),
|
|
374
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
375
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
376
|
+
"button",
|
|
377
|
+
{
|
|
378
|
+
onClick: () => onPageChange(currentPage - 1),
|
|
379
|
+
disabled: currentPage === 1,
|
|
380
|
+
className: `p-2 rounded ${currentPage === 1 ? "text-gray-400 cursor-not-allowed" : `text-gray-700 ${hoverColor}`}`,
|
|
381
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Icon, { name: "ChevronLeft", className: "w-4 h-4" })
|
|
382
|
+
}
|
|
383
|
+
),
|
|
384
|
+
getPageNumbers().map((page, idx) => typeof page === "number" ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
385
|
+
"button",
|
|
386
|
+
{
|
|
387
|
+
onClick: () => onPageChange(page),
|
|
388
|
+
className: `px-3 py-1 rounded text-sm ${currentPage === page ? activeColor : `text-gray-700 ${hoverColor}`}`,
|
|
389
|
+
children: page
|
|
390
|
+
},
|
|
391
|
+
idx
|
|
392
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "px-2 text-gray-500", children: page }, idx)),
|
|
393
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
394
|
+
"button",
|
|
395
|
+
{
|
|
396
|
+
onClick: () => onPageChange(currentPage + 1),
|
|
397
|
+
disabled: currentPage === totalPages,
|
|
398
|
+
className: `p-2 rounded ${currentPage === totalPages ? "text-gray-400 cursor-not-allowed" : `text-gray-700 ${hoverColor}`}`,
|
|
399
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Icon, { name: "ChevronRight", className: "w-4 h-4" })
|
|
400
|
+
}
|
|
401
|
+
)
|
|
402
|
+
] })
|
|
403
|
+
] });
|
|
404
|
+
};
|
|
405
|
+
|
|
406
|
+
// src/components/ColumnSelector.tsx
|
|
407
|
+
var import_react3 = require("react");
|
|
408
|
+
var import_jsx_runtime9 = require("react/jsx-runtime");
|
|
409
|
+
var ColumnSelector = ({
|
|
410
|
+
columns,
|
|
411
|
+
visibleColumns,
|
|
412
|
+
onColumnToggle,
|
|
413
|
+
onReset,
|
|
414
|
+
primaryColor = "purple",
|
|
415
|
+
minColumns = 1,
|
|
416
|
+
maxColumns = 5,
|
|
417
|
+
label = "Show Columns",
|
|
418
|
+
position = "right"
|
|
419
|
+
}) => {
|
|
420
|
+
const [isOpen, setIsOpen] = (0, import_react3.useState)(false);
|
|
421
|
+
const dropdownRef = (0, import_react3.useRef)(null);
|
|
422
|
+
(0, import_react3.useEffect)(() => {
|
|
423
|
+
const handleClickOutside = (event) => {
|
|
424
|
+
if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {
|
|
425
|
+
setIsOpen(false);
|
|
426
|
+
}
|
|
427
|
+
};
|
|
428
|
+
if (isOpen) {
|
|
429
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
430
|
+
}
|
|
431
|
+
return () => {
|
|
432
|
+
document.removeEventListener("mousedown", handleClickOutside);
|
|
433
|
+
};
|
|
434
|
+
}, [isOpen]);
|
|
435
|
+
const checkboxBg = primaryColor === "purple" ? "rgb(147 51 234)" : `var(--${primaryColor}-600)`;
|
|
436
|
+
const checkboxBorder = primaryColor === "purple" ? "rgb(147 51 234)" : `var(--${primaryColor}-600)`;
|
|
437
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "relative group", ref: dropdownRef, children: [
|
|
438
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
439
|
+
"button",
|
|
440
|
+
{
|
|
441
|
+
onClick: () => setIsOpen(!isOpen),
|
|
442
|
+
className: "p-2 rounded cursor-pointer text-gray-600 hover:bg-gray-100 transition-colors",
|
|
443
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Icon, { name: "Columns", className: "w-5 h-5" })
|
|
444
|
+
}
|
|
445
|
+
),
|
|
446
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: `absolute z-50 opacity-0 group-hover:opacity-100 transition-opacity pointer-events-none ${position === "left" ? "left-full ml-2" : "right-full mr-2"} top-1/2 -translate-y-1/2`, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "bg-gray-800 text-white text-xs px-2 py-1 rounded whitespace-nowrap relative", children: [
|
|
447
|
+
"Column Visibility",
|
|
448
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: `absolute ${position === "left" ? "right-full border-r-gray-800 border-r-4 border-y-transparent border-y-4 border-l-0" : "left-full border-l-gray-800 border-l-4 border-y-transparent border-y-4 border-r-0"} top-1/2 -translate-y-1/2` })
|
|
449
|
+
] }) }),
|
|
450
|
+
isOpen && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "absolute right-0 mt-2 w-56 bg-white border border-gray-200 rounded-lg shadow-xl z-50 py-2", children: [
|
|
451
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "px-3 py-2 border-b border-gray-200", children: [
|
|
452
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("p", { className: "text-xs font-medium text-gray-700 uppercase", children: label }),
|
|
453
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("p", { className: "text-xs text-gray-500 mt-1", children: [
|
|
454
|
+
visibleColumns.length,
|
|
455
|
+
" of ",
|
|
456
|
+
columns.length,
|
|
457
|
+
" selected"
|
|
458
|
+
] })
|
|
459
|
+
] }),
|
|
460
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "max-h-64 overflow-y-auto", children: columns.map((column) => {
|
|
461
|
+
const isVisible = visibleColumns.includes(column.key);
|
|
462
|
+
const canUncheck = visibleColumns.length > minColumns;
|
|
463
|
+
const canCheck = visibleColumns.length < maxColumns;
|
|
464
|
+
const isDisabled = isVisible && !canUncheck || !isVisible && !canCheck;
|
|
465
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
466
|
+
"label",
|
|
467
|
+
{
|
|
468
|
+
className: `flex items-center px-3 py-2 ${isDisabled ? "opacity-50 cursor-not-allowed" : "hover:bg-gray-50 cursor-pointer"}`,
|
|
469
|
+
title: isDisabled ? isVisible ? `At least ${minColumns} column(s) must be visible` : `Maximum ${maxColumns} columns can be visible` : "",
|
|
470
|
+
children: [
|
|
471
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "relative group mr-3", children: [
|
|
472
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
473
|
+
"input",
|
|
474
|
+
{
|
|
475
|
+
type: "checkbox",
|
|
476
|
+
checked: isVisible,
|
|
477
|
+
onChange: () => !isDisabled && onColumnToggle(column.key),
|
|
478
|
+
disabled: isDisabled,
|
|
479
|
+
className: "sr-only"
|
|
480
|
+
}
|
|
481
|
+
),
|
|
482
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
483
|
+
"div",
|
|
484
|
+
{
|
|
485
|
+
className: `w-5 h-5 border-2 rounded-lg cursor-pointer transition-all duration-300 flex items-center justify-center transform hover:scale-105 active:scale-95`,
|
|
486
|
+
style: {
|
|
487
|
+
borderColor: isVisible ? checkboxBorder : "rgb(209 213 219)",
|
|
488
|
+
backgroundColor: isVisible ? checkboxBg : "white"
|
|
489
|
+
},
|
|
490
|
+
children: isVisible && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Icon, { name: "Check", className: "w-3 h-3 text-white", strokeWidth: 2.5 })
|
|
491
|
+
}
|
|
492
|
+
)
|
|
493
|
+
] }),
|
|
494
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "text-sm text-gray-700", children: column.title })
|
|
495
|
+
]
|
|
496
|
+
},
|
|
497
|
+
column.key
|
|
498
|
+
);
|
|
499
|
+
}) }),
|
|
500
|
+
onReset && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "px-3 py-2 border-t border-gray-200", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
501
|
+
"button",
|
|
502
|
+
{
|
|
503
|
+
onClick: onReset,
|
|
504
|
+
className: "w-full text-xs text-gray-600 hover:text-gray-900 py-1 hover:bg-gray-50 rounded",
|
|
505
|
+
children: "Reset to Default"
|
|
506
|
+
}
|
|
507
|
+
) })
|
|
508
|
+
] })
|
|
509
|
+
] });
|
|
510
|
+
};
|
|
511
|
+
|
|
512
|
+
// src/components/SmartTable.tsx
|
|
513
|
+
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
514
|
+
function SmartTable({
|
|
515
|
+
data,
|
|
516
|
+
columns,
|
|
517
|
+
className = "",
|
|
518
|
+
showCheckbox = false,
|
|
519
|
+
showActions = false,
|
|
520
|
+
onEdit,
|
|
521
|
+
onDelete,
|
|
522
|
+
onRowClick,
|
|
523
|
+
loading = false,
|
|
524
|
+
emptyMessage = "No data available",
|
|
525
|
+
selectedRows = [],
|
|
526
|
+
onSelectionChange,
|
|
527
|
+
rowKey = "id",
|
|
528
|
+
bulkActions = [],
|
|
529
|
+
onSearch,
|
|
530
|
+
searchPlaceholder = "Search...",
|
|
531
|
+
sidebarActions = [],
|
|
532
|
+
sidebarPosition = "right",
|
|
533
|
+
onAdd,
|
|
534
|
+
onRefresh,
|
|
535
|
+
onExport,
|
|
536
|
+
onPrint,
|
|
537
|
+
onSettings,
|
|
538
|
+
showAdd = false,
|
|
539
|
+
showRefresh = false,
|
|
540
|
+
showExport = false,
|
|
541
|
+
showPrint = false,
|
|
542
|
+
showSettings = false,
|
|
543
|
+
tableHeight = "65vh",
|
|
544
|
+
styles = {},
|
|
545
|
+
primaryColor = "purple",
|
|
546
|
+
pagination,
|
|
547
|
+
showColumnSelector = true,
|
|
548
|
+
columnSelectorLabel = "Show Columns",
|
|
549
|
+
visibleColumns,
|
|
550
|
+
onColumnVisibilityChange,
|
|
551
|
+
minVisibleColumns = 1,
|
|
552
|
+
maxVisibleColumns = 5,
|
|
553
|
+
maxHeight = "65vh",
|
|
554
|
+
skeletonRows = 10
|
|
555
|
+
}) {
|
|
556
|
+
const [sortConfig, setSortConfig] = (0, import_react4.useState)(null);
|
|
557
|
+
const [showBulkActions, setShowBulkActions] = (0, import_react4.useState)(false);
|
|
558
|
+
const [searchValue, setSearchValue] = (0, import_react4.useState)("");
|
|
559
|
+
const [isRefreshing, setIsRefreshing] = (0, import_react4.useState)(false);
|
|
560
|
+
const [isColumnSelectorOpen, setIsColumnSelectorOpen] = (0, import_react4.useState)(false);
|
|
561
|
+
const [internalVisibleColumns, setInternalVisibleColumns] = (0, import_react4.useState)(
|
|
562
|
+
visibleColumns || columns.map((col) => String(col.key))
|
|
563
|
+
);
|
|
564
|
+
const activeVisibleColumns = visibleColumns || internalVisibleColumns;
|
|
565
|
+
const displayColumns = (0, import_react4.useMemo)(
|
|
566
|
+
() => columns.filter((col) => activeVisibleColumns.includes(String(col.key))),
|
|
567
|
+
[columns, activeVisibleColumns]
|
|
568
|
+
);
|
|
569
|
+
const handleColumnToggle = (columnKey) => {
|
|
570
|
+
const newVisibleColumns = activeVisibleColumns.includes(columnKey) ? activeVisibleColumns.filter((key) => key !== columnKey) : [...activeVisibleColumns, columnKey];
|
|
571
|
+
if (onColumnVisibilityChange) {
|
|
572
|
+
onColumnVisibilityChange(newVisibleColumns);
|
|
573
|
+
} else {
|
|
574
|
+
setInternalVisibleColumns(newVisibleColumns);
|
|
575
|
+
}
|
|
576
|
+
};
|
|
577
|
+
const handleColumnReset = () => {
|
|
578
|
+
const firstFiveColumns = columns.slice(0, 5).map((col) => String(col.key));
|
|
579
|
+
if (onColumnVisibilityChange) {
|
|
580
|
+
onColumnVisibilityChange(firstFiveColumns);
|
|
581
|
+
} else {
|
|
582
|
+
setInternalVisibleColumns(firstFiveColumns);
|
|
583
|
+
}
|
|
584
|
+
};
|
|
585
|
+
const handleSort = (0, import_react4.useCallback)((key) => {
|
|
586
|
+
setSortConfig((prev) => ({
|
|
587
|
+
key,
|
|
588
|
+
direction: (prev == null ? void 0 : prev.key) === key && prev.direction === "asc" ? "desc" : "asc"
|
|
589
|
+
}));
|
|
590
|
+
}, []);
|
|
591
|
+
const sortedData = (0, import_react4.useMemo)(() => {
|
|
592
|
+
if (!sortConfig) return data;
|
|
593
|
+
return [...data].sort((a, b) => {
|
|
594
|
+
const aVal = a[sortConfig.key];
|
|
595
|
+
const bVal = b[sortConfig.key];
|
|
596
|
+
if (aVal < bVal) return sortConfig.direction === "asc" ? -1 : 1;
|
|
597
|
+
if (aVal > bVal) return sortConfig.direction === "asc" ? 1 : -1;
|
|
598
|
+
return 0;
|
|
599
|
+
});
|
|
600
|
+
}, [data, sortConfig]);
|
|
601
|
+
const handleSelectAll = (0, import_react4.useCallback)(() => {
|
|
602
|
+
const allKeys = data.map((row) => String(row[rowKey]));
|
|
603
|
+
onSelectionChange == null ? void 0 : onSelectionChange(selectedRows.length === data.length ? [] : allKeys);
|
|
604
|
+
}, [data, selectedRows, onSelectionChange, rowKey]);
|
|
605
|
+
const handleRowSelect = (0, import_react4.useCallback)((row) => {
|
|
606
|
+
const key = String(row[rowKey]);
|
|
607
|
+
const newSelection = selectedRows.includes(key) ? selectedRows.filter((k) => k !== key) : [...selectedRows, key];
|
|
608
|
+
onSelectionChange == null ? void 0 : onSelectionChange(newSelection);
|
|
609
|
+
}, [selectedRows, onSelectionChange, rowKey]);
|
|
610
|
+
const handleSearch = (0, import_react4.useCallback)((value) => {
|
|
611
|
+
setSearchValue(value);
|
|
612
|
+
onSearch == null ? void 0 : onSearch(value);
|
|
613
|
+
}, [onSearch]);
|
|
614
|
+
const selectAll = selectedRows.length === data.length && data.length > 0;
|
|
615
|
+
const defaultBulkActions = [
|
|
616
|
+
{
|
|
617
|
+
label: "Delete",
|
|
618
|
+
color: "red",
|
|
619
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Icon, { name: "Trash2", className: "w-4 h-4" }),
|
|
620
|
+
onClick: (selected) => alert(`Delete ${selected.length} items`)
|
|
621
|
+
}
|
|
622
|
+
];
|
|
623
|
+
const actionsToShow = bulkActions.length > 0 ? bulkActions : defaultBulkActions;
|
|
624
|
+
const handleRefresh = () => {
|
|
625
|
+
setIsRefreshing(true);
|
|
626
|
+
if (onRefresh) {
|
|
627
|
+
onRefresh();
|
|
628
|
+
}
|
|
629
|
+
setTimeout(() => setIsRefreshing(false), 1e3);
|
|
630
|
+
};
|
|
631
|
+
const defaultAdd = () => {
|
|
632
|
+
console.log("Add new item");
|
|
633
|
+
};
|
|
634
|
+
const defaultExport = () => {
|
|
635
|
+
const csv = [columns.map((col) => col.title).join(",")];
|
|
636
|
+
data.forEach((row) => {
|
|
637
|
+
csv.push(columns.map((col) => row[col.key]).join(","));
|
|
638
|
+
});
|
|
639
|
+
const blob = new Blob([csv.join("\n")], { type: "text/csv" });
|
|
640
|
+
const url = URL.createObjectURL(blob);
|
|
641
|
+
const a = document.createElement("a");
|
|
642
|
+
a.href = url;
|
|
643
|
+
a.download = "export.csv";
|
|
644
|
+
a.click();
|
|
645
|
+
};
|
|
646
|
+
const defaultPrint = () => {
|
|
647
|
+
window.print();
|
|
648
|
+
};
|
|
649
|
+
const defaultSettings = () => {
|
|
650
|
+
console.log("Open settings");
|
|
651
|
+
};
|
|
652
|
+
const allSidebarActions = [
|
|
653
|
+
...showColumnSelector ? [{
|
|
654
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Icon, { name: "Columns", className: "w-5 h-5" }),
|
|
655
|
+
label: columnSelectorLabel,
|
|
656
|
+
onClick: () => setIsColumnSelectorOpen(true)
|
|
657
|
+
}] : [],
|
|
658
|
+
...showAdd || onAdd ? [{
|
|
659
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Icon, { name: "Plus", className: "w-5 h-5" }),
|
|
660
|
+
label: "Add New",
|
|
661
|
+
onClick: onAdd || defaultAdd
|
|
662
|
+
}] : [],
|
|
663
|
+
...showRefresh || onRefresh ? [{
|
|
664
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Icon, { name: "RefreshCw", className: `w-5 h-5 ${isRefreshing ? "animate-spin" : ""}`, style: { color: isRefreshing ? primaryColor === "purple" ? "rgb(147 51 234)" : `var(--${primaryColor}-600)` : void 0 } }),
|
|
665
|
+
label: "Refresh",
|
|
666
|
+
onClick: handleRefresh
|
|
667
|
+
}] : [],
|
|
668
|
+
...showExport || onExport ? [{
|
|
669
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Icon, { name: "Download", className: "w-5 h-5" }),
|
|
670
|
+
label: "Export CSV",
|
|
671
|
+
onClick: onExport || defaultExport
|
|
672
|
+
}] : [],
|
|
673
|
+
...showPrint || onPrint ? [{
|
|
674
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Icon, { name: "Printer", className: "w-5 h-5" }),
|
|
675
|
+
label: "Print",
|
|
676
|
+
onClick: onPrint || defaultPrint
|
|
677
|
+
}] : [],
|
|
678
|
+
...showSettings || onSettings ? [{
|
|
679
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Icon, { name: "Settings", className: "w-5 h-5" }),
|
|
680
|
+
label: "Settings",
|
|
681
|
+
onClick: onSettings || defaultSettings
|
|
682
|
+
}] : [],
|
|
683
|
+
...sidebarActions
|
|
684
|
+
];
|
|
685
|
+
const positionClasses = {
|
|
686
|
+
right: "right-0 top-0 bottom-0 flex-col border-l",
|
|
687
|
+
left: "left-0 top-0 bottom-0 flex-col border-r",
|
|
688
|
+
top: "top-0 left-0 right-0 flex-row w-full border-b",
|
|
689
|
+
bottom: "bottom-0 left-0 right-0 flex-row w-full border-t"
|
|
690
|
+
};
|
|
691
|
+
const tooltipPosition = sidebarPosition === "right" ? "left" : sidebarPosition === "left" ? "right" : sidebarPosition === "top" ? "bottom" : "top";
|
|
692
|
+
const containerClasses = sidebarPosition === "top" || sidebarPosition === "bottom" ? "flex-row" : "flex-col";
|
|
693
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className, children: [
|
|
694
|
+
onSearch && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "mb-4 flex gap-4", children: [
|
|
695
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
696
|
+
SearchBar,
|
|
697
|
+
{
|
|
698
|
+
value: searchValue,
|
|
699
|
+
onChange: handleSearch,
|
|
700
|
+
placeholder: searchPlaceholder,
|
|
701
|
+
primaryColor
|
|
702
|
+
}
|
|
703
|
+
),
|
|
704
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
705
|
+
BulkActionsDropdown,
|
|
706
|
+
{
|
|
707
|
+
selectedCount: selectedRows.length,
|
|
708
|
+
isOpen: showBulkActions,
|
|
709
|
+
onToggle: () => setShowBulkActions(!showBulkActions),
|
|
710
|
+
actions: actionsToShow.map((action) => ({
|
|
711
|
+
...action,
|
|
712
|
+
onClick: () => action.onClick(selectedRows)
|
|
713
|
+
})),
|
|
714
|
+
onClose: () => setShowBulkActions(false)
|
|
715
|
+
}
|
|
716
|
+
)
|
|
717
|
+
] }),
|
|
718
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex", children: [
|
|
719
|
+
allSidebarActions.length > 0 && sidebarPosition === "left" && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: styles.sidebar || `bg-white border border-gray-200 rounded-l-lg p-2`, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: `flex flex-col items-center gap-4`, children: allSidebarActions.map((action, idx) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "relative group", children: idx === 0 && showColumnSelector && isColumnSelectorOpen ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
720
|
+
ColumnSelector,
|
|
721
|
+
{
|
|
722
|
+
columns: columns.map((col) => ({ key: String(col.key), title: col.title })),
|
|
723
|
+
visibleColumns: activeVisibleColumns,
|
|
724
|
+
onColumnToggle: handleColumnToggle,
|
|
725
|
+
onReset: handleColumnReset,
|
|
726
|
+
primaryColor,
|
|
727
|
+
minColumns: minVisibleColumns,
|
|
728
|
+
maxColumns: maxVisibleColumns,
|
|
729
|
+
label: columnSelectorLabel,
|
|
730
|
+
position: "right"
|
|
731
|
+
}
|
|
732
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_jsx_runtime10.Fragment, { children: [
|
|
733
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
734
|
+
"button",
|
|
735
|
+
{
|
|
736
|
+
onClick: action.onClick,
|
|
737
|
+
className: styles.sidebarButton || `p-2 rounded cursor-pointer text-gray-600 transition-colors`,
|
|
738
|
+
onMouseEnter: (e) => {
|
|
739
|
+
if (!styles.sidebarButtonHover) {
|
|
740
|
+
e.currentTarget.style.backgroundColor = `${primaryColor === "purple" ? "rgb(250 245 255)" : `var(--${primaryColor}-50)`}`;
|
|
741
|
+
e.currentTarget.style.color = `${primaryColor === "purple" ? "rgb(147 51 234)" : `var(--${primaryColor}-600)`}`;
|
|
742
|
+
}
|
|
743
|
+
},
|
|
744
|
+
onMouseLeave: (e) => {
|
|
745
|
+
if (!styles.sidebarButtonHover) {
|
|
746
|
+
e.currentTarget.style.backgroundColor = "";
|
|
747
|
+
e.currentTarget.style.color = "";
|
|
748
|
+
}
|
|
749
|
+
},
|
|
750
|
+
children: action.icon
|
|
751
|
+
}
|
|
752
|
+
),
|
|
753
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: `absolute z-50 opacity-0 group-hover:opacity-100 transition-opacity pointer-events-none left-full ml-2 top-1/2 -translate-y-1/2`, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "bg-gray-800 text-white text-xs px-2 py-1 rounded whitespace-nowrap relative", children: [
|
|
754
|
+
action.label,
|
|
755
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: `absolute right-full top-1/2 -translate-y-1/2 border-r-gray-800 border-r-4 border-y-transparent border-y-4 border-l-0` })
|
|
756
|
+
] }) })
|
|
757
|
+
] }) }, idx)) }) }),
|
|
758
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: styles.container || `bg-white ${allSidebarActions.length > 0 ? sidebarPosition === "left" ? "rounded-r-lg" : "rounded-l-lg" : "rounded-lg"} border border-gray-200 flex-1 overflow-hidden`, children: [
|
|
759
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: styles.body || `${sortedData.length === 0 ? "flex items-center justify-center" : "overflow-auto"} [&::-webkit-scrollbar-track]:mt-11 [&::-webkit-scrollbar]:w-0.5 [&::-webkit-scrollbar]:h-0.5 [&::-webkit-scrollbar-track]:bg-transparent [&::-webkit-scrollbar-thumb]:rounded-full dark:[&::-webkit-scrollbar-thumb]:bg-${primaryColor}-600 [&::-webkit-scrollbar-thumb]:bg-gray-300`, style: { height: maxHeight, maxHeight }, children: sortedData.length === 0 && !loading ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "text-center text-gray-500", children: emptyMessage }) : /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("table", { className: styles.table || "min-w-full table-fixed", children: [
|
|
760
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("thead", { className: styles.header || "sticky top-0 z-10 bg-white shadow-sm", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
761
|
+
TableHeader,
|
|
762
|
+
{
|
|
763
|
+
columns: displayColumns,
|
|
764
|
+
showCheckbox,
|
|
765
|
+
showActions,
|
|
766
|
+
selectAll,
|
|
767
|
+
onSelectAll: handleSelectAll,
|
|
768
|
+
sortConfig,
|
|
769
|
+
onSort: handleSort,
|
|
770
|
+
styles,
|
|
771
|
+
primaryColor
|
|
772
|
+
}
|
|
773
|
+
) }),
|
|
774
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("tbody", { children: loading ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
775
|
+
TableSkeleton,
|
|
776
|
+
{
|
|
777
|
+
columns: displayColumns,
|
|
778
|
+
showCheckbox,
|
|
779
|
+
showActions,
|
|
780
|
+
rows: skeletonRows
|
|
781
|
+
}
|
|
782
|
+
) : sortedData.map((row, idx) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
783
|
+
TableRow,
|
|
784
|
+
{
|
|
785
|
+
row,
|
|
786
|
+
columns: displayColumns,
|
|
787
|
+
showCheckbox,
|
|
788
|
+
showActions,
|
|
789
|
+
isSelected: selectedRows.includes(String(row[rowKey])),
|
|
790
|
+
onSelect: () => handleRowSelect(row),
|
|
791
|
+
onRowClick: () => onRowClick == null ? void 0 : onRowClick(row),
|
|
792
|
+
onEdit: onEdit ? () => onEdit(row) : void 0,
|
|
793
|
+
onDelete: onDelete ? () => onDelete(row) : void 0,
|
|
794
|
+
styles,
|
|
795
|
+
primaryColor
|
|
796
|
+
},
|
|
797
|
+
idx
|
|
798
|
+
)) })
|
|
799
|
+
] }) }),
|
|
800
|
+
pagination && data.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
801
|
+
Pagination,
|
|
802
|
+
{
|
|
803
|
+
currentPage: pagination.currentPage,
|
|
804
|
+
totalPages: pagination.totalPages,
|
|
805
|
+
pageSize: pagination.pageSize,
|
|
806
|
+
totalItems: pagination.totalItems,
|
|
807
|
+
onPageChange: pagination.onPageChange,
|
|
808
|
+
onPageSizeChange: pagination.onPageSizeChange,
|
|
809
|
+
pageSizeOptions: pagination.pageSizeOptions,
|
|
810
|
+
primaryColor
|
|
811
|
+
}
|
|
812
|
+
) })
|
|
813
|
+
] }),
|
|
814
|
+
allSidebarActions.length > 0 && sidebarPosition === "right" && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: styles.sidebar || `bg-white border border-gray-200 rounded-r-lg p-2`, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: `flex flex-col items-center gap-4`, children: allSidebarActions.map((action, idx) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "relative group", children: idx === 0 && showColumnSelector && isColumnSelectorOpen ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
815
|
+
ColumnSelector,
|
|
816
|
+
{
|
|
817
|
+
columns: columns.map((col) => ({ key: String(col.key), title: col.title })),
|
|
818
|
+
visibleColumns: activeVisibleColumns,
|
|
819
|
+
onColumnToggle: handleColumnToggle,
|
|
820
|
+
onReset: handleColumnReset,
|
|
821
|
+
primaryColor,
|
|
822
|
+
minColumns: minVisibleColumns,
|
|
823
|
+
maxColumns: maxVisibleColumns,
|
|
824
|
+
label: columnSelectorLabel,
|
|
825
|
+
position: "left"
|
|
826
|
+
}
|
|
827
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_jsx_runtime10.Fragment, { children: [
|
|
828
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
829
|
+
"button",
|
|
830
|
+
{
|
|
831
|
+
onClick: action.onClick,
|
|
832
|
+
className: styles.sidebarButton || `p-2 rounded cursor-pointer text-gray-600 transition-colors`,
|
|
833
|
+
onMouseEnter: (e) => {
|
|
834
|
+
if (!styles.sidebarButtonHover) {
|
|
835
|
+
e.currentTarget.style.backgroundColor = `${primaryColor === "purple" ? "rgb(250 245 255)" : `var(--${primaryColor}-50)`}`;
|
|
836
|
+
e.currentTarget.style.color = `${primaryColor === "purple" ? "rgb(147 51 234)" : `var(--${primaryColor}-600)`}`;
|
|
837
|
+
}
|
|
838
|
+
},
|
|
839
|
+
onMouseLeave: (e) => {
|
|
840
|
+
if (!styles.sidebarButtonHover) {
|
|
841
|
+
e.currentTarget.style.backgroundColor = "";
|
|
842
|
+
e.currentTarget.style.color = "";
|
|
843
|
+
}
|
|
844
|
+
},
|
|
845
|
+
children: action.icon
|
|
846
|
+
}
|
|
847
|
+
),
|
|
848
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: `absolute z-50 opacity-0 group-hover:opacity-100 transition-opacity pointer-events-none right-full mr-2 top-1/2 -translate-y-1/2`, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "bg-gray-800 text-white text-xs px-2 py-1 rounded whitespace-nowrap relative", children: [
|
|
849
|
+
action.label,
|
|
850
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: `absolute left-full top-1/2 -translate-y-1/2 border-l-gray-800 border-l-4 border-y-transparent border-y-4 border-r-0` })
|
|
851
|
+
] }) })
|
|
852
|
+
] }) }, idx)) }) })
|
|
853
|
+
] })
|
|
854
|
+
] });
|
|
855
|
+
}
|
|
856
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
857
|
+
0 && (module.exports = {
|
|
858
|
+
ColumnSelector,
|
|
859
|
+
Icon,
|
|
860
|
+
Pagination,
|
|
861
|
+
SmartTable,
|
|
862
|
+
Tooltip,
|
|
863
|
+
getIcon
|
|
864
|
+
});
|