@withwiz/toolkit 0.1.4 → 0.2.1
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/auth/index.js +3 -3
- package/dist/chunk-6JZQE7ZQ.js +225 -0
- package/dist/chunk-7IY3RQQL.js +151 -0
- package/dist/{chunk-SLG26KHZ.js → chunk-FH6E36YZ.js} +1 -1
- package/dist/chunk-IPXPCBDO.js +127 -0
- package/dist/chunk-KHYY4KCV.js +110 -0
- package/dist/chunk-MAATEX2R.js +81 -0
- package/dist/chunk-NY5QXT33.js +31 -0
- package/dist/chunk-SEZJN4TC.js +136 -0
- package/dist/components/ui/DataTable.d.ts +8 -103
- package/dist/components/ui/DataTable.js +17 -602
- package/dist/components/ui/data-table/DataTable.d.ts +2 -0
- package/dist/components/ui/data-table/DataTable.js +22 -0
- package/dist/components/ui/data-table/DataTableBody.d.ts +19 -0
- package/dist/components/ui/data-table/DataTableBody.js +10 -0
- package/dist/components/ui/data-table/DataTableBulkActions.d.ts +17 -0
- package/dist/components/ui/data-table/DataTableBulkActions.js +12 -0
- package/dist/components/ui/data-table/DataTableFilters.d.ts +15 -0
- package/dist/components/ui/data-table/DataTableFilters.js +13 -0
- package/dist/components/ui/data-table/DataTablePagination.d.ts +10 -0
- package/dist/components/ui/data-table/DataTablePagination.js +11 -0
- package/dist/components/ui/data-table/DataTableSearch.d.ts +24 -0
- package/dist/components/ui/data-table/DataTableSearch.js +12 -0
- package/dist/components/ui/data-table/index.d.ts +13 -0
- package/dist/components/ui/data-table/types.d.ts +115 -0
- package/dist/constants/index.js +13 -13
- package/dist/error/hooks/index.js +2 -2
- package/dist/error/hooks/useErrorHandler.js +2 -2
- package/dist/error/index.js +25 -25
- package/dist/error/recovery/index.js +7 -7
- package/dist/geolocation/index.js +4 -4
- package/dist/geolocation/providers/index.js +4 -4
- package/dist/hooks/useDataTable.d.ts +45 -0
- package/dist/hooks/useDataTable.js +13 -11
- package/dist/middleware/error-handler.js +2 -2
- package/dist/middleware/index.js +3 -3
- package/dist/middleware/wrappers.js +3 -3
- package/package.json +3 -1
- package/dist/{chunk-TMVS4F7E.js → chunk-5OWZKYWQ.js} +3 -3
- package/dist/{chunk-IAJNC34M.js → chunk-6UAYU5NU.js} +3 -3
- package/dist/{chunk-QF6FH4GZ.js → chunk-S73334QY.js} +3 -3
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import {
|
|
2
|
+
formatLabel
|
|
3
|
+
} from "./chunk-NY5QXT33.js";
|
|
4
|
+
import {
|
|
5
|
+
LoadingBar
|
|
6
|
+
} from "./chunk-34WAGUT5.js";
|
|
7
|
+
import {
|
|
8
|
+
Button
|
|
9
|
+
} from "./chunk-L25BNU3E.js";
|
|
10
|
+
|
|
11
|
+
// src/components/ui/data-table/DataTableBulkActions.tsx
|
|
12
|
+
import { CheckSquare, Square, Loader2 } from "lucide-react";
|
|
13
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
14
|
+
function DataTableBulkActions({
|
|
15
|
+
bulkActions,
|
|
16
|
+
localSelectedIds,
|
|
17
|
+
dataLength,
|
|
18
|
+
bulkActionLoading,
|
|
19
|
+
onSelectAll,
|
|
20
|
+
onBulkAction,
|
|
21
|
+
labels
|
|
22
|
+
}) {
|
|
23
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
24
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3 p-3 bg-muted rounded-lg", children: [
|
|
25
|
+
/* @__PURE__ */ jsx("div", { className: "flex flex-col sm:flex-row items-start sm:items-center gap-3", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
26
|
+
/* @__PURE__ */ jsxs(
|
|
27
|
+
Button,
|
|
28
|
+
{
|
|
29
|
+
"data-testid": "select-all-btn",
|
|
30
|
+
variant: "outline",
|
|
31
|
+
size: "sm",
|
|
32
|
+
onClick: () => {
|
|
33
|
+
const allSelected = localSelectedIds.length === dataLength && dataLength > 0;
|
|
34
|
+
onSelectAll(!allSelected);
|
|
35
|
+
},
|
|
36
|
+
className: "flex items-center gap-1 h-9 px-3",
|
|
37
|
+
children: [
|
|
38
|
+
localSelectedIds.length === dataLength && dataLength > 0 ? /* @__PURE__ */ jsx(CheckSquare, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx(Square, { className: "h-4 w-4" }),
|
|
39
|
+
/* @__PURE__ */ jsx("span", { className: "hidden sm:inline", children: labels.selectAll }),
|
|
40
|
+
/* @__PURE__ */ jsx("span", { className: "sm:hidden", children: labels.selectAllShort })
|
|
41
|
+
]
|
|
42
|
+
}
|
|
43
|
+
),
|
|
44
|
+
/* @__PURE__ */ jsx("span", { className: "text-sm text-muted-foreground", children: formatLabel(labels.selected, { count: localSelectedIds.length, total: dataLength }) })
|
|
45
|
+
] }) }),
|
|
46
|
+
localSelectedIds.length > 0 && /* @__PURE__ */ jsx("div", { className: "grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-6 gap-2", children: bulkActions.map((action) => {
|
|
47
|
+
var _a;
|
|
48
|
+
const isLoading = bulkActionLoading === action.key;
|
|
49
|
+
const isDisabled = !!bulkActionLoading || ((_a = action.disabled) == null ? void 0 : _a.call(action, localSelectedIds)) || localSelectedIds.length === 0;
|
|
50
|
+
return /* @__PURE__ */ jsxs(
|
|
51
|
+
Button,
|
|
52
|
+
{
|
|
53
|
+
"data-testid": `bulk-action-${action.key}`,
|
|
54
|
+
variant: action.variant || "outline",
|
|
55
|
+
size: "sm",
|
|
56
|
+
onClick: () => onBulkAction(action),
|
|
57
|
+
disabled: isDisabled,
|
|
58
|
+
className: "flex items-center gap-1 h-9 text-xs",
|
|
59
|
+
children: [
|
|
60
|
+
isLoading ? /* @__PURE__ */ jsx(Loader2, { className: "h-3 w-3 animate-spin" }) : action.icon,
|
|
61
|
+
/* @__PURE__ */ jsx("span", { className: "hidden sm:inline", children: isLoading ? labels.processing : action.label }),
|
|
62
|
+
/* @__PURE__ */ jsx("span", { className: "sm:hidden", children: isLoading ? "..." : action.label.split(" ")[0] })
|
|
63
|
+
]
|
|
64
|
+
},
|
|
65
|
+
action.key
|
|
66
|
+
);
|
|
67
|
+
}) })
|
|
68
|
+
] }),
|
|
69
|
+
bulkActionLoading && /* @__PURE__ */ jsxs("div", { className: "p-3 bg-muted/50 rounded-lg", children: [
|
|
70
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
|
|
71
|
+
/* @__PURE__ */ jsx(Loader2, { className: "h-4 w-4 animate-spin text-primary" }),
|
|
72
|
+
/* @__PURE__ */ jsx("span", { className: "text-sm text-muted-foreground", children: formatLabel(labels.processingItems, { count: localSelectedIds.length }) })
|
|
73
|
+
] }),
|
|
74
|
+
/* @__PURE__ */ jsx(LoadingBar, { size: "sm", variant: "primary", className: "mt-2" })
|
|
75
|
+
] })
|
|
76
|
+
] });
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export {
|
|
80
|
+
DataTableBulkActions
|
|
81
|
+
};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
// src/components/ui/data-table/types.ts
|
|
2
|
+
var DEFAULT_LABELS = {
|
|
3
|
+
search: "Search",
|
|
4
|
+
filter: "Filter",
|
|
5
|
+
filterActive: "Active",
|
|
6
|
+
clearFilters: "Clear Filters",
|
|
7
|
+
selectAll: "Select All",
|
|
8
|
+
selectAllShort: "All",
|
|
9
|
+
selected: "{count} / {total} selected",
|
|
10
|
+
processing: "Processing...",
|
|
11
|
+
processingItems: "Processing {count} items...",
|
|
12
|
+
loading: "Loading data...",
|
|
13
|
+
perPage: "{size} per page",
|
|
14
|
+
all: "All",
|
|
15
|
+
min: "Min",
|
|
16
|
+
max: "Max",
|
|
17
|
+
previous: "Previous",
|
|
18
|
+
next: "Next",
|
|
19
|
+
showing: "Showing {start} to {end} of {total} results"
|
|
20
|
+
};
|
|
21
|
+
function formatLabel(template, values) {
|
|
22
|
+
return Object.entries(values).reduce(
|
|
23
|
+
(result, [key, value]) => result.replace(new RegExp(`\\{${key}\\}`, "g"), String(value)),
|
|
24
|
+
template
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export {
|
|
29
|
+
DEFAULT_LABELS,
|
|
30
|
+
formatLabel
|
|
31
|
+
};
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Input
|
|
3
|
+
} from "./chunk-RJUVBBZG.js";
|
|
4
|
+
import {
|
|
5
|
+
Label
|
|
6
|
+
} from "./chunk-IJEZ7G7S.js";
|
|
7
|
+
import {
|
|
8
|
+
Select,
|
|
9
|
+
SelectContent,
|
|
10
|
+
SelectItem,
|
|
11
|
+
SelectTrigger,
|
|
12
|
+
SelectValue
|
|
13
|
+
} from "./chunk-WDUFQFDP.js";
|
|
14
|
+
import {
|
|
15
|
+
Button
|
|
16
|
+
} from "./chunk-L25BNU3E.js";
|
|
17
|
+
import {
|
|
18
|
+
cn
|
|
19
|
+
} from "./chunk-62FLBG6B.js";
|
|
20
|
+
import {
|
|
21
|
+
__spreadProps,
|
|
22
|
+
__spreadValues
|
|
23
|
+
} from "./chunk-ORMEWXMH.js";
|
|
24
|
+
|
|
25
|
+
// src/components/ui/data-table/DataTableFilters.tsx
|
|
26
|
+
import { RefreshCw } from "lucide-react";
|
|
27
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
28
|
+
function DataTableFilters({
|
|
29
|
+
filters,
|
|
30
|
+
filterValues,
|
|
31
|
+
onFilterChange,
|
|
32
|
+
onClearFilters,
|
|
33
|
+
hasActiveFilters,
|
|
34
|
+
labels
|
|
35
|
+
}) {
|
|
36
|
+
return /* @__PURE__ */ jsxs("div", { className: "p-2 bg-muted/50 rounded-lg space-y-2", children: [
|
|
37
|
+
/* @__PURE__ */ jsx("div", { className: "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-4", children: filters.map((filter) => {
|
|
38
|
+
var _a, _b, _c, _d, _e;
|
|
39
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("space-y-1", filter.className), children: [
|
|
40
|
+
/* @__PURE__ */ jsx(Label, { className: "text-sm font-medium", children: filter.label }),
|
|
41
|
+
filter.type === "text" && /* @__PURE__ */ jsx(
|
|
42
|
+
Input,
|
|
43
|
+
{
|
|
44
|
+
"data-testid": `filter-${filter.key}`,
|
|
45
|
+
type: "text",
|
|
46
|
+
value: filterValues[filter.key] || "",
|
|
47
|
+
onChange: (e) => onFilterChange == null ? void 0 : onFilterChange(filter.key, e.target.value),
|
|
48
|
+
placeholder: filter.placeholder,
|
|
49
|
+
className: "text-xs"
|
|
50
|
+
}
|
|
51
|
+
),
|
|
52
|
+
filter.type === "select" && /* @__PURE__ */ jsxs(
|
|
53
|
+
Select,
|
|
54
|
+
{
|
|
55
|
+
value: filterValues[filter.key] || "all",
|
|
56
|
+
onValueChange: (value) => onFilterChange == null ? void 0 : onFilterChange(filter.key, value),
|
|
57
|
+
children: [
|
|
58
|
+
/* @__PURE__ */ jsx(SelectTrigger, { "data-testid": `filter-${filter.key}`, className: "text-xs w-full h-9", children: /* @__PURE__ */ jsx(SelectValue, { placeholder: filter.placeholder }) }),
|
|
59
|
+
/* @__PURE__ */ jsxs(SelectContent, { children: [
|
|
60
|
+
/* @__PURE__ */ jsx(SelectItem, { value: "all", children: labels.all }),
|
|
61
|
+
(_a = filter.options) == null ? void 0 : _a.map((option) => /* @__PURE__ */ jsx(SelectItem, { value: option.value, children: option.label }, option.value))
|
|
62
|
+
] })
|
|
63
|
+
]
|
|
64
|
+
}
|
|
65
|
+
),
|
|
66
|
+
filter.type === "date" && /* @__PURE__ */ jsx(
|
|
67
|
+
Input,
|
|
68
|
+
{
|
|
69
|
+
type: "date",
|
|
70
|
+
value: filterValues[filter.key] || "",
|
|
71
|
+
onChange: (e) => onFilterChange == null ? void 0 : onFilterChange(filter.key, e.target.value),
|
|
72
|
+
className: "text-xs"
|
|
73
|
+
}
|
|
74
|
+
),
|
|
75
|
+
filter.type === "number" && /* @__PURE__ */ jsx(
|
|
76
|
+
Input,
|
|
77
|
+
{
|
|
78
|
+
type: "number",
|
|
79
|
+
value: filterValues[filter.key] || "",
|
|
80
|
+
onChange: (e) => onFilterChange == null ? void 0 : onFilterChange(filter.key, e.target.value),
|
|
81
|
+
placeholder: filter.placeholder,
|
|
82
|
+
className: "text-xs"
|
|
83
|
+
}
|
|
84
|
+
),
|
|
85
|
+
filter.type === "range" && /* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
|
|
86
|
+
/* @__PURE__ */ jsx(
|
|
87
|
+
Input,
|
|
88
|
+
{
|
|
89
|
+
type: filter.inputType || "text",
|
|
90
|
+
value: ((_b = filterValues[filter.key]) == null ? void 0 : _b.min) || ((_c = filterValues[filter.key]) == null ? void 0 : _c.start) || "",
|
|
91
|
+
onChange: (e) => {
|
|
92
|
+
const currentValue = filterValues[filter.key] || {};
|
|
93
|
+
const newValue = filter.key.includes("date") || filter.key.includes("Date") ? __spreadProps(__spreadValues({}, currentValue), { start: e.target.value }) : __spreadProps(__spreadValues({}, currentValue), { min: e.target.value });
|
|
94
|
+
onFilterChange == null ? void 0 : onFilterChange(filter.key, newValue);
|
|
95
|
+
},
|
|
96
|
+
className: "text-xs",
|
|
97
|
+
placeholder: filter.minPlaceholder || labels.min
|
|
98
|
+
}
|
|
99
|
+
),
|
|
100
|
+
/* @__PURE__ */ jsx(
|
|
101
|
+
Input,
|
|
102
|
+
{
|
|
103
|
+
type: filter.inputType || "text",
|
|
104
|
+
value: ((_d = filterValues[filter.key]) == null ? void 0 : _d.max) || ((_e = filterValues[filter.key]) == null ? void 0 : _e.end) || "",
|
|
105
|
+
onChange: (e) => {
|
|
106
|
+
const currentValue = filterValues[filter.key] || {};
|
|
107
|
+
const newValue = filter.key.includes("date") || filter.key.includes("Date") ? __spreadProps(__spreadValues({}, currentValue), { end: e.target.value }) : __spreadProps(__spreadValues({}, currentValue), { max: e.target.value });
|
|
108
|
+
onFilterChange == null ? void 0 : onFilterChange(filter.key, newValue);
|
|
109
|
+
},
|
|
110
|
+
className: "text-xs",
|
|
111
|
+
placeholder: filter.maxPlaceholder || labels.max
|
|
112
|
+
}
|
|
113
|
+
)
|
|
114
|
+
] })
|
|
115
|
+
] }, filter.key);
|
|
116
|
+
}) }),
|
|
117
|
+
hasActiveFilters && onClearFilters && /* @__PURE__ */ jsx("div", { className: "flex justify-end", children: /* @__PURE__ */ jsxs(
|
|
118
|
+
Button,
|
|
119
|
+
{
|
|
120
|
+
"data-testid": "clear-filters-btn",
|
|
121
|
+
variant: "outline",
|
|
122
|
+
size: "sm",
|
|
123
|
+
onClick: onClearFilters,
|
|
124
|
+
className: "flex items-center gap-2",
|
|
125
|
+
children: [
|
|
126
|
+
/* @__PURE__ */ jsx(RefreshCw, { className: "h-4 w-4" }),
|
|
127
|
+
labels.clearFilters
|
|
128
|
+
]
|
|
129
|
+
}
|
|
130
|
+
) })
|
|
131
|
+
] });
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
export {
|
|
135
|
+
DataTableFilters
|
|
136
|
+
};
|
|
@@ -1,103 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
selected?: string;
|
|
10
|
-
processing?: string;
|
|
11
|
-
processingItems?: string;
|
|
12
|
-
loading?: string;
|
|
13
|
-
perPage?: string;
|
|
14
|
-
all?: string;
|
|
15
|
-
min?: string;
|
|
16
|
-
max?: string;
|
|
17
|
-
previous?: string;
|
|
18
|
-
next?: string;
|
|
19
|
-
showing?: string;
|
|
20
|
-
}
|
|
21
|
-
export interface ColumnDef<T> {
|
|
22
|
-
key: string;
|
|
23
|
-
header: string;
|
|
24
|
-
accessorKey?: keyof T;
|
|
25
|
-
cell?: (item: T) => React.ReactNode;
|
|
26
|
-
sortable?: boolean;
|
|
27
|
-
width?: string;
|
|
28
|
-
className?: string;
|
|
29
|
-
hidden?: boolean;
|
|
30
|
-
responsive?: {
|
|
31
|
-
sm?: boolean;
|
|
32
|
-
md?: boolean;
|
|
33
|
-
lg?: boolean;
|
|
34
|
-
xl?: boolean;
|
|
35
|
-
};
|
|
36
|
-
}
|
|
37
|
-
export interface BulkAction {
|
|
38
|
-
key: string;
|
|
39
|
-
label: string;
|
|
40
|
-
icon?: React.ReactNode;
|
|
41
|
-
variant?: "default" | "destructive" | "outline" | "secondary" | "ghost" | "link";
|
|
42
|
-
onClick: (selectedIds: string[]) => Promise<void>;
|
|
43
|
-
disabled?: (selectedIds: string[]) => boolean;
|
|
44
|
-
}
|
|
45
|
-
export interface FilterConfig {
|
|
46
|
-
key: string;
|
|
47
|
-
label: string;
|
|
48
|
-
type: 'text' | 'select' | 'date' | 'number' | 'switch' | 'range';
|
|
49
|
-
options?: {
|
|
50
|
-
value: string;
|
|
51
|
-
label: string;
|
|
52
|
-
}[];
|
|
53
|
-
placeholder?: string;
|
|
54
|
-
className?: string;
|
|
55
|
-
inputType?: 'text' | 'number' | 'date';
|
|
56
|
-
minPlaceholder?: string;
|
|
57
|
-
maxPlaceholder?: string;
|
|
58
|
-
}
|
|
59
|
-
export interface PaginationConfig {
|
|
60
|
-
page: number;
|
|
61
|
-
pageSize: number;
|
|
62
|
-
total: number;
|
|
63
|
-
pageSizeOptions?: number[];
|
|
64
|
-
onPageChange: (page: number) => void;
|
|
65
|
-
onPageSizeChange: (pageSize: number) => void;
|
|
66
|
-
}
|
|
67
|
-
export interface SortConfig {
|
|
68
|
-
sort: string;
|
|
69
|
-
order: 'asc' | 'desc';
|
|
70
|
-
onSortChange: (sort: string, order: 'asc' | 'desc') => void;
|
|
71
|
-
}
|
|
72
|
-
export interface DataTableProps<T> {
|
|
73
|
-
data: T[];
|
|
74
|
-
columns: ColumnDef<T>[];
|
|
75
|
-
loading?: boolean;
|
|
76
|
-
error?: string | null;
|
|
77
|
-
pagination?: PaginationConfig;
|
|
78
|
-
sort?: SortConfig;
|
|
79
|
-
bulkActions?: BulkAction[];
|
|
80
|
-
filters?: FilterConfig[];
|
|
81
|
-
filterValues?: Record<string, any>;
|
|
82
|
-
onFilterChange?: (key: string, value: any) => void;
|
|
83
|
-
onClearFilters?: () => void;
|
|
84
|
-
selectable?: boolean;
|
|
85
|
-
onSelectionChange?: (selectedIds: string[]) => void;
|
|
86
|
-
selectedIds?: string[];
|
|
87
|
-
getRowId: (item: T) => string;
|
|
88
|
-
className?: string;
|
|
89
|
-
emptyMessage?: string;
|
|
90
|
-
searchPlaceholder?: string;
|
|
91
|
-
onSearch?: (search: string) => void;
|
|
92
|
-
onSearchValueChange?: (searchValue: string) => void;
|
|
93
|
-
searchValue?: string;
|
|
94
|
-
showFilters?: boolean;
|
|
95
|
-
onToggleFilters?: (show: boolean) => void;
|
|
96
|
-
createButton?: ReactNode | {
|
|
97
|
-
label: string;
|
|
98
|
-
onClick: () => void;
|
|
99
|
-
};
|
|
100
|
-
/** i18n labels - 미제공 시 영어 기본값 사용 */
|
|
101
|
-
labels?: Partial<DataTableLabels>;
|
|
102
|
-
}
|
|
103
|
-
export declare function DataTable<T>({ data, columns, loading, error, pagination, sort, bulkActions, filters, filterValues, onFilterChange, onClearFilters, selectable, onSelectionChange, selectedIds, getRowId, className, emptyMessage, searchPlaceholder, onSearch, onSearchValueChange, searchValue, showFilters, onToggleFilters, createButton, labels: customLabels, }: DataTableProps<T>): import("react/jsx-runtime").JSX.Element;
|
|
1
|
+
/**
|
|
2
|
+
* DataTable
|
|
3
|
+
*
|
|
4
|
+
* 하위 호환성을 위한 re-export wrapper
|
|
5
|
+
* 실제 구현은 ./data-table/ 디렉토리에 위치
|
|
6
|
+
*/
|
|
7
|
+
export { DataTable } from "./data-table";
|
|
8
|
+
export type { DataTableLabels, ColumnDef, BulkAction, FilterConfig, PaginationConfig, SortConfig, DataTableProps, } from "./data-table";
|