@withwiz/toolkit 0.2.0 → 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.
Files changed (38) hide show
  1. package/dist/auth/index.js +18 -18
  2. package/dist/chunk-6JZQE7ZQ.js +225 -0
  3. package/dist/chunk-7IY3RQQL.js +151 -0
  4. package/dist/{chunk-SLG26KHZ.js → chunk-FH6E36YZ.js} +1 -1
  5. package/dist/chunk-IPXPCBDO.js +127 -0
  6. package/dist/chunk-KHYY4KCV.js +110 -0
  7. package/dist/chunk-MAATEX2R.js +81 -0
  8. package/dist/chunk-NY5QXT33.js +31 -0
  9. package/dist/chunk-SEZJN4TC.js +136 -0
  10. package/dist/components/ui/DataTable.d.ts +8 -103
  11. package/dist/components/ui/DataTable.js +17 -602
  12. package/dist/components/ui/data-table/DataTable.d.ts +2 -0
  13. package/dist/components/ui/data-table/DataTable.js +22 -0
  14. package/dist/components/ui/data-table/DataTableBody.d.ts +19 -0
  15. package/dist/components/ui/data-table/DataTableBody.js +10 -0
  16. package/dist/components/ui/data-table/DataTableBulkActions.d.ts +17 -0
  17. package/dist/components/ui/data-table/DataTableBulkActions.js +12 -0
  18. package/dist/components/ui/data-table/DataTableFilters.d.ts +15 -0
  19. package/dist/components/ui/data-table/DataTableFilters.js +13 -0
  20. package/dist/components/ui/data-table/DataTablePagination.d.ts +10 -0
  21. package/dist/components/ui/data-table/DataTablePagination.js +11 -0
  22. package/dist/components/ui/data-table/DataTableSearch.d.ts +24 -0
  23. package/dist/components/ui/data-table/DataTableSearch.js +12 -0
  24. package/dist/components/ui/data-table/index.d.ts +13 -0
  25. package/dist/components/ui/data-table/types.d.ts +115 -0
  26. package/dist/constants/index.js +13 -13
  27. package/dist/error/hooks/index.js +2 -2
  28. package/dist/error/hooks/useErrorHandler.js +2 -2
  29. package/dist/error/index.js +28 -28
  30. package/dist/error/recovery/index.js +5 -5
  31. package/dist/hooks/useDataTable.d.ts +45 -0
  32. package/dist/hooks/useDataTable.js +13 -11
  33. package/dist/middleware/error-handler.js +2 -2
  34. package/dist/middleware/index.js +3 -3
  35. package/dist/middleware/wrappers.js +3 -3
  36. package/package.json +3 -1
  37. package/dist/{chunk-TMVS4F7E.js → chunk-5OWZKYWQ.js} +3 -3
  38. package/dist/{chunk-IAJNC34M.js → chunk-6UAYU5NU.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
- import { ReactNode } from "react";
2
- export interface DataTableLabels {
3
- search?: string;
4
- filter?: string;
5
- filterActive?: string;
6
- clearFilters?: string;
7
- selectAll?: string;
8
- selectAllShort?: string;
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";