@jameskabz/nextcraft-ui 0.6.15 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. package/README.md +37 -3
  2. package/dist/components/craft-button.cjs +64 -4
  3. package/dist/components/craft-button.cjs.map +1 -1
  4. package/dist/components/craft-button.d.cts +5 -2
  5. package/dist/components/craft-button.d.ts +5 -2
  6. package/dist/components/craft-button.js +65 -5
  7. package/dist/components/craft-button.js.map +1 -1
  8. package/dist/components/craft-checkbox.cjs +2 -2
  9. package/dist/components/craft-checkbox.cjs.map +1 -1
  10. package/dist/components/craft-checkbox.js +2 -2
  11. package/dist/components/craft-checkbox.js.map +1 -1
  12. package/dist/components/craft-create-edit-drawer.cjs +5 -3
  13. package/dist/components/craft-create-edit-drawer.cjs.map +1 -1
  14. package/dist/components/craft-create-edit-drawer.js +5 -3
  15. package/dist/components/craft-create-edit-drawer.js.map +1 -1
  16. package/dist/components/craft-data-table-header.cjs +74 -0
  17. package/dist/components/craft-data-table-header.cjs.map +1 -0
  18. package/dist/components/craft-data-table-header.d.cts +17 -0
  19. package/dist/components/craft-data-table-header.d.ts +17 -0
  20. package/dist/components/craft-data-table-header.js +50 -0
  21. package/dist/components/craft-data-table-header.js.map +1 -0
  22. package/dist/components/craft-data-table-pagination.cjs +107 -0
  23. package/dist/components/craft-data-table-pagination.cjs.map +1 -0
  24. package/dist/components/craft-data-table-pagination.d.cts +25 -0
  25. package/dist/components/craft-data-table-pagination.d.ts +25 -0
  26. package/dist/components/craft-data-table-pagination.js +83 -0
  27. package/dist/components/craft-data-table-pagination.js.map +1 -0
  28. package/dist/components/craft-data-table.cjs +424 -192
  29. package/dist/components/craft-data-table.cjs.map +1 -1
  30. package/dist/components/craft-data-table.d.cts +61 -9
  31. package/dist/components/craft-data-table.d.ts +61 -9
  32. package/dist/components/craft-data-table.js +424 -192
  33. package/dist/components/craft-data-table.js.map +1 -1
  34. package/dist/components/craft-form-field.cjs +67 -11
  35. package/dist/components/craft-form-field.cjs.map +1 -1
  36. package/dist/components/craft-form-field.d.cts +4 -1
  37. package/dist/components/craft-form-field.d.ts +4 -1
  38. package/dist/components/craft-form-field.js +57 -11
  39. package/dist/components/craft-form-field.js.map +1 -1
  40. package/dist/components/craft-form-modal.cjs +29 -28
  41. package/dist/components/craft-form-modal.cjs.map +1 -1
  42. package/dist/components/craft-form-modal.js +29 -28
  43. package/dist/components/craft-form-modal.js.map +1 -1
  44. package/dist/components/craft-form.cjs +5 -3
  45. package/dist/components/craft-form.cjs.map +1 -1
  46. package/dist/components/craft-form.js +5 -3
  47. package/dist/components/craft-form.js.map +1 -1
  48. package/dist/components/craft-icon.cjs +26 -32
  49. package/dist/components/craft-icon.cjs.map +1 -1
  50. package/dist/components/craft-icon.d.cts +1 -2
  51. package/dist/components/craft-icon.d.ts +1 -2
  52. package/dist/components/craft-icon.js +36 -32
  53. package/dist/components/craft-icon.js.map +1 -1
  54. package/dist/components/craft-loader.cjs +195 -0
  55. package/dist/components/craft-loader.cjs.map +1 -0
  56. package/dist/components/craft-loader.d.cts +21 -0
  57. package/dist/components/craft-loader.d.ts +21 -0
  58. package/dist/components/craft-loader.js +171 -0
  59. package/dist/components/craft-loader.js.map +1 -0
  60. package/dist/components/craft-switch.cjs +4 -11
  61. package/dist/components/craft-switch.cjs.map +1 -1
  62. package/dist/components/craft-switch.js +4 -11
  63. package/dist/components/craft-switch.js.map +1 -1
  64. package/dist/components/layout/app-template.cjs +2 -3
  65. package/dist/components/layout/app-template.cjs.map +1 -1
  66. package/dist/components/layout/app-template.d.cts +1 -2
  67. package/dist/components/layout/app-template.d.ts +1 -2
  68. package/dist/components/layout/app-template.js +2 -3
  69. package/dist/components/layout/app-template.js.map +1 -1
  70. package/dist/index.cjs +9 -3
  71. package/dist/index.cjs.map +1 -1
  72. package/dist/index.d.cts +4 -2
  73. package/dist/index.d.ts +4 -2
  74. package/dist/index.js +6 -2
  75. package/dist/index.js.map +1 -1
  76. package/dist/styles.css +245 -32
  77. package/package.json +8 -8
