@kreativa/ui 0.1.0 → 0.1.2
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 +112 -6
- package/dist/index.d.ts +112 -6
- package/dist/index.js +417 -99
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +416 -100
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -22,6 +22,7 @@ var index_exports = {};
|
|
|
22
22
|
__export(index_exports, {
|
|
23
23
|
Button: () => Button,
|
|
24
24
|
Card: () => Card,
|
|
25
|
+
DataTable: () => DataTable,
|
|
25
26
|
DatePicker: () => DatePicker,
|
|
26
27
|
EmptyState: () => EmptyState,
|
|
27
28
|
FormButtonGroup: () => FormButtonGroup,
|
|
@@ -37,6 +38,7 @@ __export(index_exports, {
|
|
|
37
38
|
Table: () => Table,
|
|
38
39
|
Tabs: () => Tabs,
|
|
39
40
|
Timer: () => Timer,
|
|
41
|
+
createFilterOptions: () => createFilterOptions,
|
|
40
42
|
formatTime: () => formatTime
|
|
41
43
|
});
|
|
42
44
|
module.exports = __toCommonJS(index_exports);
|
|
@@ -338,10 +340,15 @@ function Table({
|
|
|
338
340
|
onRowClick,
|
|
339
341
|
loading = false,
|
|
340
342
|
emptyMessage = "No data available",
|
|
341
|
-
className = ""
|
|
343
|
+
className = "",
|
|
344
|
+
resizable = false,
|
|
345
|
+
fixedLayout = false
|
|
342
346
|
}) {
|
|
343
347
|
const [sortKey, setSortKey] = (0, import_react5.useState)(null);
|
|
344
348
|
const [sortDirection, setSortDirection] = (0, import_react5.useState)(null);
|
|
349
|
+
const [columnWidths, setColumnWidths] = (0, import_react5.useState)({});
|
|
350
|
+
const tableRef = (0, import_react5.useRef)(null);
|
|
351
|
+
const resizingRef = (0, import_react5.useRef)(null);
|
|
345
352
|
const handleHeaderClick = (column) => {
|
|
346
353
|
if (!column.sortable) return;
|
|
347
354
|
if (sortKey === column.key) {
|
|
@@ -370,65 +377,138 @@ function Table({
|
|
|
370
377
|
});
|
|
371
378
|
return sortDirection === "desc" ? sorted.reverse() : sorted;
|
|
372
379
|
}, [data, columns, sortKey, sortDirection]);
|
|
380
|
+
const handleResizeStart = (0, import_react5.useCallback)(
|
|
381
|
+
(e, columnKey) => {
|
|
382
|
+
e.preventDefault();
|
|
383
|
+
e.stopPropagation();
|
|
384
|
+
const headerCell = e.currentTarget.parentElement;
|
|
385
|
+
if (!headerCell) return;
|
|
386
|
+
const startWidth = headerCell.getBoundingClientRect().width;
|
|
387
|
+
resizingRef.current = {
|
|
388
|
+
columnKey,
|
|
389
|
+
startX: e.clientX,
|
|
390
|
+
startWidth
|
|
391
|
+
};
|
|
392
|
+
document.addEventListener("mousemove", handleResizeMove);
|
|
393
|
+
document.addEventListener("mouseup", handleResizeEnd);
|
|
394
|
+
document.body.style.cursor = "col-resize";
|
|
395
|
+
document.body.style.userSelect = "none";
|
|
396
|
+
},
|
|
397
|
+
[]
|
|
398
|
+
);
|
|
399
|
+
const handleResizeMove = (0, import_react5.useCallback)((e) => {
|
|
400
|
+
if (!resizingRef.current) return;
|
|
401
|
+
const { columnKey, startX, startWidth } = resizingRef.current;
|
|
402
|
+
const column = columns.find((c) => c.key === columnKey);
|
|
403
|
+
const minWidth = column?.minWidth ?? 50;
|
|
404
|
+
const newWidth = Math.max(minWidth, startWidth + (e.clientX - startX));
|
|
405
|
+
setColumnWidths((prev) => ({
|
|
406
|
+
...prev,
|
|
407
|
+
[columnKey]: newWidth
|
|
408
|
+
}));
|
|
409
|
+
}, [columns]);
|
|
410
|
+
const handleResizeEnd = (0, import_react5.useCallback)(() => {
|
|
411
|
+
resizingRef.current = null;
|
|
412
|
+
document.removeEventListener("mousemove", handleResizeMove);
|
|
413
|
+
document.removeEventListener("mouseup", handleResizeEnd);
|
|
414
|
+
document.body.style.cursor = "";
|
|
415
|
+
document.body.style.userSelect = "";
|
|
416
|
+
}, [handleResizeMove]);
|
|
373
417
|
const getSortIcon = (column) => {
|
|
374
418
|
if (!column.sortable) return null;
|
|
375
419
|
if (sortKey !== column.key) {
|
|
376
|
-
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("svg", { className: "w-4 h-4 text-gray-400", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M7 16V4m0 0L3 8m4-4l4 4m6 0v12m0 0l4-4m-4 4l-4-4" }) });
|
|
420
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("svg", { className: "w-4 h-4 text-gray-400 shrink-0", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M7 16V4m0 0L3 8m4-4l4 4m6 0v12m0 0l4-4m-4 4l-4-4" }) });
|
|
377
421
|
}
|
|
378
422
|
if (sortDirection === "asc") {
|
|
379
|
-
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("svg", { className: "w-4 h-4 text-primary-600", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M5 15l7-7 7 7" }) });
|
|
423
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("svg", { className: "w-4 h-4 text-primary-600 shrink-0", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M5 15l7-7 7 7" }) });
|
|
380
424
|
}
|
|
381
|
-
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("svg", { className: "w-4 h-4 text-primary-600", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M19 9l-7 7-7-7" }) });
|
|
425
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("svg", { className: "w-4 h-4 text-primary-600 shrink-0", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M19 9l-7 7-7-7" }) });
|
|
382
426
|
};
|
|
383
427
|
const alignmentClasses = {
|
|
384
428
|
left: "text-left",
|
|
385
429
|
center: "text-center",
|
|
386
430
|
right: "text-right"
|
|
387
431
|
};
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
432
|
+
const getColumnStyle = (column) => {
|
|
433
|
+
if (columnWidths[column.key]) {
|
|
434
|
+
return { width: columnWidths[column.key], minWidth: columnWidths[column.key] };
|
|
435
|
+
}
|
|
436
|
+
if (column.width) {
|
|
437
|
+
return { width: column.width, minWidth: column.minWidth ?? 50 };
|
|
438
|
+
}
|
|
439
|
+
return { minWidth: column.minWidth ?? 50 };
|
|
440
|
+
};
|
|
441
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: `overflow-x-auto ${className}`, children: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
|
|
442
|
+
"table",
|
|
443
|
+
{
|
|
444
|
+
ref: tableRef,
|
|
445
|
+
className: "w-full border-collapse",
|
|
446
|
+
style: { tableLayout: fixedLayout || resizable ? "fixed" : "auto" },
|
|
447
|
+
children: [
|
|
448
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("tr", { className: "bg-gray-50 border-b border-gray-200", children: columns.map((column, index) => /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
|
|
449
|
+
"th",
|
|
450
|
+
{
|
|
451
|
+
className: `
|
|
452
|
+
px-4 py-3 text-sm font-semibold text-gray-700 relative
|
|
394
453
|
${alignmentClasses[column.align ?? "left"]}
|
|
395
454
|
${column.sortable ? "cursor-pointer select-none hover:bg-gray-100" : ""}
|
|
396
455
|
`,
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
456
|
+
style: getColumnStyle(column),
|
|
457
|
+
onClick: () => handleHeaderClick(column),
|
|
458
|
+
children: [
|
|
459
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
|
|
460
|
+
"div",
|
|
461
|
+
{
|
|
462
|
+
className: `flex items-center gap-1 overflow-hidden ${column.align === "right" ? "justify-end" : column.align === "center" ? "justify-center" : ""}`,
|
|
463
|
+
children: [
|
|
464
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "truncate", children: column.header }),
|
|
465
|
+
getSortIcon(column)
|
|
466
|
+
]
|
|
467
|
+
}
|
|
468
|
+
),
|
|
469
|
+
resizable && index < columns.length - 1 && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
470
|
+
"div",
|
|
471
|
+
{
|
|
472
|
+
className: "absolute top-0 right-0 w-1 h-full cursor-col-resize bg-transparent hover:bg-primary-300 transition-colors",
|
|
473
|
+
onMouseDown: (e) => handleResizeStart(e, column.key),
|
|
474
|
+
onClick: (e) => e.stopPropagation()
|
|
475
|
+
}
|
|
476
|
+
)
|
|
477
|
+
]
|
|
478
|
+
},
|
|
479
|
+
column.key
|
|
480
|
+
)) }) }),
|
|
481
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("tbody", { children: loading ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("tr", { children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("td", { colSpan: columns.length, className: "px-4 py-8 text-center text-gray-500", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex items-center justify-center gap-2", children: [
|
|
482
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "w-5 h-5 border-2 border-primary-200 border-t-primary-600 rounded-full animate-spin" }),
|
|
483
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { children: "Loading..." })
|
|
484
|
+
] }) }) }) : sortedData.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("tr", { children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("td", { colSpan: columns.length, className: "px-4 py-8 text-center text-gray-500", children: emptyMessage }) }) : sortedData.map((item) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
485
|
+
"tr",
|
|
486
|
+
{
|
|
487
|
+
className: `
|
|
413
488
|
border-b border-gray-100 hover:bg-gray-50 transition-colors
|
|
414
489
|
${onRowClick ? "cursor-pointer" : ""}
|
|
415
490
|
`,
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
491
|
+
onClick: () => onRowClick?.(item),
|
|
492
|
+
children: columns.map((column) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
493
|
+
"td",
|
|
494
|
+
{
|
|
495
|
+
className: `px-4 py-3 text-sm text-gray-800 overflow-hidden ${alignmentClasses[column.align ?? "left"]}`,
|
|
496
|
+
style: getColumnStyle(column),
|
|
497
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "truncate", children: column.render(item) })
|
|
498
|
+
},
|
|
499
|
+
column.key
|
|
500
|
+
))
|
|
423
501
|
},
|
|
424
|
-
|
|
425
|
-
))
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
] }) });
|
|
502
|
+
getRowKey(item)
|
|
503
|
+
)) })
|
|
504
|
+
]
|
|
505
|
+
}
|
|
506
|
+
) });
|
|
430
507
|
}
|
|
431
508
|
|
|
509
|
+
// src/components/DataTable.tsx
|
|
510
|
+
var import_react7 = require("react");
|
|
511
|
+
|
|
432
512
|
// src/components/Select.tsx
|
|
433
513
|
var import_react6 = require("react");
|
|
434
514
|
var import_jsx_runtime14 = require("react/jsx-runtime");
|
|
@@ -612,9 +692,245 @@ function Select({
|
|
|
612
692
|
] });
|
|
613
693
|
}
|
|
614
694
|
|
|
615
|
-
// src/components/
|
|
616
|
-
var import_react7 = require("react");
|
|
695
|
+
// src/components/DataTable.tsx
|
|
617
696
|
var import_jsx_runtime15 = require("react/jsx-runtime");
|
|
697
|
+
function ColumnFilter({ column, value, onChange }) {
|
|
698
|
+
const filterType = column.filterType ?? "text";
|
|
699
|
+
if (filterType === "none") {
|
|
700
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "h-9" });
|
|
701
|
+
}
|
|
702
|
+
if (filterType === "select" && column.filterOptions) {
|
|
703
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
704
|
+
Select,
|
|
705
|
+
{
|
|
706
|
+
options: [{ value: "", label: "Alla" }, ...column.filterOptions],
|
|
707
|
+
value: value || "",
|
|
708
|
+
onChange: (val) => onChange(val),
|
|
709
|
+
placeholder: column.filterPlaceholder || "Alla",
|
|
710
|
+
className: "w-full text-sm"
|
|
711
|
+
}
|
|
712
|
+
);
|
|
713
|
+
}
|
|
714
|
+
if (filterType === "multiselect" && column.filterOptions) {
|
|
715
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
716
|
+
Select,
|
|
717
|
+
{
|
|
718
|
+
options: column.filterOptions,
|
|
719
|
+
value: value || [],
|
|
720
|
+
onChange: (val) => onChange(val),
|
|
721
|
+
placeholder: column.filterPlaceholder || "Alla",
|
|
722
|
+
multiple: true,
|
|
723
|
+
className: "w-full text-sm"
|
|
724
|
+
}
|
|
725
|
+
);
|
|
726
|
+
}
|
|
727
|
+
if (filterType === "boolean") {
|
|
728
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
729
|
+
Select,
|
|
730
|
+
{
|
|
731
|
+
options: [
|
|
732
|
+
{ value: "", label: "Alla" },
|
|
733
|
+
{ value: "true", label: "Ja" },
|
|
734
|
+
{ value: "false", label: "Nej" }
|
|
735
|
+
],
|
|
736
|
+
value: value || "",
|
|
737
|
+
onChange: (val) => onChange(val),
|
|
738
|
+
className: "w-full text-sm"
|
|
739
|
+
}
|
|
740
|
+
);
|
|
741
|
+
}
|
|
742
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
743
|
+
Input,
|
|
744
|
+
{
|
|
745
|
+
type: "text",
|
|
746
|
+
value: value || "",
|
|
747
|
+
onChange: (e) => onChange(e.target.value),
|
|
748
|
+
placeholder: column.filterPlaceholder || `Filtrera ${column.header.toLowerCase()}...`,
|
|
749
|
+
className: "w-full text-sm h-9"
|
|
750
|
+
}
|
|
751
|
+
);
|
|
752
|
+
}
|
|
753
|
+
function DataTable({
|
|
754
|
+
data,
|
|
755
|
+
columns,
|
|
756
|
+
getRowKey,
|
|
757
|
+
onRowClick,
|
|
758
|
+
loading,
|
|
759
|
+
emptyMessage = "Ingen data att visa.",
|
|
760
|
+
className,
|
|
761
|
+
showFilters = true,
|
|
762
|
+
initialSortKey,
|
|
763
|
+
initialSortDirection = "asc",
|
|
764
|
+
onFilteredDataChange
|
|
765
|
+
}) {
|
|
766
|
+
const [filters, setFilters] = (0, import_react7.useState)({});
|
|
767
|
+
const [sortKey, setSortKey] = (0, import_react7.useState)(initialSortKey || null);
|
|
768
|
+
const [sortDirection, setSortDirection] = (0, import_react7.useState)(initialSortDirection);
|
|
769
|
+
const handleFilterChange = (0, import_react7.useCallback)((columnKey, value) => {
|
|
770
|
+
setFilters((prev) => {
|
|
771
|
+
const next = { ...prev };
|
|
772
|
+
if (value === "" || Array.isArray(value) && value.length === 0) {
|
|
773
|
+
delete next[columnKey];
|
|
774
|
+
} else {
|
|
775
|
+
next[columnKey] = value;
|
|
776
|
+
}
|
|
777
|
+
return next;
|
|
778
|
+
});
|
|
779
|
+
}, []);
|
|
780
|
+
const clearFilters = (0, import_react7.useCallback)(() => {
|
|
781
|
+
setFilters({});
|
|
782
|
+
}, []);
|
|
783
|
+
const filteredData = (0, import_react7.useMemo)(() => {
|
|
784
|
+
let result = [...data];
|
|
785
|
+
for (const [columnKey, filterValue] of Object.entries(filters)) {
|
|
786
|
+
if (!filterValue || Array.isArray(filterValue) && filterValue.length === 0) continue;
|
|
787
|
+
const column = columns.find((c) => c.key === columnKey);
|
|
788
|
+
if (!column) continue;
|
|
789
|
+
const getFilterableValue = column.filterValue || ((item) => {
|
|
790
|
+
return item[columnKey];
|
|
791
|
+
});
|
|
792
|
+
result = result.filter((item) => {
|
|
793
|
+
const itemValue = getFilterableValue(item);
|
|
794
|
+
if (itemValue === null || itemValue === void 0) {
|
|
795
|
+
return filterValue === "";
|
|
796
|
+
}
|
|
797
|
+
const filterType = column.filterType ?? "text";
|
|
798
|
+
if (filterType === "boolean") {
|
|
799
|
+
const boolFilterValue = filterValue === "true";
|
|
800
|
+
return itemValue === boolFilterValue;
|
|
801
|
+
}
|
|
802
|
+
if (filterType === "multiselect" && Array.isArray(filterValue)) {
|
|
803
|
+
return filterValue.includes(String(itemValue));
|
|
804
|
+
}
|
|
805
|
+
if (filterType === "select") {
|
|
806
|
+
return String(itemValue).toLowerCase() === String(filterValue).toLowerCase();
|
|
807
|
+
}
|
|
808
|
+
return String(itemValue).toLowerCase().includes(String(filterValue).toLowerCase());
|
|
809
|
+
});
|
|
810
|
+
}
|
|
811
|
+
return result;
|
|
812
|
+
}, [data, filters, columns]);
|
|
813
|
+
const sortedData = (0, import_react7.useMemo)(() => {
|
|
814
|
+
if (!sortKey) return filteredData;
|
|
815
|
+
const column = columns.find((c) => c.key === sortKey);
|
|
816
|
+
if (!column) return filteredData;
|
|
817
|
+
const sorted = [...filteredData].sort((a, b) => {
|
|
818
|
+
if (column.sortFn) {
|
|
819
|
+
return column.sortFn(a, b);
|
|
820
|
+
}
|
|
821
|
+
const getValueForSort = column.filterValue || ((item) => {
|
|
822
|
+
return item[sortKey];
|
|
823
|
+
});
|
|
824
|
+
const aVal = getValueForSort(a);
|
|
825
|
+
const bVal = getValueForSort(b);
|
|
826
|
+
if (aVal === null || aVal === void 0) return 1;
|
|
827
|
+
if (bVal === null || bVal === void 0) return -1;
|
|
828
|
+
if (typeof aVal === "string" && typeof bVal === "string") {
|
|
829
|
+
return aVal.localeCompare(bVal, "sv");
|
|
830
|
+
}
|
|
831
|
+
if (aVal < bVal) return -1;
|
|
832
|
+
if (aVal > bVal) return 1;
|
|
833
|
+
return 0;
|
|
834
|
+
});
|
|
835
|
+
return sortDirection === "desc" ? sorted.reverse() : sorted;
|
|
836
|
+
}, [filteredData, sortKey, sortDirection, columns]);
|
|
837
|
+
(0, import_react7.useMemo)(() => {
|
|
838
|
+
onFilteredDataChange?.(sortedData);
|
|
839
|
+
}, [sortedData, onFilteredDataChange]);
|
|
840
|
+
const handleSort = (0, import_react7.useCallback)((columnKey) => {
|
|
841
|
+
if (sortKey === columnKey) {
|
|
842
|
+
setSortDirection((prev) => prev === "asc" ? "desc" : "asc");
|
|
843
|
+
} else {
|
|
844
|
+
setSortKey(columnKey);
|
|
845
|
+
setSortDirection("asc");
|
|
846
|
+
}
|
|
847
|
+
}, [sortKey]);
|
|
848
|
+
const tableColumns = (0, import_react7.useMemo)(() => {
|
|
849
|
+
return columns.map((column) => {
|
|
850
|
+
const isSortable = column.sortable !== false && column.filterType !== "none";
|
|
851
|
+
const isCurrentSort = sortKey === column.key;
|
|
852
|
+
return {
|
|
853
|
+
key: column.key,
|
|
854
|
+
header: isSortable ? /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
|
|
855
|
+
"button",
|
|
856
|
+
{
|
|
857
|
+
onClick: () => handleSort(column.key),
|
|
858
|
+
className: "flex items-center gap-1 hover:text-gray-900 transition-colors w-full text-left",
|
|
859
|
+
children: [
|
|
860
|
+
column.header,
|
|
861
|
+
isCurrentSort ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "text-primary-600", children: sortDirection === "asc" ? "\u2191" : "\u2193" }) : /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "text-gray-400 opacity-50", children: "\u2195" })
|
|
862
|
+
]
|
|
863
|
+
}
|
|
864
|
+
) : column.header,
|
|
865
|
+
render: column.render,
|
|
866
|
+
width: column.width,
|
|
867
|
+
align: column.align,
|
|
868
|
+
sortable: false
|
|
869
|
+
// We handle sorting ourselves
|
|
870
|
+
};
|
|
871
|
+
});
|
|
872
|
+
}, [columns, sortKey, sortDirection, handleSort]);
|
|
873
|
+
const hasActiveFilters = Object.keys(filters).length > 0;
|
|
874
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className, children: [
|
|
875
|
+
showFilters && /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "mb-4", children: [
|
|
876
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "flex flex-wrap items-center gap-2 mb-2", children: [
|
|
877
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("span", { className: "text-sm text-gray-500", children: [
|
|
878
|
+
"Visar ",
|
|
879
|
+
sortedData.length,
|
|
880
|
+
" av ",
|
|
881
|
+
data.length
|
|
882
|
+
] }),
|
|
883
|
+
hasActiveFilters && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
884
|
+
"button",
|
|
885
|
+
{
|
|
886
|
+
onClick: clearFilters,
|
|
887
|
+
className: "text-sm text-primary-600 hover:underline",
|
|
888
|
+
children: "Rensa filter"
|
|
889
|
+
}
|
|
890
|
+
)
|
|
891
|
+
] }),
|
|
892
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 xl:grid-cols-6 gap-3 p-3 bg-gray-50 border border-gray-200 rounded-lg", children: columns.filter((col) => col.filterType !== "none").map((column) => /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "min-w-0", children: [
|
|
893
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("label", { className: "text-xs text-gray-500 mb-1 block truncate", children: column.header }),
|
|
894
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
895
|
+
ColumnFilter,
|
|
896
|
+
{
|
|
897
|
+
column,
|
|
898
|
+
value: filters[column.key] || "",
|
|
899
|
+
onChange: (value) => handleFilterChange(column.key, value)
|
|
900
|
+
}
|
|
901
|
+
)
|
|
902
|
+
] }, column.key)) })
|
|
903
|
+
] }),
|
|
904
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
905
|
+
Table,
|
|
906
|
+
{
|
|
907
|
+
data: sortedData,
|
|
908
|
+
columns: tableColumns,
|
|
909
|
+
getRowKey,
|
|
910
|
+
onRowClick,
|
|
911
|
+
loading,
|
|
912
|
+
emptyMessage
|
|
913
|
+
}
|
|
914
|
+
)
|
|
915
|
+
] });
|
|
916
|
+
}
|
|
917
|
+
function createFilterOptions(data, getValue, labelMap) {
|
|
918
|
+
const uniqueValues = /* @__PURE__ */ new Set();
|
|
919
|
+
for (const item of data) {
|
|
920
|
+
const value = getValue(item);
|
|
921
|
+
if (value !== null && value !== void 0 && value !== "") {
|
|
922
|
+
uniqueValues.add(value);
|
|
923
|
+
}
|
|
924
|
+
}
|
|
925
|
+
return Array.from(uniqueValues).sort((a, b) => a.localeCompare(b, "sv")).map((value) => ({
|
|
926
|
+
value,
|
|
927
|
+
label: labelMap?.[value] || value
|
|
928
|
+
}));
|
|
929
|
+
}
|
|
930
|
+
|
|
931
|
+
// src/components/Tabs.tsx
|
|
932
|
+
var import_react8 = require("react");
|
|
933
|
+
var import_jsx_runtime16 = require("react/jsx-runtime");
|
|
618
934
|
function Tabs({
|
|
619
935
|
tabs,
|
|
620
936
|
activeTab: controlledActiveTab,
|
|
@@ -625,7 +941,7 @@ function Tabs({
|
|
|
625
941
|
className = ""
|
|
626
942
|
}) {
|
|
627
943
|
const isControlled = controlledActiveTab !== void 0;
|
|
628
|
-
const [internalActiveTab, setInternalActiveTab] = (0,
|
|
944
|
+
const [internalActiveTab, setInternalActiveTab] = (0, import_react8.useState)(
|
|
629
945
|
defaultTab || tabs.find((t) => !t.disabled)?.id || tabs[0]?.id
|
|
630
946
|
);
|
|
631
947
|
const activeTab = isControlled ? controlledActiveTab : internalActiveTab;
|
|
@@ -693,11 +1009,11 @@ function Tabs({
|
|
|
693
1009
|
}
|
|
694
1010
|
};
|
|
695
1011
|
const styles = variantStyles[variant];
|
|
696
|
-
return /* @__PURE__ */ (0,
|
|
697
|
-
/* @__PURE__ */ (0,
|
|
1012
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className, children: [
|
|
1013
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: `flex ${styles.container}`, role: "tablist", children: tabs.map((tab, index) => {
|
|
698
1014
|
const isActive = tab.id === activeTab;
|
|
699
1015
|
const isDisabled = tab.disabled ?? false;
|
|
700
|
-
return /* @__PURE__ */ (0,
|
|
1016
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
701
1017
|
"button",
|
|
702
1018
|
{
|
|
703
1019
|
type: "button",
|
|
@@ -709,7 +1025,7 @@ function Tabs({
|
|
|
709
1025
|
className: styles.tab(isActive, isDisabled),
|
|
710
1026
|
onClick: () => handleTabClick(tab),
|
|
711
1027
|
onKeyDown: (e) => handleKeyDown(e, index),
|
|
712
|
-
children: /* @__PURE__ */ (0,
|
|
1028
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("span", { className: "flex items-center gap-2", children: [
|
|
713
1029
|
tab.icon,
|
|
714
1030
|
tab.label
|
|
715
1031
|
] })
|
|
@@ -717,13 +1033,13 @@ function Tabs({
|
|
|
717
1033
|
tab.id
|
|
718
1034
|
);
|
|
719
1035
|
}) }),
|
|
720
|
-
renderContent && activeContent && /* @__PURE__ */ (0,
|
|
1036
|
+
renderContent && activeContent && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "pt-4", role: "tabpanel", children: activeContent })
|
|
721
1037
|
] });
|
|
722
1038
|
}
|
|
723
1039
|
|
|
724
1040
|
// src/components/DatePicker.tsx
|
|
725
|
-
var
|
|
726
|
-
var
|
|
1041
|
+
var import_react9 = require("react");
|
|
1042
|
+
var import_jsx_runtime17 = require("react/jsx-runtime");
|
|
727
1043
|
var WEEKDAYS = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"];
|
|
728
1044
|
var MONTHS = [
|
|
729
1045
|
"January",
|
|
@@ -826,12 +1142,12 @@ function DatePicker({
|
|
|
826
1142
|
disabled = false,
|
|
827
1143
|
className = ""
|
|
828
1144
|
}) {
|
|
829
|
-
const [isOpen, setIsOpen] = (0,
|
|
830
|
-
const [viewDate, setViewDate] = (0,
|
|
831
|
-
const [hoverDate, setHoverDate] = (0,
|
|
832
|
-
const containerRef = (0,
|
|
833
|
-
const [selectingEnd, setSelectingEnd] = (0,
|
|
834
|
-
(0,
|
|
1145
|
+
const [isOpen, setIsOpen] = (0, import_react9.useState)(false);
|
|
1146
|
+
const [viewDate, setViewDate] = (0, import_react9.useState)(/* @__PURE__ */ new Date());
|
|
1147
|
+
const [hoverDate, setHoverDate] = (0, import_react9.useState)(null);
|
|
1148
|
+
const containerRef = (0, import_react9.useRef)(null);
|
|
1149
|
+
const [selectingEnd, setSelectingEnd] = (0, import_react9.useState)(false);
|
|
1150
|
+
(0, import_react9.useEffect)(() => {
|
|
835
1151
|
const handleClickOutside = (e) => {
|
|
836
1152
|
if (containerRef.current && !containerRef.current.contains(e.target)) {
|
|
837
1153
|
setIsOpen(false);
|
|
@@ -841,7 +1157,7 @@ function DatePicker({
|
|
|
841
1157
|
document.addEventListener("mousedown", handleClickOutside);
|
|
842
1158
|
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
843
1159
|
}, []);
|
|
844
|
-
const displayText = (0,
|
|
1160
|
+
const displayText = (0, import_react9.useMemo)(() => {
|
|
845
1161
|
if (!value) return "";
|
|
846
1162
|
if (range) {
|
|
847
1163
|
const rangeValue = value;
|
|
@@ -858,7 +1174,7 @@ function DatePicker({
|
|
|
858
1174
|
}
|
|
859
1175
|
return formatDate(value);
|
|
860
1176
|
}, [value, range]);
|
|
861
|
-
const calendarDays = (0,
|
|
1177
|
+
const calendarDays = (0, import_react9.useMemo)(() => {
|
|
862
1178
|
const year = viewDate.getFullYear();
|
|
863
1179
|
const month = viewDate.getMonth();
|
|
864
1180
|
const firstDay = new Date(year, month, 1);
|
|
@@ -941,9 +1257,9 @@ function DatePicker({
|
|
|
941
1257
|
};
|
|
942
1258
|
const today = /* @__PURE__ */ new Date();
|
|
943
1259
|
today.setHours(0, 0, 0, 0);
|
|
944
|
-
return /* @__PURE__ */ (0,
|
|
945
|
-
label && /* @__PURE__ */ (0,
|
|
946
|
-
/* @__PURE__ */ (0,
|
|
1260
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { ref: containerRef, className: `relative ${className}`, children: [
|
|
1261
|
+
label && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("label", { className: "block text-sm font-medium text-gray-700 mb-2", children: label }),
|
|
1262
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
947
1263
|
"div",
|
|
948
1264
|
{
|
|
949
1265
|
className: `
|
|
@@ -953,15 +1269,15 @@ function DatePicker({
|
|
|
953
1269
|
transition-all
|
|
954
1270
|
`,
|
|
955
1271
|
onClick: () => !disabled && setIsOpen(!isOpen),
|
|
956
|
-
children: /* @__PURE__ */ (0,
|
|
957
|
-
/* @__PURE__ */ (0,
|
|
958
|
-
/* @__PURE__ */ (0,
|
|
1272
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "flex items-center justify-between", children: [
|
|
1273
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: displayText ? "text-gray-800" : "text-gray-400", children: displayText || placeholder }),
|
|
1274
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("svg", { className: "w-5 h-5 text-gray-400", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z" }) })
|
|
959
1275
|
] })
|
|
960
1276
|
}
|
|
961
1277
|
),
|
|
962
|
-
error && /* @__PURE__ */ (0,
|
|
963
|
-
isOpen && /* @__PURE__ */ (0,
|
|
964
|
-
range && /* @__PURE__ */ (0,
|
|
1278
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("p", { className: "mt-1 text-xs text-red-600", children: error }),
|
|
1279
|
+
isOpen && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "absolute z-50 mt-1 bg-white border border-gray-200 rounded-xl shadow-lg p-4", children: /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: range ? "flex gap-4" : "", children: [
|
|
1280
|
+
range && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "border-r border-gray-100 pr-4 space-y-1", children: PRESET_RANGES.map((preset) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
965
1281
|
"button",
|
|
966
1282
|
{
|
|
967
1283
|
type: "button",
|
|
@@ -971,42 +1287,42 @@ function DatePicker({
|
|
|
971
1287
|
},
|
|
972
1288
|
preset.label
|
|
973
1289
|
)) }),
|
|
974
|
-
/* @__PURE__ */ (0,
|
|
975
|
-
/* @__PURE__ */ (0,
|
|
976
|
-
/* @__PURE__ */ (0,
|
|
1290
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { children: [
|
|
1291
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "flex items-center justify-between mb-4", children: [
|
|
1292
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
977
1293
|
"button",
|
|
978
1294
|
{
|
|
979
1295
|
type: "button",
|
|
980
1296
|
className: "p-1 hover:bg-gray-100 rounded",
|
|
981
1297
|
onClick: goToPrevMonth,
|
|
982
|
-
children: /* @__PURE__ */ (0,
|
|
1298
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("svg", { className: "w-5 h-5 text-gray-600", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M15 19l-7-7 7-7" }) })
|
|
983
1299
|
}
|
|
984
1300
|
),
|
|
985
|
-
/* @__PURE__ */ (0,
|
|
1301
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("span", { className: "text-sm font-semibold text-gray-800", children: [
|
|
986
1302
|
MONTHS[viewDate.getMonth()],
|
|
987
1303
|
" ",
|
|
988
1304
|
viewDate.getFullYear()
|
|
989
1305
|
] }),
|
|
990
|
-
/* @__PURE__ */ (0,
|
|
1306
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
991
1307
|
"button",
|
|
992
1308
|
{
|
|
993
1309
|
type: "button",
|
|
994
1310
|
className: "p-1 hover:bg-gray-100 rounded",
|
|
995
1311
|
onClick: goToNextMonth,
|
|
996
|
-
children: /* @__PURE__ */ (0,
|
|
1312
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("svg", { className: "w-5 h-5 text-gray-600", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M9 5l7 7-7 7" }) })
|
|
997
1313
|
}
|
|
998
1314
|
)
|
|
999
1315
|
] }),
|
|
1000
|
-
/* @__PURE__ */ (0,
|
|
1001
|
-
/* @__PURE__ */ (0,
|
|
1316
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "grid grid-cols-7 gap-1 mb-2", children: WEEKDAYS.map((day) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "text-center text-xs font-medium text-gray-500 py-1", children: day }, day)) }),
|
|
1317
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "grid grid-cols-7 gap-1", children: calendarDays.map((date, index) => {
|
|
1002
1318
|
if (!date) {
|
|
1003
|
-
return /* @__PURE__ */ (0,
|
|
1319
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "w-9 h-9" }, `empty-${index}`);
|
|
1004
1320
|
}
|
|
1005
1321
|
const isDisabled = isDateDisabled(date);
|
|
1006
1322
|
const isSelected = isDateSelected(date);
|
|
1007
1323
|
const inRange = isDateInRange(date);
|
|
1008
1324
|
const isToday = isSameDay(date, today);
|
|
1009
|
-
return /* @__PURE__ */ (0,
|
|
1325
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
1010
1326
|
"button",
|
|
1011
1327
|
{
|
|
1012
1328
|
type: "button",
|
|
@@ -1032,8 +1348,8 @@ function DatePicker({
|
|
|
1032
1348
|
}
|
|
1033
1349
|
|
|
1034
1350
|
// src/components/Timer.tsx
|
|
1035
|
-
var
|
|
1036
|
-
var
|
|
1351
|
+
var import_react10 = require("react");
|
|
1352
|
+
var import_jsx_runtime18 = require("react/jsx-runtime");
|
|
1037
1353
|
function formatTime(totalSeconds) {
|
|
1038
1354
|
const hours = Math.floor(totalSeconds / 3600);
|
|
1039
1355
|
const minutes = Math.floor(totalSeconds % 3600 / 60);
|
|
@@ -1057,20 +1373,20 @@ function Timer({
|
|
|
1057
1373
|
elapsedSeconds: controlledElapsedSeconds
|
|
1058
1374
|
}) {
|
|
1059
1375
|
const isControlled = controlledIsRunning !== void 0;
|
|
1060
|
-
const [internalIsRunning, setInternalIsRunning] = (0,
|
|
1061
|
-
const [internalElapsedSeconds, setInternalElapsedSeconds] = (0,
|
|
1376
|
+
const [internalIsRunning, setInternalIsRunning] = (0, import_react10.useState)(false);
|
|
1377
|
+
const [internalElapsedSeconds, setInternalElapsedSeconds] = (0, import_react10.useState)(initialSeconds);
|
|
1062
1378
|
const isRunning = isControlled ? controlledIsRunning : internalIsRunning;
|
|
1063
1379
|
const elapsedSeconds = isControlled ? controlledElapsedSeconds ?? 0 : internalElapsedSeconds;
|
|
1064
|
-
const intervalRef = (0,
|
|
1065
|
-
const startTimeRef = (0,
|
|
1066
|
-
(0,
|
|
1380
|
+
const intervalRef = (0, import_react10.useRef)(null);
|
|
1381
|
+
const startTimeRef = (0, import_react10.useRef)(null);
|
|
1382
|
+
(0, import_react10.useEffect)(() => {
|
|
1067
1383
|
return () => {
|
|
1068
1384
|
if (intervalRef.current) {
|
|
1069
1385
|
clearInterval(intervalRef.current);
|
|
1070
1386
|
}
|
|
1071
1387
|
};
|
|
1072
1388
|
}, []);
|
|
1073
|
-
(0,
|
|
1389
|
+
(0, import_react10.useEffect)(() => {
|
|
1074
1390
|
if (isControlled) return;
|
|
1075
1391
|
if (isRunning) {
|
|
1076
1392
|
intervalRef.current = setInterval(() => {
|
|
@@ -1093,7 +1409,7 @@ function Timer({
|
|
|
1093
1409
|
}
|
|
1094
1410
|
};
|
|
1095
1411
|
}, [isRunning, isControlled, onTick]);
|
|
1096
|
-
const handleStart = (0,
|
|
1412
|
+
const handleStart = (0, import_react10.useCallback)(() => {
|
|
1097
1413
|
const now = /* @__PURE__ */ new Date();
|
|
1098
1414
|
startTimeRef.current = now;
|
|
1099
1415
|
if (!isControlled) {
|
|
@@ -1101,13 +1417,13 @@ function Timer({
|
|
|
1101
1417
|
}
|
|
1102
1418
|
onStart?.(now);
|
|
1103
1419
|
}, [isControlled, onStart]);
|
|
1104
|
-
const handleStop = (0,
|
|
1420
|
+
const handleStop = (0, import_react10.useCallback)(() => {
|
|
1105
1421
|
if (!isControlled) {
|
|
1106
1422
|
setInternalIsRunning(false);
|
|
1107
1423
|
}
|
|
1108
1424
|
onStop?.(elapsedSeconds);
|
|
1109
1425
|
}, [isControlled, elapsedSeconds, onStop]);
|
|
1110
|
-
const handleReset = (0,
|
|
1426
|
+
const handleReset = (0, import_react10.useCallback)(() => {
|
|
1111
1427
|
if (!isControlled) {
|
|
1112
1428
|
setInternalIsRunning(false);
|
|
1113
1429
|
setInternalElapsedSeconds(0);
|
|
@@ -1115,7 +1431,7 @@ function Timer({
|
|
|
1115
1431
|
startTimeRef.current = null;
|
|
1116
1432
|
onReset?.();
|
|
1117
1433
|
}, [isControlled, onReset]);
|
|
1118
|
-
const handleToggle = (0,
|
|
1434
|
+
const handleToggle = (0, import_react10.useCallback)(() => {
|
|
1119
1435
|
if (isRunning) {
|
|
1120
1436
|
handleStop();
|
|
1121
1437
|
} else {
|
|
@@ -1143,10 +1459,10 @@ function Timer({
|
|
|
1143
1459
|
}
|
|
1144
1460
|
};
|
|
1145
1461
|
const styles = sizeClasses3[size];
|
|
1146
|
-
return /* @__PURE__ */ (0,
|
|
1147
|
-
/* @__PURE__ */ (0,
|
|
1148
|
-
/* @__PURE__ */ (0,
|
|
1149
|
-
/* @__PURE__ */ (0,
|
|
1462
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: `flex items-center ${styles.container} ${className}`, children: [
|
|
1463
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: `font-mono font-bold text-gray-800 ${styles.time} tabular-nums`, children: formatTime(elapsedSeconds) }),
|
|
1464
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
1465
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
1150
1466
|
"button",
|
|
1151
1467
|
{
|
|
1152
1468
|
type: "button",
|
|
@@ -1160,14 +1476,14 @@ function Timer({
|
|
|
1160
1476
|
title: isRunning ? "Pause" : "Start",
|
|
1161
1477
|
children: isRunning ? (
|
|
1162
1478
|
// Pause icon
|
|
1163
|
-
/* @__PURE__ */ (0,
|
|
1479
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("svg", { className: styles.icon, fill: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("path", { d: "M6 4h4v16H6V4zm8 0h4v16h-4V4z" }) })
|
|
1164
1480
|
) : (
|
|
1165
1481
|
// Play icon
|
|
1166
|
-
/* @__PURE__ */ (0,
|
|
1482
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("svg", { className: styles.icon, fill: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("path", { d: "M8 5v14l11-7z" }) })
|
|
1167
1483
|
)
|
|
1168
1484
|
}
|
|
1169
1485
|
),
|
|
1170
|
-
elapsedSeconds > 0 && /* @__PURE__ */ (0,
|
|
1486
|
+
elapsedSeconds > 0 && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
1171
1487
|
"button",
|
|
1172
1488
|
{
|
|
1173
1489
|
type: "button",
|
|
@@ -1178,10 +1494,10 @@ function Timer({
|
|
|
1178
1494
|
transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500
|
|
1179
1495
|
`,
|
|
1180
1496
|
title: "Stop",
|
|
1181
|
-
children: /* @__PURE__ */ (0,
|
|
1497
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("svg", { className: styles.icon, fill: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("path", { d: "M6 6h12v12H6z" }) })
|
|
1182
1498
|
}
|
|
1183
1499
|
),
|
|
1184
|
-
showReset && elapsedSeconds > 0 && !isRunning && /* @__PURE__ */ (0,
|
|
1500
|
+
showReset && elapsedSeconds > 0 && !isRunning && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
1185
1501
|
"button",
|
|
1186
1502
|
{
|
|
1187
1503
|
type: "button",
|
|
@@ -1192,7 +1508,7 @@ function Timer({
|
|
|
1192
1508
|
transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-gray-400
|
|
1193
1509
|
`,
|
|
1194
1510
|
title: "Reset",
|
|
1195
|
-
children: /* @__PURE__ */ (0,
|
|
1511
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("svg", { className: styles.icon, fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15" }) })
|
|
1196
1512
|
}
|
|
1197
1513
|
)
|
|
1198
1514
|
] })
|
|
@@ -1202,6 +1518,7 @@ function Timer({
|
|
|
1202
1518
|
0 && (module.exports = {
|
|
1203
1519
|
Button,
|
|
1204
1520
|
Card,
|
|
1521
|
+
DataTable,
|
|
1205
1522
|
DatePicker,
|
|
1206
1523
|
EmptyState,
|
|
1207
1524
|
FormButtonGroup,
|
|
@@ -1217,6 +1534,7 @@ function Timer({
|
|
|
1217
1534
|
Table,
|
|
1218
1535
|
Tabs,
|
|
1219
1536
|
Timer,
|
|
1537
|
+
createFilterOptions,
|
|
1220
1538
|
formatTime
|
|
1221
1539
|
});
|
|
1222
1540
|
//# sourceMappingURL=index.js.map
|