ar-design 0.2.55 → 0.2.57

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 (28) hide show
  1. package/dist/assets/css/components/data-display/chip/chip.css +1 -1
  2. package/dist/assets/css/components/data-display/table/filter-popup.css +11 -0
  3. package/dist/assets/css/components/data-display/table/scroll.css +6 -2
  4. package/dist/assets/css/components/data-display/table/styles.css +5 -2
  5. package/dist/assets/css/components/data-display/typography/title/core.css +1 -1
  6. package/dist/assets/css/components/feedback/progress/progress.css +1 -1
  7. package/dist/assets/css/components/feedback/tooltip/styles.css +2 -2
  8. package/dist/assets/css/components/form/date-picker/calendar/header.css +1 -1
  9. package/dist/assets/css/components/form/date-picker/clock/header.css +1 -1
  10. package/dist/assets/css/components/form/select/styles.css +1 -1
  11. package/dist/assets/css/components/form/upload/animations.css +1 -1
  12. package/dist/assets/css/components/form/upload/styles.css +2 -2
  13. package/dist/assets/css/components/navigation/menu/styles.css +1 -1
  14. package/dist/components/data-display/table/FilterPopup.d.ts +12 -0
  15. package/dist/components/data-display/table/FilterPopup.js +59 -0
  16. package/dist/components/data-display/table/IProps.d.ts +21 -14
  17. package/dist/components/data-display/table/THeadCell.d.ts +7 -0
  18. package/dist/components/data-display/table/THeadCell.js +27 -0
  19. package/dist/components/data-display/table/index.js +233 -78
  20. package/dist/components/form/checkbox/index.js +7 -12
  21. package/dist/components/icons/Compiler.js +1 -1
  22. package/dist/components/icons/Svg.js +2 -2
  23. package/dist/components/icons/index.d.ts +1 -0
  24. package/dist/components/icons/index.js +2 -2
  25. package/dist/libs/core/service/index.d.ts +1 -1
  26. package/dist/libs/infrastructure/shared/Enums.d.ts +10 -0
  27. package/dist/libs/infrastructure/shared/Enums.js +11 -0
  28. package/package.json +1 -1
@@ -9,6 +9,6 @@
9
9
  font-weight: 600;
10
10
  white-space: nowrap;
11
11
  user-select: none;
12
- -webkit-text-stroke: 0.5px var(--white);
12
+ /* -webkit-text-stroke: 0.5px var(--white); */
13
13
  letter-spacing: 1px;
14
14
  }
@@ -0,0 +1,11 @@
1
+ .ar-table-filter-popup {
2
+ position: absolute;
3
+ background-color: var(--white);
4
+ width: 225px;
5
+ max-height: 300px;
6
+ padding: 1rem;
7
+ border-radius: var(--border-radius-sm);
8
+ box-shadow: 0px 10px 15px -5px rgba(var(--black-rgb), 0.1);
9
+ transition: top 350ms, left 1s cubic-bezier(0.68, -0.6, 0.32, 1.6);
10
+ z-index: 5;
11
+ }
@@ -20,7 +20,9 @@
20
20
  }
21
21
 
22
22
  .ar-table > .content > table > thead > tr > th.sticky-left.sticky,
23
- .ar-table > .content > table > thead > tr > th.sticky-right.sticky {
23
+ .ar-table > .content > table > thead > tr > th.sticky-right.sticky,
24
+ .ar-table > .content > table > thead > tr > th.sticky-left.active-sticky,
25
+ .ar-table > .content > table > thead > tr > th.sticky-right.active-sticky {
24
26
  background-color: var(--gray-100);
25
27
  }
26
28
  .ar-table > .content > table > thead > tr > th.sticky-left.sticky::after,
@@ -42,7 +44,9 @@
42
44
  right: auto;
43
45
  }
44
46
  .ar-table > .content > table > tbody > tr > td.sticky-left.sticky,
45
- .ar-table > .content > table > tbody > tr > td.sticky-right.sticky {
47
+ .ar-table > .content > table > tbody > tr > td.sticky-right.sticky,
48
+ .ar-table > .content > table > tbody > tr > td.sticky-left.active-sticky,
49
+ .ar-table > .content > table > tbody > tr > td.sticky-right.active-sticky {
46
50
  background-color: var(--gray-100);
47
51
  box-shadow: inset -1px 0 0 0 var(--gray-200);
48
52
  }
@@ -25,7 +25,7 @@
25
25
  }
26
26
  .ar-table > .header > .title > h3 {
27
27
  color: var(--gray-700);
28
- -webkit-text-stroke: 0.25px var(--gray-700);
28
+ /* -webkit-text-stroke: 0.25px var(--gray-700); */
29
29
  }
30
30
  .ar-table > .header > .title > h5 {
31
31
  color: var(--gray-600);
@@ -83,11 +83,12 @@
83
83
  .ar-table > .content > table > thead > tr > th {
84
84
  position: relative;
85
85
  color: var(--gray-700);
86
- -webkit-text-stroke: 0.25px var(--gray-700);
86
+ /* -webkit-text-stroke: 0.25px var(--gray-700); */
87
87
  text-align: left;
88
88
  text-wrap: nowrap;
89
89
  z-index: 2;
90
90
  }
91
+
91
92
  .ar-table > .content > table > thead > tr > th > .filter-field {
92
93
  display: flex;
93
94
  flex-direction: row;
@@ -96,6 +97,7 @@
96
97
  gap: 0.5rem;
97
98
  min-width: 100%;
98
99
  }
100
+
99
101
  .ar-table > .content > table > thead > tr > th::after {
100
102
  position: absolute;
101
103
  top: 50%;
@@ -231,3 +233,4 @@
231
233
  }
232
234
 
233
235
  @import url("./scroll.css");
236
+ @import url("./filter-popup.css");
@@ -1,5 +1,5 @@
1
1
  .ar-typography-title {
2
2
  color: var(--gray-700);
3
3
  font-family: var(--system);
4
- -webkit-text-stroke: 0.5px var(--gray-700);
4
+ /* -webkit-text-stroke: 0.5px var(--gray-700); */
5
5
  }
@@ -33,7 +33,7 @@
33
33
  color: var(--white);
34
34
  font-size: 0.75rem;
35
35
  line-height: 1rem;
36
- -webkit-text-stroke: 0.75px var(--white);
36
+ /* -webkit-text-stroke: 0.75px var(--white); */
37
37
  z-index: 1;
38
38
  }