@@ -35,7 +35,14 @@ module.exports = __toCommonJS(craft_data_table_exports);
35
35
  var import_jsx_runtime = require("react/jsx-runtime");
36
36
  var React = __toESM(require("react"), 1);
37
37
  var import_cn = require("../utils/cn");
38
- var import_craft_pagination = require("../components/craft-pagination");
38
+ var import_craft_button = require("../components/craft-button");
39
+ var import_craft_checkbox = require("../components/craft-checkbox");
40
+ var import_craft_icon = require("../components/craft-icon");
41
+ var import_craft_modal = require("../components/craft-modal");
42
+ var import_craft_tooltip = require("../components/craft-tooltip");
43
+ var import_craft_loader = require("../components/craft-loader");
44
+ var import_craft_data_table_header = require("../components/craft-data-table-header");
45
+ var import_craft_data_table_pagination = require("../components/craft-data-table-pagination");
39
46
  function getColumnValue(column, row) {
40
47
  if (typeof column.accessor === "function") return column.accessor(row);
41
48
  const record = row;
@@ -49,18 +56,58 @@ function normalizeValue(value) {
49
56
  if (value instanceof Date) return value.getTime();
50
57
  return String(value).toLowerCase();
51
58
  }
59
+ function truncateText(text, maxWords) {
60
+ const words = text.split(" ");
61
+ if (words.length <= maxWords) return text;
62
+ return `${words.slice(0, maxWords).join(" ")}...`;
63
+ }
64
+ function resolveActionVariant(variant) {
65
+ switch (variant) {
66
+ case "solid":
67
+ case "default":
68
+ case "primary":
69
+ return "solid";
70
+ case "gradient":
71
+ return "gradient";
72
+ case "outline":
73
+ case "primaryOutline":
74
+ case "dangerOutline":
75
+ case "successOutline":
76
+ return "outline";
77
+ case "ghost":
78
+ case "link":
79
+ case "secondary":
80
+ case "danger":
81
+ case "success":
82
+ case "warning":
83
+ case "info":
84
+ case "subtle":
85
+ case "dark":
86
+ case "light":
87
+ default:
88
+ return "ghost";
89
+ }
90
+ }
52
91
  function CraftDataTable({
53
92
  data,
54
93
  columns,
94
+ title,
95
+ description,
55
96
  tone,
56
97
  className,
57
- loading = false,
58
- emptyState,
59
98
  toolbar,
99
+ emptyState,
100
+ actions = [],
101
+ showActionsColumn = true,
102
+ selectable,
103
+ enableRowSelection = true,
104
+ selectedRowIds,
105
+ onRowSelectionChange,
106
+ getRowId,
107
+ rowKey,
60
108
  enableSorting = true,
61
109
  enableFiltering = true,
62
110
  enableColumnVisibility = true,
63
- enableRowSelection = true,
64
111
  enablePagination = true,
65
112
  showGlobalFilter,
66
113
  manualSorting = false,
@@ -74,14 +121,39 @@ function CraftDataTable({
74
121
  onGlobalFilterChange,
75
122
  columnVisibility,
76
123
  onColumnVisibilityChange,
77
- selectedRowIds,
78
- onRowSelectionChange,
79
- getRowId,
80
124
  pageIndex,
81
125
  pageSize = 10,
82
126
  pageCount,
83
127
  onPageChange,
84
- onPageSizeChange
128
+ onPageSizeChange,
129
+ striped = false,
130
+ hoverable = true,
131
+ clickableRows = false,
132
+ emptyText = "No data available",
133
+ emptySubtitle = "Try adjusting your search or filter criteria",
134
+ variant = "default",
135
+ density = "normal",
136
+ headerVariant = "default",
137
+ headerPadding = "normal",
138
+ paginationVariant = "default",
139
+ paginationPadding = "normal",
140
+ loading = false,
141
+ dataLoading = false,
142
+ sortLoading = false,
143
+ paginationLoading = false,
144
+ bulkLoading = false,
145
+ rowLoading = {},
146
+ loadingType = "dots",
147
+ loadingSize = "medium",
148
+ loadingColor = "rgb(var(--nc-accent-1))",
149
+ loadingText = "Loading...",
150
+ loadingTextPosition = "bottom",
151
+ loadingBackground = "rgba(0, 0, 0, 0.35)",
152
+ showSkeleton = true,
153
+ skeletonRows = 5,
154
+ truncateWords = 10,
155
+ enableTextModal = true,
156
+ onRowClick
85
157
  }) {
86
158
  const [internalSort, setInternalSort] = React.useState(null);
87
159
  const [internalFilters, setInternalFilters] = React.useState({});
@@ -95,12 +167,15 @@ function CraftDataTable({
95
167
  const [internalSelection, setInternalSelection] = React.useState({});
96
168
  const [internalPageIndex, setInternalPageIndex] = React.useState(0);
97
169
  const [showColumns, setShowColumns] = React.useState(false);
170
+ const [showModal, setShowModal] = React.useState(false);
171
+ const [modalContent, setModalContent] = React.useState("");
98
172
  const resolvedSort = sortBy != null ? sortBy : internalSort;
99
173
  const resolvedFilters = filters != null ? filters : internalFilters;
100
174
  const resolvedGlobalFilter = globalFilter != null ? globalFilter : internalGlobalFilter;
101
175
  const resolvedVisibility = columnVisibility != null ? columnVisibility : internalVisibility;
102
176
  const resolvedSelection = selectedRowIds != null ? selectedRowIds : internalSelection;
103
177
  const resolvedPageIndex = pageIndex != null ? pageIndex : internalPageIndex;
178
+ const resolvedSelectable = selectable != null ? selectable : enableRowSelection;
104
179
  const setSort = (next) => {
105
180
  if (sortBy === void 0) setInternalSort(next);
106
181
  onSortChange == null ? void 0 : onSortChange(next);
@@ -175,9 +250,11 @@ function CraftDataTable({
175
250
  const rowIdFor = React.useCallback(
176
251
  (row, index) => {
177
252
  var _a;
178
- return (_a = getRowId == null ? void 0 : getRowId(row, index)) != null ? _a : String(index);
253
+ if (getRowId) return getRowId(row, index);
254
+ if (rowKey) return String((_a = row[rowKey]) != null ? _a : index);
255
+ return String(index);
179
256
  },
180
- [getRowId]
257
+ [getRowId, rowKey]
181
258
  );
182
259
  const pageStartIndex = enablePagination && !manualPagination ? resolvedPageIndex * pageSize : 0;
183
260
  const pageRowIds = pagedData.map(
@@ -204,200 +281,355 @@ function CraftDataTable({
204
281
  }
205
282
  setSort(null);
206
283
  };
207
- const emptyContent = emptyState != null ? emptyState : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "text-center text-sm text-[rgb(var(--nc-fg-muted))]", children: "No results found." });
208
284
  const resolvedShowGlobalFilter = showGlobalFilter != null ? showGlobalFilter : enableFiltering && !toolbar;
209
285
  const setGlobalFilter = (next) => {
210
286
  if (globalFilter === void 0) setInternalGlobalFilter(next);
211
287
  onGlobalFilterChange == null ? void 0 : onGlobalFilterChange(next);
212
288
  };
289
+ const shouldShowActionsColumn = React.useMemo(() => {
290
+ if (!showActionsColumn) return false;
291
+ if (!actions || actions.length === 0) return false;
292
+ return actions.some((action) => {
293
+ if (action.permission === void 0) return true;
294
+ if (typeof action.permission === "boolean") return action.permission;
295
+ return true;
296
+ });
297
+ }, [actions, showActionsColumn]);
298
+ const getVisibleActions = (item) => actions.filter((action) => {
299
+ if (action.permission !== void 0) {
300
+ if (typeof action.permission === "boolean" && !action.permission) return false;
301
+ if (typeof action.permission === "function" && !action.permission(item)) return false;
302
+ }
303
+ if (action.visible && typeof action.visible === "function") {
304
+ return action.visible(item);
305
+ }
306
+ if (typeof action.visible === "boolean") return action.visible;
307
+ return true;
308
+ });
309
+ const isActionDisabled = (action, item) => {
310
+ if (action.disabled && typeof action.disabled === "function") return action.disabled(item);
311
+ if (typeof action.disabled === "boolean") return action.disabled;
312
+ return false;
313
+ };
314
+ const handleActionClick = (action, item) => {
315
+ var _a;
316
+ if (isActionDisabled(action, item)) return;
317
+ (_a = action.onClick) == null ? void 0 : _a.call(action, item);
318
+ };
319
+ const totalColumns = visibleColumns.length + (resolvedSelectable ? 1 : 0) + (shouldShowActionsColumn ? 1 : 0);
320
+ const densityPadding = {
321
+ compact: "px-4 py-2",
322
+ normal: "px-6 py-4",
323
+ comfortable: "px-8 py-6"
324
+ };
325
+ const headerPaddingClasses = {
326
+ compact: "px-4 py-2",
327
+ normal: "px-6 py-3",
328
+ comfortable: "px-8 py-4"
329
+ };
330
+ const rowClassNames = (isSelected, rowId, index) => (0, import_cn.cn)(
331
+ "transition-colors",
332
+ variant === "bordered" && "border-b border-[rgb(var(--nc-border)/0.2)]",
333
+ variant === "minimal" && "border-b border-[rgb(var(--nc-border)/0.15)]",
334
+ striped && index % 2 === 1 && "bg-[rgb(var(--nc-surface)/0.04)]",
335
+ hoverable && !clickableRows && "hover:bg-[rgb(var(--nc-surface)/0.12)]",
336
+ clickableRows && "cursor-pointer hover:bg-[rgb(var(--nc-surface)/0.16)]",
337
+ isSelected && "bg-[rgb(var(--nc-accent-1)/0.12)]",
338
+ rowLoading[rowId] && "opacity-60"
339
+ );
340
+ const containerClasses = (0, import_cn.cn)(
341
+ "overflow-hidden rounded-3xl border border-[rgb(var(--nc-border)/0.3)]",
342
+ "bg-[rgb(var(--nc-surface)/0.08)] shadow-[0_18px_50px_rgba(0,0,0,0.35)] backdrop-blur-2xl",
343
+ variant === "minimal" && "border-transparent bg-transparent shadow-none"
344
+ );
345
+ const openModal = (content) => {
346
+ if (!enableTextModal) return;
347
+ setModalContent(content);
348
+ setShowModal(true);
349
+ };
350
+ const closeModal = () => {
351
+ setShowModal(false);
352
+ setModalContent("");
353
+ };
213
354
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: (0, import_cn.cn)("space-y-4", className), "data-nc-theme": tone, children: [
214
355
  toolbar,
215
- resolvedShowGlobalFilter && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex items-center justify-between gap-3 rounded-2xl border border-[rgb(var(--nc-border)/0.3)] bg-[rgb(var(--nc-surface)/0.12)] px-3 py-2 text-sm text-[rgb(var(--nc-fg))]", children: [
216
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "text-xs text-[rgb(var(--nc-fg-muted))]", children: "Global filter" }),
217
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
218
- "input",
219
- {
220
- type: "search",
221
- value: resolvedGlobalFilter,
222
- onChange: (event) => setGlobalFilter(event.target.value),
223
- placeholder: "Search all columns...",
224
- className: "w-full max-w-xs rounded-xl border border-[rgb(var(--nc-border)/0.3)] bg-[rgb(var(--nc-surface)/0.18)] px-3 py-2 text-xs text-[rgb(var(--nc-fg))]"
225
- }
226
- )
227
- ] }),
228
- enableColumnVisibility && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "relative flex justify-end", children: [
229
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
230
- "button",
231
- {
232
- type: "button",
233
- className: "rounded-xl border border-[rgb(var(--nc-border)/0.3)] bg-[rgb(var(--nc-surface)/0.12)] px-3 py-2 text-xs text-[rgb(var(--nc-fg))] transition hover:bg-[rgb(var(--nc-surface)/0.2)]",
234
- onClick: () => setShowColumns((prev) => !prev),
235
- children: "Columns"
236
- }
237
- ),
238
- showColumns && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "absolute right-0 top-10 z-20 w-48 rounded-2xl border border-[rgb(var(--nc-border)/0.3)] bg-[rgb(var(--nc-surface)/0.2)] p-3 shadow-[0_12px_30px_rgba(0,0,0,0.35)] backdrop-blur-2xl", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "grid gap-2", children: columns.map((column) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
239
- "label",
240
- {
241
- className: "flex items-center gap-2 text-xs text-[rgb(var(--nc-fg))]",
242
- children: [
243
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
244
- "input",
245
- {
246
- type: "checkbox",
247
- className: "h-4 w-4 accent-[rgb(var(--nc-accent-1))]",
248
- checked: resolvedVisibility[column.id] !== false,
249
- onChange: (event) => setVisibility({
250
- ...resolvedVisibility,
251
- [column.id]: event.target.checked
252
- })
253
- }
254
- ),
255
- column.header
256
- ]
257
- },
258
- column.id
259
- )) }) })
260
- ] }),
261
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "overflow-hidden rounded-3xl border border-[rgb(var(--nc-border)/0.3)] bg-[rgb(var(--nc-surface)/0.08)] shadow-[0_18px_50px_rgba(0,0,0,0.35)] backdrop-blur-2xl", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("table", { className: "w-full border-collapse text-left text-sm", children: [
262
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("thead", { className: "bg-[rgb(var(--nc-surface)/0.12)] text-[rgb(var(--nc-fg-muted))]", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("tr", { children: [
263
- enableRowSelection && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { className: "w-12 px-4 py-3", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
264
- "input",
265
- {
266
- ref: headerCheckboxRef,
267
- type: "checkbox",
268
- className: "h-4 w-4 accent-[rgb(var(--nc-accent-1))]",
269
- checked: allSelected,
270
- onChange: (event) => {
271
- const next = { ...resolvedSelection };
272
- pageRowIds.forEach((id) => {
273
- next[id] = event.target.checked;
274
- });
275
- setSelection(next);
356
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
357
+ import_craft_data_table_header.CraftDataTableHeader,
358
+ {
359
+ title,
360
+ description,
361
+ variant: headerVariant,
362
+ padding: headerPadding,
363
+ tone,
364
+ filters: resolvedShowGlobalFilter ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex items-center gap-2 rounded-2xl border border-[rgb(var(--nc-border)/0.3)] bg-[rgb(var(--nc-surface)/0.12)] px-3 py-2 text-xs text-[rgb(var(--nc-fg))]", children: [
365
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_craft_icon.CraftIcon, { name: "search", className: "h-4 w-4 text-[rgb(var(--nc-fg-muted))]" }),
366
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
367
+ "input",
368
+ {
369
+ type: "search",
370
+ value: resolvedGlobalFilter,
371
+ onChange: (event) => setGlobalFilter(event.target.value),
372
+ placeholder: "Search all columns...",
373
+ className: "w-full max-w-xs bg-transparent text-xs text-[rgb(var(--nc-fg))] placeholder:text-[rgb(var(--nc-fg-muted))] focus:outline-none"
276
374
  }
277
- }
278
- ) }),
279
- visibleColumns.map((column) => {
280
- var _a;
281
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
282
- "th",
375
+ )
376
+ ] }) : null,
377
+ actions: enableColumnVisibility ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "relative", children: [
378
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
379
+ import_craft_button.CraftButton,
283
380
  {
284
- className: (0, import_cn.cn)(
285
- "px-4 py-3 text-xs font-semibold uppercase tracking-[0.2em]",
286
- column.headerClassName
287
- ),
288
- style: { width: column.width },
289
- children: [
290
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
291
- "button",
292
- {
293
- type: "button",
294
- className: (0, import_cn.cn)(
295
- "flex items-center gap-2",
296
- enableSorting && column.sortable !== false ? "cursor-pointer" : "cursor-default"
297
- ),
298
- onClick: () => toggleSort(column),
299
- children: [
300
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: column.header }),
301
- (resolvedSort == null ? void 0 : resolvedSort.id) === column.id && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "text-[rgb(var(--nc-accent-1))]", children: resolvedSort.desc ? "\u2193" : "\u2191" })
302
- ]
303
- }
304
- ),
305
- enableFiltering && column.filterable !== false && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
306
- "input",
307
- {
308
- type: "text",
309
- value: (_a = resolvedFilters[column.id]) != null ? _a : "",
310
- onChange: (event) => setFilters({
311
- ...resolvedFilters,
312
- [column.id]: event.target.value
313
- }),
314
- placeholder: "Filter",
315
- className: "mt-2 w-full rounded-xl border border-[rgb(var(--nc-border)/0.3)] bg-[rgb(var(--nc-surface)/0.18)] px-2 py-1 text-xs text-[rgb(var(--nc-fg))]"
316
- }
317
- )
318
- ]
319
- },
320
- column.id
321
- );
322
- })
323
- ] }) }),
324
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("tbody", { className: "text-[rgb(var(--nc-fg))]", children: [
325
- loading && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("tr", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
326
- "td",
327
- {
328
- colSpan: visibleColumns.length + (enableRowSelection ? 1 : 0),
329
- className: "px-4 py-10 text-center text-sm text-[rgb(var(--nc-fg-muted))]",
330
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "inline-flex items-center gap-2", children: [
331
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "h-4 w-4 animate-spin rounded-full border-2 border-[rgb(var(--nc-fg-muted))] border-t-transparent" }),
332
- "Loading data..."
333
- ] })
334
- }
335
- ) }),
336
- !loading && pagedData.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("tr", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
337
- "td",
381
+ type: "button",
382
+ variant: "ghost",
383
+ size: "sm",
384
+ onClick: () => setShowColumns((prev) => !prev),
385
+ children: "Columns"
386
+ }
387
+ ),
388
+ showColumns && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "absolute right-0 top-12 z-20 w-56 rounded-2xl border border-[rgb(var(--nc-border)/0.3)] bg-[rgb(var(--nc-surface)/0.2)] p-3 shadow-[0_12px_30px_rgba(0,0,0,0.35)] backdrop-blur-2xl", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "grid gap-2", children: columns.map((column) => {
389
+ var _a, _b;
390
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
391
+ "label",
392
+ {
393
+ className: "flex items-center gap-2 text-xs text-[rgb(var(--nc-fg))]",
394
+ children: [
395
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
396
+ "input",
397
+ {
398
+ type: "checkbox",
399
+ className: "h-4 w-4 accent-[rgb(var(--nc-accent-1))]",
400
+ checked: resolvedVisibility[column.id] !== false,
401
+ onChange: (event) => setVisibility({
402
+ ...resolvedVisibility,
403
+ [column.id]: event.target.checked
404
+ })
405
+ }
406
+ ),
407
+ (_b = (_a = column.header) != null ? _a : column.label) != null ? _b : column.id
408
+ ]
409
+ },
410
+ column.id
411
+ );
412
+ }) }) })
413
+ ] }) : null
414
+ }
415
+ ),
416
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: containerClasses, children: [
417
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "relative", children: [
418
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
419
+ import_craft_loader.CraftLoader,
338
420
  {
339
- colSpan: visibleColumns.length + (enableRowSelection ? 1 : 0),
340
- className: "px-4 py-10",
341
- children: emptyContent
421
+ loading: loading || dataLoading,
422
+ type: loadingType,
423
+ size: loadingSize,
424
+ color: loadingColor,
425
+ overlay: true,
426
+ text: loadingText,
427
+ textPosition: loadingTextPosition,
428
+ backgroundColor: loadingBackground
342
429
  }
343
- ) }),
344
- !loading && pagedData.map((row, rowIndex) => {
345
- const rowId = rowIdFor(row, pageStartIndex + rowIndex);
346
- const isSelected = resolvedSelection[rowId];
347
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
348
- "tr",
349
- {
350
- className: (0, import_cn.cn)(
351
- "border-t border-[rgb(var(--nc-border)/0.15)]",
352
- isSelected && "bg-[rgb(var(--nc-accent-1)/0.08)]"
353
- ),
354
- children: [
355
- enableRowSelection && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { className: "px-4 py-4", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
356
- "input",
357
- {
358
- type: "checkbox",
359
- className: "h-4 w-4 accent-[rgb(var(--nc-accent-1))]",
360
- checked: isSelected,
361
- onChange: (event) => setSelection({
362
- ...resolvedSelection,
363
- [rowId]: event.target.checked
364
- })
365
- }
366
- ) }),
367
- visibleColumns.map((column) => {
368
- var _a;
369
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
370
- "td",
430
+ ),
431
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: (0, import_cn.cn)("overflow-x-auto", (loading || dataLoading) && "opacity-60"), children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("table", { className: "min-w-full border-collapse text-left text-sm", children: [
432
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("thead", { className: "bg-[rgb(var(--nc-surface)/0.12)] text-[rgb(var(--nc-fg-muted))]", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("tr", { children: [
433
+ resolvedSelectable && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { className: (0, import_cn.cn)("w-12", headerPaddingClasses[density]), children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "flex items-center justify-center", children: bulkLoading ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_craft_loader.CraftLoader, { loading: true, type: "spin", size: "small", color: loadingColor }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
434
+ import_craft_checkbox.CraftCheckbox,
435
+ {
436
+ ref: headerCheckboxRef,
437
+ checked: allSelected,
438
+ onChange: (event) => {
439
+ const next = { ...resolvedSelection };
440
+ pageRowIds.forEach((id) => {
441
+ next[id] = event.target.checked;
442
+ });
443
+ setSelection(next);
444
+ }
445
+ }
446
+ ) }) }),
447
+ visibleColumns.map((column) => {
448
+ var _a, _b, _c;
449
+ const headerLabel = (_b = (_a = column.header) != null ? _a : column.label) != null ? _b : column.id;
450
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
451
+ "th",
452
+ {
453
+ className: (0, import_cn.cn)(
454
+ headerPaddingClasses[density],
455
+ "text-xs font-semibold uppercase tracking-[0.2em]",
456
+ column.headerClassName
457
+ ),
458
+ style: { width: column.width },
459
+ children: [
460
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
461
+ "button",
462
+ {
463
+ type: "button",
464
+ className: (0, import_cn.cn)(
465
+ "flex w-full items-center gap-2",
466
+ enableSorting && column.sortable !== false ? "cursor-pointer" : "cursor-default"
467
+ ),
468
+ onClick: () => toggleSort(column),
469
+ children: [
470
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: headerLabel }),
471
+ sortLoading && (resolvedSort == null ? void 0 : resolvedSort.id) === column.id ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_craft_loader.CraftLoader, { loading: true, type: "spin", size: "small", color: loadingColor }) : null,
472
+ (resolvedSort == null ? void 0 : resolvedSort.id) === column.id && !sortLoading ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "text-[rgb(var(--nc-accent-1))]", children: resolvedSort.desc ? "\u2193" : "\u2191" }) : null
473
+ ]
474
+ }
475
+ ),
476
+ enableFiltering && column.filterable !== false && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
477
+ "input",
478
+ {
479
+ type: "text",
480
+ value: (_c = resolvedFilters[column.id]) != null ? _c : "",
481
+ onChange: (event) => setFilters({
482
+ ...resolvedFilters,
483
+ [column.id]: event.target.value
484
+ }),
485
+ placeholder: "Filter",
486
+ className: "mt-2 w-full rounded-xl border border-[rgb(var(--nc-border)/0.3)] bg-[rgb(var(--nc-surface)/0.18)] px-2 py-1 text-xs text-[rgb(var(--nc-fg))]"
487
+ }
488
+ )
489
+ ]
490
+ },
491
+ column.id
492
+ );
493
+ }),
494
+ shouldShowActionsColumn && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { className: (0, import_cn.cn)(headerPaddingClasses[density], "text-xs uppercase"), children: "Actions" })
495
+ ] }) }),
496
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("tbody", { className: "text-[rgb(var(--nc-fg))]", children: showSkeleton && (loading || dataLoading) ? Array.from({ length: skeletonRows }).map((_, rowIndex) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("tr", { className: "animate-pulse", children: [
497
+ resolvedSelectable && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { className: (0, import_cn.cn)(headerPaddingClasses[density], "w-12"), children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "h-4 w-4 rounded bg-[rgb(var(--nc-border)/0.3)]" }) }),
498
+ visibleColumns.map((column) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { className: (0, import_cn.cn)(densityPadding[density]), children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "h-4 w-3/4 rounded bg-[rgb(var(--nc-border)/0.3)]" }) }, column.id)),
499
+ shouldShowActionsColumn && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { className: (0, import_cn.cn)(densityPadding[density]), children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex items-center justify-center gap-2", children: [
500
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "h-6 w-6 rounded bg-[rgb(var(--nc-border)/0.3)]" }),
501
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "h-6 w-6 rounded bg-[rgb(var(--nc-border)/0.3)]" })
502
+ ] }) })
503
+ ] }, `skeleton-${rowIndex}`)) : pagedData.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("tr", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { colSpan: totalColumns, className: (0, import_cn.cn)(densityPadding[density], "py-12"), children: emptyState != null ? emptyState : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex flex-col items-center justify-center text-center", children: [
504
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
505
+ import_craft_icon.CraftIcon,
506
+ {
507
+ name: "search",
508
+ className: "mb-4 h-12 w-12 text-[rgb(var(--nc-fg-muted))]"
509
+ }
510
+ ),
511
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-base font-semibold text-[rgb(var(--nc-fg))]", children: emptyText }),
512
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-sm text-[rgb(var(--nc-fg-muted))]", children: emptySubtitle })
513
+ ] }) }) }) : pagedData.map((row, rowIndex) => {
514
+ const rowId = rowIdFor(row, pageStartIndex + rowIndex);
515
+ const isSelected = Boolean(resolvedSelection[rowId]);
516
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
517
+ "tr",
518
+ {
519
+ className: rowClassNames(isSelected, rowId, rowIndex),
520
+ onClick: () => {
521
+ if (!clickableRows) return;
522
+ onRowClick == null ? void 0 : onRowClick({ item: row, index: rowIndex });
523
+ },
524
+ children: [
525
+ resolvedSelectable && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { className: (0, import_cn.cn)(densityPadding[density], "w-12"), children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
526
+ import_craft_checkbox.CraftCheckbox,
371
527
  {
372
- className: (0, import_cn.cn)(
373
- "px-4 py-4",
374
- column.align === "center" && "text-center",
375
- column.align === "right" && "text-right",
376
- column.cellClassName
377
- ),
378
- children: column.cell ? column.cell(row) : String((_a = getColumnValue(column, row)) != null ? _a : "")
379
- },
380
- column.id
381
- );
382
- })
383
- ]
384
- },
385
- rowId
386
- );
387
- })
388
- ] })
389
- ] }) }),
390
- enablePagination && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
391
- import_craft_pagination.CraftPagination,
392
- {
393
- pageIndex: resolvedPageIndex,
394
- pageCount: resolvedPageCount,
395
- onPageChange: setPageIndex,
396
- pageSize,
397
- onPageSizeChange,
398
- tone
399
- }
400
- )
528
+ checked: isSelected,
529
+ onChange: (event) => setSelection({
530
+ ...resolvedSelection,
531
+ [rowId]: event.target.checked
532
+ })
533
+ }
534
+ ) }),
535
+ visibleColumns.map((column) => {
536
+ var _a, _b, _c;
537
+ const rawValue = getColumnValue(column, row);
538
+ const formatted = column.formatter ? column.formatter(rawValue, row) : rawValue;
539
+ const content = column.cell ? column.cell(row) : formatted != null ? formatted : "";
540
+ if (enableTextModal && !column.cell && typeof formatted === "string" && ((_a = column.truncate) != null ? _a : true) && formatted.split(" ").length > ((_b = column.maxWords) != null ? _b : truncateWords)) {
541
+ const maxWords = (_c = column.maxWords) != null ? _c : truncateWords;
542
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
543
+ "td",
544
+ {
545
+ className: (0, import_cn.cn)(
546
+ densityPadding[density],
547
+ column.align === "center" && "text-center",
548
+ column.align === "right" && "text-right",
549
+ column.cellClassName
550
+ ),
551
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
552
+ "button",
553
+ {
554
+ type: "button",
555
+ className: "text-[rgb(var(--nc-accent-1))] hover:text-[rgb(var(--nc-accent-2))]",
556
+ onClick: () => openModal(formatted),
557
+ children: truncateText(formatted, maxWords)
558
+ }
559
+ )
560
+ },
561
+ column.id
562
+ );
563
+ }
564
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
565
+ "td",
566
+ {
567
+ className: (0, import_cn.cn)(
568
+ densityPadding[density],
569
+ column.align === "center" && "text-center",
570
+ column.align === "right" && "text-right",
571
+ column.cellClassName
572
+ ),
573
+ children: content
574
+ },
575
+ column.id
576
+ );
577
+ }),
578
+ shouldShowActionsColumn && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { className: (0, import_cn.cn)(densityPadding[density]), children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "flex items-center justify-center gap-2", children: getVisibleActions(row).map((action) => {
579
+ const tooltip = typeof action.tooltip === "function" ? action.tooltip(row) : action.tooltip;
580
+ const className2 = typeof action.className === "function" ? action.className(row) : action.className;
581
+ const button = /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
582
+ import_craft_button.CraftButton,
583
+ {
584
+ type: "button",
585
+ size: "sm",
586
+ variant: resolveActionVariant(action.variant),
587
+ disabled: isActionDisabled(action, row),
588
+ className: (0, import_cn.cn)("h-8 w-8 p-0", className2),
589
+ onClick: (event) => {
590
+ event.stopPropagation();
591
+ handleActionClick(action, row);
592
+ },
593
+ children: action.icon ? typeof action.icon === "string" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_craft_icon.CraftIcon, { name: action.icon, className: "h-4 w-4" }) : action.icon : action.label ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "text-[11px]", children: action.label }) : null
594
+ }
595
+ );
596
+ if (tooltip) {
597
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_craft_tooltip.CraftTooltip, { content: tooltip, children: button }, action.key);
598
+ }
599
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(React.Fragment, { children: button }, action.key);
600
+ }) }) })
601
+ ]
602
+ },
603
+ rowId
604
+ );
605
+ }) })
606
+ ] }) })
607
+ ] }),
608
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
609
+ import_craft_data_table_pagination.CraftDataTablePagination,
610
+ {
611
+ currentPage: resolvedPageIndex,
612
+ totalPages: resolvedPageCount,
613
+ total: filteredData.length,
614
+ pageSize,
615
+ selectable: Boolean(resolvedSelectable),
616
+ selectedCount: Object.values(resolvedSelection).filter(Boolean).length,
617
+ showPagination: enablePagination,
618
+ loading: paginationLoading,
619
+ disabled: loading || dataLoading,
620
+ onPageChange: setPageIndex,
621
+ onPageSizeChange,
622
+ variant: paginationVariant,
623
+ padding: paginationPadding,
624
+ tone
625
+ }
626
+ )
627
+ ] }),
628
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_craft_modal.CraftModal, { open: showModal, onOpenChange: setShowModal, title: "Full Text", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "space-y-3", children: [
629
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-sm text-[rgb(var(--nc-fg-muted))]", children: "Full content" }),
630
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "text-sm text-[rgb(var(--nc-fg))] whitespace-pre-wrap wrap-break-words", children: modalContent }),
631
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "flex justify-end", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_craft_button.CraftButton, { type: "button", variant: "ghost", onClick: closeModal, children: "Close" }) })
632
+ ] }) })
401
633
  ] });
402
634
  }
403
635
  // Annotate the CommonJS export names for ESM import in node: