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.
@@ -1,5 +1,6 @@
1
1
  import React from "react";
2
2
  declare const Box: React.FC<{
3
3
  children: React.ReactNode;
4
+ direction?: "flex-start" | "center" | "flex-end";
4
5
  }>;
5
6
  export default Box;
@@ -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, { 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;
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, useImperativeHandle, useRef, useState } from "react";
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 TableWithRef = forwardRef(({ children, title, description, data, columns, actions, selections, previousSelections, searchedParams, pagination, config = { isSearchable: false }, }, ref) => {
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
- // 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);
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
- let allChecked = false;
204
+ selections(selectionItems);
205
+ }, [selectionItems]);
206
+ useEffect(() => {
207
+ if (!selections)
208
+ return;
261
209
  if (_checkboxItems.current.length > 0) {
262
- allChecked = _checkboxItems.current.every((item) => item?.checked === true);
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", { 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 }))))))),
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("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 }) } }))))));
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().length > 0 ? (getData().map((item, index) => (React.createElement("tr", { key: `row-${index}-${Math.random()}` },
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
- }))))) : (React.createElement("tr", null,
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
- // Actions'ı ekliyoruz.
410
- const Table = TableWithRef;
411
- Table.Actions = Actions;
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
- // Arama kriterlerine uygun olan değerleri bir state e gönderiyoruz.
204
- setFilteredOptions(options?.filter((option) => {
205
- if (!optionsOpen)
206
- return option;
207
- return option.text.toLocaleLowerCase().includes(searchText.toLocaleLowerCase());
208
- }));
209
- setIsSearchTextEqual(options?.some((option) => {
210
- if (!optionsOpen)
211
- return option;
212
- return option.text.toLocaleLowerCase() == searchText.toLocaleLowerCase();
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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ar-design",
3
- "version": "0.2.20",
3
+ "version": "0.2.22",
4
4
  "main": "./dist/index.js",
5
5
  "module": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",