ar-design 0.2.20 → 0.2.22
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/components/data-display/grid-system/box/Box.d.ts +1 -0
- package/dist/components/data-display/grid-system/box/Box.js +2 -1
- package/dist/components/data-display/grid-system/index.d.ts +1 -0
- package/dist/components/data-display/table/_index.d.ts +13 -0
- package/dist/components/data-display/table/_index.js +412 -0
- package/dist/components/data-display/table/index.d.ts +5 -11
- package/dist/components/data-display/table/index.js +23 -94
- package/dist/components/form/select/index.js +25 -13
- package/package.json +1 -1
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
const Box = ({ children }) => {
|
|
2
|
+
const Box = ({ children, direction = "flex-start", }) => {
|
|
3
3
|
return (React.createElement("div", { style: {
|
|
4
4
|
display: "flex",
|
|
5
5
|
flexDirection: "row",
|
|
6
6
|
flexWrap: "nowrap",
|
|
7
|
+
justifyContent: direction,
|
|
7
8
|
alignItems: "center",
|
|
8
9
|
gap: ".5rem",
|
|
9
10
|
} }, children));
|
|
@@ -2,6 +2,7 @@ import "../../../assets/css/components/data-display/grid-system/styles.css";
|
|
|
2
2
|
declare const Grid: {
|
|
3
3
|
Box: import("react").FC<{
|
|
4
4
|
children: import("react").ReactNode;
|
|
5
|
+
direction?: "flex-start" | "center" | "flex-end";
|
|
5
6
|
}>;
|
|
6
7
|
Row: import("react").FC<import("./row/Types").Props>;
|
|
7
8
|
Column: import("react").FC<import("./column/IProps").default>;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import "../../../assets/css/components/data-display/table/styles.css";
|
|
2
|
+
import IProps from "./IProps";
|
|
3
|
+
import React, { ReactElement } from "react";
|
|
4
|
+
declare const TableWithRef: <T>(props: IProps<T> & {
|
|
5
|
+
ref?: React.ForwardedRef<HTMLTableElement>;
|
|
6
|
+
}) => ReactElement;
|
|
7
|
+
type TableCompoundComponents = typeof TableWithRef & {
|
|
8
|
+
Actions: React.FC<{
|
|
9
|
+
children: React.ReactElement | React.ReactElement[];
|
|
10
|
+
}>;
|
|
11
|
+
};
|
|
12
|
+
declare const Table: TableCompoundComponents;
|
|
13
|
+
export default Table;
|
|
@@ -0,0 +1,412 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import "../../../assets/css/components/data-display/table/styles.css";
|
|
3
|
+
import { ARIcon } from "../../icons";
|
|
4
|
+
import Button from "../../form/button";
|
|
5
|
+
import Checkbox from "../../form/checkbox";
|
|
6
|
+
import Pagination from "../../navigation/pagination";
|
|
7
|
+
import React, { forwardRef, useCallback, useEffect, useImperativeHandle, useRef, useState } from "react";
|
|
8
|
+
import Actions from "./Actions";
|
|
9
|
+
import Input from "../../form/input";
|
|
10
|
+
import Popover from "../../feedback/popover";
|
|
11
|
+
const TableWithRef = forwardRef(({ children, title, description, data, columns, actions, selections, previousSelections, searchedParams, pagination, config = { isSearchable: false }, }, ref) => {
|
|
12
|
+
// refs
|
|
13
|
+
const _tableWrapper = useRef(null);
|
|
14
|
+
const _table = useRef(null);
|
|
15
|
+
const _tableContent = useRef(null);
|
|
16
|
+
const _checkboxItems = useRef([]);
|
|
17
|
+
const _filterCheckboxItems = useRef([]);
|
|
18
|
+
// refs -> Search
|
|
19
|
+
const _searchTextInputs = useRef([]);
|
|
20
|
+
const _searchTimeOut = useRef(null);
|
|
21
|
+
// className
|
|
22
|
+
const _tableClassName = ["ar-table", "scroll"];
|
|
23
|
+
// states
|
|
24
|
+
const [selectAll, setSelectAll] = useState(false);
|
|
25
|
+
const [selectionItems, setSelectionItems] = useState([]);
|
|
26
|
+
// const [thWidths, setThWidths] = useState<number[]>([]);
|
|
27
|
+
// states -> Search
|
|
28
|
+
const [searchedText, setSearchedText] = useState(undefined);
|
|
29
|
+
const [_searchedParams, setSearchedParams] = useState(undefined);
|
|
30
|
+
const [checkboxSelectedParams, setCheckboxSelectedParams] = useState(undefined);
|
|
31
|
+
// const [selectedfilterCheckboxItems, setSelectedfilterCheckboxItems] = useState<
|
|
32
|
+
// {
|
|
33
|
+
// selectedCount: number;
|
|
34
|
+
// columnKey: string;
|
|
35
|
+
// }[]
|
|
36
|
+
// >([]);
|
|
37
|
+
// const [searchedFilters, setSearchedFilters] = useState<string | undefined>(undefined);
|
|
38
|
+
// const [totalRecords, setTotalRecords] = useState<number>(0);
|
|
39
|
+
const [currentPage, setCurrentPage] = useState(1);
|
|
40
|
+
if (config && Object.keys(config.scroll || {}).length > 0) {
|
|
41
|
+
if (_tableContent.current && config.scroll) {
|
|
42
|
+
if (config.scroll.maxHeight) {
|
|
43
|
+
_tableContent.current.style.maxHeight = `${config?.scroll?.maxHeight}rem`;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
// Custom Attributes
|
|
48
|
+
useImperativeHandle(ref, () => {
|
|
49
|
+
const tableCurrent = _table.current;
|
|
50
|
+
return {
|
|
51
|
+
...tableCurrent,
|
|
52
|
+
filterCleaner: () => {
|
|
53
|
+
if (config.isServerSide) {
|
|
54
|
+
setSearchedParams({});
|
|
55
|
+
pagination && pagination.onChange(1);
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
setSearchedText({});
|
|
59
|
+
}
|
|
60
|
+
setCurrentPage(1);
|
|
61
|
+
_searchTextInputs.current.map((item) => item && (item.value = ""));
|
|
62
|
+
},
|
|
63
|
+
};
|
|
64
|
+
});
|
|
65
|
+
// methods
|
|
66
|
+
const handleScroll = () => {
|
|
67
|
+
if (!_tableWrapper.current)
|
|
68
|
+
return;
|
|
69
|
+
const wrapperRect = _tableWrapper.current.getBoundingClientRect();
|
|
70
|
+
const updateStickyPositions = (elements) => {
|
|
71
|
+
elements.forEach((element) => {
|
|
72
|
+
const leftChildren = Array.from(element.childNodes)
|
|
73
|
+
.filter((node) => node.nodeType === Node.ELEMENT_NODE)
|
|
74
|
+
.filter((child) => child.dataset.stickyPosition === "left");
|
|
75
|
+
const rightChildren = Array.from(element.childNodes)
|
|
76
|
+
.filter((node) => node.nodeType === Node.ELEMENT_NODE)
|
|
77
|
+
.filter((child) => child.dataset.stickyPosition === "right")
|
|
78
|
+
.reverse();
|
|
79
|
+
// Calculate positions and minimize `getBoundingClientRect` calls
|
|
80
|
+
const leftRects = leftChildren.map((child) => child.getBoundingClientRect());
|
|
81
|
+
const rightRects = rightChildren.map((child) => child.getBoundingClientRect());
|
|
82
|
+
const leftPrevious = leftRects.map((rect) => Math.abs(rect.right - wrapperRect.left));
|
|
83
|
+
const rightPrevious = rightRects.map((rect) => Math.abs(rect.left - wrapperRect.right));
|
|
84
|
+
// #region Left
|
|
85
|
+
leftChildren.forEach((child, index) => {
|
|
86
|
+
const prevLeft = index > 0 ? leftPrevious[index - 1] : 0;
|
|
87
|
+
if (index > 0) {
|
|
88
|
+
const childLeft = leftRects[index].left - wrapperRect.left;
|
|
89
|
+
if (Math.floor(childLeft) === Math.floor(prevLeft)) {
|
|
90
|
+
if (!child.classList.contains("active-sticky"))
|
|
91
|
+
child.classList.add("active-sticky");
|
|
92
|
+
}
|
|
93
|
+
else
|
|
94
|
+
child.classList.remove("active-sticky");
|
|
95
|
+
child.style.left = `${prevLeft}px`;
|
|
96
|
+
}
|
|
97
|
+
else
|
|
98
|
+
child.classList.add("sticky");
|
|
99
|
+
if (child.nodeName === "TD")
|
|
100
|
+
child.style.zIndex = `${leftChildren.length - index}`;
|
|
101
|
+
});
|
|
102
|
+
// #endregion
|
|
103
|
+
// #region Right
|
|
104
|
+
rightChildren.forEach((child, index) => {
|
|
105
|
+
const prevRight = index > 0 ? rightPrevious[index - 1] : 0;
|
|
106
|
+
if (index > 0) {
|
|
107
|
+
const childRight = Math.abs(rightRects[index].right - wrapperRect.right);
|
|
108
|
+
if (Math.floor(childRight) === Math.floor(prevRight)) {
|
|
109
|
+
if (!child.classList.contains("active-sticky"))
|
|
110
|
+
child.classList.add("active-sticky");
|
|
111
|
+
}
|
|
112
|
+
else
|
|
113
|
+
child.classList.remove("active-sticky");
|
|
114
|
+
child.style.right = `${prevRight}px`;
|
|
115
|
+
}
|
|
116
|
+
else
|
|
117
|
+
child.classList.add("sticky");
|
|
118
|
+
});
|
|
119
|
+
// #endregion
|
|
120
|
+
});
|
|
121
|
+
};
|
|
122
|
+
const theadElements = _tableWrapper.current.querySelectorAll("table > thead > tr");
|
|
123
|
+
const tbodyElements = _tableWrapper.current.querySelectorAll("table > tbody > tr");
|
|
124
|
+
requestAnimationFrame(() => {
|
|
125
|
+
updateStickyPositions(theadElements);
|
|
126
|
+
updateStickyPositions(tbodyElements);
|
|
127
|
+
});
|
|
128
|
+
};
|
|
129
|
+
const handleSearch = (event) => {
|
|
130
|
+
if (config.isServerSide) {
|
|
131
|
+
if (_searchTimeOut.current)
|
|
132
|
+
clearTimeout(_searchTimeOut.current);
|
|
133
|
+
_searchTimeOut.current = setTimeout(() => {
|
|
134
|
+
setSearchedParams((prev) => ({ ...prev, [event.target.name]: event.target.value }));
|
|
135
|
+
setCurrentPage(1);
|
|
136
|
+
pagination && pagination.onChange(1);
|
|
137
|
+
}, 750);
|
|
138
|
+
}
|
|
139
|
+
else {
|
|
140
|
+
setCurrentPage(1);
|
|
141
|
+
setSearchedText((prev) => ({ ...prev, [event.target.name]: event.target.value }));
|
|
142
|
+
}
|
|
143
|
+
};
|
|
144
|
+
const handleCheckboxChange = useCallback(async (event) => {
|
|
145
|
+
event.stopPropagation();
|
|
146
|
+
setCheckboxSelectedParams((prev) => {
|
|
147
|
+
const updatedValues = new Set(prev?.[event.target.name] || []);
|
|
148
|
+
event.target.checked ? updatedValues.add(event.target.value) : updatedValues.delete(event.target.value);
|
|
149
|
+
return {
|
|
150
|
+
...prev,
|
|
151
|
+
...(Array.from(updatedValues).length > 0
|
|
152
|
+
? { [event.target.name]: Array.from(updatedValues) }
|
|
153
|
+
: { [event.target.name]: [] }),
|
|
154
|
+
};
|
|
155
|
+
});
|
|
156
|
+
}, []);
|
|
157
|
+
// Derinlemesine arama yapmak için özyinelemeli bir fonksiyon tanımlayalım.
|
|
158
|
+
const deepSearch = (item, searchedText) => {
|
|
159
|
+
if (!searchedText)
|
|
160
|
+
return false;
|
|
161
|
+
// Eğer değer bir sayı veya string ise, aranan metinle eşleşip eşleşmediğini kontrol ediyoruz.
|
|
162
|
+
return Object.entries(searchedText).every(([key, value]) => {
|
|
163
|
+
const _itemValue = item[key];
|
|
164
|
+
if (typeof _itemValue === "number" || typeof _itemValue === "string") {
|
|
165
|
+
if (Array.isArray(value)) {
|
|
166
|
+
if (value.length === 0)
|
|
167
|
+
return true;
|
|
168
|
+
else
|
|
169
|
+
return value.some((v) => _itemValue.toString().toLocaleLowerCase().includes(v.toLocaleLowerCase()));
|
|
170
|
+
}
|
|
171
|
+
return _itemValue.toString().toLocaleLowerCase().includes(value.toLocaleLowerCase());
|
|
172
|
+
}
|
|
173
|
+
if (typeof _itemValue === "object") {
|
|
174
|
+
if (Array.isArray(value)) {
|
|
175
|
+
if (value.length === 0)
|
|
176
|
+
return true;
|
|
177
|
+
else {
|
|
178
|
+
return value.some((v) => Object.entries(_itemValue ?? {}).some(([_, objValue]) => String(objValue).toLocaleLowerCase().includes(v.toLocaleLowerCase())));
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
return Object.entries(_itemValue ?? {}).some(([_, objValue]) => String(objValue).toLocaleLowerCase().includes(value.toLocaleLowerCase()));
|
|
182
|
+
}
|
|
183
|
+
if (Array.isArray(_itemValue)) {
|
|
184
|
+
console.log("Buradasın", _itemValue);
|
|
185
|
+
}
|
|
186
|
+
return false;
|
|
187
|
+
});
|
|
188
|
+
};
|
|
189
|
+
const getData = useCallback(() => {
|
|
190
|
+
let _data = [...data];
|
|
191
|
+
if (searchedText)
|
|
192
|
+
_data = _data.filter((item) => deepSearch(item, searchedText));
|
|
193
|
+
if (pagination && !config.isServerSide) {
|
|
194
|
+
const indexOfLastRow = currentPage * pagination.perPage;
|
|
195
|
+
const indexOfFirstRow = indexOfLastRow - pagination.perPage;
|
|
196
|
+
_data = _data.slice(indexOfFirstRow, indexOfLastRow);
|
|
197
|
+
}
|
|
198
|
+
// Veriler yenilenmesi durumunda tablo üzerindeki hesaplamalar tekrar yapılacaktır.
|
|
199
|
+
setTimeout(() => handleScroll(), 0);
|
|
200
|
+
return _data;
|
|
201
|
+
}, [data, searchedText, currentPage]);
|
|
202
|
+
// useEffects
|
|
203
|
+
useEffect(() => {
|
|
204
|
+
// Eğer `previousSelections` özelliğinden değer geliyorsa bu daha önce seçim yapılmış öğeleri gönderiyorum
|
|
205
|
+
// demektir ve otomatik olarak seçim yap demek anlamına gekmektedir.
|
|
206
|
+
if (previousSelections && previousSelections.length > 0) {
|
|
207
|
+
const validSelections = data.filter((item) => previousSelections.some((selected) => JSON.stringify(selected) === JSON.stringify(item)));
|
|
208
|
+
setSelectionItems(validSelections);
|
|
209
|
+
}
|
|
210
|
+
}, [previousSelections]);
|
|
211
|
+
useEffect(() => {
|
|
212
|
+
if (!selections || selectionItems.length === 0)
|
|
213
|
+
return;
|
|
214
|
+
selections(selectionItems);
|
|
215
|
+
}, [selectionItems]);
|
|
216
|
+
useEffect(() => {
|
|
217
|
+
if (config?.isServerSide && searchedParams) {
|
|
218
|
+
// const query = Object.entries(_searchedParams ?? {})
|
|
219
|
+
// .map(([key, value]) => {
|
|
220
|
+
// return `${key}=${value}`;
|
|
221
|
+
// })
|
|
222
|
+
// .join("&");
|
|
223
|
+
const query = new URLSearchParams(_searchedParams).toString();
|
|
224
|
+
searchedParams(_searchedParams, query);
|
|
225
|
+
}
|
|
226
|
+
}, [_searchedParams]);
|
|
227
|
+
useEffect(() => {
|
|
228
|
+
if (config.isServerSide) {
|
|
229
|
+
if (_searchTimeOut.current)
|
|
230
|
+
clearTimeout(_searchTimeOut.current);
|
|
231
|
+
setSearchedParams(checkboxSelectedParams);
|
|
232
|
+
}
|
|
233
|
+
else {
|
|
234
|
+
setSearchedText(checkboxSelectedParams);
|
|
235
|
+
}
|
|
236
|
+
setCurrentPage(1);
|
|
237
|
+
pagination && pagination.onChange(1);
|
|
238
|
+
// Filters...
|
|
239
|
+
// setSelectedfilterCheckboxItems((prev) => {
|
|
240
|
+
// debugger;
|
|
241
|
+
// const columnKeys = Object.keys(checkboxSelectedParams ?? {});
|
|
242
|
+
// const selectedCount = _filterCheckboxItems.current.filter((x) => x?.checked).length;
|
|
243
|
+
// const updatedItems = [...prev];
|
|
244
|
+
// columnKeys.forEach((columnKey) => {
|
|
245
|
+
// const existingIndex = updatedItems.findIndex((item) => item.columnKey === columnKey);
|
|
246
|
+
// if (existingIndex !== -1) {
|
|
247
|
+
// // Eğer aynı key varsa, güncelle
|
|
248
|
+
// updatedItems[existingIndex] = { columnKey, selectedCount };
|
|
249
|
+
// } else {
|
|
250
|
+
// // Eğer aynı key yoksa, ekle
|
|
251
|
+
// updatedItems.push({ columnKey, selectedCount });
|
|
252
|
+
// }
|
|
253
|
+
// });
|
|
254
|
+
// return updatedItems;
|
|
255
|
+
// });
|
|
256
|
+
}, [checkboxSelectedParams]);
|
|
257
|
+
useEffect(() => {
|
|
258
|
+
if (!selections)
|
|
259
|
+
return;
|
|
260
|
+
let allChecked = false;
|
|
261
|
+
if (_checkboxItems.current.length > 0) {
|
|
262
|
+
allChecked = _checkboxItems.current.every((item) => item?.checked === true);
|
|
263
|
+
}
|
|
264
|
+
setSelectAll(allChecked);
|
|
265
|
+
}, [selectionItems, currentPage]);
|
|
266
|
+
// useEffect(() => {
|
|
267
|
+
// if (!_tableContent.current) return;
|
|
268
|
+
// const th = _tableContent.current?.querySelectorAll("table > thead > tr:first-child > th");
|
|
269
|
+
// th.forEach((item) => setThWidths((prev) => [...prev, item.getBoundingClientRect().width]));
|
|
270
|
+
// }, []);
|
|
271
|
+
return (React.createElement("div", { ref: _tableWrapper, className: _tableClassName.map((c) => c).join(" ") },
|
|
272
|
+
(title || description || actions || React.Children.count(children) > 0) && (React.createElement("div", { className: "header" },
|
|
273
|
+
React.createElement("div", { className: "title" },
|
|
274
|
+
React.createElement("h3", null, title),
|
|
275
|
+
React.createElement("h5", null, description)),
|
|
276
|
+
React.createElement("div", { className: "actions" },
|
|
277
|
+
React.Children.count(children) > 0 && React.createElement("div", null, React.Children.map(children, (child) => child)),
|
|
278
|
+
actions && (React.createElement(React.Fragment, null,
|
|
279
|
+
actions.create && (React.createElement(Button, { variant: "outlined", status: "dark", icon: { element: React.createElement(ARIcon, { icon: "Add", size: 16 }) }, tooltip: { text: actions.create.tooltip, direction: "top" }, onClick: actions.create.onClick })),
|
|
280
|
+
actions.import && (React.createElement(Button, { variant: "outlined", status: "dark", icon: { element: React.createElement(ARIcon, { icon: "Import", size: 16 }) }, tooltip: { text: actions.import.tooltip, direction: "top" }, onClick: actions.import.onClick })),
|
|
281
|
+
actions.filterClear && (React.createElement(Button, { variant: "outlined", status: "dark", icon: { element: React.createElement(ARIcon, { icon: "Trash", size: 16 }) }, tooltip: { text: actions.filterClear.tooltip, direction: "top" }, onClick: actions.filterClear.onClick }))))))),
|
|
282
|
+
React.createElement("div", { ref: _tableContent, className: "content", onScroll: handleScroll },
|
|
283
|
+
React.createElement("table", { ref: ref },
|
|
284
|
+
React.createElement("thead", null,
|
|
285
|
+
React.createElement("tr", { key: "selection" },
|
|
286
|
+
selections && (React.createElement("th", { className: "selection-col sticky-left", "data-sticky-position": "left" },
|
|
287
|
+
React.createElement(Checkbox, { variant: "filled", status: "primary", checked: selectAll, onChange: (event) => {
|
|
288
|
+
if (_checkboxItems.current.length > 0) {
|
|
289
|
+
setSelectAll(event.target.checked);
|
|
290
|
+
_checkboxItems.current.forEach((item) => {
|
|
291
|
+
if (item) {
|
|
292
|
+
if (item.checked !== event.target.checked)
|
|
293
|
+
item.click();
|
|
294
|
+
}
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
} }))),
|
|
298
|
+
columns.map((c, cIndex) => {
|
|
299
|
+
let _className = [];
|
|
300
|
+
if (c.config?.sticky)
|
|
301
|
+
_className.push(`sticky-${c.config.sticky}`);
|
|
302
|
+
if (!c.config?.width)
|
|
303
|
+
_className.push("min-w");
|
|
304
|
+
if (c.config?.alignContent) {
|
|
305
|
+
_className.push(`align-content-${c.config.alignContent}`);
|
|
306
|
+
}
|
|
307
|
+
return (React.createElement("th", { key: `column-${cIndex}-${Math.random()}`, ...(_className.length > 0 && {
|
|
308
|
+
className: `${_className.map((c) => c).join(" ")}`,
|
|
309
|
+
}), ...(c.config?.width
|
|
310
|
+
? {
|
|
311
|
+
style: { minWidth: c.config.width },
|
|
312
|
+
}
|
|
313
|
+
: // : { style: { maxWidth: thWidths[cIndex], minWidth: thWidths[cIndex] } })}
|
|
314
|
+
{ style: {} }), ...(c.config?.sticky && {
|
|
315
|
+
"data-sticky-position": c.config.sticky,
|
|
316
|
+
}) }, c.title));
|
|
317
|
+
})),
|
|
318
|
+
config?.isSearchable && (React.createElement("tr", { key: "isSearchable" },
|
|
319
|
+
selections && (React.createElement("th", { key: `column-selections`, className: "selection-col sticky-left", "data-sticky-position": "left" })),
|
|
320
|
+
columns.map((c, cIndex) => {
|
|
321
|
+
if (!c.key)
|
|
322
|
+
return React.createElement("th", null);
|
|
323
|
+
let _className = [];
|
|
324
|
+
if (c.config?.sticky)
|
|
325
|
+
_className.push(`sticky-${c.config.sticky}`);
|
|
326
|
+
if (c.config?.alignContent) {
|
|
327
|
+
_className.push(`align-content-${c.config.alignContent}`);
|
|
328
|
+
}
|
|
329
|
+
return (React.createElement("th", { key: `column-${cIndex}`, ...(_className.length > 0 && {
|
|
330
|
+
className: `${_className.map((c) => c).join(" ")}`,
|
|
331
|
+
}), ...(c.config?.sticky && {
|
|
332
|
+
"data-sticky-position": c.config.sticky,
|
|
333
|
+
}) },
|
|
334
|
+
React.createElement("div", { className: "filter-field" },
|
|
335
|
+
React.createElement(Input, { ref: (element) => (_searchTextInputs.current[cIndex] = element), variant: c.key && !c.filters ? "filled" : "outlined", status: "light", name: typeof c.key !== "object" ? String(c.key) : String(c.key.field), onChange: handleSearch, disabled: !c.key || !!c.filters }),
|
|
336
|
+
c.filters && (React.createElement(Popover, { content: React.createElement(React.Fragment, null,
|
|
337
|
+
React.createElement("div", null, c.filters.map((filter, fIndex) => {
|
|
338
|
+
const name = typeof c.key !== "object" ? String(c.key) : String(c.key.field);
|
|
339
|
+
return (React.createElement("div", null,
|
|
340
|
+
React.createElement(Checkbox, { ref: (element) => (_filterCheckboxItems.current[fIndex] = element), label: filter.text, name: name, status: "primary", value: filter.value, checked: checkboxSelectedParams?.[name]?.includes(String(filter.value)), onChange: async (event) => await handleCheckboxChange(event) })));
|
|
341
|
+
}))), windowBlur: true },
|
|
342
|
+
React.createElement(Button, { variant: "borderless", icon: { element: React.createElement(ARIcon, { icon: "Filter", stroke: "var(--primary)", size: 16 }) } }))))));
|
|
343
|
+
})))),
|
|
344
|
+
React.createElement("tbody", null, getData().length > 0 ? (getData().map((item, index) => (React.createElement("tr", { key: `row-${index}-${Math.random()}` },
|
|
345
|
+
selections && (React.createElement("td", { key: `selection-${index}`, className: "sticky-left", "data-sticky-position": "left" },
|
|
346
|
+
React.createElement(Checkbox, { ref: (element) => (_checkboxItems.current[index] = element), status: "primary", checked: selectionItems.some((selectionItem) => JSON.stringify(selectionItem) === JSON.stringify(item)), onChange: (event) => {
|
|
347
|
+
if (event.target.checked)
|
|
348
|
+
setSelectionItems((prev) => [...prev, item]);
|
|
349
|
+
else
|
|
350
|
+
setSelectionItems((prev) => prev.filter((_item) => _item !== item));
|
|
351
|
+
} }))),
|
|
352
|
+
columns.map((c, cIndex) => {
|
|
353
|
+
let _className = [];
|
|
354
|
+
let render; // TODO: Generic yapmak için çalışma yap. (Daha Sonra)
|
|
355
|
+
// `c.key` bir string ise
|
|
356
|
+
if (typeof c.key !== "object") {
|
|
357
|
+
render = c.render ? c.render(item) : item[c.key];
|
|
358
|
+
}
|
|
359
|
+
// `c.key` bir nesne ise ve `nestedKey` mevcutsa
|
|
360
|
+
else if (typeof c.key === "object") {
|
|
361
|
+
const _item = item[c.key.field];
|
|
362
|
+
if (_item && typeof _item === "object") {
|
|
363
|
+
render = c.render ? c.render(item) : _item[c.key.nestedKey];
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
// Diğer durumlarda `null` döndür
|
|
367
|
+
else {
|
|
368
|
+
render = null;
|
|
369
|
+
}
|
|
370
|
+
// const isTypeOfNumber = typeof render === "number" ? "type-of-number" : "";
|
|
371
|
+
// if (isTypeOfNumber) _className.push(isTypeOfNumber);
|
|
372
|
+
if (c.config?.sticky)
|
|
373
|
+
_className.push(`sticky-${c.config.sticky}`);
|
|
374
|
+
if (c.config?.alignContent)
|
|
375
|
+
_className.push(`align-content-${c.config.alignContent}`);
|
|
376
|
+
if (c.config?.textWrap)
|
|
377
|
+
_className.push(`text-${c.config.textWrap}`);
|
|
378
|
+
return (React.createElement("td", { key: `cell-${index}-${cIndex}`, ...(_className.length > 0 && {
|
|
379
|
+
className: `${_className.map((c) => c).join(" ")}`,
|
|
380
|
+
}), ...(c.config?.width
|
|
381
|
+
? {
|
|
382
|
+
style: { minWidth: c.config.width },
|
|
383
|
+
}
|
|
384
|
+
: // : {
|
|
385
|
+
// style: { maxWidth: thWidths[cIndex], minWidth: thWidths[cIndex] },
|
|
386
|
+
// })}
|
|
387
|
+
{
|
|
388
|
+
style: {},
|
|
389
|
+
}), ...(c.config?.sticky && {
|
|
390
|
+
"data-sticky-position": c.config.sticky,
|
|
391
|
+
}) }, React.isValidElement(render) ? render : String(render)));
|
|
392
|
+
}))))) : (React.createElement("tr", null,
|
|
393
|
+
React.createElement("td", { colSpan: columns.length + 1 }, "Herhangi bir kay\u0131t bulunamad\u0131!")))))),
|
|
394
|
+
pagination && pagination.totalRecords > pagination.perPage && (React.createElement("div", { className: "footer" },
|
|
395
|
+
React.createElement("span", null,
|
|
396
|
+
React.createElement("strong", null,
|
|
397
|
+
"Showing ",
|
|
398
|
+
getData().length),
|
|
399
|
+
" ",
|
|
400
|
+
React.createElement("span", null,
|
|
401
|
+
"of ",
|
|
402
|
+
pagination?.perPage ?? getData().length,
|
|
403
|
+
" agreement")),
|
|
404
|
+
React.createElement(Pagination, { totalRecords: pagination.totalRecords, currentPage: currentPage, perPage: pagination.perPage, onChange: (currentPage) => {
|
|
405
|
+
config.isServerSide && pagination.onChange(currentPage);
|
|
406
|
+
setCurrentPage(currentPage);
|
|
407
|
+
} })))));
|
|
408
|
+
});
|
|
409
|
+
// Actions'ı ekliyoruz.
|
|
410
|
+
const Table = TableWithRef;
|
|
411
|
+
Table.Actions = Actions;
|
|
412
|
+
export default Table;
|
|
@@ -1,13 +1,7 @@
|
|
|
1
1
|
import "../../../assets/css/components/data-display/table/styles.css";
|
|
2
2
|
import IProps from "./IProps";
|
|
3
|
-
import React
|
|
4
|
-
declare const
|
|
5
|
-
ref?: React.
|
|
6
|
-
}) =>
|
|
7
|
-
|
|
8
|
-
Actions: React.FC<{
|
|
9
|
-
children: React.ReactElement | React.ReactElement[];
|
|
10
|
-
}>;
|
|
11
|
-
};
|
|
12
|
-
declare const Table: TableCompoundComponents;
|
|
13
|
-
export default Table;
|
|
3
|
+
import React from "react";
|
|
4
|
+
declare const _default: <T extends object>(props: IProps<T> & {
|
|
5
|
+
ref?: React.Ref<HTMLTableElement>;
|
|
6
|
+
}) => JSX.Element;
|
|
7
|
+
export default _default;
|
|
@@ -4,14 +4,12 @@ import { ARIcon } from "../../icons";
|
|
|
4
4
|
import Button from "../../form/button";
|
|
5
5
|
import Checkbox from "../../form/checkbox";
|
|
6
6
|
import Pagination from "../../navigation/pagination";
|
|
7
|
-
import React, { forwardRef, useCallback, useEffect,
|
|
8
|
-
import Actions from "./Actions";
|
|
7
|
+
import React, { forwardRef, memo, useCallback, useEffect, useRef, useState } from "react";
|
|
9
8
|
import Input from "../../form/input";
|
|
10
9
|
import Popover from "../../feedback/popover";
|
|
11
|
-
const
|
|
10
|
+
const Table = forwardRef(({ children, title, description, data, columns, actions, selections, previousSelections, searchedParams, pagination, config = { isSearchable: false }, }, ref) => {
|
|
12
11
|
// refs
|
|
13
12
|
const _tableWrapper = useRef(null);
|
|
14
|
-
const _table = useRef(null);
|
|
15
13
|
const _tableContent = useRef(null);
|
|
16
14
|
const _checkboxItems = useRef([]);
|
|
17
15
|
const _filterCheckboxItems = useRef([]);
|
|
@@ -23,19 +21,11 @@ const TableWithRef = forwardRef(({ children, title, description, data, columns,
|
|
|
23
21
|
// states
|
|
24
22
|
const [selectAll, setSelectAll] = useState(false);
|
|
25
23
|
const [selectionItems, setSelectionItems] = useState([]);
|
|
26
|
-
// const [thWidths, setThWidths] = useState<number[]>([]);
|
|
27
24
|
// states -> Search
|
|
28
25
|
const [searchedText, setSearchedText] = useState(undefined);
|
|
29
26
|
const [_searchedParams, setSearchedParams] = useState(undefined);
|
|
30
27
|
const [checkboxSelectedParams, setCheckboxSelectedParams] = useState(undefined);
|
|
31
|
-
//
|
|
32
|
-
// {
|
|
33
|
-
// selectedCount: number;
|
|
34
|
-
// columnKey: string;
|
|
35
|
-
// }[]
|
|
36
|
-
// >([]);
|
|
37
|
-
// const [searchedFilters, setSearchedFilters] = useState<string | undefined>(undefined);
|
|
38
|
-
// const [totalRecords, setTotalRecords] = useState<number>(0);
|
|
28
|
+
// states -> Pagination
|
|
39
29
|
const [currentPage, setCurrentPage] = useState(1);
|
|
40
30
|
if (config && Object.keys(config.scroll || {}).length > 0) {
|
|
41
31
|
if (_tableContent.current && config.scroll) {
|
|
@@ -44,24 +34,6 @@ const TableWithRef = forwardRef(({ children, title, description, data, columns,
|
|
|
44
34
|
}
|
|
45
35
|
}
|
|
46
36
|
}
|
|
47
|
-
// Custom Attributes
|
|
48
|
-
useImperativeHandle(ref, () => {
|
|
49
|
-
const tableCurrent = _table.current;
|
|
50
|
-
return {
|
|
51
|
-
...tableCurrent,
|
|
52
|
-
filterCleaner: () => {
|
|
53
|
-
if (config.isServerSide) {
|
|
54
|
-
setSearchedParams({});
|
|
55
|
-
pagination && pagination.onChange(1);
|
|
56
|
-
}
|
|
57
|
-
else {
|
|
58
|
-
setSearchedText({});
|
|
59
|
-
}
|
|
60
|
-
setCurrentPage(1);
|
|
61
|
-
_searchTextInputs.current.map((item) => item && (item.value = ""));
|
|
62
|
-
},
|
|
63
|
-
};
|
|
64
|
-
});
|
|
65
37
|
// methods
|
|
66
38
|
const handleScroll = () => {
|
|
67
39
|
if (!_tableWrapper.current)
|
|
@@ -208,18 +180,8 @@ const TableWithRef = forwardRef(({ children, title, description, data, columns,
|
|
|
208
180
|
setSelectionItems(validSelections);
|
|
209
181
|
}
|
|
210
182
|
}, [previousSelections]);
|
|
211
|
-
useEffect(() => {
|
|
212
|
-
if (!selections || selectionItems.length === 0)
|
|
213
|
-
return;
|
|
214
|
-
selections(selectionItems);
|
|
215
|
-
}, [selectionItems]);
|
|
216
183
|
useEffect(() => {
|
|
217
184
|
if (config?.isServerSide && searchedParams) {
|
|
218
|
-
// const query = Object.entries(_searchedParams ?? {})
|
|
219
|
-
// .map(([key, value]) => {
|
|
220
|
-
// return `${key}=${value}`;
|
|
221
|
-
// })
|
|
222
|
-
// .join("&");
|
|
223
185
|
const query = new URLSearchParams(_searchedParams).toString();
|
|
224
186
|
searchedParams(_searchedParams, query);
|
|
225
187
|
}
|
|
@@ -235,50 +197,25 @@ const TableWithRef = forwardRef(({ children, title, description, data, columns,
|
|
|
235
197
|
}
|
|
236
198
|
setCurrentPage(1);
|
|
237
199
|
pagination && pagination.onChange(1);
|
|
238
|
-
// Filters...
|
|
239
|
-
// setSelectedfilterCheckboxItems((prev) => {
|
|
240
|
-
// debugger;
|
|
241
|
-
// const columnKeys = Object.keys(checkboxSelectedParams ?? {});
|
|
242
|
-
// const selectedCount = _filterCheckboxItems.current.filter((x) => x?.checked).length;
|
|
243
|
-
// const updatedItems = [...prev];
|
|
244
|
-
// columnKeys.forEach((columnKey) => {
|
|
245
|
-
// const existingIndex = updatedItems.findIndex((item) => item.columnKey === columnKey);
|
|
246
|
-
// if (existingIndex !== -1) {
|
|
247
|
-
// // Eğer aynı key varsa, güncelle
|
|
248
|
-
// updatedItems[existingIndex] = { columnKey, selectedCount };
|
|
249
|
-
// } else {
|
|
250
|
-
// // Eğer aynı key yoksa, ekle
|
|
251
|
-
// updatedItems.push({ columnKey, selectedCount });
|
|
252
|
-
// }
|
|
253
|
-
// });
|
|
254
|
-
// return updatedItems;
|
|
255
|
-
// });
|
|
256
200
|
}, [checkboxSelectedParams]);
|
|
257
201
|
useEffect(() => {
|
|
258
202
|
if (!selections)
|
|
259
203
|
return;
|
|
260
|
-
|
|
204
|
+
selections(selectionItems);
|
|
205
|
+
}, [selectionItems]);
|
|
206
|
+
useEffect(() => {
|
|
207
|
+
if (!selections)
|
|
208
|
+
return;
|
|
261
209
|
if (_checkboxItems.current.length > 0) {
|
|
262
|
-
|
|
210
|
+
setSelectAll(_checkboxItems.current.every((item) => item?.checked === true));
|
|
263
211
|
}
|
|
264
|
-
setSelectAll(allChecked);
|
|
265
212
|
}, [selectionItems, currentPage]);
|
|
266
|
-
// useEffect(() => {
|
|
267
|
-
// if (!_tableContent.current) return;
|
|
268
|
-
// const th = _tableContent.current?.querySelectorAll("table > thead > tr:first-child > th");
|
|
269
|
-
// th.forEach((item) => setThWidths((prev) => [...prev, item.getBoundingClientRect().width]));
|
|
270
|
-
// }, []);
|
|
271
213
|
return (React.createElement("div", { ref: _tableWrapper, className: _tableClassName.map((c) => c).join(" ") },
|
|
272
214
|
(title || description || actions || React.Children.count(children) > 0) && (React.createElement("div", { className: "header" },
|
|
273
215
|
React.createElement("div", { className: "title" },
|
|
274
216
|
React.createElement("h3", null, title),
|
|
275
217
|
React.createElement("h5", null, description)),
|
|
276
|
-
React.createElement("div",
|
|
277
|
-
React.Children.count(children) > 0 && React.createElement("div", null, React.Children.map(children, (child) => child)),
|
|
278
|
-
actions && (React.createElement(React.Fragment, null,
|
|
279
|
-
actions.create && (React.createElement(Button, { variant: "outlined", status: "dark", icon: { element: React.createElement(ARIcon, { icon: "Add", size: 16 }) }, tooltip: { text: actions.create.tooltip, direction: "top" }, onClick: actions.create.onClick })),
|
|
280
|
-
actions.import && (React.createElement(Button, { variant: "outlined", status: "dark", icon: { element: React.createElement(ARIcon, { icon: "Import", size: 16 }) }, tooltip: { text: actions.import.tooltip, direction: "top" }, onClick: actions.import.onClick })),
|
|
281
|
-
actions.filterClear && (React.createElement(Button, { variant: "outlined", status: "dark", icon: { element: React.createElement(ARIcon, { icon: "Trash", size: 16 }) }, tooltip: { text: actions.filterClear.tooltip, direction: "top" }, onClick: actions.filterClear.onClick }))))))),
|
|
218
|
+
React.createElement("div", null))),
|
|
282
219
|
React.createElement("div", { ref: _tableContent, className: "content", onScroll: handleScroll },
|
|
283
220
|
React.createElement("table", { ref: ref },
|
|
284
221
|
React.createElement("thead", null,
|
|
@@ -318,8 +255,6 @@ const TableWithRef = forwardRef(({ children, title, description, data, columns,
|
|
|
318
255
|
config?.isSearchable && (React.createElement("tr", { key: "isSearchable" },
|
|
319
256
|
selections && (React.createElement("th", { key: `column-selections`, className: "selection-col sticky-left", "data-sticky-position": "left" })),
|
|
320
257
|
columns.map((c, cIndex) => {
|
|
321
|
-
if (!c.key)
|
|
322
|
-
return React.createElement("th", null);
|
|
323
258
|
let _className = [];
|
|
324
259
|
if (c.config?.sticky)
|
|
325
260
|
_className.push(`sticky-${c.config.sticky}`);
|
|
@@ -330,18 +265,16 @@ const TableWithRef = forwardRef(({ children, title, description, data, columns,
|
|
|
330
265
|
className: `${_className.map((c) => c).join(" ")}`,
|
|
331
266
|
}), ...(c.config?.sticky && {
|
|
332
267
|
"data-sticky-position": c.config.sticky,
|
|
333
|
-
}) },
|
|
334
|
-
React.createElement("
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
}))), windowBlur: true },
|
|
342
|
-
React.createElement(Button, { variant: "borderless", icon: { element: React.createElement(ARIcon, { icon: "Filter", stroke: "var(--primary)", size: 16 }) } }))))));
|
|
268
|
+
}) }, c.key && (React.createElement("div", { className: "filter-field" },
|
|
269
|
+
React.createElement(Input, { ref: (element) => (_searchTextInputs.current[cIndex] = element), variant: c.key && !c.filters ? "filled" : "outlined", status: "light", name: typeof c.key !== "object" ? String(c.key) : String(c.key.field), onChange: handleSearch, disabled: !c.key || !!c.filters }),
|
|
270
|
+
c.filters && (React.createElement(Popover, { content: React.createElement("div", null, c.filters.map((filter, fIndex) => {
|
|
271
|
+
const name = typeof c.key !== "object" ? String(c.key) : String(c.key.field);
|
|
272
|
+
return (React.createElement("div", null,
|
|
273
|
+
React.createElement(Checkbox, { ref: (element) => (_filterCheckboxItems.current[fIndex] = element), label: filter.text, name: name, status: "primary", value: filter.value, checked: checkboxSelectedParams?.[name]?.includes(String(filter.value)), onChange: async (event) => await handleCheckboxChange(event) })));
|
|
274
|
+
})), windowBlur: true },
|
|
275
|
+
React.createElement(Button, { variant: "borderless", icon: { element: React.createElement(ARIcon, { icon: "Filter", stroke: "var(--primary)", size: 16 }) } })))))));
|
|
343
276
|
})))),
|
|
344
|
-
React.createElement("tbody", null, getData().
|
|
277
|
+
React.createElement("tbody", null, getData().map((item, index) => (React.createElement("tr", { key: `row-${index}-${Math.random()}` },
|
|
345
278
|
selections && (React.createElement("td", { key: `selection-${index}`, className: "sticky-left", "data-sticky-position": "left" },
|
|
346
279
|
React.createElement(Checkbox, { ref: (element) => (_checkboxItems.current[index] = element), status: "primary", checked: selectionItems.some((selectionItem) => JSON.stringify(selectionItem) === JSON.stringify(item)), onChange: (event) => {
|
|
347
280
|
if (event.target.checked)
|
|
@@ -367,8 +300,6 @@ const TableWithRef = forwardRef(({ children, title, description, data, columns,
|
|
|
367
300
|
else {
|
|
368
301
|
render = null;
|
|
369
302
|
}
|
|
370
|
-
// const isTypeOfNumber = typeof render === "number" ? "type-of-number" : "";
|
|
371
|
-
// if (isTypeOfNumber) _className.push(isTypeOfNumber);
|
|
372
303
|
if (c.config?.sticky)
|
|
373
304
|
_className.push(`sticky-${c.config.sticky}`);
|
|
374
305
|
if (c.config?.alignContent)
|
|
@@ -389,8 +320,7 @@ const TableWithRef = forwardRef(({ children, title, description, data, columns,
|
|
|
389
320
|
}), ...(c.config?.sticky && {
|
|
390
321
|
"data-sticky-position": c.config.sticky,
|
|
391
322
|
}) }, React.isValidElement(render) ? render : String(render)));
|
|
392
|
-
})))))
|
|
393
|
-
React.createElement("td", { colSpan: columns.length + 1 }, "Herhangi bir kay\u0131t bulunamad\u0131!")))))),
|
|
323
|
+
}))))))),
|
|
394
324
|
pagination && pagination.totalRecords > pagination.perPage && (React.createElement("div", { className: "footer" },
|
|
395
325
|
React.createElement("span", null,
|
|
396
326
|
React.createElement("strong", null,
|
|
@@ -406,7 +336,6 @@ const TableWithRef = forwardRef(({ children, title, description, data, columns,
|
|
|
406
336
|
setCurrentPage(currentPage);
|
|
407
337
|
} })))));
|
|
408
338
|
});
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
export default Table;
|
|
339
|
+
export default memo(Table, (prevProps, nextProps) => {
|
|
340
|
+
return JSON.stringify(prevProps.data) === JSON.stringify(nextProps.data);
|
|
341
|
+
});
|
|
@@ -15,6 +15,7 @@ const Select = ({ variant = "outlined", status, border = { radius: "sm" }, optio
|
|
|
15
15
|
const _options = useRef(null);
|
|
16
16
|
const _optionItems = useRef([]);
|
|
17
17
|
const _searchField = useRef(null);
|
|
18
|
+
// const _searchTimeOut = useRef<NodeJS.Timeout | null>(null);
|
|
18
19
|
let _otoFocus = useRef().current;
|
|
19
20
|
let _navigationIndex = useRef(0);
|
|
20
21
|
// states
|
|
@@ -64,6 +65,14 @@ const Select = ({ variant = "outlined", status, border = { radius: "sm" }, optio
|
|
|
64
65
|
else if (key === "Escape")
|
|
65
66
|
setOptionsOpen(false);
|
|
66
67
|
};
|
|
68
|
+
// const handleSearch = (value: string) => {
|
|
69
|
+
// if (searchText.length === 0 || !onSearch) return;
|
|
70
|
+
// if (_searchTimeOut.current) clearTimeout(_searchTimeOut.current);
|
|
71
|
+
// _searchTimeOut.current = setTimeout(() => {
|
|
72
|
+
// setSearchText(value);
|
|
73
|
+
// onSearch(value);
|
|
74
|
+
// }, 750);
|
|
75
|
+
// };
|
|
67
76
|
const handlePosition = () => {
|
|
68
77
|
if (_options.current) {
|
|
69
78
|
const optionRect = _options.current.getBoundingClientRect();
|
|
@@ -200,17 +209,22 @@ const Select = ({ variant = "outlined", status, border = { radius: "sm" }, optio
|
|
|
200
209
|
};
|
|
201
210
|
}, [optionsOpen]);
|
|
202
211
|
useEffect(() => {
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
return option;
|
|
212
|
-
|
|
213
|
-
|
|
212
|
+
if (searchText.length > 0 && onSearch) {
|
|
213
|
+
onSearch(searchText);
|
|
214
|
+
}
|
|
215
|
+
else {
|
|
216
|
+
// Arama kriterlerine uygun olan değerleri bir state e gönderiyoruz.
|
|
217
|
+
setFilteredOptions(options?.filter((option) => {
|
|
218
|
+
if (!optionsOpen)
|
|
219
|
+
return option;
|
|
220
|
+
return option.text.toLocaleLowerCase().includes(searchText.toLocaleLowerCase());
|
|
221
|
+
}));
|
|
222
|
+
setIsSearchTextEqual(options?.some((option) => {
|
|
223
|
+
if (!optionsOpen)
|
|
224
|
+
return option;
|
|
225
|
+
return option.text.toLocaleLowerCase() == searchText.toLocaleLowerCase();
|
|
226
|
+
}));
|
|
227
|
+
}
|
|
214
228
|
// Arama yapılması durumunda değerleri sıfırla.
|
|
215
229
|
setNavigationIndex(0);
|
|
216
230
|
_navigationIndex.current = 0;
|
|
@@ -219,8 +233,6 @@ const Select = ({ variant = "outlined", status, border = { radius: "sm" }, optio
|
|
|
219
233
|
optionItems[_navigationIndex.current]?.classList.add("navigate-with-arrow-keys");
|
|
220
234
|
// Yeniden konumlandır.
|
|
221
235
|
setTimeout(() => handlePosition(), 0);
|
|
222
|
-
// Aramayı bileşen dışında kullanmak için dışarı aktarım metodu.
|
|
223
|
-
onSearch && onSearch(searchText);
|
|
224
236
|
}, [searchText]);
|
|
225
237
|
useEffect(() => {
|
|
226
238
|
// Seçilen öğeye 'navigate-with-arrow-keys' sınıfını ekle
|