39
39
  .ar-progress > .ar-progress-value > span::before {
@@ -24,11 +24,11 @@
24
24
  color: var(--gray-700);
25
25
  font-size: 0.85rem;
26
26
  text-wrap: nowrap;
27
- -webkit-text-stroke: 0.75px var(--gray-700);
27
+ /* -webkit-text-stroke: 0.75px var(--gray-700); */
28
28
  }
29
29
  .ar-tooltip > .text > .bullet {
30
30
  color: var(--gray-400);
31
- -webkit-text-stroke: 0px;
31
+ /* -webkit-text-stroke: 0px; */
32
32
  }
33
33
 
34
34
  .ar-tooltip::before {
@@ -25,7 +25,7 @@
25
25
  height: var(--input-height);
26
26
  }
27
27
  .ar-date-calendar > .header > .select-field > .selects > div > span {
28
- -webkit-text-stroke: 1px var(--black);
28
+ /* -webkit-text-stroke: 1px var(--black); */
29
29
  user-select: none;
30
30
  }
31
31
 
@@ -4,5 +4,5 @@
4
4
  align-items: center;
5
5
  border-bottom: solid 1px var(--gray-200);
6
6
  text-align: center;
7
- -webkit-text-stroke: 1px var(--black);
7
+ /* -webkit-text-stroke: 1px var(--black); */
8
8
  }
@@ -88,7 +88,7 @@
88
88
  .ar-select-wrapper > .ar-select > .selections > .items > span.placeholder {
89
89
  color: var(--dark);
90
90
  font-family: var(--system);
91
- -webkit-text-stroke: 0.25px var(--dark);
91
+ /* -webkit-text-stroke: 0.25px var(--dark); */
92
92
  }
93
93
  .ar-select-wrapper > .ar-select > .selections > ul {
94
94
  display: flex;
@@ -5,7 +5,7 @@
5
5
  50% {
6
6
  box-shadow: 0 0 0 2.5px rgba(var(--warning-rgb), 0.25);
7
7
  color: var(--warning);
8
- -webkit-text-stroke: 1px var(--warning);
8
+ /* -webkit-text-stroke: 1px var(--warning); */
9
9
  transform: scale(1.25);
10
10
  }
11
11
  100% {
@@ -54,7 +54,7 @@
54
54
  }
55
55
  .ar-upload-button > .ar-upload-files > ul > li .content > span:first-child.error {
56
56
  color: var(--danger);
57
- -webkit-text-stroke: 0.5px var(--danger);
57
+ /* -webkit-text-stroke: 0.5px var(--danger); */
58
58
  }
59
59
  .ar-upload-button > .ar-upload-files > ul > li .content > span:last-child {
60
60
  background-color: rgba(var(--danger-rgb), 0.1);
@@ -64,7 +64,7 @@
64
64
  color: rgba(var(--danger-rgb), 0.5);
65
65
  font-size: 0.75rem;
66
66
  text-align: center;
67
- -webkit-text-stroke: 1px rgba(var(--danger-rgb), 0.5);
67
+ /* -webkit-text-stroke: 1px rgba(var(--danger-rgb), 0.5); */
68
68
  line-height: 0.85rem;
69
69
  cursor: pointer;
70
70
  }
@@ -13,7 +13,7 @@
13
13
  list-style: none;
14
14
  }
15
15
  .ar-menu > ul li {
16
- -webkit-text-stroke: 0.5px var(--black);
16
+ /* -webkit-text-stroke: 0.5px var(--black); */
17
17
  }
18
18
 
