@kreativa/ui 0.1.1 → 0.1.3
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/dist/index.d.mts +25 -7
- package/dist/index.d.ts +25 -7
- package/dist/index.js +120 -41
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +137 -58
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -286,7 +286,7 @@ function FormButtonGroup({
|
|
|
286
286
|
}
|
|
287
287
|
|
|
288
288
|
// src/components/Table.tsx
|
|
289
|
-
import { useState, useMemo } from "react";
|
|
289
|
+
import { useState, useMemo, useRef, useCallback } from "react";
|
|
290
290
|
import { jsx as jsx13, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
291
291
|
function Table({
|
|
292
292
|
data,
|
|
@@ -295,10 +295,15 @@ function Table({
|
|
|
295
295
|
onRowClick,
|
|
296
296
|
loading = false,
|
|
297
297
|
emptyMessage = "No data available",
|
|
298
|
-
className = ""
|
|
298
|
+
className = "",
|
|
299
|
+
resizable = false,
|
|
300
|
+
fixedLayout = false
|
|
299
301
|
}) {
|
|
300
302
|
const [sortKey, setSortKey] = useState(null);
|
|
301
303
|
const [sortDirection, setSortDirection] = useState(null);
|
|
304
|
+
const [columnWidths, setColumnWidths] = useState({});
|
|
305
|
+
const tableRef = useRef(null);
|
|
306
|
+
const resizingRef = useRef(null);
|
|
302
307
|
const handleHeaderClick = (column) => {
|
|
303
308
|
if (!column.sortable) return;
|
|
304
309
|
if (sortKey === column.key) {
|
|
@@ -327,70 +332,140 @@ function Table({
|
|
|
327
332
|
});
|
|
328
333
|
return sortDirection === "desc" ? sorted.reverse() : sorted;
|
|
329
334
|
}, [data, columns, sortKey, sortDirection]);
|
|
335
|
+
const handleResizeStart = useCallback(
|
|
336
|
+
(e, columnKey) => {
|
|
337
|
+
e.preventDefault();
|
|
338
|
+
e.stopPropagation();
|
|
339
|
+
const headerCell = e.currentTarget.parentElement;
|
|
340
|
+
if (!headerCell) return;
|
|
341
|
+
const startWidth = headerCell.getBoundingClientRect().width;
|
|
342
|
+
resizingRef.current = {
|
|
343
|
+
columnKey,
|
|
344
|
+
startX: e.clientX,
|
|
345
|
+
startWidth
|
|
346
|
+
};
|
|
347
|
+
document.addEventListener("mousemove", handleResizeMove);
|
|
348
|
+
document.addEventListener("mouseup", handleResizeEnd);
|
|
349
|
+
document.body.style.cursor = "col-resize";
|
|
350
|
+
document.body.style.userSelect = "none";
|
|
351
|
+
},
|
|
352
|
+
[]
|
|
353
|
+
);
|
|
354
|
+
const handleResizeMove = useCallback((e) => {
|
|
355
|
+
if (!resizingRef.current) return;
|
|
356
|
+
const { columnKey, startX, startWidth } = resizingRef.current;
|
|
357
|
+
const column = columns.find((c) => c.key === columnKey);
|
|
358
|
+
const minWidth = column?.minWidth ?? 50;
|
|
359
|
+
const newWidth = Math.max(minWidth, startWidth + (e.clientX - startX));
|
|
360
|
+
setColumnWidths((prev) => ({
|
|
361
|
+
...prev,
|
|
362
|
+
[columnKey]: newWidth
|
|
363
|
+
}));
|
|
364
|
+
}, [columns]);
|
|
365
|
+
const handleResizeEnd = useCallback(() => {
|
|
366
|
+
resizingRef.current = null;
|
|
367
|
+
document.removeEventListener("mousemove", handleResizeMove);
|
|
368
|
+
document.removeEventListener("mouseup", handleResizeEnd);
|
|
369
|
+
document.body.style.cursor = "";
|
|
370
|
+
document.body.style.userSelect = "";
|
|
371
|
+
}, [handleResizeMove]);
|
|
330
372
|
const getSortIcon = (column) => {
|
|
331
373
|
if (!column.sortable) return null;
|
|
332
374
|
if (sortKey !== column.key) {
|
|
333
|
-
return /* @__PURE__ */ jsx13("svg", { className: "w-4 h-4 text-gray-400", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx13("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M7 16V4m0 0L3 8m4-4l4 4m6 0v12m0 0l4-4m-4 4l-4-4" }) });
|
|
375
|
+
return /* @__PURE__ */ jsx13("svg", { className: "w-4 h-4 text-gray-400 shrink-0", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx13("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M7 16V4m0 0L3 8m4-4l4 4m6 0v12m0 0l4-4m-4 4l-4-4" }) });
|
|
334
376
|
}
|
|
335
377
|
if (sortDirection === "asc") {
|
|
336
|
-
return /* @__PURE__ */ jsx13("svg", { className: "w-4 h-4 text-primary-600", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx13("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M5 15l7-7 7 7" }) });
|
|
378
|
+
return /* @__PURE__ */ jsx13("svg", { className: "w-4 h-4 text-primary-600 shrink-0", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx13("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M5 15l7-7 7 7" }) });
|
|
337
379
|
}
|
|
338
|
-
return /* @__PURE__ */ jsx13("svg", { className: "w-4 h-4 text-primary-600", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx13("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M19 9l-7 7-7-7" }) });
|
|
380
|
+
return /* @__PURE__ */ jsx13("svg", { className: "w-4 h-4 text-primary-600 shrink-0", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx13("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M19 9l-7 7-7-7" }) });
|
|
339
381
|
};
|
|
340
382
|
const alignmentClasses = {
|
|
341
383
|
left: "text-left",
|
|
342
384
|
center: "text-center",
|
|
343
385
|
right: "text-right"
|
|
344
386
|
};
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
387
|
+
const getColumnStyle = (column) => {
|
|
388
|
+
if (columnWidths[column.key]) {
|
|
389
|
+
return { width: columnWidths[column.key], minWidth: columnWidths[column.key] };
|
|
390
|
+
}
|
|
391
|
+
if (column.width) {
|
|
392
|
+
return { width: column.width, minWidth: column.minWidth ?? 50 };
|
|
393
|
+
}
|
|
394
|
+
return { minWidth: column.minWidth ?? 50 };
|
|
395
|
+
};
|
|
396
|
+
return /* @__PURE__ */ jsx13("div", { className: `overflow-x-auto ${className}`, children: /* @__PURE__ */ jsxs9(
|
|
397
|
+
"table",
|
|
398
|
+
{
|
|
399
|
+
ref: tableRef,
|
|
400
|
+
className: "w-full border-collapse",
|
|
401
|
+
style: { tableLayout: fixedLayout || resizable ? "fixed" : "auto" },
|
|
402
|
+
children: [
|
|
403
|
+
/* @__PURE__ */ jsx13("thead", { children: /* @__PURE__ */ jsx13("tr", { className: "bg-gray-50 border-b border-gray-200", children: columns.map((column, index) => /* @__PURE__ */ jsxs9(
|
|
404
|
+
"th",
|
|
405
|
+
{
|
|
406
|
+
className: `
|
|
407
|
+
px-4 py-3 text-sm font-semibold text-gray-700 relative
|
|
351
408
|
${alignmentClasses[column.align ?? "left"]}
|
|
352
409
|
${column.sortable ? "cursor-pointer select-none hover:bg-gray-100" : ""}
|
|
353
410
|
`,
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
411
|
+
style: getColumnStyle(column),
|
|
412
|
+
onClick: () => handleHeaderClick(column),
|
|
413
|
+
children: [
|
|
414
|
+
/* @__PURE__ */ jsxs9(
|
|
415
|
+
"div",
|
|
416
|
+
{
|
|
417
|
+
className: `flex items-center gap-1 overflow-hidden ${column.align === "right" ? "justify-end" : column.align === "center" ? "justify-center" : ""}`,
|
|
418
|
+
children: [
|
|
419
|
+
/* @__PURE__ */ jsx13("span", { className: "truncate", children: column.header }),
|
|
420
|
+
getSortIcon(column)
|
|
421
|
+
]
|
|
422
|
+
}
|
|
423
|
+
),
|
|
424
|
+
resizable && index < columns.length - 1 && /* @__PURE__ */ jsx13(
|
|
425
|
+
"div",
|
|
426
|
+
{
|
|
427
|
+
className: "absolute top-0 right-0 w-1 h-full cursor-col-resize bg-transparent hover:bg-primary-300 transition-colors",
|
|
428
|
+
onMouseDown: (e) => handleResizeStart(e, column.key),
|
|
429
|
+
onClick: (e) => e.stopPropagation()
|
|
430
|
+
}
|
|
431
|
+
)
|
|
432
|
+
]
|
|
433
|
+
},
|
|
434
|
+
column.key
|
|
435
|
+
)) }) }),
|
|
436
|
+
/* @__PURE__ */ jsx13("tbody", { children: loading ? /* @__PURE__ */ jsx13("tr", { children: /* @__PURE__ */ jsx13("td", { colSpan: columns.length, className: "px-4 py-8 text-center text-gray-500", children: /* @__PURE__ */ jsxs9("div", { className: "flex items-center justify-center gap-2", children: [
|
|
437
|
+
/* @__PURE__ */ jsx13("div", { className: "w-5 h-5 border-2 border-primary-200 border-t-primary-600 rounded-full animate-spin" }),
|
|
438
|
+
/* @__PURE__ */ jsx13("span", { children: "Loading..." })
|
|
439
|
+
] }) }) }) : sortedData.length === 0 ? /* @__PURE__ */ jsx13("tr", { children: /* @__PURE__ */ jsx13("td", { colSpan: columns.length, className: "px-4 py-8 text-center text-gray-500", children: emptyMessage }) }) : sortedData.map((item) => /* @__PURE__ */ jsx13(
|
|
440
|
+
"tr",
|
|
441
|
+
{
|
|
442
|
+
className: `
|
|
370
443
|
border-b border-gray-100 hover:bg-gray-50 transition-colors
|
|
371
444
|
${onRowClick ? "cursor-pointer" : ""}
|
|
372
445
|
`,
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
446
|
+
onClick: () => onRowClick?.(item),
|
|
447
|
+
children: columns.map((column) => /* @__PURE__ */ jsx13(
|
|
448
|
+
"td",
|
|
449
|
+
{
|
|
450
|
+
className: `px-4 py-3 text-sm text-gray-800 overflow-hidden ${alignmentClasses[column.align ?? "left"]}`,
|
|
451
|
+
style: getColumnStyle(column),
|
|
452
|
+
children: /* @__PURE__ */ jsx13("div", { className: "truncate", children: column.render(item) })
|
|
453
|
+
},
|
|
454
|
+
column.key
|
|
455
|
+
))
|
|
380
456
|
},
|
|
381
|
-
|
|
382
|
-
))
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
] }) });
|
|
457
|
+
getRowKey(item)
|
|
458
|
+
)) })
|
|
459
|
+
]
|
|
460
|
+
}
|
|
461
|
+
) });
|
|
387
462
|
}
|
|
388
463
|
|
|
389
464
|
// src/components/DataTable.tsx
|
|
390
|
-
import { useState as useState3, useMemo as useMemo3, useCallback } from "react";
|
|
465
|
+
import { useState as useState3, useMemo as useMemo3, useCallback as useCallback2 } from "react";
|
|
391
466
|
|
|
392
467
|
// src/components/Select.tsx
|
|
393
|
-
import { useState as useState2, useRef, useEffect as useEffect2, useMemo as useMemo2 } from "react";
|
|
468
|
+
import { useState as useState2, useRef as useRef2, useEffect as useEffect2, useMemo as useMemo2 } from "react";
|
|
394
469
|
import { jsx as jsx14, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
395
470
|
function Select({
|
|
396
471
|
options,
|
|
@@ -407,8 +482,8 @@ function Select({
|
|
|
407
482
|
const [isOpen, setIsOpen] = useState2(false);
|
|
408
483
|
const [searchTerm, setSearchTerm] = useState2("");
|
|
409
484
|
const [highlightedIndex, setHighlightedIndex] = useState2(0);
|
|
410
|
-
const containerRef =
|
|
411
|
-
const inputRef =
|
|
485
|
+
const containerRef = useRef2(null);
|
|
486
|
+
const inputRef = useRef2(null);
|
|
412
487
|
const filteredOptions = useMemo2(() => {
|
|
413
488
|
if (!searchTerm) return options;
|
|
414
489
|
const term = searchTerm.toLowerCase();
|
|
@@ -641,12 +716,14 @@ function DataTable({
|
|
|
641
716
|
showFilters = true,
|
|
642
717
|
initialSortKey,
|
|
643
718
|
initialSortDirection = "asc",
|
|
644
|
-
onFilteredDataChange
|
|
719
|
+
onFilteredDataChange,
|
|
720
|
+
resizable = false,
|
|
721
|
+
fixedLayout = false
|
|
645
722
|
}) {
|
|
646
723
|
const [filters, setFilters] = useState3({});
|
|
647
724
|
const [sortKey, setSortKey] = useState3(initialSortKey || null);
|
|
648
725
|
const [sortDirection, setSortDirection] = useState3(initialSortDirection);
|
|
649
|
-
const handleFilterChange =
|
|
726
|
+
const handleFilterChange = useCallback2((columnKey, value) => {
|
|
650
727
|
setFilters((prev) => {
|
|
651
728
|
const next = { ...prev };
|
|
652
729
|
if (value === "" || Array.isArray(value) && value.length === 0) {
|
|
@@ -657,7 +734,7 @@ function DataTable({
|
|
|
657
734
|
return next;
|
|
658
735
|
});
|
|
659
736
|
}, []);
|
|
660
|
-
const clearFilters =
|
|
737
|
+
const clearFilters = useCallback2(() => {
|
|
661
738
|
setFilters({});
|
|
662
739
|
}, []);
|
|
663
740
|
const filteredData = useMemo3(() => {
|
|
@@ -717,7 +794,7 @@ function DataTable({
|
|
|
717
794
|
useMemo3(() => {
|
|
718
795
|
onFilteredDataChange?.(sortedData);
|
|
719
796
|
}, [sortedData, onFilteredDataChange]);
|
|
720
|
-
const handleSort =
|
|
797
|
+
const handleSort = useCallback2((columnKey) => {
|
|
721
798
|
if (sortKey === columnKey) {
|
|
722
799
|
setSortDirection((prev) => prev === "asc" ? "desc" : "asc");
|
|
723
800
|
} else {
|
|
@@ -789,7 +866,9 @@ function DataTable({
|
|
|
789
866
|
getRowKey,
|
|
790
867
|
onRowClick,
|
|
791
868
|
loading,
|
|
792
|
-
emptyMessage
|
|
869
|
+
emptyMessage,
|
|
870
|
+
resizable,
|
|
871
|
+
fixedLayout
|
|
793
872
|
}
|
|
794
873
|
)
|
|
795
874
|
] });
|
|
@@ -918,7 +997,7 @@ function Tabs({
|
|
|
918
997
|
}
|
|
919
998
|
|
|
920
999
|
// src/components/DatePicker.tsx
|
|
921
|
-
import { useState as useState5, useRef as
|
|
1000
|
+
import { useState as useState5, useRef as useRef3, useEffect as useEffect3, useMemo as useMemo4 } from "react";
|
|
922
1001
|
import { jsx as jsx17, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
923
1002
|
var WEEKDAYS = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"];
|
|
924
1003
|
var MONTHS = [
|
|
@@ -1025,7 +1104,7 @@ function DatePicker({
|
|
|
1025
1104
|
const [isOpen, setIsOpen] = useState5(false);
|
|
1026
1105
|
const [viewDate, setViewDate] = useState5(/* @__PURE__ */ new Date());
|
|
1027
1106
|
const [hoverDate, setHoverDate] = useState5(null);
|
|
1028
|
-
const containerRef =
|
|
1107
|
+
const containerRef = useRef3(null);
|
|
1029
1108
|
const [selectingEnd, setSelectingEnd] = useState5(false);
|
|
1030
1109
|
useEffect3(() => {
|
|
1031
1110
|
const handleClickOutside = (e) => {
|
|
@@ -1228,7 +1307,7 @@ function DatePicker({
|
|
|
1228
1307
|
}
|
|
1229
1308
|
|
|
1230
1309
|
// src/components/Timer.tsx
|
|
1231
|
-
import { useState as useState6, useEffect as useEffect4, useCallback as
|
|
1310
|
+
import { useState as useState6, useEffect as useEffect4, useCallback as useCallback3, useRef as useRef4 } from "react";
|
|
1232
1311
|
import { jsx as jsx18, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
1233
1312
|
function formatTime(totalSeconds) {
|
|
1234
1313
|
const hours = Math.floor(totalSeconds / 3600);
|
|
@@ -1257,8 +1336,8 @@ function Timer({
|
|
|
1257
1336
|
const [internalElapsedSeconds, setInternalElapsedSeconds] = useState6(initialSeconds);
|
|
1258
1337
|
const isRunning = isControlled ? controlledIsRunning : internalIsRunning;
|
|
1259
1338
|
const elapsedSeconds = isControlled ? controlledElapsedSeconds ?? 0 : internalElapsedSeconds;
|
|
1260
|
-
const intervalRef =
|
|
1261
|
-
const startTimeRef =
|
|
1339
|
+
const intervalRef = useRef4(null);
|
|
1340
|
+
const startTimeRef = useRef4(null);
|
|
1262
1341
|
useEffect4(() => {
|
|
1263
1342
|
return () => {
|
|
1264
1343
|
if (intervalRef.current) {
|
|
@@ -1289,7 +1368,7 @@ function Timer({
|
|
|
1289
1368
|
}
|
|
1290
1369
|
};
|
|
1291
1370
|
}, [isRunning, isControlled, onTick]);
|
|
1292
|
-
const handleStart =
|
|
1371
|
+
const handleStart = useCallback3(() => {
|
|
1293
1372
|
const now = /* @__PURE__ */ new Date();
|
|
1294
1373
|
startTimeRef.current = now;
|
|
1295
1374
|
if (!isControlled) {
|
|
@@ -1297,13 +1376,13 @@ function Timer({
|
|
|
1297
1376
|
}
|
|
1298
1377
|
onStart?.(now);
|
|
1299
1378
|
}, [isControlled, onStart]);
|
|
1300
|
-
const handleStop =
|
|
1379
|
+
const handleStop = useCallback3(() => {
|
|
1301
1380
|
if (!isControlled) {
|
|
1302
1381
|
setInternalIsRunning(false);
|
|
1303
1382
|
}
|
|
1304
1383
|
onStop?.(elapsedSeconds);
|
|
1305
1384
|
}, [isControlled, elapsedSeconds, onStop]);
|
|
1306
|
-
const handleReset =
|
|
1385
|
+
const handleReset = useCallback3(() => {
|
|
1307
1386
|
if (!isControlled) {
|
|
1308
1387
|
setInternalIsRunning(false);
|
|
1309
1388
|
setInternalElapsedSeconds(0);
|
|
@@ -1311,7 +1390,7 @@ function Timer({
|
|
|
1311
1390
|
startTimeRef.current = null;
|
|
1312
1391
|
onReset?.();
|
|
1313
1392
|
}, [isControlled, onReset]);
|
|
1314
|
-
const handleToggle =
|
|
1393
|
+
const handleToggle = useCallback3(() => {
|
|
1315
1394
|
if (isRunning) {
|
|
1316
1395
|
handleStop();
|
|
1317
1396
|
} else {
|