@acmekit/dashboard 2.13.7 → 2.13.9
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/api-key-management-create-VWUERPPB.mjs +170 -0
- package/dist/api-key-management-detail-V4ENQHYY.mjs +306 -0
- package/dist/api-key-management-edit-R44OHS7B.mjs +106 -0
- package/dist/api-key-management-list-K2XPKF5E.mjs +400 -0
- package/dist/app.js +16765 -1370
- package/dist/app.mjs +786 -1030
- package/dist/chunk-22YYMH6M.mjs +382 -0
- package/dist/chunk-2U3RK3JG.mjs +474 -0
- package/dist/chunk-535OVBXR.mjs +226 -0
- package/dist/chunk-774WSTCC.mjs +19 -0
- package/dist/chunk-C76H5USB.mjs +16 -0
- package/dist/chunk-DFFLVEZ5.mjs +40 -0
- package/dist/chunk-DN3MIYQH.mjs +140 -0
- package/dist/chunk-DQCEH3X2.mjs +28 -0
- package/dist/chunk-DTY37DDZ.mjs +20 -0
- package/dist/chunk-EFRMWHRX.mjs +84 -0
- package/dist/chunk-FXYH54JP.mjs +16 -0
- package/dist/chunk-G22WWLPG.mjs +44 -0
- package/dist/chunk-G2VJOHHV.mjs +32 -0
- package/dist/chunk-GBFVWROS.mjs +58 -0
- package/dist/chunk-ITNQKZQQ.mjs +142 -0
- package/dist/chunk-IUCDCPJU.mjs +0 -0
- package/dist/chunk-LKWTBYYC.mjs +35 -0
- package/dist/{chunk-4VYJHIB3.mjs → chunk-ND3ODI36.mjs} +0 -72
- package/dist/chunk-OAHCJFG3.mjs +17 -0
- package/dist/chunk-RPAL6FHW.mjs +73 -0
- package/dist/{chunk-JSJZMTQG.mjs → chunk-RREPQMYC.mjs} +14 -41
- package/dist/chunk-S3REQHPQ.mjs +86 -0
- package/dist/chunk-S4DMV3ZT.mjs +35 -0
- package/dist/chunk-ST2YB7JN.mjs +74 -0
- package/dist/chunk-TCNCAWYD.mjs +9 -0
- package/dist/chunk-ULSPL3DR.mjs +126 -0
- package/dist/chunk-WILMJYUB.mjs +35 -0
- package/dist/chunk-XIM7X4FB.mjs +83 -0
- package/dist/chunk-YLPAZ2DP.mjs +1837 -0
- package/dist/chunk-YRWSG3YM.mjs +80 -0
- package/dist/{invite-S5USGDOZ.mjs → invite-XGPZZBUP.mjs} +15 -7
- package/dist/{login-AIMR26AL.mjs → login-GNP3QIPI.mjs} +25 -12
- package/dist/profile-detail-YX27F7N6.mjs +96 -0
- package/dist/profile-edit-2VRDU75O.mjs +173 -0
- package/dist/{reset-password-UQPRHMB3.mjs → reset-password-TWRNZO6Z.mjs} +7 -3
- package/dist/settings-3XWLL5LG.mjs +545 -0
- package/dist/translation-list-CCEQJNED.mjs +581 -0
- package/dist/translations-edit-E57GVUFV.mjs +5376 -0
- package/dist/user-detail-KUSRRVNX.mjs +169 -0
- package/dist/user-edit-HTN3ZGCL.mjs +114 -0
- package/dist/user-invite-E3FAAU3V.mjs +361 -0
- package/dist/user-list-KNJ5S3IM.mjs +1116 -0
- package/dist/user-metadata-5GQK75DT.mjs +425 -0
- package/dist/workflow-execution-detail-LZXCRVNC.mjs +819 -0
- package/dist/workflow-execution-list-HQ3V6TML.mjs +175 -0
- package/package.json +9 -9
- package/src/components/layout/settings-layout/settings-layout.tsx +8 -2
- package/src/dashboard-app/routes/get-route.map.tsx +1 -14
- package/src/hooks/api/api-keys.tsx +0 -49
- package/src/hooks/api/index.ts +0 -1
- package/src/providers/keybind-provider/hooks.tsx +0 -145
- package/src/routes/translations/translation-list/translation-list.tsx +10 -21
- package/src/routes/translations/translations-edit/translations-edit.tsx +14 -11
- package/src/vite-env.d.ts +3 -1
- package/dist/chunk-FBTP4AJM.mjs +0 -221
- package/dist/chunk-QYOO4QR6.mjs +0 -73
- package/src/components/data-table/helpers/sales-channels/index.ts +0 -4
- package/src/components/data-table/helpers/sales-channels/use-sales-channel-table-columns.tsx +0 -61
- package/src/components/data-table/helpers/sales-channels/use-sales-channel-table-empty-state.tsx +0 -22
- package/src/components/data-table/helpers/sales-channels/use-sales-channel-table-filters.tsx +0 -33
- package/src/components/data-table/helpers/sales-channels/use-sales-channel-table-query.tsx +0 -30
- package/src/routes/api-key-management/api-key-management-detail/components/api-key-sales-channel-section/api-key-sales-channel-section.tsx +0 -206
- package/src/routes/api-key-management/api-key-management-detail/components/api-key-sales-channel-section/index.ts +0 -1
- package/src/routes/store/common/hooks/use-currencies-table-columns.tsx +0 -29
- package/src/routes/store/common/hooks/use-currencies-table-query.tsx +0 -21
- package/src/routes/store/common/hooks/use-locales-table-columns.tsx +0 -29
- package/src/routes/store/common/hooks/use-locales-table-query.tsx +0 -21
- package/src/routes/store/store-detail/components/store-general-section/index.ts +0 -1
- package/src/routes/store/store-detail/components/store-general-section/store-general-section.tsx +0 -48
- package/src/routes/store/store-detail/index.ts +0 -2
- package/src/routes/store/store-detail/loader.ts +0 -18
- package/src/routes/store/store-detail/store-detail.tsx +0 -42
- package/src/routes/store/store-edit/components/edit-store-form/edit-store-form.tsx +0 -83
- package/src/routes/store/store-edit/index.ts +0 -1
- package/src/routes/store/store-edit/store-edit.tsx +0 -25
- package/src/routes/store/store-metadata/index.ts +0 -1
- package/src/routes/store/store-metadata/store-metadata.tsx +0 -24
|
@@ -0,0 +1,1837 @@
|
|
|
1
|
+
import {
|
|
2
|
+
useDate
|
|
3
|
+
} from "./chunk-DFFLVEZ5.mjs";
|
|
4
|
+
import {
|
|
5
|
+
TableSkeleton
|
|
6
|
+
} from "./chunk-ITNQKZQQ.mjs";
|
|
7
|
+
import {
|
|
8
|
+
useDocumentDirection
|
|
9
|
+
} from "./chunk-S4DMV3ZT.mjs";
|
|
10
|
+
|
|
11
|
+
// src/components/table/data-table/data-table.tsx
|
|
12
|
+
import { clx as clx9 } from "@acmekit/ui";
|
|
13
|
+
import { memo } from "react";
|
|
14
|
+
|
|
15
|
+
// src/components/common/empty-table-content/empty-table-content.tsx
|
|
16
|
+
import { ExclamationCircle, MagnifyingGlass, PlusMini } from "@acmekit/icons";
|
|
17
|
+
import { Button, Text, clx } from "@acmekit/ui";
|
|
18
|
+
import { useTranslation } from "react-i18next";
|
|
19
|
+
import { Link } from "react-router-dom";
|
|
20
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
21
|
+
var NoResults = ({ title, message, className }) => {
|
|
22
|
+
const { t: t2 } = useTranslation();
|
|
23
|
+
return /* @__PURE__ */ jsx(
|
|
24
|
+
"div",
|
|
25
|
+
{
|
|
26
|
+
className: clx(
|
|
27
|
+
"flex h-[400px] w-full items-center justify-center",
|
|
28
|
+
className
|
|
29
|
+
),
|
|
30
|
+
children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-y-2", children: [
|
|
31
|
+
/* @__PURE__ */ jsx(MagnifyingGlass, {}),
|
|
32
|
+
/* @__PURE__ */ jsx(Text, { size: "small", leading: "compact", weight: "plus", children: title ?? t2("general.noResultsTitle") }),
|
|
33
|
+
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: message ?? t2("general.noResultsMessage") })
|
|
34
|
+
] })
|
|
35
|
+
}
|
|
36
|
+
);
|
|
37
|
+
};
|
|
38
|
+
var DefaultButton = ({ action }) => action && /* @__PURE__ */ jsx(Link, { to: action.to, children: /* @__PURE__ */ jsx(Button, { variant: "secondary", size: "small", children: action.label }) });
|
|
39
|
+
var TransparentIconLeftButton = ({ action }) => action && /* @__PURE__ */ jsx(Link, { to: action.to, children: /* @__PURE__ */ jsxs(Button, { variant: "transparent", className: "text-ui-fg-interactive", children: [
|
|
40
|
+
/* @__PURE__ */ jsx(PlusMini, {}),
|
|
41
|
+
" ",
|
|
42
|
+
action.label
|
|
43
|
+
] }) });
|
|
44
|
+
var NoRecords = ({
|
|
45
|
+
title,
|
|
46
|
+
message,
|
|
47
|
+
action,
|
|
48
|
+
className,
|
|
49
|
+
buttonVariant = "default",
|
|
50
|
+
icon = /* @__PURE__ */ jsx(ExclamationCircle, { className: "text-ui-fg-subtle" })
|
|
51
|
+
}) => {
|
|
52
|
+
const { t: t2 } = useTranslation();
|
|
53
|
+
return /* @__PURE__ */ jsxs(
|
|
54
|
+
"div",
|
|
55
|
+
{
|
|
56
|
+
className: clx(
|
|
57
|
+
"flex h-[150px] w-full flex-col items-center justify-center gap-y-4",
|
|
58
|
+
className
|
|
59
|
+
),
|
|
60
|
+
children: [
|
|
61
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-y-3", children: [
|
|
62
|
+
icon,
|
|
63
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-y-1", children: [
|
|
64
|
+
/* @__PURE__ */ jsx(Text, { size: "small", leading: "compact", weight: "plus", children: title ?? t2("general.noRecordsTitle") }),
|
|
65
|
+
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: message ?? t2("general.noRecordsMessage") })
|
|
66
|
+
] })
|
|
67
|
+
] }),
|
|
68
|
+
buttonVariant === "default" && /* @__PURE__ */ jsx(DefaultButton, { action }),
|
|
69
|
+
buttonVariant === "transparentIconLeft" && /* @__PURE__ */ jsx(TransparentIconLeftButton, { action })
|
|
70
|
+
]
|
|
71
|
+
}
|
|
72
|
+
);
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
// src/components/table/data-table/data-table-filter/data-table-filter.tsx
|
|
76
|
+
import { Button as Button2, clx as clx7 } from "@acmekit/ui";
|
|
77
|
+
import { Popover as RadixPopover6 } from "radix-ui";
|
|
78
|
+
import { useCallback as useCallback3, useEffect as useEffect3, useMemo as useMemo2, useRef, useState as useState5 } from "react";
|
|
79
|
+
import { useSearchParams as useSearchParams2 } from "react-router-dom";
|
|
80
|
+
import { useTranslation as useTranslation6 } from "react-i18next";
|
|
81
|
+
|
|
82
|
+
// src/components/table/data-table/data-table-filter/context.tsx
|
|
83
|
+
import { createContext, useContext } from "react";
|
|
84
|
+
var DataTableFilterContext = createContext(null);
|
|
85
|
+
var useDataTableFilterContext = () => {
|
|
86
|
+
const ctx = useContext(DataTableFilterContext);
|
|
87
|
+
if (!ctx) {
|
|
88
|
+
throw new Error(
|
|
89
|
+
"useDataTableFacetedFilterContext must be used within a DataTableFacetedFilter"
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
return ctx;
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
// src/components/table/data-table/data-table-filter/date-filter.tsx
|
|
96
|
+
import { EllipseMiniSolid } from "@acmekit/icons";
|
|
97
|
+
import { DatePicker, Text as Text3, clx as clx3 } from "@acmekit/ui";
|
|
98
|
+
import isEqual from "lodash.isequal";
|
|
99
|
+
import { Popover as RadixPopover2 } from "radix-ui";
|
|
100
|
+
import { useMemo, useState } from "react";
|
|
101
|
+
import { t } from "i18next";
|
|
102
|
+
import { useTranslation as useTranslation3 } from "react-i18next";
|
|
103
|
+
|
|
104
|
+
// src/components/table/data-table/hooks.tsx
|
|
105
|
+
import { useSearchParams } from "react-router-dom";
|
|
106
|
+
var useSelectedParams = ({
|
|
107
|
+
param,
|
|
108
|
+
prefix,
|
|
109
|
+
multiple = false
|
|
110
|
+
}) => {
|
|
111
|
+
const [searchParams, setSearchParams] = useSearchParams();
|
|
112
|
+
const identifier = prefix ? `${prefix}_${param}` : param;
|
|
113
|
+
const offsetKey = prefix ? `${prefix}_offset` : "offset";
|
|
114
|
+
const add = (value) => {
|
|
115
|
+
setSearchParams((prev) => {
|
|
116
|
+
const newValue = new URLSearchParams(prev);
|
|
117
|
+
const updateMultipleValues = () => {
|
|
118
|
+
const existingValues = newValue.get(identifier)?.split(",") || [];
|
|
119
|
+
if (!existingValues.includes(value)) {
|
|
120
|
+
existingValues.push(value);
|
|
121
|
+
newValue.set(identifier, existingValues.join(","));
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
const updateSingleValue = () => {
|
|
125
|
+
newValue.set(identifier, value);
|
|
126
|
+
};
|
|
127
|
+
multiple ? updateMultipleValues() : updateSingleValue();
|
|
128
|
+
newValue.delete(offsetKey);
|
|
129
|
+
return newValue;
|
|
130
|
+
});
|
|
131
|
+
};
|
|
132
|
+
const deleteParam = (value) => {
|
|
133
|
+
const deleteMultipleValues = (prev) => {
|
|
134
|
+
const existingValues = prev.get(identifier)?.split(",") || [];
|
|
135
|
+
const index = existingValues.indexOf(value || "");
|
|
136
|
+
if (index > -1) {
|
|
137
|
+
existingValues.splice(index, 1);
|
|
138
|
+
prev.set(identifier, existingValues.join(","));
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
const deleteSingleValue = (prev) => {
|
|
142
|
+
prev.delete(identifier);
|
|
143
|
+
};
|
|
144
|
+
setSearchParams((prev) => {
|
|
145
|
+
if (value) {
|
|
146
|
+
multiple ? deleteMultipleValues(prev) : deleteSingleValue(prev);
|
|
147
|
+
if (!prev.get(identifier)) {
|
|
148
|
+
prev.delete(identifier);
|
|
149
|
+
}
|
|
150
|
+
} else {
|
|
151
|
+
prev.delete(identifier);
|
|
152
|
+
}
|
|
153
|
+
prev.delete(offsetKey);
|
|
154
|
+
return prev;
|
|
155
|
+
});
|
|
156
|
+
};
|
|
157
|
+
const get = () => {
|
|
158
|
+
return searchParams.get(identifier)?.split(",").filter(Boolean) || [];
|
|
159
|
+
};
|
|
160
|
+
return { add, delete: deleteParam, get };
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
// src/components/table/data-table/data-table-filter/filter-chip.tsx
|
|
164
|
+
import { XMarkMini } from "@acmekit/icons";
|
|
165
|
+
import { Text as Text2, clx as clx2 } from "@acmekit/ui";
|
|
166
|
+
import { Popover as RadixPopover } from "radix-ui";
|
|
167
|
+
import { useTranslation as useTranslation2 } from "react-i18next";
|
|
168
|
+
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
169
|
+
var FilterChip = ({
|
|
170
|
+
hadPreviousValue,
|
|
171
|
+
label,
|
|
172
|
+
value,
|
|
173
|
+
readonly,
|
|
174
|
+
hasOperator,
|
|
175
|
+
onRemove
|
|
176
|
+
}) => {
|
|
177
|
+
const { t: t2 } = useTranslation2();
|
|
178
|
+
const handleRemove = (e) => {
|
|
179
|
+
e.stopPropagation();
|
|
180
|
+
onRemove();
|
|
181
|
+
};
|
|
182
|
+
return /* @__PURE__ */ jsxs2("div", { className: "bg-ui-bg-field transition-fg shadow-borders-base text-ui-fg-subtle flex cursor-default select-none items-stretch overflow-hidden rounded-md", children: [
|
|
183
|
+
!hadPreviousValue && /* @__PURE__ */ jsx2(RadixPopover.Anchor, {}),
|
|
184
|
+
/* @__PURE__ */ jsx2(
|
|
185
|
+
"div",
|
|
186
|
+
{
|
|
187
|
+
className: clx2(
|
|
188
|
+
"flex items-center justify-center whitespace-nowrap px-2 py-1",
|
|
189
|
+
{
|
|
190
|
+
"border-r": !!(value || hadPreviousValue)
|
|
191
|
+
}
|
|
192
|
+
),
|
|
193
|
+
children: /* @__PURE__ */ jsx2(Text2, { size: "small", weight: "plus", leading: "compact", children: label })
|
|
194
|
+
}
|
|
195
|
+
),
|
|
196
|
+
/* @__PURE__ */ jsxs2("div", { className: "flex w-full items-center overflow-hidden", children: [
|
|
197
|
+
hasOperator && !!(value || hadPreviousValue) && /* @__PURE__ */ jsx2("div", { className: "border-r p-1 px-2", children: /* @__PURE__ */ jsx2(
|
|
198
|
+
Text2,
|
|
199
|
+
{
|
|
200
|
+
size: "small",
|
|
201
|
+
weight: "plus",
|
|
202
|
+
leading: "compact",
|
|
203
|
+
className: "text-ui-fg-muted",
|
|
204
|
+
children: t2("general.is")
|
|
205
|
+
}
|
|
206
|
+
) }),
|
|
207
|
+
!!(value || hadPreviousValue) && /* @__PURE__ */ jsx2(
|
|
208
|
+
RadixPopover.Trigger,
|
|
209
|
+
{
|
|
210
|
+
asChild: true,
|
|
211
|
+
className: clx2(
|
|
212
|
+
"flex-1 cursor-pointer overflow-hidden border-r p-1 px-2",
|
|
213
|
+
{
|
|
214
|
+
"hover:bg-ui-bg-field-hover": !readonly,
|
|
215
|
+
"data-[state=open]:bg-ui-bg-field-hover": !readonly
|
|
216
|
+
}
|
|
217
|
+
),
|
|
218
|
+
children: /* @__PURE__ */ jsx2(
|
|
219
|
+
Text2,
|
|
220
|
+
{
|
|
221
|
+
size: "small",
|
|
222
|
+
leading: "compact",
|
|
223
|
+
weight: "plus",
|
|
224
|
+
className: "truncate text-nowrap",
|
|
225
|
+
children: value || "\xA0"
|
|
226
|
+
}
|
|
227
|
+
)
|
|
228
|
+
}
|
|
229
|
+
)
|
|
230
|
+
] }),
|
|
231
|
+
!readonly && !!(value || hadPreviousValue) && /* @__PURE__ */ jsx2(
|
|
232
|
+
"button",
|
|
233
|
+
{
|
|
234
|
+
onClick: handleRemove,
|
|
235
|
+
className: clx2(
|
|
236
|
+
"text-ui-fg-muted transition-fg flex items-center justify-center p-1",
|
|
237
|
+
"hover:bg-ui-bg-subtle-hover",
|
|
238
|
+
"active:bg-ui-bg-subtle-pressed active:text-ui-fg-base"
|
|
239
|
+
),
|
|
240
|
+
children: /* @__PURE__ */ jsx2(XMarkMini, {})
|
|
241
|
+
}
|
|
242
|
+
)
|
|
243
|
+
] });
|
|
244
|
+
};
|
|
245
|
+
var filter_chip_default = FilterChip;
|
|
246
|
+
|
|
247
|
+
// src/components/table/data-table/data-table-filter/date-filter.tsx
|
|
248
|
+
import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
249
|
+
var DateFilter = ({
|
|
250
|
+
filter,
|
|
251
|
+
prefix,
|
|
252
|
+
readonly,
|
|
253
|
+
openOnMount
|
|
254
|
+
}) => {
|
|
255
|
+
const [open, setOpen] = useState(openOnMount);
|
|
256
|
+
const [showCustom, setShowCustom] = useState(false);
|
|
257
|
+
const { getFullDate } = useDate();
|
|
258
|
+
const { key, label } = filter;
|
|
259
|
+
const { removeFilter } = useDataTableFilterContext();
|
|
260
|
+
const selectedParams = useSelectedParams({ param: key, prefix });
|
|
261
|
+
const presets = usePresets();
|
|
262
|
+
const handleSelectPreset = (value) => {
|
|
263
|
+
selectedParams.add(JSON.stringify(value));
|
|
264
|
+
setShowCustom(false);
|
|
265
|
+
};
|
|
266
|
+
const handleSelectCustom = () => {
|
|
267
|
+
selectedParams.delete();
|
|
268
|
+
setShowCustom((prev) => !prev);
|
|
269
|
+
};
|
|
270
|
+
const currentValue = selectedParams.get();
|
|
271
|
+
const currentDateComparison = parseDateComparison(currentValue);
|
|
272
|
+
const customStartValue = getDateFromComparison(currentDateComparison, "$gte");
|
|
273
|
+
const customEndValue = getDateFromComparison(currentDateComparison, "$lte");
|
|
274
|
+
const handleCustomDateChange = (value, pos) => {
|
|
275
|
+
const key2 = pos === "start" ? "$gte" : "$lte";
|
|
276
|
+
let dateValue = value;
|
|
277
|
+
if (key2 === "$lte" && value) {
|
|
278
|
+
dateValue = new Date(value.getTime());
|
|
279
|
+
dateValue.setHours(23, 59, 59, 999);
|
|
280
|
+
}
|
|
281
|
+
selectedParams.add(
|
|
282
|
+
JSON.stringify({
|
|
283
|
+
...currentDateComparison || {},
|
|
284
|
+
[key2]: dateValue?.toISOString()
|
|
285
|
+
})
|
|
286
|
+
);
|
|
287
|
+
};
|
|
288
|
+
const getDisplayValueFromPresets = () => {
|
|
289
|
+
const preset = presets.find((p) => isEqual(p.value, currentDateComparison));
|
|
290
|
+
return preset?.label;
|
|
291
|
+
};
|
|
292
|
+
const formatCustomDate = (date) => {
|
|
293
|
+
return date ? getFullDate({ date }) : void 0;
|
|
294
|
+
};
|
|
295
|
+
const getCustomDisplayValue = () => {
|
|
296
|
+
const formattedDates = [customStartValue, customEndValue].map(
|
|
297
|
+
formatCustomDate
|
|
298
|
+
);
|
|
299
|
+
return formattedDates.filter(Boolean).join(" - ");
|
|
300
|
+
};
|
|
301
|
+
const displayValue = getDisplayValueFromPresets() || getCustomDisplayValue();
|
|
302
|
+
const [previousValue, setPreviousValue] = useState(
|
|
303
|
+
displayValue
|
|
304
|
+
);
|
|
305
|
+
const handleRemove = () => {
|
|
306
|
+
selectedParams.delete();
|
|
307
|
+
removeFilter(key);
|
|
308
|
+
};
|
|
309
|
+
let timeoutId = null;
|
|
310
|
+
const handleOpenChange = (open2) => {
|
|
311
|
+
setOpen(open2);
|
|
312
|
+
setPreviousValue(displayValue);
|
|
313
|
+
if (timeoutId) {
|
|
314
|
+
clearTimeout(timeoutId);
|
|
315
|
+
}
|
|
316
|
+
if (!open2 && !currentValue.length) {
|
|
317
|
+
timeoutId = setTimeout(() => {
|
|
318
|
+
removeFilter(key);
|
|
319
|
+
}, 200);
|
|
320
|
+
}
|
|
321
|
+
};
|
|
322
|
+
return /* @__PURE__ */ jsxs3(RadixPopover2.Root, { modal: true, open, onOpenChange: handleOpenChange, children: [
|
|
323
|
+
/* @__PURE__ */ jsx3(
|
|
324
|
+
filter_chip_default,
|
|
325
|
+
{
|
|
326
|
+
hadPreviousValue: !!previousValue,
|
|
327
|
+
label,
|
|
328
|
+
value: displayValue,
|
|
329
|
+
onRemove: handleRemove,
|
|
330
|
+
readonly
|
|
331
|
+
}
|
|
332
|
+
),
|
|
333
|
+
!readonly && /* @__PURE__ */ jsx3(RadixPopover2.Portal, { children: /* @__PURE__ */ jsxs3(
|
|
334
|
+
RadixPopover2.Content,
|
|
335
|
+
{
|
|
336
|
+
"data-name": "date_filter_content",
|
|
337
|
+
align: "start",
|
|
338
|
+
sideOffset: 8,
|
|
339
|
+
collisionPadding: 24,
|
|
340
|
+
className: clx3(
|
|
341
|
+
"bg-ui-bg-base text-ui-fg-base shadow-elevation-flyout h-full max-h-[var(--radix-popper-available-height)] w-[300px] overflow-auto rounded-lg"
|
|
342
|
+
),
|
|
343
|
+
onInteractOutside: (e) => {
|
|
344
|
+
if (e.target instanceof HTMLElement) {
|
|
345
|
+
if (e.target.attributes.getNamedItem("data-name")?.value === "filters_menu_content") {
|
|
346
|
+
e.preventDefault();
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
},
|
|
350
|
+
children: [
|
|
351
|
+
/* @__PURE__ */ jsxs3("ul", { className: "w-full p-1", children: [
|
|
352
|
+
presets.map((preset) => {
|
|
353
|
+
const isSelected = selectedParams.get().includes(JSON.stringify(preset.value));
|
|
354
|
+
return /* @__PURE__ */ jsx3("li", { children: /* @__PURE__ */ jsxs3(
|
|
355
|
+
"button",
|
|
356
|
+
{
|
|
357
|
+
className: "bg-ui-bg-base hover:bg-ui-bg-base-hover focus-visible:bg-ui-bg-base-pressed text-ui-fg-base data-[disabled]:text-ui-fg-disabled txt-compact-small relative flex w-full cursor-pointer select-none items-center rounded-md px-2 py-1.5 outline-none transition-colors data-[disabled]:pointer-events-none",
|
|
358
|
+
type: "button",
|
|
359
|
+
onClick: () => {
|
|
360
|
+
handleSelectPreset(preset.value);
|
|
361
|
+
},
|
|
362
|
+
children: [
|
|
363
|
+
/* @__PURE__ */ jsx3(
|
|
364
|
+
"div",
|
|
365
|
+
{
|
|
366
|
+
className: clx3(
|
|
367
|
+
"transition-fg flex h-5 w-5 items-center justify-center",
|
|
368
|
+
{
|
|
369
|
+
"[&_svg]:invisible": !isSelected
|
|
370
|
+
}
|
|
371
|
+
),
|
|
372
|
+
children: /* @__PURE__ */ jsx3(EllipseMiniSolid, {})
|
|
373
|
+
}
|
|
374
|
+
),
|
|
375
|
+
preset.label
|
|
376
|
+
]
|
|
377
|
+
}
|
|
378
|
+
) }, preset.label);
|
|
379
|
+
}),
|
|
380
|
+
/* @__PURE__ */ jsx3("li", { children: /* @__PURE__ */ jsxs3(
|
|
381
|
+
"button",
|
|
382
|
+
{
|
|
383
|
+
className: "bg-ui-bg-base hover:bg-ui-bg-base-hover focus-visible:bg-ui-bg-base-pressed text-ui-fg-base data-[disabled]:text-ui-fg-disabled txt-compact-small relative flex w-full cursor-pointer select-none items-center rounded-md px-2 py-1.5 outline-none transition-colors data-[disabled]:pointer-events-none",
|
|
384
|
+
type: "button",
|
|
385
|
+
onClick: handleSelectCustom,
|
|
386
|
+
children: [
|
|
387
|
+
/* @__PURE__ */ jsx3(
|
|
388
|
+
"div",
|
|
389
|
+
{
|
|
390
|
+
className: clx3(
|
|
391
|
+
"transition-fg flex h-5 w-5 items-center justify-center",
|
|
392
|
+
{
|
|
393
|
+
"[&_svg]:invisible": !showCustom
|
|
394
|
+
}
|
|
395
|
+
),
|
|
396
|
+
children: /* @__PURE__ */ jsx3(EllipseMiniSolid, {})
|
|
397
|
+
}
|
|
398
|
+
),
|
|
399
|
+
t("filters.date.custom")
|
|
400
|
+
]
|
|
401
|
+
}
|
|
402
|
+
) })
|
|
403
|
+
] }),
|
|
404
|
+
showCustom && /* @__PURE__ */ jsxs3("div", { className: "border-t px-1 pb-3 pt-1", children: [
|
|
405
|
+
/* @__PURE__ */ jsxs3("div", { children: [
|
|
406
|
+
/* @__PURE__ */ jsx3("div", { className: "px-2 py-1", children: /* @__PURE__ */ jsx3(Text3, { size: "xsmall", leading: "compact", weight: "plus", children: t("filters.date.from") }) }),
|
|
407
|
+
/* @__PURE__ */ jsx3("div", { className: "px-2 py-1", children: /* @__PURE__ */ jsx3(
|
|
408
|
+
DatePicker,
|
|
409
|
+
{
|
|
410
|
+
modal: true,
|
|
411
|
+
maxValue: customEndValue,
|
|
412
|
+
value: customStartValue,
|
|
413
|
+
onChange: (d) => handleCustomDateChange(d, "start")
|
|
414
|
+
}
|
|
415
|
+
) })
|
|
416
|
+
] }),
|
|
417
|
+
/* @__PURE__ */ jsxs3("div", { children: [
|
|
418
|
+
/* @__PURE__ */ jsx3("div", { className: "px-2 py-1", children: /* @__PURE__ */ jsx3(Text3, { size: "xsmall", leading: "compact", weight: "plus", children: t("filters.date.to") }) }),
|
|
419
|
+
/* @__PURE__ */ jsx3("div", { className: "px-2 py-1", children: /* @__PURE__ */ jsx3(
|
|
420
|
+
DatePicker,
|
|
421
|
+
{
|
|
422
|
+
modal: true,
|
|
423
|
+
minValue: customStartValue,
|
|
424
|
+
value: customEndValue || void 0,
|
|
425
|
+
onChange: (d) => {
|
|
426
|
+
handleCustomDateChange(d, "end");
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
) })
|
|
430
|
+
] })
|
|
431
|
+
] })
|
|
432
|
+
]
|
|
433
|
+
}
|
|
434
|
+
) })
|
|
435
|
+
] });
|
|
436
|
+
};
|
|
437
|
+
var today = /* @__PURE__ */ new Date();
|
|
438
|
+
today.setHours(0, 0, 0, 0);
|
|
439
|
+
var usePresets = () => {
|
|
440
|
+
const { t: t2 } = useTranslation3();
|
|
441
|
+
return useMemo(
|
|
442
|
+
() => [
|
|
443
|
+
{
|
|
444
|
+
label: t2("filters.date.today"),
|
|
445
|
+
value: {
|
|
446
|
+
$gte: today.toISOString()
|
|
447
|
+
}
|
|
448
|
+
},
|
|
449
|
+
{
|
|
450
|
+
label: t2("filters.date.lastSevenDays"),
|
|
451
|
+
value: {
|
|
452
|
+
$gte: new Date(
|
|
453
|
+
today.getTime() - 7 * 24 * 60 * 60 * 1e3
|
|
454
|
+
).toISOString()
|
|
455
|
+
// 7 days ago
|
|
456
|
+
}
|
|
457
|
+
},
|
|
458
|
+
{
|
|
459
|
+
label: t2("filters.date.lastThirtyDays"),
|
|
460
|
+
value: {
|
|
461
|
+
$gte: new Date(
|
|
462
|
+
today.getTime() - 30 * 24 * 60 * 60 * 1e3
|
|
463
|
+
).toISOString()
|
|
464
|
+
// 30 days ago
|
|
465
|
+
}
|
|
466
|
+
},
|
|
467
|
+
{
|
|
468
|
+
label: t2("filters.date.lastNinetyDays"),
|
|
469
|
+
value: {
|
|
470
|
+
$gte: new Date(
|
|
471
|
+
today.getTime() - 90 * 24 * 60 * 60 * 1e3
|
|
472
|
+
).toISOString()
|
|
473
|
+
// 90 days ago
|
|
474
|
+
}
|
|
475
|
+
},
|
|
476
|
+
{
|
|
477
|
+
label: t2("filters.date.lastTwelveMonths"),
|
|
478
|
+
value: {
|
|
479
|
+
$gte: new Date(
|
|
480
|
+
today.getTime() - 365 * 24 * 60 * 60 * 1e3
|
|
481
|
+
).toISOString()
|
|
482
|
+
// 365 days ago
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
],
|
|
486
|
+
[t2]
|
|
487
|
+
);
|
|
488
|
+
};
|
|
489
|
+
var parseDateComparison = (value) => {
|
|
490
|
+
return value?.length ? JSON.parse(value.join(",")) : null;
|
|
491
|
+
};
|
|
492
|
+
var getDateFromComparison = (comparison, key) => {
|
|
493
|
+
if (!comparison?.[key]) {
|
|
494
|
+
return void 0;
|
|
495
|
+
}
|
|
496
|
+
const compareDate = new Date(comparison[key]);
|
|
497
|
+
if (key === "$lte") {
|
|
498
|
+
compareDate.setHours(0, 0, 0, 0);
|
|
499
|
+
}
|
|
500
|
+
return compareDate;
|
|
501
|
+
};
|
|
502
|
+
|
|
503
|
+
// src/components/table/data-table/data-table-filter/number-filter.tsx
|
|
504
|
+
import { EllipseMiniSolid as EllipseMiniSolid2 } from "@acmekit/icons";
|
|
505
|
+
import { Input, Label, clx as clx4 } from "@acmekit/ui";
|
|
506
|
+
import debounce from "lodash.debounce";
|
|
507
|
+
import {
|
|
508
|
+
Popover as RadixPopover3,
|
|
509
|
+
RadioGroup as RadixRadioGroup
|
|
510
|
+
} from "radix-ui";
|
|
511
|
+
import { useCallback, useEffect, useState as useState2 } from "react";
|
|
512
|
+
import { useTranslation as useTranslation4 } from "react-i18next";
|
|
513
|
+
import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
514
|
+
var NumberFilter = ({
|
|
515
|
+
filter,
|
|
516
|
+
prefix,
|
|
517
|
+
readonly,
|
|
518
|
+
openOnMount
|
|
519
|
+
}) => {
|
|
520
|
+
const { t: t2 } = useTranslation4();
|
|
521
|
+
const [open, setOpen] = useState2(openOnMount);
|
|
522
|
+
const { key, label } = filter;
|
|
523
|
+
const { removeFilter } = useDataTableFilterContext();
|
|
524
|
+
const selectedParams = useSelectedParams({
|
|
525
|
+
param: key,
|
|
526
|
+
prefix,
|
|
527
|
+
multiple: false
|
|
528
|
+
});
|
|
529
|
+
const currentValue = selectedParams.get();
|
|
530
|
+
const [previousValue, setPreviousValue] = useState2(
|
|
531
|
+
currentValue
|
|
532
|
+
);
|
|
533
|
+
const [operator, setOperator] = useState2(
|
|
534
|
+
getOperator(currentValue)
|
|
535
|
+
);
|
|
536
|
+
const debouncedOnChange = useCallback(
|
|
537
|
+
debounce((e, operator2) => {
|
|
538
|
+
const value = e.target.value;
|
|
539
|
+
const curr = JSON.parse(currentValue?.join(",") || "{}");
|
|
540
|
+
const isCurrentNumber = !isNaN(Number(curr));
|
|
541
|
+
const handleValue = (operator3) => {
|
|
542
|
+
if (!value && isCurrentNumber) {
|
|
543
|
+
selectedParams.delete();
|
|
544
|
+
return;
|
|
545
|
+
}
|
|
546
|
+
if (curr && !value) {
|
|
547
|
+
delete curr[operator3];
|
|
548
|
+
selectedParams.add(JSON.stringify(curr));
|
|
549
|
+
return;
|
|
550
|
+
}
|
|
551
|
+
if (!curr) {
|
|
552
|
+
selectedParams.add(JSON.stringify({ [operator3]: value }));
|
|
553
|
+
return;
|
|
554
|
+
}
|
|
555
|
+
selectedParams.add(JSON.stringify({ ...curr, [operator3]: value }));
|
|
556
|
+
};
|
|
557
|
+
switch (operator2) {
|
|
558
|
+
case "eq":
|
|
559
|
+
if (!value) {
|
|
560
|
+
selectedParams.delete();
|
|
561
|
+
} else {
|
|
562
|
+
selectedParams.add(value);
|
|
563
|
+
}
|
|
564
|
+
break;
|
|
565
|
+
case "lt":
|
|
566
|
+
case "gt":
|
|
567
|
+
handleValue(operator2);
|
|
568
|
+
break;
|
|
569
|
+
}
|
|
570
|
+
}, 500),
|
|
571
|
+
[selectedParams, currentValue]
|
|
572
|
+
);
|
|
573
|
+
useEffect(() => {
|
|
574
|
+
return () => {
|
|
575
|
+
debouncedOnChange.cancel();
|
|
576
|
+
};
|
|
577
|
+
}, [debouncedOnChange]);
|
|
578
|
+
let timeoutId = null;
|
|
579
|
+
const handleOpenChange = (open2) => {
|
|
580
|
+
setOpen(open2);
|
|
581
|
+
setPreviousValue(currentValue);
|
|
582
|
+
if (timeoutId) {
|
|
583
|
+
clearTimeout(timeoutId);
|
|
584
|
+
}
|
|
585
|
+
if (!open2 && !currentValue.length) {
|
|
586
|
+
timeoutId = setTimeout(() => {
|
|
587
|
+
removeFilter(key);
|
|
588
|
+
}, 200);
|
|
589
|
+
}
|
|
590
|
+
};
|
|
591
|
+
const handleRemove = () => {
|
|
592
|
+
selectedParams.delete();
|
|
593
|
+
removeFilter(key);
|
|
594
|
+
};
|
|
595
|
+
const operators = [
|
|
596
|
+
{
|
|
597
|
+
operator: "exact",
|
|
598
|
+
label: t2("filters.compare.exact")
|
|
599
|
+
},
|
|
600
|
+
{
|
|
601
|
+
operator: "range",
|
|
602
|
+
label: t2("filters.compare.range")
|
|
603
|
+
}
|
|
604
|
+
];
|
|
605
|
+
const GT_KEY = `${key}-gt`;
|
|
606
|
+
const LT_KEY = `${key}-lt`;
|
|
607
|
+
const EQ_KEY = key;
|
|
608
|
+
const displayValue = parseDisplayValue(currentValue, t2);
|
|
609
|
+
const previousDisplayValue = parseDisplayValue(previousValue, t2);
|
|
610
|
+
return /* @__PURE__ */ jsxs4(RadixPopover3.Root, { modal: true, open, onOpenChange: handleOpenChange, children: [
|
|
611
|
+
/* @__PURE__ */ jsx4(
|
|
612
|
+
filter_chip_default,
|
|
613
|
+
{
|
|
614
|
+
hasOperator: true,
|
|
615
|
+
hadPreviousValue: !!previousDisplayValue,
|
|
616
|
+
label,
|
|
617
|
+
value: displayValue,
|
|
618
|
+
onRemove: handleRemove,
|
|
619
|
+
readonly
|
|
620
|
+
}
|
|
621
|
+
),
|
|
622
|
+
!readonly && /* @__PURE__ */ jsx4(RadixPopover3.Portal, { children: /* @__PURE__ */ jsxs4(
|
|
623
|
+
RadixPopover3.Content,
|
|
624
|
+
{
|
|
625
|
+
"data-name": "number_filter_content",
|
|
626
|
+
align: "start",
|
|
627
|
+
sideOffset: 8,
|
|
628
|
+
collisionPadding: 24,
|
|
629
|
+
className: clx4(
|
|
630
|
+
"bg-ui-bg-base text-ui-fg-base shadow-elevation-flyout max-h-[var(--radix-popper-available-height)] w-[300px] divide-y overflow-y-auto rounded-lg outline-none"
|
|
631
|
+
),
|
|
632
|
+
onInteractOutside: (e) => {
|
|
633
|
+
if (e.target instanceof HTMLElement) {
|
|
634
|
+
if (e.target.attributes.getNamedItem("data-name")?.value === "filters_menu_content") {
|
|
635
|
+
e.preventDefault();
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
},
|
|
639
|
+
children: [
|
|
640
|
+
/* @__PURE__ */ jsx4("div", { className: "p-1", children: /* @__PURE__ */ jsx4(
|
|
641
|
+
RadixRadioGroup.Root,
|
|
642
|
+
{
|
|
643
|
+
value: operator,
|
|
644
|
+
onValueChange: (val) => setOperator(val),
|
|
645
|
+
className: "flex flex-col items-start",
|
|
646
|
+
orientation: "vertical",
|
|
647
|
+
autoFocus: true,
|
|
648
|
+
children: operators.map((o) => /* @__PURE__ */ jsxs4(
|
|
649
|
+
RadixRadioGroup.Item,
|
|
650
|
+
{
|
|
651
|
+
value: o.operator,
|
|
652
|
+
className: "txt-compact-small hover:bg-ui-bg-base-hover focus-visible:bg-ui-bg-base-hover active:bg-ui-bg-base-pressed transition-fg grid w-full grid-cols-[20px_1fr] gap-2 rounded-[4px] px-2 py-1.5 text-left outline-none",
|
|
653
|
+
children: [
|
|
654
|
+
/* @__PURE__ */ jsx4("div", { className: "size-5", children: /* @__PURE__ */ jsx4(RadixRadioGroup.Indicator, { children: /* @__PURE__ */ jsx4(EllipseMiniSolid2, {}) }) }),
|
|
655
|
+
/* @__PURE__ */ jsx4("span", { className: "w-full", children: o.label })
|
|
656
|
+
]
|
|
657
|
+
},
|
|
658
|
+
o.operator
|
|
659
|
+
))
|
|
660
|
+
}
|
|
661
|
+
) }),
|
|
662
|
+
/* @__PURE__ */ jsx4("div", { children: operator === "range" ? /* @__PURE__ */ jsxs4("div", { className: "px-1 pb-3 pt-1", children: [
|
|
663
|
+
/* @__PURE__ */ jsx4("div", { className: "px-2 py-1.5", children: /* @__PURE__ */ jsx4(Label, { size: "xsmall", weight: "plus", htmlFor: GT_KEY, children: t2("filters.compare.greaterThan") }) }),
|
|
664
|
+
/* @__PURE__ */ jsx4("div", { className: "px-2 py-0.5", children: /* @__PURE__ */ jsx4(
|
|
665
|
+
Input,
|
|
666
|
+
{
|
|
667
|
+
name: GT_KEY,
|
|
668
|
+
size: "small",
|
|
669
|
+
type: "number",
|
|
670
|
+
defaultValue: getValue(currentValue, "gt"),
|
|
671
|
+
onChange: (e) => debouncedOnChange(e, "gt")
|
|
672
|
+
}
|
|
673
|
+
) }),
|
|
674
|
+
/* @__PURE__ */ jsx4("div", { className: "px-2 py-1.5", children: /* @__PURE__ */ jsx4(Label, { size: "xsmall", weight: "plus", htmlFor: LT_KEY, children: t2("filters.compare.lessThan") }) }),
|
|
675
|
+
/* @__PURE__ */ jsx4("div", { className: "px-2 py-0.5", children: /* @__PURE__ */ jsx4(
|
|
676
|
+
Input,
|
|
677
|
+
{
|
|
678
|
+
name: LT_KEY,
|
|
679
|
+
size: "small",
|
|
680
|
+
type: "number",
|
|
681
|
+
defaultValue: getValue(currentValue, "lt"),
|
|
682
|
+
onChange: (e) => debouncedOnChange(e, "lt")
|
|
683
|
+
}
|
|
684
|
+
) })
|
|
685
|
+
] }, "range") : /* @__PURE__ */ jsxs4("div", { className: "px-1 pb-3 pt-1", children: [
|
|
686
|
+
/* @__PURE__ */ jsx4("div", { className: "px-2 py-1.5", children: /* @__PURE__ */ jsx4(Label, { size: "xsmall", weight: "plus", htmlFor: EQ_KEY, children: label }) }),
|
|
687
|
+
/* @__PURE__ */ jsx4("div", { className: "px-2 py-0.5", children: /* @__PURE__ */ jsx4(
|
|
688
|
+
Input,
|
|
689
|
+
{
|
|
690
|
+
name: EQ_KEY,
|
|
691
|
+
size: "small",
|
|
692
|
+
type: "number",
|
|
693
|
+
defaultValue: getValue(currentValue, "eq"),
|
|
694
|
+
onChange: (e) => debouncedOnChange(e, "eq")
|
|
695
|
+
}
|
|
696
|
+
) })
|
|
697
|
+
] }, "exact") })
|
|
698
|
+
]
|
|
699
|
+
}
|
|
700
|
+
) })
|
|
701
|
+
] });
|
|
702
|
+
};
|
|
703
|
+
var parseDisplayValue = (value, t2) => {
|
|
704
|
+
const parsed = JSON.parse(value?.join(",") || "{}");
|
|
705
|
+
let displayValue = "";
|
|
706
|
+
if (typeof parsed === "object") {
|
|
707
|
+
const parts = [];
|
|
708
|
+
if (parsed.gt) {
|
|
709
|
+
parts.push(t2("filters.compare.greaterThanLabel", { value: parsed.gt }));
|
|
710
|
+
}
|
|
711
|
+
if (parsed.lt) {
|
|
712
|
+
parts.push(
|
|
713
|
+
t2("filters.compare.lessThanLabel", {
|
|
714
|
+
value: parsed.lt
|
|
715
|
+
})
|
|
716
|
+
);
|
|
717
|
+
}
|
|
718
|
+
displayValue = parts.join(` ${t2("filters.compare.andLabel")} `);
|
|
719
|
+
}
|
|
720
|
+
if (typeof parsed === "number") {
|
|
721
|
+
displayValue = parsed.toString();
|
|
722
|
+
}
|
|
723
|
+
return displayValue;
|
|
724
|
+
};
|
|
725
|
+
var parseValue = (value) => {
|
|
726
|
+
if (!value) {
|
|
727
|
+
return void 0;
|
|
728
|
+
}
|
|
729
|
+
const val = value.join(",");
|
|
730
|
+
if (!val) {
|
|
731
|
+
return void 0;
|
|
732
|
+
}
|
|
733
|
+
return JSON.parse(val);
|
|
734
|
+
};
|
|
735
|
+
var getValue = (value, key) => {
|
|
736
|
+
const parsed = parseValue(value);
|
|
737
|
+
if (typeof parsed === "object") {
|
|
738
|
+
return parsed[key];
|
|
739
|
+
}
|
|
740
|
+
if (typeof parsed === "number" && key === "eq") {
|
|
741
|
+
return parsed;
|
|
742
|
+
}
|
|
743
|
+
return void 0;
|
|
744
|
+
};
|
|
745
|
+
var getOperator = (value) => {
|
|
746
|
+
const parsed = parseValue(value);
|
|
747
|
+
return typeof parsed === "object" ? "range" : "exact";
|
|
748
|
+
};
|
|
749
|
+
|
|
750
|
+
// src/components/table/data-table/data-table-filter/select-filter.tsx
|
|
751
|
+
import { CheckMini, EllipseMiniSolid as EllipseMiniSolid3, XMarkMini as XMarkMini2 } from "@acmekit/icons";
|
|
752
|
+
import { clx as clx5 } from "@acmekit/ui";
|
|
753
|
+
import { Command } from "cmdk";
|
|
754
|
+
import { Popover as RadixPopover4 } from "radix-ui";
|
|
755
|
+
import { useState as useState3 } from "react";
|
|
756
|
+
import { useTranslation as useTranslation5 } from "react-i18next";
|
|
757
|
+
import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
758
|
+
var SelectFilter = ({
|
|
759
|
+
filter,
|
|
760
|
+
prefix,
|
|
761
|
+
readonly,
|
|
762
|
+
multiple,
|
|
763
|
+
searchable,
|
|
764
|
+
options,
|
|
765
|
+
openOnMount
|
|
766
|
+
}) => {
|
|
767
|
+
const [open, setOpen] = useState3(openOnMount);
|
|
768
|
+
const [search, setSearch] = useState3("");
|
|
769
|
+
const [searchRef, setSearchRef] = useState3(null);
|
|
770
|
+
const { t: t2 } = useTranslation5();
|
|
771
|
+
const { removeFilter } = useDataTableFilterContext();
|
|
772
|
+
const { key, label } = filter;
|
|
773
|
+
const selectedParams = useSelectedParams({ param: key, prefix, multiple });
|
|
774
|
+
const currentValue = selectedParams.get();
|
|
775
|
+
const labelValues = currentValue.map((v) => options.find((o) => o.value === v)?.label).filter(Boolean);
|
|
776
|
+
const [previousValue, setPreviousValue] = useState3(labelValues);
|
|
777
|
+
const handleRemove = () => {
|
|
778
|
+
selectedParams.delete();
|
|
779
|
+
removeFilter(key);
|
|
780
|
+
};
|
|
781
|
+
let timeoutId = null;
|
|
782
|
+
const handleOpenChange = (open2) => {
|
|
783
|
+
setOpen(open2);
|
|
784
|
+
setPreviousValue(labelValues);
|
|
785
|
+
if (timeoutId) {
|
|
786
|
+
clearTimeout(timeoutId);
|
|
787
|
+
}
|
|
788
|
+
if (!open2 && !currentValue.length) {
|
|
789
|
+
timeoutId = setTimeout(() => {
|
|
790
|
+
removeFilter(key);
|
|
791
|
+
}, 200);
|
|
792
|
+
}
|
|
793
|
+
};
|
|
794
|
+
const handleClearSearch = () => {
|
|
795
|
+
setSearch("");
|
|
796
|
+
if (searchRef) {
|
|
797
|
+
searchRef.focus();
|
|
798
|
+
}
|
|
799
|
+
};
|
|
800
|
+
const handleSelect = (value) => {
|
|
801
|
+
const isSelected = selectedParams.get().includes(String(value));
|
|
802
|
+
if (isSelected) {
|
|
803
|
+
selectedParams.delete(String(value));
|
|
804
|
+
} else {
|
|
805
|
+
selectedParams.add(String(value));
|
|
806
|
+
}
|
|
807
|
+
};
|
|
808
|
+
const normalizedValues = labelValues ? Array.isArray(labelValues) ? labelValues : [labelValues] : null;
|
|
809
|
+
const normalizedPrev = previousValue ? Array.isArray(previousValue) ? previousValue : [previousValue] : null;
|
|
810
|
+
return /* @__PURE__ */ jsxs5(RadixPopover4.Root, { modal: true, open, onOpenChange: handleOpenChange, children: [
|
|
811
|
+
/* @__PURE__ */ jsx5(
|
|
812
|
+
filter_chip_default,
|
|
813
|
+
{
|
|
814
|
+
hasOperator: true,
|
|
815
|
+
hadPreviousValue: !!normalizedPrev?.length,
|
|
816
|
+
readonly,
|
|
817
|
+
label,
|
|
818
|
+
value: normalizedValues?.join(", "),
|
|
819
|
+
onRemove: handleRemove
|
|
820
|
+
}
|
|
821
|
+
),
|
|
822
|
+
!readonly && /* @__PURE__ */ jsx5(RadixPopover4.Portal, { children: /* @__PURE__ */ jsx5(
|
|
823
|
+
RadixPopover4.Content,
|
|
824
|
+
{
|
|
825
|
+
hideWhenDetached: true,
|
|
826
|
+
align: "start",
|
|
827
|
+
sideOffset: 8,
|
|
828
|
+
collisionPadding: 8,
|
|
829
|
+
className: clx5(
|
|
830
|
+
"bg-ui-bg-base text-ui-fg-base shadow-elevation-flyout z-[1] h-full max-h-[200px] w-[300px] overflow-hidden rounded-lg outline-none"
|
|
831
|
+
),
|
|
832
|
+
onInteractOutside: (e) => {
|
|
833
|
+
if (e.target instanceof HTMLElement) {
|
|
834
|
+
if (e.target.attributes.getNamedItem("data-name")?.value === "filters_menu_content") {
|
|
835
|
+
e.preventDefault();
|
|
836
|
+
e.stopPropagation();
|
|
837
|
+
}
|
|
838
|
+
}
|
|
839
|
+
},
|
|
840
|
+
children: /* @__PURE__ */ jsxs5(Command, { className: "h-full", children: [
|
|
841
|
+
searchable && /* @__PURE__ */ jsx5("div", { className: "border-b p-1", children: /* @__PURE__ */ jsxs5("div", { className: "grid grid-cols-[1fr_20px] gap-x-2 rounded-md px-2 py-1", children: [
|
|
842
|
+
/* @__PURE__ */ jsx5(
|
|
843
|
+
Command.Input,
|
|
844
|
+
{
|
|
845
|
+
ref: setSearchRef,
|
|
846
|
+
value: search,
|
|
847
|
+
onValueChange: setSearch,
|
|
848
|
+
className: "txt-compact-small placeholder:text-ui-fg-muted bg-transparent outline-none",
|
|
849
|
+
placeholder: "Search"
|
|
850
|
+
}
|
|
851
|
+
),
|
|
852
|
+
/* @__PURE__ */ jsx5("div", { className: "flex h-5 w-5 items-center justify-center", children: /* @__PURE__ */ jsx5(
|
|
853
|
+
"button",
|
|
854
|
+
{
|
|
855
|
+
disabled: !search,
|
|
856
|
+
onClick: handleClearSearch,
|
|
857
|
+
className: clx5(
|
|
858
|
+
"transition-fg text-ui-fg-muted focus-visible:bg-ui-bg-base-pressed rounded-md outline-none",
|
|
859
|
+
{
|
|
860
|
+
invisible: !search
|
|
861
|
+
}
|
|
862
|
+
),
|
|
863
|
+
children: /* @__PURE__ */ jsx5(XMarkMini2, {})
|
|
864
|
+
}
|
|
865
|
+
) })
|
|
866
|
+
] }) }),
|
|
867
|
+
/* @__PURE__ */ jsx5(Command.Empty, { className: "txt-compact-small flex items-center justify-center p-1", children: /* @__PURE__ */ jsx5("span", { className: "w-full px-2 py-1 text-center", children: t2("general.noResultsTitle") }) }),
|
|
868
|
+
/* @__PURE__ */ jsx5(Command.List, { className: "h-full max-h-[163px] min-h-[0] overflow-auto p-1 outline-none", children: options.map((option) => {
|
|
869
|
+
const isSelected = selectedParams.get().includes(String(option.value));
|
|
870
|
+
return /* @__PURE__ */ jsxs5(
|
|
871
|
+
Command.Item,
|
|
872
|
+
{
|
|
873
|
+
className: "bg-ui-bg-base hover:bg-ui-bg-base-hover aria-selected:bg-ui-bg-base-pressed focus-visible:bg-ui-bg-base-pressed text-ui-fg-base data-[disabled]:text-ui-fg-disabled txt-compact-small relative flex cursor-pointer select-none items-center gap-x-2 rounded-md px-2 py-1.5 outline-none transition-colors data-[disabled]:pointer-events-none",
|
|
874
|
+
value: option.label,
|
|
875
|
+
onSelect: () => {
|
|
876
|
+
handleSelect(option.value);
|
|
877
|
+
},
|
|
878
|
+
children: [
|
|
879
|
+
/* @__PURE__ */ jsx5(
|
|
880
|
+
"div",
|
|
881
|
+
{
|
|
882
|
+
className: clx5(
|
|
883
|
+
"transition-fg flex h-5 w-5 items-center justify-center",
|
|
884
|
+
{
|
|
885
|
+
"[&_svg]:invisible": !isSelected
|
|
886
|
+
}
|
|
887
|
+
),
|
|
888
|
+
children: multiple ? /* @__PURE__ */ jsx5(CheckMini, {}) : /* @__PURE__ */ jsx5(EllipseMiniSolid3, {})
|
|
889
|
+
}
|
|
890
|
+
),
|
|
891
|
+
option.label
|
|
892
|
+
]
|
|
893
|
+
},
|
|
894
|
+
String(option.value)
|
|
895
|
+
);
|
|
896
|
+
}) })
|
|
897
|
+
] })
|
|
898
|
+
}
|
|
899
|
+
) })
|
|
900
|
+
] });
|
|
901
|
+
};
|
|
902
|
+
|
|
903
|
+
// src/components/table/data-table/data-table-filter/string-filter.tsx
|
|
904
|
+
import { Input as Input2, Label as Label2, clx as clx6 } from "@acmekit/ui";
|
|
905
|
+
import debounce2 from "lodash.debounce";
|
|
906
|
+
import { Popover as RadixPopover5 } from "radix-ui";
|
|
907
|
+
import { useCallback as useCallback2, useEffect as useEffect2, useState as useState4 } from "react";
|
|
908
|
+
import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
909
|
+
var StringFilter = ({
|
|
910
|
+
filter,
|
|
911
|
+
prefix,
|
|
912
|
+
readonly,
|
|
913
|
+
openOnMount
|
|
914
|
+
}) => {
|
|
915
|
+
const [open, setOpen] = useState4(openOnMount);
|
|
916
|
+
const { key, label } = filter;
|
|
917
|
+
const { removeFilter } = useDataTableFilterContext();
|
|
918
|
+
const selectedParams = useSelectedParams({ param: key, prefix });
|
|
919
|
+
const query = selectedParams.get();
|
|
920
|
+
const [previousValue, setPreviousValue] = useState4(
|
|
921
|
+
query?.[0]
|
|
922
|
+
);
|
|
923
|
+
const debouncedOnChange = useCallback2(
|
|
924
|
+
debounce2((e) => {
|
|
925
|
+
const value = e.target.value;
|
|
926
|
+
if (!value) {
|
|
927
|
+
selectedParams.delete();
|
|
928
|
+
} else {
|
|
929
|
+
selectedParams.add(value);
|
|
930
|
+
}
|
|
931
|
+
}, 500),
|
|
932
|
+
[selectedParams]
|
|
933
|
+
);
|
|
934
|
+
useEffect2(() => {
|
|
935
|
+
return () => {
|
|
936
|
+
debouncedOnChange.cancel();
|
|
937
|
+
};
|
|
938
|
+
}, [debouncedOnChange]);
|
|
939
|
+
let timeoutId = null;
|
|
940
|
+
const handleOpenChange = (open2) => {
|
|
941
|
+
setOpen(open2);
|
|
942
|
+
setPreviousValue(query?.[0]);
|
|
943
|
+
if (timeoutId) {
|
|
944
|
+
clearTimeout(timeoutId);
|
|
945
|
+
}
|
|
946
|
+
if (!open2 && !query.length) {
|
|
947
|
+
timeoutId = setTimeout(() => {
|
|
948
|
+
removeFilter(key);
|
|
949
|
+
}, 200);
|
|
950
|
+
}
|
|
951
|
+
};
|
|
952
|
+
const handleRemove = () => {
|
|
953
|
+
selectedParams.delete();
|
|
954
|
+
removeFilter(key);
|
|
955
|
+
};
|
|
956
|
+
return /* @__PURE__ */ jsxs6(RadixPopover5.Root, { modal: true, open, onOpenChange: handleOpenChange, children: [
|
|
957
|
+
/* @__PURE__ */ jsx6(
|
|
958
|
+
filter_chip_default,
|
|
959
|
+
{
|
|
960
|
+
hasOperator: true,
|
|
961
|
+
hadPreviousValue: !!previousValue,
|
|
962
|
+
label,
|
|
963
|
+
value: query?.[0],
|
|
964
|
+
onRemove: handleRemove,
|
|
965
|
+
readonly
|
|
966
|
+
}
|
|
967
|
+
),
|
|
968
|
+
!readonly && /* @__PURE__ */ jsx6(RadixPopover5.Portal, { children: /* @__PURE__ */ jsx6(
|
|
969
|
+
RadixPopover5.Content,
|
|
970
|
+
{
|
|
971
|
+
hideWhenDetached: true,
|
|
972
|
+
align: "start",
|
|
973
|
+
sideOffset: 8,
|
|
974
|
+
collisionPadding: 8,
|
|
975
|
+
className: clx6(
|
|
976
|
+
"bg-ui-bg-base text-ui-fg-base shadow-elevation-flyout z-[1] h-full max-h-[200px] w-[300px] overflow-hidden rounded-lg outline-none"
|
|
977
|
+
),
|
|
978
|
+
onInteractOutside: (e) => {
|
|
979
|
+
if (e.target instanceof HTMLElement) {
|
|
980
|
+
if (e.target.attributes.getNamedItem("data-name")?.value === "filters_menu_content") {
|
|
981
|
+
e.preventDefault();
|
|
982
|
+
e.stopPropagation();
|
|
983
|
+
}
|
|
984
|
+
}
|
|
985
|
+
},
|
|
986
|
+
children: /* @__PURE__ */ jsxs6("div", { className: "px-1 pb-3 pt-1", children: [
|
|
987
|
+
/* @__PURE__ */ jsx6("div", { className: "px-2 py-1.5", children: /* @__PURE__ */ jsx6(Label2, { size: "xsmall", weight: "plus", htmlFor: key, children: label }) }),
|
|
988
|
+
/* @__PURE__ */ jsx6("div", { className: "px-2 py-0.5", children: /* @__PURE__ */ jsx6(
|
|
989
|
+
Input2,
|
|
990
|
+
{
|
|
991
|
+
name: key,
|
|
992
|
+
size: "small",
|
|
993
|
+
defaultValue: query?.[0] || void 0,
|
|
994
|
+
onChange: debouncedOnChange
|
|
995
|
+
}
|
|
996
|
+
) })
|
|
997
|
+
] })
|
|
998
|
+
}
|
|
999
|
+
) })
|
|
1000
|
+
] });
|
|
1001
|
+
};
|
|
1002
|
+
|
|
1003
|
+
// src/components/table/data-table/data-table-filter/data-table-filter.tsx
|
|
1004
|
+
import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
1005
|
+
var DataTableFilter = ({
|
|
1006
|
+
filters,
|
|
1007
|
+
readonly,
|
|
1008
|
+
prefix
|
|
1009
|
+
}) => {
|
|
1010
|
+
const { t: t2 } = useTranslation6();
|
|
1011
|
+
const [searchParams] = useSearchParams2();
|
|
1012
|
+
const [open, setOpen] = useState5(false);
|
|
1013
|
+
const [activeFilters, setActiveFilters] = useState5(
|
|
1014
|
+
getInitialFilters({ searchParams, filters, prefix })
|
|
1015
|
+
);
|
|
1016
|
+
const availableFilters = filters.filter(
|
|
1017
|
+
(f) => !activeFilters.find((af) => af.key === f.key)
|
|
1018
|
+
);
|
|
1019
|
+
const initialMount = useRef(true);
|
|
1020
|
+
useEffect3(() => {
|
|
1021
|
+
if (initialMount.current) {
|
|
1022
|
+
const params = new URLSearchParams(searchParams);
|
|
1023
|
+
filters.forEach((filter) => {
|
|
1024
|
+
const key = prefix ? `${prefix}_${filter.key}` : filter.key;
|
|
1025
|
+
const value = params.get(key);
|
|
1026
|
+
if (value && !activeFilters.find((af) => af.key === filter.key)) {
|
|
1027
|
+
if (filter.type === "select") {
|
|
1028
|
+
setActiveFilters((prev) => [
|
|
1029
|
+
...prev,
|
|
1030
|
+
{
|
|
1031
|
+
...filter,
|
|
1032
|
+
multiple: filter.multiple,
|
|
1033
|
+
options: filter.options,
|
|
1034
|
+
openOnMount: false
|
|
1035
|
+
}
|
|
1036
|
+
]);
|
|
1037
|
+
} else {
|
|
1038
|
+
setActiveFilters((prev) => [
|
|
1039
|
+
...prev,
|
|
1040
|
+
{ ...filter, openOnMount: false }
|
|
1041
|
+
]);
|
|
1042
|
+
}
|
|
1043
|
+
}
|
|
1044
|
+
});
|
|
1045
|
+
}
|
|
1046
|
+
initialMount.current = false;
|
|
1047
|
+
}, [activeFilters, filters, prefix, searchParams]);
|
|
1048
|
+
const addFilter = (filter) => {
|
|
1049
|
+
setOpen(false);
|
|
1050
|
+
setActiveFilters((prev) => [...prev, { ...filter, openOnMount: true }]);
|
|
1051
|
+
};
|
|
1052
|
+
const removeFilter = useCallback3((key) => {
|
|
1053
|
+
setActiveFilters((prev) => prev.filter((f) => f.key !== key));
|
|
1054
|
+
}, []);
|
|
1055
|
+
const removeAllFilters = useCallback3(() => {
|
|
1056
|
+
setActiveFilters([]);
|
|
1057
|
+
}, []);
|
|
1058
|
+
return /* @__PURE__ */ jsx7(
|
|
1059
|
+
DataTableFilterContext.Provider,
|
|
1060
|
+
{
|
|
1061
|
+
value: useMemo2(
|
|
1062
|
+
() => ({
|
|
1063
|
+
removeFilter,
|
|
1064
|
+
removeAllFilters
|
|
1065
|
+
}),
|
|
1066
|
+
[removeAllFilters, removeFilter]
|
|
1067
|
+
),
|
|
1068
|
+
children: /* @__PURE__ */ jsxs7("div", { className: "max-w-2/3 flex flex-wrap items-center gap-2", children: [
|
|
1069
|
+
activeFilters.map((filter) => {
|
|
1070
|
+
switch (filter.type) {
|
|
1071
|
+
case "select":
|
|
1072
|
+
return /* @__PURE__ */ jsx7(
|
|
1073
|
+
SelectFilter,
|
|
1074
|
+
{
|
|
1075
|
+
filter,
|
|
1076
|
+
prefix,
|
|
1077
|
+
readonly,
|
|
1078
|
+
options: filter.options,
|
|
1079
|
+
multiple: filter.multiple,
|
|
1080
|
+
searchable: filter.searchable,
|
|
1081
|
+
openOnMount: filter.openOnMount
|
|
1082
|
+
},
|
|
1083
|
+
filter.key
|
|
1084
|
+
);
|
|
1085
|
+
case "date":
|
|
1086
|
+
return /* @__PURE__ */ jsx7(
|
|
1087
|
+
DateFilter,
|
|
1088
|
+
{
|
|
1089
|
+
filter,
|
|
1090
|
+
prefix,
|
|
1091
|
+
readonly,
|
|
1092
|
+
openOnMount: filter.openOnMount
|
|
1093
|
+
},
|
|
1094
|
+
filter.key
|
|
1095
|
+
);
|
|
1096
|
+
case "string":
|
|
1097
|
+
return /* @__PURE__ */ jsx7(
|
|
1098
|
+
StringFilter,
|
|
1099
|
+
{
|
|
1100
|
+
filter,
|
|
1101
|
+
prefix,
|
|
1102
|
+
readonly,
|
|
1103
|
+
openOnMount: filter.openOnMount
|
|
1104
|
+
},
|
|
1105
|
+
filter.key
|
|
1106
|
+
);
|
|
1107
|
+
case "number":
|
|
1108
|
+
return /* @__PURE__ */ jsx7(
|
|
1109
|
+
NumberFilter,
|
|
1110
|
+
{
|
|
1111
|
+
filter,
|
|
1112
|
+
prefix,
|
|
1113
|
+
readonly,
|
|
1114
|
+
openOnMount: filter.openOnMount
|
|
1115
|
+
},
|
|
1116
|
+
filter.key
|
|
1117
|
+
);
|
|
1118
|
+
default:
|
|
1119
|
+
break;
|
|
1120
|
+
}
|
|
1121
|
+
}),
|
|
1122
|
+
!readonly && availableFilters.length > 0 && /* @__PURE__ */ jsxs7(RadixPopover6.Root, { modal: true, open, onOpenChange: setOpen, children: [
|
|
1123
|
+
/* @__PURE__ */ jsx7(RadixPopover6.Trigger, { asChild: true, id: "filters_menu_trigger", children: /* @__PURE__ */ jsx7(Button2, { size: "small", variant: "secondary", children: t2("filters.addFilter") }) }),
|
|
1124
|
+
/* @__PURE__ */ jsx7(RadixPopover6.Portal, { children: /* @__PURE__ */ jsx7(
|
|
1125
|
+
RadixPopover6.Content,
|
|
1126
|
+
{
|
|
1127
|
+
className: clx7(
|
|
1128
|
+
"bg-ui-bg-base text-ui-fg-base shadow-elevation-flyout z-[1] h-full max-h-[200px] w-[300px] overflow-auto rounded-lg p-1 outline-none"
|
|
1129
|
+
),
|
|
1130
|
+
"data-name": "filters_menu_content",
|
|
1131
|
+
align: "start",
|
|
1132
|
+
sideOffset: 8,
|
|
1133
|
+
collisionPadding: 8,
|
|
1134
|
+
onCloseAutoFocus: (e) => {
|
|
1135
|
+
const hasOpenFilter = activeFilters.find(
|
|
1136
|
+
(filter) => filter.openOnMount
|
|
1137
|
+
);
|
|
1138
|
+
if (hasOpenFilter) {
|
|
1139
|
+
e.preventDefault();
|
|
1140
|
+
}
|
|
1141
|
+
},
|
|
1142
|
+
children: availableFilters.map((filter) => {
|
|
1143
|
+
return /* @__PURE__ */ jsx7(
|
|
1144
|
+
"div",
|
|
1145
|
+
{
|
|
1146
|
+
className: "bg-ui-bg-base hover:bg-ui-bg-base-hover focus-visible:bg-ui-bg-base-pressed text-ui-fg-base data-[disabled]:text-ui-fg-disabled txt-compact-small relative flex cursor-pointer select-none items-center rounded-md px-2 py-1.5 outline-none transition-colors data-[disabled]:pointer-events-none",
|
|
1147
|
+
role: "menuitem",
|
|
1148
|
+
onClick: () => {
|
|
1149
|
+
addFilter(filter);
|
|
1150
|
+
},
|
|
1151
|
+
children: filter.label
|
|
1152
|
+
},
|
|
1153
|
+
filter.key
|
|
1154
|
+
);
|
|
1155
|
+
})
|
|
1156
|
+
}
|
|
1157
|
+
) })
|
|
1158
|
+
] }),
|
|
1159
|
+
!readonly && activeFilters.length > 0 && /* @__PURE__ */ jsx7(ClearAllFilters, { filters, prefix })
|
|
1160
|
+
] })
|
|
1161
|
+
}
|
|
1162
|
+
);
|
|
1163
|
+
};
|
|
1164
|
+
var ClearAllFilters = ({ filters, prefix }) => {
|
|
1165
|
+
const { removeAllFilters } = useDataTableFilterContext();
|
|
1166
|
+
const [_, setSearchParams] = useSearchParams2();
|
|
1167
|
+
const handleRemoveAll = () => {
|
|
1168
|
+
setSearchParams((prev) => {
|
|
1169
|
+
const newValues = new URLSearchParams(prev);
|
|
1170
|
+
filters.forEach((filter) => {
|
|
1171
|
+
newValues.delete(prefix ? `${prefix}_${filter.key}` : filter.key);
|
|
1172
|
+
});
|
|
1173
|
+
return newValues;
|
|
1174
|
+
});
|
|
1175
|
+
removeAllFilters();
|
|
1176
|
+
};
|
|
1177
|
+
return /* @__PURE__ */ jsx7(
|
|
1178
|
+
"button",
|
|
1179
|
+
{
|
|
1180
|
+
type: "button",
|
|
1181
|
+
onClick: handleRemoveAll,
|
|
1182
|
+
className: clx7(
|
|
1183
|
+
"text-ui-fg-muted transition-fg txt-compact-small-plus rounded-md px-2 py-1",
|
|
1184
|
+
"hover:text-ui-fg-subtle",
|
|
1185
|
+
"focus-visible:shadow-borders-focus"
|
|
1186
|
+
),
|
|
1187
|
+
children: "Clear all"
|
|
1188
|
+
}
|
|
1189
|
+
);
|
|
1190
|
+
};
|
|
1191
|
+
var getInitialFilters = ({
|
|
1192
|
+
searchParams,
|
|
1193
|
+
filters,
|
|
1194
|
+
prefix
|
|
1195
|
+
}) => {
|
|
1196
|
+
const params = new URLSearchParams(searchParams);
|
|
1197
|
+
const activeFilters = [];
|
|
1198
|
+
filters.forEach((filter) => {
|
|
1199
|
+
const key = prefix ? `${prefix}_${filter.key}` : filter.key;
|
|
1200
|
+
const value = params.get(key);
|
|
1201
|
+
if (value) {
|
|
1202
|
+
if (filter.type === "select") {
|
|
1203
|
+
activeFilters.push({
|
|
1204
|
+
...filter,
|
|
1205
|
+
multiple: filter.multiple,
|
|
1206
|
+
options: filter.options,
|
|
1207
|
+
openOnMount: false
|
|
1208
|
+
});
|
|
1209
|
+
} else {
|
|
1210
|
+
activeFilters.push({ ...filter, openOnMount: false });
|
|
1211
|
+
}
|
|
1212
|
+
}
|
|
1213
|
+
});
|
|
1214
|
+
return activeFilters;
|
|
1215
|
+
};
|
|
1216
|
+
|
|
1217
|
+
// src/components/table/data-table/data-table-order-by/data-table-order-by.tsx
|
|
1218
|
+
import { DescendingSorting } from "@acmekit/icons";
|
|
1219
|
+
import { DropdownMenu, IconButton } from "@acmekit/ui";
|
|
1220
|
+
import { useState as useState6 } from "react";
|
|
1221
|
+
import { useTranslation as useTranslation7 } from "react-i18next";
|
|
1222
|
+
import { useSearchParams as useSearchParams3 } from "react-router-dom";
|
|
1223
|
+
import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
1224
|
+
var initState = (params, prefix) => {
|
|
1225
|
+
const param = prefix ? `${prefix}_order` : "order";
|
|
1226
|
+
const sortParam = params.get(param);
|
|
1227
|
+
if (!sortParam) {
|
|
1228
|
+
return {
|
|
1229
|
+
dir: "asc" /* ASC */
|
|
1230
|
+
};
|
|
1231
|
+
}
|
|
1232
|
+
const dir = sortParam.startsWith("-") ? "desc" /* DESC */ : "asc" /* ASC */;
|
|
1233
|
+
const key = sortParam.replace("-", "");
|
|
1234
|
+
return {
|
|
1235
|
+
key,
|
|
1236
|
+
dir
|
|
1237
|
+
};
|
|
1238
|
+
};
|
|
1239
|
+
var DataTableOrderBy = ({
|
|
1240
|
+
keys,
|
|
1241
|
+
prefix
|
|
1242
|
+
}) => {
|
|
1243
|
+
const [searchParams, setSearchParams] = useSearchParams3();
|
|
1244
|
+
const [state, setState] = useState6(initState(searchParams, prefix));
|
|
1245
|
+
const param = prefix ? `${prefix}_order` : "order";
|
|
1246
|
+
const { t: t2 } = useTranslation7();
|
|
1247
|
+
const direction = useDocumentDirection();
|
|
1248
|
+
const handleDirChange = (dir) => {
|
|
1249
|
+
setState((prev) => ({
|
|
1250
|
+
...prev,
|
|
1251
|
+
dir
|
|
1252
|
+
}));
|
|
1253
|
+
updateOrderParam({
|
|
1254
|
+
key: state.key,
|
|
1255
|
+
dir
|
|
1256
|
+
});
|
|
1257
|
+
};
|
|
1258
|
+
const handleKeyChange = (value) => {
|
|
1259
|
+
setState((prev) => ({
|
|
1260
|
+
...prev,
|
|
1261
|
+
key: value
|
|
1262
|
+
}));
|
|
1263
|
+
updateOrderParam({
|
|
1264
|
+
key: value,
|
|
1265
|
+
dir: state.dir
|
|
1266
|
+
});
|
|
1267
|
+
};
|
|
1268
|
+
const updateOrderParam = (state2) => {
|
|
1269
|
+
if (!state2.key) {
|
|
1270
|
+
setSearchParams((prev) => {
|
|
1271
|
+
prev.delete(param);
|
|
1272
|
+
return prev;
|
|
1273
|
+
});
|
|
1274
|
+
return;
|
|
1275
|
+
}
|
|
1276
|
+
const orderParam = state2.dir === "asc" /* ASC */ ? state2.key : `-${state2.key}`;
|
|
1277
|
+
setSearchParams((prev) => {
|
|
1278
|
+
prev.set(param, orderParam);
|
|
1279
|
+
return prev;
|
|
1280
|
+
});
|
|
1281
|
+
};
|
|
1282
|
+
return /* @__PURE__ */ jsxs8(DropdownMenu, { dir: direction, children: [
|
|
1283
|
+
/* @__PURE__ */ jsx8(DropdownMenu.Trigger, { asChild: true, children: /* @__PURE__ */ jsx8(IconButton, { size: "small", children: /* @__PURE__ */ jsx8(DescendingSorting, {}) }) }),
|
|
1284
|
+
/* @__PURE__ */ jsxs8(DropdownMenu.Content, { className: "z-[1]", align: "end", children: [
|
|
1285
|
+
/* @__PURE__ */ jsx8(
|
|
1286
|
+
DropdownMenu.RadioGroup,
|
|
1287
|
+
{
|
|
1288
|
+
value: state.key,
|
|
1289
|
+
onValueChange: handleKeyChange,
|
|
1290
|
+
children: keys.map((key) => {
|
|
1291
|
+
const stringKey = String(key.key);
|
|
1292
|
+
return /* @__PURE__ */ jsx8(
|
|
1293
|
+
DropdownMenu.RadioItem,
|
|
1294
|
+
{
|
|
1295
|
+
value: stringKey,
|
|
1296
|
+
onSelect: (event) => event.preventDefault(),
|
|
1297
|
+
children: key.label
|
|
1298
|
+
},
|
|
1299
|
+
stringKey
|
|
1300
|
+
);
|
|
1301
|
+
})
|
|
1302
|
+
}
|
|
1303
|
+
),
|
|
1304
|
+
/* @__PURE__ */ jsx8(DropdownMenu.Separator, {}),
|
|
1305
|
+
/* @__PURE__ */ jsxs8(
|
|
1306
|
+
DropdownMenu.RadioGroup,
|
|
1307
|
+
{
|
|
1308
|
+
value: state.dir,
|
|
1309
|
+
onValueChange: handleDirChange,
|
|
1310
|
+
children: [
|
|
1311
|
+
/* @__PURE__ */ jsxs8(
|
|
1312
|
+
DropdownMenu.RadioItem,
|
|
1313
|
+
{
|
|
1314
|
+
className: "flex items-center justify-between",
|
|
1315
|
+
value: "asc",
|
|
1316
|
+
onSelect: (event) => event.preventDefault(),
|
|
1317
|
+
children: [
|
|
1318
|
+
t2("general.ascending"),
|
|
1319
|
+
/* @__PURE__ */ jsx8(DropdownMenu.Label, { children: "1 - 30" })
|
|
1320
|
+
]
|
|
1321
|
+
}
|
|
1322
|
+
),
|
|
1323
|
+
/* @__PURE__ */ jsxs8(
|
|
1324
|
+
DropdownMenu.RadioItem,
|
|
1325
|
+
{
|
|
1326
|
+
className: "flex items-center justify-between",
|
|
1327
|
+
value: "desc",
|
|
1328
|
+
onSelect: (event) => event.preventDefault(),
|
|
1329
|
+
children: [
|
|
1330
|
+
t2("general.descending"),
|
|
1331
|
+
/* @__PURE__ */ jsx8(DropdownMenu.Label, { children: "30 - 1" })
|
|
1332
|
+
]
|
|
1333
|
+
}
|
|
1334
|
+
)
|
|
1335
|
+
]
|
|
1336
|
+
}
|
|
1337
|
+
)
|
|
1338
|
+
] })
|
|
1339
|
+
] });
|
|
1340
|
+
};
|
|
1341
|
+
|
|
1342
|
+
// src/components/table/data-table/data-table-search/data-table-search.tsx
|
|
1343
|
+
import { Input as Input3 } from "@acmekit/ui";
|
|
1344
|
+
import { useCallback as useCallback4, useEffect as useEffect4 } from "react";
|
|
1345
|
+
import { useTranslation as useTranslation8 } from "react-i18next";
|
|
1346
|
+
import debounce3 from "lodash.debounce";
|
|
1347
|
+
import { jsx as jsx9 } from "react/jsx-runtime";
|
|
1348
|
+
var DataTableSearch = ({
|
|
1349
|
+
placeholder,
|
|
1350
|
+
prefix,
|
|
1351
|
+
autofocus
|
|
1352
|
+
}) => {
|
|
1353
|
+
const { t: t2 } = useTranslation8();
|
|
1354
|
+
const placeholderText = placeholder || t2("general.search");
|
|
1355
|
+
const selectedParams = useSelectedParams({
|
|
1356
|
+
param: "q",
|
|
1357
|
+
prefix,
|
|
1358
|
+
multiple: false
|
|
1359
|
+
});
|
|
1360
|
+
const query = selectedParams.get();
|
|
1361
|
+
const debouncedOnChange = useCallback4(
|
|
1362
|
+
debounce3((e) => {
|
|
1363
|
+
const value = e.target.value;
|
|
1364
|
+
if (!value) {
|
|
1365
|
+
selectedParams.delete();
|
|
1366
|
+
} else {
|
|
1367
|
+
selectedParams.add(value);
|
|
1368
|
+
}
|
|
1369
|
+
}, 500),
|
|
1370
|
+
[selectedParams]
|
|
1371
|
+
);
|
|
1372
|
+
useEffect4(() => {
|
|
1373
|
+
return () => {
|
|
1374
|
+
debouncedOnChange.cancel();
|
|
1375
|
+
};
|
|
1376
|
+
}, [debouncedOnChange]);
|
|
1377
|
+
return /* @__PURE__ */ jsx9(
|
|
1378
|
+
Input3,
|
|
1379
|
+
{
|
|
1380
|
+
autoComplete: "off",
|
|
1381
|
+
name: "q",
|
|
1382
|
+
type: "search",
|
|
1383
|
+
size: "small",
|
|
1384
|
+
autoFocus: autofocus,
|
|
1385
|
+
defaultValue: query?.[0] || void 0,
|
|
1386
|
+
onChange: debouncedOnChange,
|
|
1387
|
+
placeholder: placeholderText
|
|
1388
|
+
}
|
|
1389
|
+
);
|
|
1390
|
+
};
|
|
1391
|
+
|
|
1392
|
+
// src/components/table/data-table/data-table-query/data-table-query.tsx
|
|
1393
|
+
import { jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
1394
|
+
var DataTableQuery = ({
|
|
1395
|
+
search,
|
|
1396
|
+
orderBy,
|
|
1397
|
+
filters,
|
|
1398
|
+
prefix
|
|
1399
|
+
}) => {
|
|
1400
|
+
return (search || orderBy || filters || prefix) && /* @__PURE__ */ jsxs9("div", { className: "flex items-start justify-between gap-x-4 px-6 py-4", children: [
|
|
1401
|
+
/* @__PURE__ */ jsx10("div", { className: "w-full max-w-[60%]", children: filters && filters.length > 0 && /* @__PURE__ */ jsx10(DataTableFilter, { filters, prefix }) }),
|
|
1402
|
+
/* @__PURE__ */ jsxs9("div", { className: "flex shrink-0 items-center gap-x-2", children: [
|
|
1403
|
+
search && /* @__PURE__ */ jsx10(
|
|
1404
|
+
DataTableSearch,
|
|
1405
|
+
{
|
|
1406
|
+
prefix,
|
|
1407
|
+
autofocus: search === "autofocus"
|
|
1408
|
+
}
|
|
1409
|
+
),
|
|
1410
|
+
orderBy && /* @__PURE__ */ jsx10(DataTableOrderBy, { keys: orderBy, prefix })
|
|
1411
|
+
] })
|
|
1412
|
+
] });
|
|
1413
|
+
};
|
|
1414
|
+
|
|
1415
|
+
// src/components/table/data-table/data-table-root/data-table-root.tsx
|
|
1416
|
+
import { CommandBar, Table, clx as clx8 } from "@acmekit/ui";
|
|
1417
|
+
import {
|
|
1418
|
+
flexRender
|
|
1419
|
+
} from "@tanstack/react-table";
|
|
1420
|
+
import {
|
|
1421
|
+
Fragment,
|
|
1422
|
+
useEffect as useEffect5,
|
|
1423
|
+
useRef as useRef2,
|
|
1424
|
+
useState as useState7
|
|
1425
|
+
} from "react";
|
|
1426
|
+
import { useTranslation as useTranslation9 } from "react-i18next";
|
|
1427
|
+
import { Link as Link2 } from "react-router-dom";
|
|
1428
|
+
import { jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
1429
|
+
var DataTableRoot = ({
|
|
1430
|
+
table,
|
|
1431
|
+
columns,
|
|
1432
|
+
pagination,
|
|
1433
|
+
navigateTo,
|
|
1434
|
+
commands,
|
|
1435
|
+
count = 0,
|
|
1436
|
+
noResults = false,
|
|
1437
|
+
noHeader = false,
|
|
1438
|
+
layout = "fit"
|
|
1439
|
+
}) => {
|
|
1440
|
+
const { t: t2 } = useTranslation9();
|
|
1441
|
+
const [showStickyBorder, setShowStickyBorder] = useState7(false);
|
|
1442
|
+
const scrollableRef = useRef2(null);
|
|
1443
|
+
const hasSelect = columns.find((c) => c.id === "select");
|
|
1444
|
+
const hasActions = columns.find((c) => c.id === "actions");
|
|
1445
|
+
const hasCommandBar = commands && commands.length > 0;
|
|
1446
|
+
const rowSelection = table.getState().rowSelection;
|
|
1447
|
+
const { pageIndex, pageSize } = table.getState().pagination;
|
|
1448
|
+
const colCount = columns.length - (hasSelect ? 1 : 0) - (hasActions ? 1 : 0);
|
|
1449
|
+
const colWidth = 100 / colCount;
|
|
1450
|
+
const handleHorizontalScroll = (e) => {
|
|
1451
|
+
const scrollLeft = e.currentTarget.scrollLeft;
|
|
1452
|
+
if (scrollLeft > 0) {
|
|
1453
|
+
setShowStickyBorder(true);
|
|
1454
|
+
} else {
|
|
1455
|
+
setShowStickyBorder(false);
|
|
1456
|
+
}
|
|
1457
|
+
};
|
|
1458
|
+
const handleAction = async (action) => {
|
|
1459
|
+
await action(rowSelection).then(() => {
|
|
1460
|
+
table.resetRowSelection();
|
|
1461
|
+
});
|
|
1462
|
+
};
|
|
1463
|
+
useEffect5(() => {
|
|
1464
|
+
scrollableRef.current?.scroll({ top: 0, left: 0 });
|
|
1465
|
+
}, [pageIndex]);
|
|
1466
|
+
return /* @__PURE__ */ jsxs10(
|
|
1467
|
+
"div",
|
|
1468
|
+
{
|
|
1469
|
+
className: clx8("flex w-full flex-col overflow-hidden", {
|
|
1470
|
+
"flex flex-1 flex-col": layout === "fill"
|
|
1471
|
+
}),
|
|
1472
|
+
children: [
|
|
1473
|
+
/* @__PURE__ */ jsx11(
|
|
1474
|
+
"div",
|
|
1475
|
+
{
|
|
1476
|
+
ref: scrollableRef,
|
|
1477
|
+
onScroll: handleHorizontalScroll,
|
|
1478
|
+
className: clx8("w-full", {
|
|
1479
|
+
"min-h-0 flex-grow overflow-auto": layout === "fill",
|
|
1480
|
+
"overflow-x-auto": layout === "fit"
|
|
1481
|
+
}),
|
|
1482
|
+
children: !noResults ? /* @__PURE__ */ jsxs10(Table, { className: "relative w-full", children: [
|
|
1483
|
+
!noHeader && /* @__PURE__ */ jsx11(Table.Header, { className: "border-t-0", children: table.getHeaderGroups().map((headerGroup) => {
|
|
1484
|
+
return /* @__PURE__ */ jsx11(
|
|
1485
|
+
Table.Row,
|
|
1486
|
+
{
|
|
1487
|
+
className: clx8({
|
|
1488
|
+
"relative border-b-0 [&_th:last-of-type]:w-[1%] [&_th:last-of-type]:whitespace-nowrap": hasActions,
|
|
1489
|
+
"[&_th:first-of-type]:w-[1%] [&_th:first-of-type]:whitespace-nowrap": hasSelect
|
|
1490
|
+
}),
|
|
1491
|
+
children: headerGroup.headers.map((header, index) => {
|
|
1492
|
+
const isActionHeader = header.id === "actions";
|
|
1493
|
+
const isSelectHeader = header.id === "select";
|
|
1494
|
+
const isSpecialHeader = isActionHeader || isSelectHeader;
|
|
1495
|
+
const firstHeader = headerGroup.headers.findIndex(
|
|
1496
|
+
(h) => h.id !== "select"
|
|
1497
|
+
);
|
|
1498
|
+
const isFirstHeader = firstHeader !== -1 ? header.id === headerGroup.headers[firstHeader].id : index === 0;
|
|
1499
|
+
const isStickyHeader = isSelectHeader || isFirstHeader;
|
|
1500
|
+
return /* @__PURE__ */ jsx11(
|
|
1501
|
+
Table.HeaderCell,
|
|
1502
|
+
{
|
|
1503
|
+
"data-table-header-id": header.id,
|
|
1504
|
+
style: {
|
|
1505
|
+
width: !isSpecialHeader ? `${colWidth}%` : void 0
|
|
1506
|
+
},
|
|
1507
|
+
className: clx8({
|
|
1508
|
+
"bg-ui-bg-subtle sticky start-0 after:absolute after:inset-y-0 after:right-0 after:h-full after:w-px after:bg-transparent after:content-['']": isStickyHeader,
|
|
1509
|
+
"start-[68px]": isStickyHeader && hasSelect && !isSelectHeader,
|
|
1510
|
+
"after:bg-ui-border-base": showStickyBorder && isStickyHeader && !isSpecialHeader
|
|
1511
|
+
}),
|
|
1512
|
+
children: flexRender(
|
|
1513
|
+
header.column.columnDef.header,
|
|
1514
|
+
header.getContext()
|
|
1515
|
+
)
|
|
1516
|
+
},
|
|
1517
|
+
header.id
|
|
1518
|
+
);
|
|
1519
|
+
})
|
|
1520
|
+
},
|
|
1521
|
+
headerGroup.id
|
|
1522
|
+
);
|
|
1523
|
+
}) }),
|
|
1524
|
+
/* @__PURE__ */ jsx11(Table.Body, { className: "border-b-0", children: table.getRowModel().rows.map((row) => {
|
|
1525
|
+
const to = navigateTo ? navigateTo(row) : void 0;
|
|
1526
|
+
const isRowDisabled = hasSelect && !row.getCanSelect();
|
|
1527
|
+
const isOdd = row.depth % 2 !== 0;
|
|
1528
|
+
const cells = row.getVisibleCells();
|
|
1529
|
+
return /* @__PURE__ */ jsx11(
|
|
1530
|
+
Table.Row,
|
|
1531
|
+
{
|
|
1532
|
+
"data-selected": row.getIsSelected(),
|
|
1533
|
+
className: clx8(
|
|
1534
|
+
"transition-fg group/row group relative [&_td:last-of-type]:w-[1%] [&_td:last-of-type]:whitespace-nowrap",
|
|
1535
|
+
"has-[[data-row-link]:focus-visible]:bg-ui-bg-base-hover",
|
|
1536
|
+
{
|
|
1537
|
+
"bg-ui-bg-subtle hover:bg-ui-bg-subtle-hover": isOdd,
|
|
1538
|
+
"cursor-pointer": !!to,
|
|
1539
|
+
"bg-ui-bg-highlight hover:bg-ui-bg-highlight-hover": row.getIsSelected(),
|
|
1540
|
+
"!bg-ui-bg-disabled !hover:bg-ui-bg-disabled": isRowDisabled
|
|
1541
|
+
}
|
|
1542
|
+
),
|
|
1543
|
+
children: cells.map((cell, index) => {
|
|
1544
|
+
const visibleCells = row.getVisibleCells();
|
|
1545
|
+
const isSelectCell = cell.column.id === "select";
|
|
1546
|
+
const firstCell = visibleCells.findIndex(
|
|
1547
|
+
(h) => h.column.id !== "select"
|
|
1548
|
+
);
|
|
1549
|
+
const isFirstCell = firstCell !== -1 ? cell.column.id === visibleCells[firstCell].column.id : index === 0;
|
|
1550
|
+
const isStickyCell = isSelectCell || isFirstCell;
|
|
1551
|
+
const depthOffset = row.depth > 0 && isFirstCell ? row.depth * 14 + 24 : void 0;
|
|
1552
|
+
const hasLeftOffset = isStickyCell && hasSelect && !isSelectCell;
|
|
1553
|
+
const Inner = flexRender(
|
|
1554
|
+
cell.column.columnDef.cell,
|
|
1555
|
+
cell.getContext()
|
|
1556
|
+
);
|
|
1557
|
+
const isTabableLink = isFirstCell && !!to;
|
|
1558
|
+
const shouldRenderAsLink = !!to && !isSelectCell;
|
|
1559
|
+
return /* @__PURE__ */ jsx11(
|
|
1560
|
+
Table.Cell,
|
|
1561
|
+
{
|
|
1562
|
+
className: clx8({
|
|
1563
|
+
"!ps-0 !pe-0": shouldRenderAsLink,
|
|
1564
|
+
"bg-ui-bg-base group-data-[selected=true]/row:bg-ui-bg-highlight group-data-[selected=true]/row:group-hover/row:bg-ui-bg-highlight-hover group-hover/row:bg-ui-bg-base-hover transition-fg group-has-[[data-row-link]:focus-visible]:bg-ui-bg-base-hover sticky start-0 after:absolute after:inset-y-0 after:right-0 after:h-full after:w-px after:bg-transparent after:content-['']": isStickyCell,
|
|
1565
|
+
"bg-ui-bg-subtle group-hover/row:bg-ui-bg-subtle-hover": isOdd && isStickyCell,
|
|
1566
|
+
"start-[68px]": hasLeftOffset,
|
|
1567
|
+
"after:bg-ui-border-base": showStickyBorder && isStickyCell && !isSelectCell,
|
|
1568
|
+
"!bg-ui-bg-disabled !hover:bg-ui-bg-disabled": isRowDisabled
|
|
1569
|
+
}),
|
|
1570
|
+
style: {
|
|
1571
|
+
paddingLeft: depthOffset ? `${depthOffset}px` : void 0
|
|
1572
|
+
},
|
|
1573
|
+
children: shouldRenderAsLink ? /* @__PURE__ */ jsx11(
|
|
1574
|
+
Link2,
|
|
1575
|
+
{
|
|
1576
|
+
to,
|
|
1577
|
+
className: "size-full outline-none",
|
|
1578
|
+
"data-row-link": true,
|
|
1579
|
+
tabIndex: isTabableLink ? 0 : -1,
|
|
1580
|
+
children: /* @__PURE__ */ jsx11(
|
|
1581
|
+
"div",
|
|
1582
|
+
{
|
|
1583
|
+
className: clx8(
|
|
1584
|
+
"flex size-full items-center pe-6",
|
|
1585
|
+
{
|
|
1586
|
+
"ps-6": isTabableLink && !hasLeftOffset
|
|
1587
|
+
}
|
|
1588
|
+
),
|
|
1589
|
+
children: Inner
|
|
1590
|
+
}
|
|
1591
|
+
)
|
|
1592
|
+
}
|
|
1593
|
+
) : Inner
|
|
1594
|
+
},
|
|
1595
|
+
cell.id
|
|
1596
|
+
);
|
|
1597
|
+
})
|
|
1598
|
+
},
|
|
1599
|
+
row.id
|
|
1600
|
+
);
|
|
1601
|
+
}) })
|
|
1602
|
+
] }) : /* @__PURE__ */ jsx11("div", { className: clx8({ "border-b": layout === "fit" }), children: /* @__PURE__ */ jsx11(NoResults, {}) })
|
|
1603
|
+
}
|
|
1604
|
+
),
|
|
1605
|
+
pagination && /* @__PURE__ */ jsx11("div", { className: clx8({ "border-t": layout === "fill" }), children: /* @__PURE__ */ jsx11(
|
|
1606
|
+
Pagination,
|
|
1607
|
+
{
|
|
1608
|
+
canNextPage: table.getCanNextPage(),
|
|
1609
|
+
canPreviousPage: table.getCanPreviousPage(),
|
|
1610
|
+
nextPage: table.nextPage,
|
|
1611
|
+
previousPage: table.previousPage,
|
|
1612
|
+
count,
|
|
1613
|
+
pageIndex,
|
|
1614
|
+
pageCount: table.getPageCount(),
|
|
1615
|
+
pageSize
|
|
1616
|
+
}
|
|
1617
|
+
) }),
|
|
1618
|
+
hasCommandBar && /* @__PURE__ */ jsx11(CommandBar, { open: !!Object.keys(rowSelection).length, children: /* @__PURE__ */ jsxs10(CommandBar.Bar, { children: [
|
|
1619
|
+
/* @__PURE__ */ jsx11(CommandBar.Value, { children: t2("general.countSelected", {
|
|
1620
|
+
count: Object.keys(rowSelection).length
|
|
1621
|
+
}) }),
|
|
1622
|
+
/* @__PURE__ */ jsx11(CommandBar.Seperator, {}),
|
|
1623
|
+
commands?.map((command, index) => {
|
|
1624
|
+
return /* @__PURE__ */ jsxs10(Fragment, { children: [
|
|
1625
|
+
/* @__PURE__ */ jsx11(
|
|
1626
|
+
CommandBar.Command,
|
|
1627
|
+
{
|
|
1628
|
+
label: command.label,
|
|
1629
|
+
shortcut: command.shortcut,
|
|
1630
|
+
action: () => handleAction(command.action)
|
|
1631
|
+
}
|
|
1632
|
+
),
|
|
1633
|
+
index < commands.length - 1 && /* @__PURE__ */ jsx11(CommandBar.Seperator, {})
|
|
1634
|
+
] }, index);
|
|
1635
|
+
})
|
|
1636
|
+
] }) })
|
|
1637
|
+
]
|
|
1638
|
+
}
|
|
1639
|
+
);
|
|
1640
|
+
};
|
|
1641
|
+
var Pagination = (props) => {
|
|
1642
|
+
const { t: t2 } = useTranslation9();
|
|
1643
|
+
const translations = {
|
|
1644
|
+
of: t2("general.of"),
|
|
1645
|
+
results: t2("general.results"),
|
|
1646
|
+
pages: t2("general.pages"),
|
|
1647
|
+
prev: t2("general.prev"),
|
|
1648
|
+
next: t2("general.next")
|
|
1649
|
+
};
|
|
1650
|
+
return /* @__PURE__ */ jsx11(
|
|
1651
|
+
Table.Pagination,
|
|
1652
|
+
{
|
|
1653
|
+
className: "flex-shrink-0",
|
|
1654
|
+
...props,
|
|
1655
|
+
translations
|
|
1656
|
+
}
|
|
1657
|
+
);
|
|
1658
|
+
};
|
|
1659
|
+
|
|
1660
|
+
// src/components/table/data-table/data-table.tsx
|
|
1661
|
+
import { jsx as jsx12, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
1662
|
+
var MemoizedDataTableQuery = memo(DataTableQuery);
|
|
1663
|
+
var _DataTable = ({
|
|
1664
|
+
table,
|
|
1665
|
+
columns,
|
|
1666
|
+
pagination,
|
|
1667
|
+
navigateTo,
|
|
1668
|
+
commands,
|
|
1669
|
+
count = 0,
|
|
1670
|
+
search = false,
|
|
1671
|
+
orderBy,
|
|
1672
|
+
filters,
|
|
1673
|
+
prefix,
|
|
1674
|
+
queryObject = {},
|
|
1675
|
+
pageSize,
|
|
1676
|
+
isLoading = false,
|
|
1677
|
+
noHeader = false,
|
|
1678
|
+
layout = "fit",
|
|
1679
|
+
noRecords: noRecordsProps = {}
|
|
1680
|
+
}) => {
|
|
1681
|
+
if (isLoading) {
|
|
1682
|
+
return /* @__PURE__ */ jsx12(
|
|
1683
|
+
TableSkeleton,
|
|
1684
|
+
{
|
|
1685
|
+
layout,
|
|
1686
|
+
rowCount: pageSize,
|
|
1687
|
+
search: !!search,
|
|
1688
|
+
filters: !!filters?.length,
|
|
1689
|
+
orderBy: !!orderBy?.length,
|
|
1690
|
+
pagination: !!pagination
|
|
1691
|
+
}
|
|
1692
|
+
);
|
|
1693
|
+
}
|
|
1694
|
+
const noQuery = Object.values(queryObject).filter((v) => Boolean(v)).length === 0;
|
|
1695
|
+
const noResults = !isLoading && count === 0 && !noQuery;
|
|
1696
|
+
const noRecords = !isLoading && count === 0 && noQuery;
|
|
1697
|
+
if (noRecords) {
|
|
1698
|
+
return /* @__PURE__ */ jsx12(
|
|
1699
|
+
NoRecords,
|
|
1700
|
+
{
|
|
1701
|
+
className: clx9({
|
|
1702
|
+
"flex h-full flex-col overflow-hidden": layout === "fill"
|
|
1703
|
+
}),
|
|
1704
|
+
...noRecordsProps
|
|
1705
|
+
}
|
|
1706
|
+
);
|
|
1707
|
+
}
|
|
1708
|
+
return /* @__PURE__ */ jsxs11(
|
|
1709
|
+
"div",
|
|
1710
|
+
{
|
|
1711
|
+
className: clx9("divide-y", {
|
|
1712
|
+
"flex h-full flex-col overflow-hidden": layout === "fill"
|
|
1713
|
+
}),
|
|
1714
|
+
children: [
|
|
1715
|
+
/* @__PURE__ */ jsx12(
|
|
1716
|
+
MemoizedDataTableQuery,
|
|
1717
|
+
{
|
|
1718
|
+
search,
|
|
1719
|
+
orderBy,
|
|
1720
|
+
filters,
|
|
1721
|
+
prefix
|
|
1722
|
+
}
|
|
1723
|
+
),
|
|
1724
|
+
/* @__PURE__ */ jsx12(
|
|
1725
|
+
DataTableRoot,
|
|
1726
|
+
{
|
|
1727
|
+
table,
|
|
1728
|
+
count,
|
|
1729
|
+
columns,
|
|
1730
|
+
pagination: true,
|
|
1731
|
+
navigateTo,
|
|
1732
|
+
commands,
|
|
1733
|
+
noResults,
|
|
1734
|
+
noHeader,
|
|
1735
|
+
layout
|
|
1736
|
+
}
|
|
1737
|
+
)
|
|
1738
|
+
]
|
|
1739
|
+
}
|
|
1740
|
+
);
|
|
1741
|
+
};
|
|
1742
|
+
|
|
1743
|
+
// src/hooks/use-data-table.tsx
|
|
1744
|
+
import {
|
|
1745
|
+
getCoreRowModel,
|
|
1746
|
+
getExpandedRowModel,
|
|
1747
|
+
getPaginationRowModel,
|
|
1748
|
+
useReactTable
|
|
1749
|
+
} from "@tanstack/react-table";
|
|
1750
|
+
import { useEffect as useEffect6, useMemo as useMemo3, useState as useState8 } from "react";
|
|
1751
|
+
import { useSearchParams as useSearchParams4 } from "react-router-dom";
|
|
1752
|
+
var useDataTable = ({
|
|
1753
|
+
data = [],
|
|
1754
|
+
columns,
|
|
1755
|
+
count = 0,
|
|
1756
|
+
pageSize: _pageSize = 20,
|
|
1757
|
+
enablePagination = true,
|
|
1758
|
+
enableRowSelection = false,
|
|
1759
|
+
enableExpandableRows = false,
|
|
1760
|
+
rowSelection: _rowSelection,
|
|
1761
|
+
getSubRows,
|
|
1762
|
+
getRowId,
|
|
1763
|
+
meta,
|
|
1764
|
+
prefix
|
|
1765
|
+
}) => {
|
|
1766
|
+
const [searchParams, setSearchParams] = useSearchParams4();
|
|
1767
|
+
const offsetKey = `${prefix ? `${prefix}_` : ""}offset`;
|
|
1768
|
+
const offset = searchParams.get(offsetKey);
|
|
1769
|
+
const [{ pageIndex, pageSize }, setPagination] = useState8({
|
|
1770
|
+
pageIndex: offset ? Math.ceil(Number(offset) / _pageSize) : 0,
|
|
1771
|
+
pageSize: _pageSize
|
|
1772
|
+
});
|
|
1773
|
+
const pagination = useMemo3(
|
|
1774
|
+
() => ({
|
|
1775
|
+
pageIndex,
|
|
1776
|
+
pageSize
|
|
1777
|
+
}),
|
|
1778
|
+
[pageIndex, pageSize]
|
|
1779
|
+
);
|
|
1780
|
+
const [localRowSelection, setLocalRowSelection] = useState8({});
|
|
1781
|
+
const rowSelection = _rowSelection?.state ?? localRowSelection;
|
|
1782
|
+
const setRowSelection = _rowSelection?.updater ?? setLocalRowSelection;
|
|
1783
|
+
useEffect6(() => {
|
|
1784
|
+
if (!enablePagination) {
|
|
1785
|
+
return;
|
|
1786
|
+
}
|
|
1787
|
+
const index = offset ? Math.ceil(Number(offset) / _pageSize) : 0;
|
|
1788
|
+
if (index === pageIndex) {
|
|
1789
|
+
return;
|
|
1790
|
+
}
|
|
1791
|
+
setPagination((prev) => ({
|
|
1792
|
+
...prev,
|
|
1793
|
+
pageIndex: index
|
|
1794
|
+
}));
|
|
1795
|
+
}, [offset, enablePagination, _pageSize, pageIndex]);
|
|
1796
|
+
const onPaginationChange = (updater) => {
|
|
1797
|
+
const state = updater(pagination);
|
|
1798
|
+
const { pageIndex: pageIndex2, pageSize: pageSize2 } = state;
|
|
1799
|
+
setSearchParams((prev) => {
|
|
1800
|
+
if (!pageIndex2) {
|
|
1801
|
+
prev.delete(offsetKey);
|
|
1802
|
+
return prev;
|
|
1803
|
+
}
|
|
1804
|
+
const newSearch = new URLSearchParams(prev);
|
|
1805
|
+
newSearch.set(offsetKey, String(pageIndex2 * pageSize2));
|
|
1806
|
+
return newSearch;
|
|
1807
|
+
});
|
|
1808
|
+
setPagination(state);
|
|
1809
|
+
return state;
|
|
1810
|
+
};
|
|
1811
|
+
const table = useReactTable({
|
|
1812
|
+
data,
|
|
1813
|
+
columns,
|
|
1814
|
+
state: {
|
|
1815
|
+
rowSelection,
|
|
1816
|
+
// We always pass a selection state to the table even if it's not enabled
|
|
1817
|
+
pagination: enablePagination ? pagination : void 0
|
|
1818
|
+
},
|
|
1819
|
+
pageCount: Math.ceil((count ?? 0) / pageSize),
|
|
1820
|
+
enableRowSelection,
|
|
1821
|
+
getRowId,
|
|
1822
|
+
getSubRows,
|
|
1823
|
+
onRowSelectionChange: enableRowSelection ? setRowSelection : void 0,
|
|
1824
|
+
onPaginationChange: enablePagination ? onPaginationChange : void 0,
|
|
1825
|
+
getCoreRowModel: getCoreRowModel(),
|
|
1826
|
+
getPaginationRowModel: enablePagination ? getPaginationRowModel() : void 0,
|
|
1827
|
+
getExpandedRowModel: enableExpandableRows ? getExpandedRowModel() : void 0,
|
|
1828
|
+
manualPagination: enablePagination ? true : void 0,
|
|
1829
|
+
meta
|
|
1830
|
+
});
|
|
1831
|
+
return { table };
|
|
1832
|
+
};
|
|
1833
|
+
|
|
1834
|
+
export {
|
|
1835
|
+
_DataTable,
|
|
1836
|
+
useDataTable
|
|
1837
|
+
};
|