19
19
  .ar-menu > ul li .item-render {
@@ -0,0 +1,12 @@
1
+ import React, { MutableRefObject, ReactNode } from "react";
2
+ interface IProps {
3
+ children: ReactNode;
4
+ tableContent: MutableRefObject<HTMLDivElement | null>;
5
+ coordinate: {
6
+ x: number;
7
+ y: number;
8
+ };
9
+ buttons: MutableRefObject<(HTMLSpanElement | null)[]>;
10
+ }
11
+ declare const FilterPopup: ({ children, tableContent, coordinate, buttons }: IProps) => false | React.ReactPortal;
12
+ export default FilterPopup;
@@ -0,0 +1,59 @@
1
+ import React, { useEffect, useRef, useState } from "react";
2
+ import ReactDOM from "react-dom";
3
+ const FilterPopup = ({ children, tableContent, coordinate, buttons }) => {
4
+ // refs
5
+ const _arTableFilterPopup = useRef(null);
6
+ // states
7
+ const [open, setOpen] = useState(false);
8
+ // methods
9
+ const handleClickOutSide = (event) => {
10
+ const target = event.target;
11
+ const clickedInsidePopup = _arTableFilterPopup.current && _arTableFilterPopup.current.contains(target);
12
+ const isOneOfButtons = buttons.current.some((button) => button === target || button?.contains(target));
13
+ if (!clickedInsidePopup && !isOneOfButtons)
14
+ setOpen(false);
15
+ };
16
+ const handleKeys = (event) => {
17
+ const key = event.key;
18
+ if (key === "Escape")
19
+ setOpen(false);
20
+ };
21
+ const handleOpen = () => setOpen(true);
22
+ const handleClose = () => setOpen(false);
23
+ // useEffects
24
+ useEffect(() => {
25
+ buttons.current.map((button) => {
26
+ if (button)
27
+ button.addEventListener("click", handleOpen);
28
+ });
29
+ return () => {
30
+ buttons.current.map((button) => {
31
+ if (button)
32
+ button.removeEventListener("click", handleOpen);
33
+ });
34
+ };
35
+ }, [buttons]);
36
+ useEffect(() => {
37
+ const firstFilterButton = buttons.current[0];
38
+ if (firstFilterButton) {
39
+ const rect = firstFilterButton.getBoundingClientRect();
40
+ coordinate.x = rect.left;
41
+ coordinate.y = rect.top + rect.height;
42
+ }
43
+ if (tableContent.current) {
44
+ tableContent.current.addEventListener("scroll", handleClose);
45
+ }
46
+ document.addEventListener("click", handleClickOutSide);
47
+ document.addEventListener("keydown", handleKeys);
48
+ return () => {
49
+ document.removeEventListener("click", handleClickOutSide);
50
+ document.removeEventListener("keydown", handleKeys);
51
+ if (tableContent.current) {
52
+ tableContent.current.removeEventListener("scroll", handleClose);
53
+ }
54
+ };
55
+ }, []);
56
+ return (open &&
57
+ ReactDOM.createPortal(React.createElement("div", { ref: _arTableFilterPopup, className: "ar-table-filter-popup", style: { top: coordinate.y, left: coordinate.x } }, children), document.body));
58
+ };
59
+ export default FilterPopup;
@@ -1,8 +1,26 @@
1
1
  import React from "react";
2
2
  import { AllowedTypes, TableColumnType } from "../../../libs/types";
3
3
  import { IChildren } from "../../../libs/types/IGlobalProps";
4
+ import { FilterOperator } from "../../../libs/infrastructure/shared/Enums";
5
+ export type Operator = "Contains" | "DoesNotContains" | "Equals" | "DoesNotEquals" | "BeginsWith" | "EndsWith" | "Blank" | "NotBlank";
6
+ export type FilterValue = {
7
+ value: string | number | boolean;
8
+ operator: FilterOperator;
9
+ };
4
10
  export type SearchedParam = {
5
- [key: string]: string;
11
+ [key: string]: FilterValue | FilterValue[];
12
+ };
13
+ export type Config = {
14
+ isServerSide?: boolean;
15
+ isSearchable?: boolean;
16
+ scroll?: {
17
+ maxHeight: number;
18
+ };
19
+ subrow?: {
20
+ openAutomatically?: boolean;
21
+ selector?: string;
22
+ button?: boolean;
23
+ };
6
24
  };
7
25
  type ImportActionType = {
8
26
  tooltip: string;
@@ -26,23 +44,12 @@ interface IProps<T> extends IChildren {
26
44
  };
27
45
  selections?: (selectionItems: T[]) => void;
28
46
  previousSelections?: T[];
29
- searchedParams?: (params: SearchedParam | undefined, query: string) => void;
47
+ searchedParams?: (params: SearchedParam | null, query: string) => void;
30
48
  pagination?: {
31
49
  totalRecords: number;
32
50
  perPage: number;
33
51
  onChange?: (currentPage: number) => void;
34
52
  };
35
- config?: {
36
- isServerSide?: boolean;
37
- isSearchable?: boolean;
38
- scroll?: {
39
- maxHeight: number;
40
- };
41
- subrow?: {
42
- openAutomatically?: boolean;
43
- selector?: string;
44
- button?: boolean;
45
- };
46
- };
53
+ config?: Config;
47
54
  }
48
55
  export default IProps;
@@ -0,0 +1,7 @@
1
+ import React from "react";
2
+ import { TableColumnType } from "../../../libs/types";
3
+ declare const MemoizedTHeadCell: <T>({ columns }: {
4
+ columns: TableColumnType<T>[];
5
+ }) => React.JSX.Element;
6
+ declare const THeadCell: typeof MemoizedTHeadCell;
7
+ export default THeadCell;
@@ -0,0 +1,27 @@
1
+ import React from "react";
2
+ const MemoizedTHeadCell = function ({ columns }) {
3
+ return (React.createElement(React.Fragment, null, columns.map((c, cIndex) => {
4
+ let _className = [];
5
+ if (c.config?.sticky)
6
+ _className.push(`sticky-${c.config.sticky}`);
7
+ if (!c.config?.width)
8
+ _className.push("min-w");
9
+ if (c.config?.alignContent) {
10
+ _className.push(`align-content-${c.config.alignContent}`);
11
+ }
12
+ return (React.createElement("th", { key: `column-${cIndex}-${Math.random()}`, ...(_className.length > 0 && {
13
+ className: `${_className.map((c) => c).join(" ")}`,
14
+ }), ...(c.config?.width
15
+ ? {
16
+ style: { minWidth: c.config.width, maxWidth: c.config.width },
17
+ }
18
+ : // : { style: { maxWidth: thWidths[cIndex], minWidth: thWidths[cIndex] } })}
19
+ { style: {} }), ...(c.config?.sticky && {
20
+ "data-sticky-position": c.config.sticky,
21
+ }) },
22
+ React.createElement("span", { style: { fontWeight: 500 } }, c.title)));
23
+ })));
24
+ };
25
+ // 👇 React.memo kullanımı sırasında generic tipi koruyoruz
26
+ const THeadCell = React.memo(MemoizedTHeadCell);
27
+ export default THeadCell;
@@ -4,11 +4,27 @@ 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, Fragment, memo, useCallback, useEffect, useMemo, useRef, useState } from "react";
7
+ import React, { forwardRef, Fragment, memo, useCallback, useEffect, useMemo, useRef, useState, } from "react";
8
8
  import Input from "../../form/input";
9
9
  import Popover from "../../feedback/popover";
10
10
  import Utils from "../../../libs/infrastructure/shared/Utils";
11
11
  import Upload from "../../form/upload";
