px-react-ui-components 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. package/.babelrc +3 -0
  2. package/README.md +126 -0
  3. package/dist/components/MyAlert/MyAlert.css +113 -0
  4. package/dist/components/MyAlert/MyAlert.js +109 -0
  5. package/dist/components/MyContainer/MyContainer.js +59 -0
  6. package/dist/components/MyContainer/MyContainer.module.css +110 -0
  7. package/dist/components/MyContainer/MyContainerBody.js +9 -0
  8. package/dist/components/MyContainer/MyContainerFooter.js +9 -0
  9. package/dist/components/MyContainer/MyContainerRight.js +10 -0
  10. package/dist/components/MyEditor/MyEditor.js +292 -0
  11. package/dist/components/MyEditor/MyEditor.scss +277 -0
  12. package/dist/components/MyFileUpload/MyFileUpload.js +288 -0
  13. package/dist/components/MyFileUpload/MyFileUpload.module.css +86 -0
  14. package/dist/components/MyImageCropper/MyImageCropper.js +95 -0
  15. package/dist/components/MyInput/MyInput.js +768 -0
  16. package/dist/components/MyInput/MyInput.module.css +420 -0
  17. package/dist/components/MyMaps/YandexMaps.js +162 -0
  18. package/dist/components/MyMenu/MenuItem.js +55 -0
  19. package/dist/components/MyMenu/MyMenu.module.css +102 -0
  20. package/dist/components/MyModal/MyModal.css +83 -0
  21. package/dist/components/MyModal/MyModal.js +71 -0
  22. package/dist/components/MyModal/MyModalBody.js +9 -0
  23. package/dist/components/MyModal/MyModalFooter.js +9 -0
  24. package/dist/components/MyNotFound/MyNotFound.css +22 -0
  25. package/dist/components/MyNotFound/MyNotFound.js +20 -0
  26. package/dist/components/MyScrollableCard/MyScrollableCard.js +74 -0
  27. package/dist/components/MyTable/MyTable.js +310 -0
  28. package/dist/components/MyTable/MyTable.module.css +350 -0
  29. package/dist/components/MyTable/MyTableBody.js +9 -0
  30. package/dist/components/MyTable/MyTableHead.js +9 -0
  31. package/dist/components/MyTabs/MyTabPane.js +17 -0
  32. package/dist/components/MyTabs/MyTabs.css +105 -0
  33. package/dist/components/MyTabs/MyTabs.js +66 -0
  34. package/dist/components/MyWaiting/MyWaiting.css +28 -0
  35. package/dist/components/MyWaiting/MyWaiting.js +27 -0
  36. package/dist/components/MyZoomImage/MyZoomImage.css +0 -0
  37. package/dist/components/MyZoomImage/MyZoomImage.js +108 -0
  38. package/dist/index.js +15 -0
  39. package/package.json +44 -0
  40. package/src/components/MyAlert/MyAlert.css +113 -0
  41. package/src/components/MyAlert/MyAlert.jsx +96 -0
  42. package/src/components/MyContainer/MyContainer.jsx +90 -0
  43. package/src/components/MyContainer/MyContainer.module.css +110 -0
  44. package/src/components/MyContainer/MyContainerBody.jsx +8 -0
  45. package/src/components/MyContainer/MyContainerFooter.jsx +8 -0
  46. package/src/components/MyContainer/MyContainerRight.jsx +11 -0
  47. package/src/components/MyEditor/MyEditor.jsx +252 -0
  48. package/src/components/MyEditor/MyEditor.scss +277 -0
  49. package/src/components/MyFileUpload/MyFileUpload.jsx +373 -0
  50. package/src/components/MyFileUpload/MyFileUpload.module.css +86 -0
  51. package/src/components/MyImageCropper/MyImageCropper.jsx +108 -0
  52. package/src/components/MyInput/MyInput.jsx +896 -0
  53. package/src/components/MyInput/MyInput.module.css +420 -0
  54. package/src/components/MyMaps/YandexMaps.jsx +186 -0
  55. package/src/components/MyMenu/MenuItem.jsx +62 -0
  56. package/src/components/MyMenu/MyMenu.module.css +102 -0
  57. package/src/components/MyModal/MyModal.css +83 -0
  58. package/src/components/MyModal/MyModal.jsx +78 -0
  59. package/src/components/MyModal/MyModalBody.jsx +8 -0
  60. package/src/components/MyModal/MyModalFooter.jsx +8 -0
  61. package/src/components/MyNotFound/MyNotFound.css +22 -0
  62. package/src/components/MyNotFound/MyNotFound.jsx +11 -0
  63. package/src/components/MyScrollableCard/MyScrollableCard.jsx +86 -0
  64. package/src/components/MyTable/MyTable.jsx +458 -0
  65. package/src/components/MyTable/MyTable.module.css +350 -0
  66. package/src/components/MyTable/MyTableBody.jsx +8 -0
  67. package/src/components/MyTable/MyTableHead.jsx +10 -0
  68. package/src/components/MyTabs/MyTabPane.jsx +9 -0
  69. package/src/components/MyTabs/MyTabs.css +105 -0
  70. package/src/components/MyTabs/MyTabs.jsx +63 -0
  71. package/src/components/MyWaiting/MyWaiting.css +28 -0
  72. package/src/components/MyWaiting/MyWaiting.jsx +27 -0
  73. package/src/components/MyZoomImage/MyZoomImage.css +0 -0
  74. package/src/components/MyZoomImage/MyZoomImage.jsx +139 -0
  75. package/src/index.js +15 -0
@@ -0,0 +1,458 @@
1
+ import React, { useEffect, useState } from "react";
2
+ import styles from "./MyTable.module.css";
3
+ import { useTranslation } from "../../context/TranslationContext";
4
+
5
+ export const MyTableIsNumeric = (value) => {
6
+ if (value === null || value === undefined || value === "") return false;
7
+ return !isNaN(value) && !isNaN(parseFloat(value));
8
+ };
9
+
10
+ export const CountBlock = ({ count }) => {
11
+ const { t } = useTranslation();
12
+
13
+ return (
14
+ <div className={styles.rowsCount}>
15
+ <span>{count}</span>
16
+ <small>{t("kayıt listelendi")}</small>
17
+ </div>
18
+ );
19
+ };
20
+
21
+ function MyTable({
22
+ columns = [], //
23
+ data = null,
24
+ emptyText = "",
25
+
26
+ children,
27
+ height = null,
28
+ totalCount = null,
29
+ onSearchText = null,
30
+ searchable = false,
31
+ showCount = false,
32
+
33
+ pageSize = 0,
34
+
35
+ selectedRow = null,
36
+ onRowClick = null,
37
+ onPageChange = null,
38
+ }) {
39
+ const { t } = useTranslation();
40
+
41
+ const tableid = `key${Date.now() + Math.random().toString(36).substr(2, 9)}`;
42
+
43
+ const [curEmptyText, setCurEmptyText] = useState(emptyText);
44
+ const [curTotalCount, setCurTotalCount] = useState(data ? data.length : totalCount);
45
+
46
+ const [searchTerm, setSearchTerm] = useState("");
47
+ const [filteredRows, setFilteredRows] = useState([]);
48
+
49
+ const [currentPage, setCurrentPage] = useState(1);
50
+ const [totalPages, setTotalPages] = useState(0);
51
+ const [sortConfig, setSortConfig] = useState({ key: null, direction: "asc" });
52
+ const [displayData, setDisplayData] = useState([]);
53
+
54
+ const arrChild = React.Children.toArray(children);
55
+
56
+ let childHeader = null;
57
+ let childBody = null;
58
+
59
+ if (arrChild.length > 0) {
60
+ for (let i = 0; i < arrChild.length; i++) {
61
+ const el = arrChild[i];
62
+ if (el.type.toString().includes("MyTableTagHead")) {
63
+ childHeader = el;
64
+ } else if (el.type.toString().includes("MyTableTagBody")) {
65
+ childBody = el;
66
+ } else if (childBody == null) {
67
+ childBody = el;
68
+ }
69
+ }
70
+ }
71
+
72
+ // Veri işleme ve sıralama
73
+ useEffect(() => {
74
+
75
+
76
+ let processedData = Array.isArray(data) ? [...data] : [];
77
+
78
+ // Arama işlemi
79
+ if (searchTerm != "") {
80
+ processedData = processedData.filter((record) => {
81
+ let _status = false;
82
+
83
+ Object.keys(record).forEach((key) => {
84
+ if (
85
+ record[key] &&
86
+ record[key]
87
+ .toString()
88
+ .toLocaleLowerCase()
89
+ .includes(searchTerm.toLocaleLowerCase())
90
+ ) {
91
+ _status = true;
92
+ }
93
+ });
94
+
95
+ return _status;
96
+ });
97
+ }
98
+
99
+ setTotalPages(Math.ceil(processedData.length / pageSize));
100
+
101
+ // Sıralama işlemi
102
+ if (sortConfig.key) {
103
+ processedData.sort((a, b) => {
104
+ const aValue = a[sortConfig.key];
105
+ const bValue = b[sortConfig.key];
106
+
107
+ if (MyTableIsNumeric(aValue) && MyTableIsNumeric(bValue)) {
108
+ return sortConfig.direction === "asc"
109
+ ? Number(aValue) - Number(bValue)
110
+ : Number(bValue) - Number(aValue);
111
+ }
112
+
113
+ return sortConfig.direction === "asc"
114
+ ? String(aValue).localeCompare(String(bValue))
115
+ : String(bValue).localeCompare(String(aValue));
116
+ });
117
+ }
118
+
119
+ // Sayfalama
120
+ if (pageSize > 0) {
121
+ const startIndex = (currentPage - 1) * pageSize;
122
+ processedData = processedData.slice(
123
+ startIndex,
124
+ startIndex + pageSize
125
+ );
126
+ }
127
+
128
+ setDisplayData(processedData);
129
+ if (data) {
130
+ setCurTotalCount(data.length);
131
+ } else {
132
+ setCurTotalCount(0);
133
+ }
134
+ }, [data, searchTerm, sortConfig, currentPage, pageSize]);
135
+
136
+ useEffect(() => {
137
+ if (emptyText == "") {
138
+ setCurEmptyText(t("Henüz bir kayıt mevcut değil!"));
139
+ }
140
+
141
+ return () => { };
142
+ }, [tableid]);
143
+
144
+
145
+
146
+ // Arama işlevi
147
+ const filterRows = (row) => {
148
+ if (!searchTerm) return true;
149
+
150
+ const cells = row.props.children;
151
+ return React.Children.toArray(cells).some((cell) => {
152
+ const cellText = cell.props.children
153
+ ? cell.props.children.toString().trim().toLocaleLowerCase()
154
+ : "";
155
+
156
+ const cleanCellText = cellText.replace(/[^a-zA-Z0-9\s]/g, ""); // Virgül ve diğer özel karakterleri temizle
157
+ const cleanSearchTerm = searchTerm
158
+ .replace(/[^a-zA-Z0-9\s]/g, "")
159
+ .toLocaleLowerCase(); // Aynı şekilde arama terimini temizle
160
+
161
+ return cleanCellText.includes(cleanSearchTerm);
162
+ });
163
+ };
164
+
165
+ // Sıralama işleyicisi
166
+ const handleSort = (key) => {
167
+ setSortConfig((prevSort) => ({
168
+ key,
169
+ direction:
170
+ prevSort.key === key && prevSort.direction === "asc"
171
+ ? "desc"
172
+ : "asc",
173
+ }));
174
+ };
175
+
176
+ // Sütun başlığı render fonksiyonu
177
+ const renderColumnHeader = (column) => {
178
+ const isSorted = sortConfig.key === column.key;
179
+ const sortDirection = isSorted ? sortConfig.direction : null;
180
+ let style = {};
181
+
182
+ if (column.style) style = { ...style, ...column.style };
183
+
184
+ if (column.width) style = { ...style, width: column.width };
185
+
186
+ //style = { ...style, minWidth: column.width || "150px" };
187
+
188
+ return (
189
+ <th
190
+ key={"head" + column.key + btoa(Math.random().toString(36).substr(2, 9))}
191
+ onClick={
192
+ column.sortable ? () => handleSort(column.key) : undefined
193
+ }
194
+ className={`
195
+ ${styles.th}
196
+ ${(column.className && column.className) || ""}
197
+ ${column.sortable ? styles.sortable : ""}
198
+ ${isSorted ? styles[`sort-${sortDirection}`] : ""}
199
+ `}
200
+ style={style}
201
+ >
202
+ {column.title}
203
+ </th>
204
+ );
205
+ };
206
+
207
+ // Hücre render fonksiyonu
208
+ const renderCell = (item, column, index) => {
209
+ const value = item[column.key];
210
+ const content = column.render ? column.render(value, item, index, currentPage) : value;
211
+ const key = "cell" + column.key + btoa(Math.random().toString(36).substr(2, 9));
212
+
213
+ // If the content is already a React element (like from a render function that returns MathJax),
214
+ // just return it directly in the cell
215
+ if (React.isValidElement(content)) {
216
+ return (
217
+ <td
218
+ key={key}
219
+ style={column.tdStyle}
220
+ className={`${styles.td} ${(column.tdClassName && column.tdClassName) || ""}`}
221
+ data-row-index={index}
222
+ >
223
+ {content}
224
+ </td>
225
+ );
226
+ }
227
+
228
+ return (
229
+ <td
230
+ key={key}
231
+ style={column.tdStyle}
232
+ className={`${styles.td} ${(column.tdClassName && column.tdClassName) || ""}`}
233
+ data-row-index={index}
234
+ >
235
+ {typeof content === 'string' ? (<span dangerouslySetInnerHTML={{ __html: content }} />)
236
+ : (
237
+ content
238
+ )}
239
+ </td>
240
+ );
241
+ };
242
+
243
+ // Filtrelenen satırları güncelle
244
+ useEffect(() => {
245
+ if (onSearchText == null) {
246
+ if (childBody) {
247
+ const rows = React.Children.toArray(childBody.props.children);
248
+ const filtered = rows.filter((row) => filterRows(row));
249
+
250
+ setFilteredRows(filtered);
251
+ }
252
+ } else {
253
+ onSearchText(searchTerm);
254
+ }
255
+ }, [searchTerm, children]);
256
+
257
+ // Sayfa değiştirme işleyicisi
258
+ const handlePageChange = (page) => {
259
+ setCurrentPage(page);
260
+ };
261
+ // Sayfalama render fonksiyonu
262
+ const renderPagination = () => {
263
+ if (pageSize == 0 || totalPages <= 1) return null;
264
+
265
+ const maxVisiblePages = 10;
266
+ let pagesToShow = [];
267
+
268
+ if (totalPages <= maxVisiblePages) {
269
+ // Toplam sayfa sayısı 10 veya daha az ise hepsini göster
270
+ pagesToShow = Array.from({ length: totalPages }, (_, i) => i + 1);
271
+ } else {
272
+ // Her zaman ilk ve son sayfayı göster
273
+ // Aktif sayfanın etrafında dengeli dağılım yap
274
+ const sidePages = 4; // Aktif sayfanın her iki yanında kaç sayfa gösterileceği
275
+
276
+ if (currentPage <= sidePages + 1) {
277
+ // Başlangıçtayız
278
+ pagesToShow = [...Array(maxVisiblePages - 1).keys()].map(
279
+ (i) => i + 1
280
+ );
281
+ pagesToShow.push(totalPages);
282
+ } else if (currentPage >= totalPages - sidePages) {
283
+ // Sondayız
284
+ pagesToShow = [1];
285
+ pagesToShow.push(
286
+ ...Array.from(
287
+ { length: maxVisiblePages - 1 },
288
+ (_, i) => totalPages - (maxVisiblePages - 2) + i
289
+ )
290
+ );
291
+ } else {
292
+ // Ortadayız
293
+ pagesToShow = [1];
294
+ const start =
295
+ currentPage - Math.floor((maxVisiblePages - 4) / 2);
296
+ const end = currentPage + Math.floor((maxVisiblePages - 4) / 2);
297
+ pagesToShow.push(
298
+ ...Array.from(
299
+ { length: end - start + 1 },
300
+ (_, i) => start + i
301
+ )
302
+ );
303
+ pagesToShow.push(totalPages);
304
+ }
305
+ }
306
+
307
+ return (
308
+ <div className={styles.pagination}>
309
+ <button
310
+ onClick={() => handlePageChange(currentPage - 1)}
311
+ disabled={currentPage === 1}
312
+ className={styles.pageButton}
313
+ >
314
+ &lt;
315
+ </button>
316
+
317
+ {pagesToShow.map((page, index) => (
318
+ <React.Fragment key={page}>
319
+ {index > 0 &&
320
+ pagesToShow[index] - pagesToShow[index - 1] > 1 && (
321
+ <span className={styles.pageEllipsis}>...</span>
322
+ )}
323
+ <button
324
+ onClick={() => handlePageChange(page)}
325
+ className={`${styles.pageButton} ${currentPage === page ? styles.activePage : ""
326
+ }`}
327
+ >
328
+ {page}
329
+ </button>
330
+ </React.Fragment>
331
+ ))}
332
+
333
+ <button
334
+ onClick={() => handlePageChange(currentPage + 1)}
335
+ disabled={currentPage === totalPages}
336
+ className={styles.pageButton}
337
+ >
338
+ &gt;
339
+ </button>
340
+ </div>
341
+ );
342
+ };
343
+
344
+ const headerCellsCount =
345
+ columns.filter(column => column.title).length > 0
346
+ ? columns.filter(column => column.title).length
347
+ : childBody
348
+ ? React.Children.count(childBody.props.children.props.children)
349
+ : 0;
350
+
351
+ return (
352
+ <div
353
+ id={tableid}
354
+ className={`${styles.myTableContainer} ${searchable && styles.searchable
355
+ } ${totalPages > 0 && styles.myTablePagination}`}
356
+ style={{ height: height }}
357
+ >
358
+ {(searchable && (
359
+ <div className={styles.searchContainer}>
360
+ <input
361
+ type="text"
362
+ placeholder={t("Ara")}
363
+ value={searchTerm}
364
+ className={styles.searchInput}
365
+ onChange={(e) => setSearchTerm(e.target.value)}
366
+ />
367
+ <CountBlock
368
+ count={
369
+ (curTotalCount && curTotalCount) ||
370
+ (childBody && childBody.props.children.length) ||
371
+ 0
372
+ }
373
+ />
374
+ </div>
375
+ )) ||
376
+ (showCount && (
377
+ <CountBlock
378
+ count={
379
+ (curTotalCount && curTotalCount) ||
380
+ (childBody && childBody.props.children.length) ||
381
+ 0
382
+ }
383
+ />
384
+ ))}
385
+
386
+ <div className={styles.myTable}>
387
+ <table className={styles.table}>
388
+ {columns.filter(column => column.title).length > 0 ? (
389
+ <thead className={styles.thead}>
390
+ <tr className={styles.tr}>
391
+ {columns.filter(column => column.title).map(renderColumnHeader)}
392
+ </tr>
393
+ </thead>
394
+ ) : (
395
+ childHeader
396
+ )}
397
+
398
+ <tbody>
399
+ {(onSearchText &&
400
+ childBody &&
401
+ childBody.props.children.length > 0 &&
402
+ childBody.props.children) ||
403
+ (filteredRows &&
404
+ filteredRows.length > 0 &&
405
+ filteredRows) ||
406
+ (displayData.length > 0 &&
407
+ displayData.map((item, index) => (
408
+ <tr
409
+ key={index}
410
+ onClick={() =>
411
+ onRowClick && onRowClick(item)
412
+ }
413
+ className={`
414
+ ${styles.tr}
415
+ ${onRowClick ? styles.clickable : ""}
416
+ ${selectedRow === item ? styles.selected : ""}
417
+ `}
418
+ >
419
+ {columns.filter(column => column.title).map((column) =>
420
+ renderCell(item, column, index)
421
+ )}
422
+ {children && (
423
+ <td>
424
+ {typeof children === "function"
425
+ ? children(item)
426
+ : children}
427
+ </td>
428
+ )}
429
+ </tr>
430
+ ))) || (
431
+ <tr className={styles.noData + " " + styles.tr}>
432
+ <td
433
+ colSpan={headerCellsCount}
434
+ className={styles.td}
435
+ >
436
+ {(searchTerm != "" && (
437
+ <span
438
+ dangerouslySetInnerHTML={{
439
+ __html: `${t(
440
+ "Aradığınız kriterlere uygun kayıt bulunamadı!"
441
+ )}<br/><b>(${searchTerm})</b>`,
442
+ }}
443
+ ></span>
444
+ )) ||
445
+ curEmptyText}
446
+ </td>
447
+ </tr>
448
+ )}
449
+ </tbody>
450
+ </table>
451
+ </div>
452
+
453
+ {totalPages > 0 && renderPagination()}
454
+ </div>
455
+ );
456
+ }
457
+
458
+ export default MyTable;