12
+ import FilterPopup from "./FilterPopup";
13
+ import { FilterOperator } from "../../../libs/infrastructure/shared/Enums";
14
+ import Select from "../../form/select";
15
+ import Grid from "../grid-system";
16
+ import THeadCell from "./THeadCell";
17
+ const filterOption = [
18
+ { value: FilterOperator.Contains, text: "İçerir" },
19
+ { value: FilterOperator.DoesNotContains, text: "İçermez" },
20
+ { value: FilterOperator.Equals, text: "Eşittir" },
21
+ { value: FilterOperator.DoesNotEquals, text: "Eşit değildir" },
22
+ { value: FilterOperator.BeginsWith, text: "İle başlar" },
23
+ { value: FilterOperator.EndsWith, text: "İle biter" },
24
+ { value: FilterOperator.Blank, text: "Boş" },
25
+ { value: FilterOperator.NotBlank, text: "Boş değil" },
26
+ ];
27
+ const { Row, Column } = Grid;
12
28
  const Table = forwardRef(({ children, title, description, data, columns, actions, selections, previousSelections, searchedParams, pagination, config = { isSearchable: false }, }, ref) => {
13
29
  // refs
14
30
  const _tableWrapper = useRef(null);
@@ -18,6 +34,8 @@ const Table = forwardRef(({ children, title, description, data, columns, actions
18
34
  // refs -> Search
19
35
  const _searchTextInputs = useRef([]);
20
36
  const _searchTimeOut = useRef(null);
37
+ // refs -> Filter
38
+ const _filterButton = useRef([]);
21
39
  // variables
22
40
  const _subrowOpenAutomatically = config.subrow?.openAutomatically ?? false;
23
41
  const _subrowSelector = config.subrow?.selector ?? "subitems";
@@ -32,9 +50,18 @@ const Table = forwardRef(({ children, title, description, data, columns, actions
32
50
  const [files, setFiles] = useState([]);
33
51
  const [formData, setFormData] = useState(undefined);
34
52
  // states -> Search
35
- const [searchedText, setSearchedText] = useState(undefined);
36
- const [_searchedParams, setSearchedParams] = useState(undefined);
37
- const [checkboxSelectedParams, setCheckboxSelectedParams] = useState(undefined);
53
+ const [searchedText, setSearchedText] = useState(null);
54
+ const [_searchedParams, setSearchedParams] = useState(null);
55
+ const [checkboxSelectedParams, setCheckboxSelectedParams] = useState(null);
56
+ // states -> Filter
57
+ const [filterButtonCoordinate, setFilterButtonCoordinate] = useState({ x: 0, y: 0 });
58
+ const [filterPopupContent, setFilterPopupContent] = useState(null);
59
+ const [filterPopupOption, setFilterPopupOption] = useState(null);
60
+ const [filterPopupOptionSearchText, setFilterPopupOptionSearchText] = useState(null);
61
+ // states -> Filter Fields Backup
62
+ const [filterCurrentColumn, setFilterCurrentColumn] = useState(null);
63
+ const [filterCurrentDataType, setFilterCurrentDataType] = useState(null);
64
+ const [filterCurrentIndex, setFilterCurrentIndex] = useState(null);
38
65
  // states -> Pagination
39
66
  const [totalRecords, setTotalRecords] = useState(0);
40
67
  const [currentPage, setCurrentPage] = useState(1);
@@ -46,7 +73,7 @@ const Table = forwardRef(({ children, title, description, data, columns, actions
46
73
  }
47
74
  }
48
75
  // methods
49
- const handleScroll = () => {
76
+ const handleScroll = useCallback(() => {
50
77
  if (!_tableWrapper.current)
51
78
  return;
52
79
  const wrapperRect = _tableWrapper.current.getBoundingClientRect();
@@ -80,7 +107,7 @@ const Table = forwardRef(({ children, title, description, data, columns, actions
80
107
  else
81
108
  child.classList.add("sticky");
82
109
  if (child.nodeName === "TD")
83
- child.style.zIndex = `${leftChildren.length - index}`;
110
+ child.style.zIndex = `5`;
84
111
  });
85
112
  // #endregion
86
113
  // #region Right
@@ -108,13 +135,20 @@ const Table = forwardRef(({ children, title, description, data, columns, actions
108
135
  updateStickyPositions(theadElements);
109
136
  updateStickyPositions(tbodyElements);
110
137
  });
111
- };
112
- const handleSearch = (event) => {
138
+ }, []);
139
+ const handleSearch = useCallback((event) => {
140
+ const { name, value } = event.target;
141
+ const operator = filterPopupOption?.key == name
142
+ ? filterPopupOption.option?.value
143
+ : FilterOperator.Contains;
113
144
  if (config.isServerSide) {
114
145
  if (_searchTimeOut.current)
115
146
  clearTimeout(_searchTimeOut.current);
116
147
  _searchTimeOut.current = setTimeout(() => {
117
- setSearchedParams((prev) => ({ ...prev, [event.target.name]: event.target.value }));
148
+ setSearchedParams((prev) => ({
149
+ ...prev,
150
+ [name]: { value: value, operator: operator },
151
+ }));
118
152
  if (pagination && pagination.onChange)
119
153
  pagination.onChange(1);
120
154
  }, 750);
@@ -122,66 +156,157 @@ const Table = forwardRef(({ children, title, description, data, columns, actions
122
156
  else {
123
157
  setSearchedText((prev) => {
124
158
  const _state = { ...prev };
125
- if (event.target.value === "") {
126
- delete _state[event.target.name]; // Key'i siliyoruz
159
+ if (value === "") {
160
+ delete _state[name]; // Key'i siliyoruz
127
161
  }
128
162
  else {
129
- _state[event.target.name] = event.target.value; // Yeni değeri ekliyoruz
163
+ _state[name] = { value: value, operator: operator }; // Yeni değeri ekliyoruz
130
164
  }
131
165
  return _state;
132
166
  });
133
167
  }
168
+ event.target.value = value;
134
169
  setCurrentPage(1);
135
- };
170
+ }, [filterPopupOption]);
136
171
  const handleCheckboxChange = useCallback(async (event) => {
137
172
  event.stopPropagation();
173
+ const { name, value, checked } = event.target;
138
174
  setCheckboxSelectedParams((prev) => {
139
- const updatedValues = new Set(prev?.[event.target.name] || []);
140
- event.target.checked ? updatedValues.add(event.target.value) : updatedValues.delete(event.target.value);
175
+ const prevFilters = prev?.[name] || [];
176
+ const updatedSet = new Set(prevFilters.map((f) => String(f.value)));
177
+ checked ? updatedSet.add(value) : updatedSet.delete(value);
178
+ const updatedArray = Array.from(updatedSet).map((v) => ({
179
+ value: v,
180
+ operator: FilterOperator.Equals, // Checkbox’lar genelde “Equals” anlamındadır.
181
+ }));
141
182
  return {
142
183
  ...prev,
143
- ...(Array.from(updatedValues).length > 0
144
- ? { [event.target.name]: Array.from(updatedValues) }
145
- : { [event.target.name]: [] }),
184
+ ...(updatedArray.length > 0 ? { [name]: updatedArray } : { [name]: [] }),
146
185
  };
147
186
  });
148
187
  }, []);
188
+ const handleFilterPopupContent = (c, dataType, index) => {
189
+ const key = typeof c.key !== "object" ? String(c.key) : String(c.key.field);
190
+ const value = Array.isArray(searchedText?.[key])
191
+ ? "" // veya ihtiyacına göre birleştirme yap: searchedText[key].map(v => v.value).join(", ").
192
+ : searchedText?.[key]?.value;
193
+ const handleChange = (event) => {
194
+ const { value } = event.target;
195
+ const input = _searchTextInputs.current[index ?? 0];
196
+ if (input) {
197
+ const event = new Event("input", { bubbles: true });
198
+ input.value = value;
199
+ input.dispatchEvent(event);
200
+ }
201
+ };
202
+ setFilterPopupContent(() => {
203
+ switch (dataType) {
204
+ case "string":
205
+ case "number":
206
+ return (React.createElement(Row, null,
207
+ React.createElement(Column, { size: 12 },
208
+ React.createElement(Select, { value: filterOption.find((x) => x.value === filterPopupOption?.option?.value && filterPopupOption.key === c.key) ?? filterOption[0], options: filterOption, onChange: (option) => {
209
+ setFilterPopupOption({ key: c.key, option: option });
210
+ }, placeholder: "Ko\u015Ful" })),
211
+ React.createElement(Column, { size: 12 },
212
+ React.createElement(Input, { value: value ?? "", onChange: handleChange, placeholder: "Ara" }))));
213
+ case "object":
214
+ case "boolean":
215
+ return (React.createElement(Row, null,
216
+ React.createElement(Column, { size: 12 },
217
+ React.createElement(Input, { placeholder: "Ara", value: value ?? "", onChange: (event) => setFilterPopupOptionSearchText(event.target.value) })),
218
+ React.createElement(Column, { size: 12 }, c.filters
219
+ ?.filter((filter) => filter.text.toLocaleLowerCase().includes(filterPopupOptionSearchText?.toLocaleLowerCase() ?? ""))
220
+ ?.map((filter, fIndex) => {
221
+ const name = typeof c.key !== "object" ? String(c.key) : String(c.key.field);
222
+ return (React.createElement("div", null,
223
+ React.createElement(Checkbox, { ref: (element) => (_filterCheckboxItems.current[fIndex] = element), label: filter.text, name: name, status: "primary", value: filter.value, checked: Array.isArray(checkboxSelectedParams?.[name]) &&
224
+ checkboxSelectedParams?.[name]?.some((f) => String(f.value) === String(filter.value)), onChange: async (event) => await handleCheckboxChange(event) })));
225
+ }))));
226
+ default:
227
+ return React.createElement(React.Fragment, null);
228
+ }
229
+ });
230
+ };
149
231
  // Derinlemesine arama yapmak için özyinelemeli bir fonksiyon olarak kullanılmaktadır.
150
232
  const deepSearch = (item, searchedText) => {
151
233
  if (!searchedText || Object.keys(searchedText).length === 0)
152
234
  return true;
153
- // Eğer değer bir sayı veya string ise, aranan metinle eşleşip eşleşmediğini kontrol ediyoruz.
154
- return Object.entries(searchedText).every(([key, value]) => {
155
- const _itemValue = item[key];
156
- if (typeof _itemValue === "number" || typeof _itemValue === "string" || typeof _itemValue === "boolean") {
157
- if (Array.isArray(value)) {
158
- if (value.length === 0)
159
- return true;
160
- else
161
- return value.some((v) => _itemValue.toString().toLocaleLowerCase().includes(v.toLocaleLowerCase()));
162
- }
163
- return _itemValue.toString().toLocaleLowerCase().includes(value.toLocaleLowerCase());
235
+ const applyOperator = (value, filter) => {
236
+ if (Array.isArray(value)) {
237
+ // Array içindeki herhangi bir öğe eşleşirse true dön
238
+ return value.some((item) => applyOperator(item, filter));
164
239
  }
165
- if (typeof _itemValue === "object") {
166
- if (Array.isArray(value)) {
167
- if (value.length === 0)
168
- return true;
169
- else {
170
- return value.some((v) => {
171
- if (Array.isArray(_itemValue)) {
172
- return Object.values(_itemValue?.[0] ?? {}).some((objValue) => {
173
- return String(objValue).toLocaleLowerCase().includes(String(v).toLocaleLowerCase());
174
- });
175
- }
176
- });
177
- }
178
- }
240
+ if (typeof value === "object" && value !== null) {
241
+ // Eğer obje ise, içindeki değerlerden biri eşleşirse true dön
242
+ return Object.values(value).some((v) => applyOperator(v, filter));
243
+ }
244
+ const text = String(value ?? "").toLocaleLowerCase();
245
+ const searchText = String(filter.value ?? "").toLocaleLowerCase();
246
+ switch (filter.operator) {
247
+ case FilterOperator.Contains:
248
+ return text.includes(searchText);
249
+ case FilterOperator.DoesNotContains:
250
+ return !text.includes(searchText);
251
+ case FilterOperator.Equals:
252
+ return text === searchText;
253
+ case FilterOperator.DoesNotEquals:
254
+ return text !== searchText;
255
+ case FilterOperator.BeginsWith:
256
+ return text.startsWith(searchText);
257
+ case FilterOperator.EndsWith:
258
+ return text.endsWith(searchText);
259
+ case FilterOperator.Blank:
260
+ return text.trim() === "";
261
+ case FilterOperator.NotBlank:
262
+ return text.trim() !== "";
263
+ default:
264
+ return false;
265
+ }
266
+ };
267
+ return Object.entries(searchedText).every(([key, param]) => {
268
+ const _itemValue = item[key];
269
+ if (Array.isArray(param)) {
270
+ if (param.length === 0)
271
+ return true;
272
+ return param.some((filter) => applyOperator(_itemValue, filter));
179
273
  }
180
- if (Array.isArray(_itemValue)) {
181
- console.log("Buradasın", _itemValue);
274
+ else {
275
+ return applyOperator(_itemValue, param);
182
276
  }
183
- return false;
184
277
  });
278
+ // Eğer değer bir sayı veya string ise, aranan metinle eşleşip eşleşmediğini kontrol ediyoruz.
279
+ // return Object.entries(searchedText).every(([key, param]) => {
280
+ // const _itemValue = item[key as keyof typeof item];
281
+ // if (typeof _itemValue === "number" || typeof _itemValue === "string" || typeof _itemValue === "boolean") {
282
+ // if (Array.isArray(param)) {
283
+ // if (param.length === 0) return true;
284
+ // else return param.some((v) => _itemValue.toString().toLocaleLowerCase().includes(v.toLocaleLowerCase()));
285
+ // }
286
+ // return _itemValue
287
+ // .toString()
288
+ // .toLocaleLowerCase()
289
+ // .includes(param.toLocaleLowerCase() ?? "");
290
+ // }
291
+ // if (typeof _itemValue === "object") {
292
+ // if (Array.isArray(param)) {
293
+ // if (param.length === 0) return true;
294
+ // else {
295
+ // return param.some((v) => {
296
+ // if (Array.isArray(_itemValue)) {
297
+ // return Object.values(_itemValue?.[0 as keyof typeof _itemValue] ?? {}).some((objValue) => {
298
+ // return String(objValue).toLocaleLowerCase().includes(String(v).toLocaleLowerCase());
299
+ // });
300
+ // }
301
+ // });
302
+ // }
303
+ // }
304
+ // }
305
+ // if (Array.isArray(_itemValue)) {
306
+ // console.log("Buradasın", _itemValue);
307
+ // }
308
+ // return false;
309
+ // });
185
310
  };
186
311
  const openAllSubrowsRecursively = (data, parentKey = "") => {
187
312
  let result = {};
@@ -297,21 +422,37 @@ const Table = forwardRef(({ children, title, description, data, columns, actions
297
422
  }, [previousSelections]);
298
423
  useEffect(() => {
299
424
  if (config?.isServerSide && searchedParams) {
300
- const query = new URLSearchParams(_searchedParams);
425
+ const searchRecord = {};
426
+ Object.entries(_searchedParams ?? {}).forEach(([key, value]) => {
427
+ if (Array.isArray(value)) {
428
+ // Çoklu filtre değerleri varsa virgülle birleştir.
429
+ searchRecord[key] = value.map((v) => v.value).join(",");
430
+ }
431
+ else if (value && typeof value === "object") {
432
+ searchRecord[key] = String(value.value);
433
+ }
434
+ });
435
+ const query = new URLSearchParams(searchRecord);
301
436
  columns.forEach((column) => {
302
- const getParamsLength = column.filters?.length;
303
- const searchedParamLength = Array.from(_searchedParams?.[column.key] ?? []).length;
304
- if (getParamsLength === searchedParamLength)
437
+ const key = column.key;
438
+ const filterValue = _searchedParams?.[key];
439
+ const filterArray = Array.isArray(filterValue) ? filterValue : filterValue ? [filterValue] : [];
440
+ const getParamsLength = column.filters?.length ?? 0;
441
+ const searchedParamLength = filterArray.length;
442
+ if (getParamsLength === searchedParamLength) {
305
443
  query.delete(column.key);
444
+ }
306
445
  });
307
446
  searchedParams(_searchedParams, query.toString());
308
447
  }
309
448
  }, [_searchedParams]);
310
449
  useEffect(() => {
450
+ if (!checkboxSelectedParams)
451
+ return;
311
452
  if (config.isServerSide) {
312
453
  if (_searchTimeOut.current)
313
454
  clearTimeout(_searchTimeOut.current);
314
- setSearchedParams(checkboxSelectedParams);
455
+ setSearchedParams((prev) => ({ ...prev, ...checkboxSelectedParams }));
315
456
  }
316
457
  else {
317
458
  setSearchedText((prev) => ({ ...prev, ...checkboxSelectedParams }));
@@ -332,6 +473,12 @@ const Table = forwardRef(({ children, title, description, data, columns, actions
332
473
  setSelectAll(_checkboxItems.current.every((item) => item?.checked === true));
333
474
  }
334
475
  }, [selectionItems, currentPage]);
476
+ useEffect(() => {
477
+ // Filter Content alanı re-render işlemi.
478
+ if (filterCurrentColumn && filterCurrentDataType) {
479
+ handleFilterPopupContent(filterCurrentColumn, filterCurrentDataType, filterCurrentIndex);
480
+ }
481
+ }, [checkboxSelectedParams, filterPopupOption, filterPopupOptionSearchText]);
335
482
  return (React.createElement("div", { ref: _tableWrapper, className: _tableClassName.map((c) => c).join(" ") },
336
483
  (title || description || actions || React.Children.count(children) > 0) && (React.createElement("div", { className: "header" },
337
484
  React.createElement("div", { className: "title" },
@@ -371,30 +518,18 @@ const Table = forwardRef(({ children, title, description, data, columns, actions
371
518
  });
372
519
  }
373
520
  } }))),
374
- columns.map((c, cIndex) => {
375
- let _className = [];
376
- if (c.config?.sticky)
377
- _className.push(`sticky-${c.config.sticky}`);
378
- if (!c.config?.width)
379
- _className.push("min-w");
380
- if (c.config?.alignContent) {
381
- _className.push(`align-content-${c.config.alignContent}`);
382
- }
383
- return (React.createElement("th", { key: `column-${cIndex}-${Math.random()}`, ...(_className.length > 0 && {
384
- className: `${_className.map((c) => c).join(" ")}`,
385
- }), ...(c.config?.width
386
- ? {
387
- style: { minWidth: c.config.width, maxWidth: c.config.width },
388
- }
389
- : // : { style: { maxWidth: thWidths[cIndex], minWidth: thWidths[cIndex] } })}
390
- { style: {} }), ...(c.config?.sticky && {
391
- "data-sticky-position": c.config.sticky,
392
- }) }, c.title));
393
- })),
521
+ React.createElement(THeadCell, { columns: columns })),
394
522
  config?.isSearchable && (React.createElement("tr", { key: "isSearchable" },
395
523
  selections && (React.createElement("th", { key: `column-selections`, className: "selection-col sticky-left", "data-sticky-position": "left" })),
396
524
  columns.map((c, cIndex) => {
397
525
  let _className = [];
526
+ const key = typeof c.key !== "object" ? String(c.key) : String(c.key.field);
527
+ const csrValue = Array.isArray(searchedText?.[key])
528
+ ? "" // veya ihtiyacına göre birleştirme yap: searchedText[key].map(v => v.value).join(", ").
529
+ : searchedText?.[key]?.value;
530
+ const ssrValue = Array.isArray(_searchedParams?.[key])
531
+ ? "" // veya ihtiyacına göre birleştirme yap: _searchedParams[key].map(v => v.value).join(", ").
532
+ : _searchedParams?.[key]?.value;
398
533
  if (c.config?.sticky)
399
534
  _className.push(`sticky-${c.config.sticky}`);
400
535
  if (c.config?.alignContent) {
@@ -405,15 +540,35 @@ const Table = forwardRef(({ children, title, description, data, columns, actions
405
540
  }), ...(c.config?.sticky && {
406
541
  "data-sticky-position": c.config.sticky,
407
542
  }) }, c.key && (React.createElement("div", { className: "filter-field" },
408
- 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 }),
409
- c.filters && (React.createElement(Popover, { content: React.createElement("div", null, c.filters.map((filter, fIndex) => {
410
- const name = typeof c.key !== "object" ? String(c.key) : String(c.key.field);
411
- return (React.createElement("div", null,
412
- 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) })));
413
- })), windowBlur: true },
414
- React.createElement(Button, { variant: "borderless", icon: { element: React.createElement(ARIcon, { icon: "Filter", stroke: "var(--primary)", size: 16 }) } })))))));
543
+ React.createElement(Input, { ref: (element) => (_searchTextInputs.current[cIndex] = element), variant: c.key && !c.filters ? "outlined" : "filled", status: "light", style: { height: "2rem" }, value: (config.isServerSide ? ssrValue : csrValue) ?? "", name: key, onInput: handleSearch, disabled: !c.key || !!c.filters }),
544
+ React.createElement("span", { ref: (element) => (_filterButton.current[cIndex] = element), onClick: (event) => {
545
+ event.stopPropagation();
546
+ // Temizlik...
547
+ setFilterPopupOptionSearchText("");
548
+ const rect = event.currentTarget.getBoundingClientRect();
549
+ const screenCenterX = window.innerWidth / 2;
550
+ // const screenCenterY = window.innerHeight / 2;
551
+ const coordinateX = rect.x > screenCenterX ? rect.x + rect.width - 225 : rect.x;
552
+ const coordinateY = rect.y + rect.height;
553
+ // data içindeki alanların tiplerini bulmak için kullanılmaktadır
554
+ const getDataFirstItem = { ...data[0] };
555
+ const key = typeof c.key !== "object" ? String(c.key) : String(c.key.field);
556
+ const getValueByKey = getDataFirstItem[key];
557
+ let dataType = typeof getValueByKey;
558
+ if (getValueByKey == null)
559
+ dataType = "string";
560
+ setFilterButtonCoordinate({ x: coordinateX, y: coordinateY });
561
+ setFilterCurrentColumn(c);
562
+ setFilterCurrentDataType(dataType);
563
+ setFilterCurrentIndex(cIndex);
564
+ handleFilterPopupContent(c, dataType, cIndex);
565
+ } },
566
+ React.createElement(Button, { variant: "borderless", status: "dark", icon: {
567
+ element: (React.createElement(ARIcon, { viewBox: "0 0 16 16", size: 24, icon: "Filter", fill: "var(--dark)", strokeWidth: 0 })),
568
+ } }))))));
415
569
  })))),
416
570
  React.createElement("tbody", null, getData.map((item, index) => (React.createElement(React.Fragment, { key: index }, renderRow(item, index))))))),
571
+ React.createElement(FilterPopup, { tableContent: _tableContent, coordinate: filterButtonCoordinate, buttons: _filterButton }, filterPopupContent),
417
572
  pagination && pagination.totalRecords > pagination.perPage && (React.createElement("div", { className: "footer" },
418
573
  React.createElement("span", null,
419
574
  React.createElement("strong", null,
@@ -1,24 +1,19 @@
1
1
  "use client";
2
- import React, { forwardRef, useEffect, useRef, useState } from "react";
3
- import "../../../assets/css/components/form/checkbox/checkbox.css";
4
2
  import Utils from "../../../libs/infrastructure/shared/Utils";
3
+ import React, { forwardRef, useRef } from "react";
4
+ import "../../../assets/css/components/form/checkbox/checkbox.css";
5
5
  const Checkbox = forwardRef(({ label, size = "normal", status, border = { radius: "sm" }, upperCase, ...attributes }, ref) => {
6
6
  // refs
7
7
  const _checkbox = useRef(null);
8
8
  const _checkboxClassName = ["ar-checkbox"];
9
- // states
10
- const [checked, setChecked] = useState(attributes.checked ?? false);
11
- _checkboxClassName.push(...Utils.GetClassName("filled", checked ? status : "light", border, size, undefined, attributes.className));
12
- // useEffects
13
- useEffect(() => {
14
- setChecked(attributes.checked ?? attributes.defaultChecked ?? false);
15
- }, [attributes.checked, attributes.defaultChecked]);
9
+ const isChecked = attributes.checked ?? false;
10
+ _checkboxClassName.push(...Utils.GetClassName("filled", isChecked ? status : "light", border, size, undefined, attributes.className));
16
11
  return (React.createElement("div", { className: "ar-checkbox-wrapper" },
17
12
  React.createElement("label", null,
18
13
  React.createElement("input", { ref: ref, type: "checkbox", ...attributes, size: 0, onChange: (event) => {
19
- (() => {
20
- setChecked(event.target.checked);
21
- })();
14
+ // (() => {
15
+ // attributes.onChange?.(event);
16
+ // })();
22
17
  (() => attributes.onChange && attributes.onChange(event))();
23
18
  } }),
24
19
  React.createElement("span", null,
@@ -86,7 +86,7 @@ class Icon {
86
86
  React.createElement("line", { x1: "4", y1: this._finishIndex, x2: "20", y2: this._finishIndex, stroke: this._stroke, strokeWidth: this._strokeWidth, strokeLinecap: "round", strokeLinejoin: "round" })));
87
87
  case "Filter":
88
88
  return (React.createElement(React.Fragment, null,
89
- React.createElement("path", { d: "M5.4 2.1h13.2c1.1 0 2 .9 2 2v2.2c0 .8-.5 1.8-1 2.3l-4.3 3.8c-.6.5-1 1.5-1 2.3V19c0 .6-.4 1.4-.9 1.7l-1.4.9c-1.3.8-3.1-.1-3.1-1.7v-5.3c0-.7-.4-1.6-.8-2.1l-3.8-4c-.5-.5-.9-1.4-.9-2V4.2c0-1.2.9-2.1 2-2.1ZM10.93 2.1 6 10", stroke: this._stroke, strokeWidth: this._strokeWidth, strokeMiterlimit: "10", strokeLinecap: "round", strokeLinejoin: "round" })));
89
+ React.createElement("path", { d: "M6 10.5a.5.5 0 0 1 .5-.5h3a.5.5 0 0 1 0 1h-3a.5.5 0 0 1-.5-.5m-2-3a.5.5 0 0 1 .5-.5h7a.5.5 0 0 1 0 1h-7a.5.5 0 0 1-.5-.5m-2-3a.5.5 0 0 1 .5-.5h11a.5.5 0 0 1 0 1h-11a.5.5 0 0 1-.5-.5", stroke: this._stroke, strokeWidth: this._strokeWidth, strokeMiterlimit: "10", strokeLinecap: "round", strokeLinejoin: "round" })));
90
90
  case "TickCircle":
91
91
  return (React.createElement(React.Fragment, null,
92
92
  React.createElement("path", { d: "M12 22c5.5 0 10-4.5 10-10S17.5 2 12 2 2 6.5 2 12s4.5 10 10 10Z", stroke: this._stroke, strokeWidth: this._strokeWidth, strokeLinecap: "round", strokeLinejoin: "round" }),
@@ -1,5 +1,5 @@
1
1
  import React from "react";
2
- const Svg = ({ children, fill = "none", width = 32, height = 32, style, }) => {
3
- return (React.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: fill, width: width, height: height, style: style }, children));
2
+ const Svg = ({ children, viewBox, fill = "none", width = 32, height = 32, style, }) => {
3
+ return (React.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: viewBox ?? "0 0 24 24", fill: fill, width: width, height: height, style: style }, children));
4
4
  };
5
5
  export default Svg;
@@ -1,6 +1,7 @@
1
1
  import React from "react";
2
2
  import { Icons, IconVariants } from "../../libs/types";
3
3
  export declare const ARIcon: React.FC<{
4
+ viewBox?: string;
4
5
  size?: string | number | undefined;
5
6
  variant?: IconVariants;
6
7
  icon: Icons;
@@ -1,7 +1,7 @@
1
1
  import React from "react";
2
2
  import Svg from "./Svg";
3
3
  import Icon from "./Compiler";
4
- export const ARIcon = ({ size, variant = "linear", icon, fill = "var(--dark)", stroke = "var(--dark)", strokeWidth = 2, style }) => {
4
+ export const ARIcon = ({ viewBox, size, variant = "linear", icon, fill = "var(--dark)", stroke = "var(--dark)", strokeWidth = 2, style, }) => {
5
5
  const { Compiler } = new Icon(fill, stroke, strokeWidth);
6
- return (React.createElement(Svg, { width: size, height: size, style: style }, Compiler(variant, icon)));
6
+ return (React.createElement(Svg, { viewBox: viewBox, fill: fill, width: size, height: size, style: style }, Compiler(variant, icon)));
7
7
  };
@@ -1,4 +1,4 @@
1
- type Result<TResponse> = {
1
+ export type Result<TResponse> = {
2
2
  response: TResponse;
3
3
  __response__: Promise<Response> | null;
4
4
  __ok__: boolean;
@@ -0,0 +1,10 @@
1
+ export declare enum FilterOperator {
2
+ Contains = 1,
3
+ DoesNotContains = 2,
4
+ Equals = 3,
5
+ DoesNotEquals = 4,
6
+ BeginsWith = 5,
7
+ EndsWith = 6,
8
+ Blank = 7,
9
+ NotBlank = 8
10
+ }
@@ -0,0 +1,11 @@
1
+ export var FilterOperator;
2
+ (function (FilterOperator) {
3
+ FilterOperator[FilterOperator["Contains"] = 1] = "Contains";
4
+ FilterOperator[FilterOperator["DoesNotContains"] = 2] = "DoesNotContains";
5
+ FilterOperator[FilterOperator["Equals"] = 3] = "Equals";
6
+ FilterOperator[FilterOperator["DoesNotEquals"] = 4] = "DoesNotEquals";
7
+ FilterOperator[FilterOperator["BeginsWith"] = 5] = "BeginsWith";
8
+ FilterOperator[FilterOperator["EndsWith"] = 6] = "EndsWith";
9
+ FilterOperator[FilterOperator["Blank"] = 7] = "Blank";
10
+ FilterOperator[FilterOperator["NotBlank"] = 8] = "NotBlank";
11
+ })(FilterOperator || (FilterOperator = {}));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ar-design",
3
- "version": "0.2.55",
3
+ "version": "0.2.57",
4
4
  "main": "./dist/index.js",
5
5
  "module": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",