ar-design 0.1.86 → 0.1.87

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.
@@ -62,6 +62,10 @@
62
62
  height: 3rem;
63
63
  padding: 0 1.5rem;
64
64
  }
65
+ .ar-table > .content > table > thead > tr > th.min-w,
66
+ .ar-table > .content > table > tbody > tr > td.min-w {
67
+ min-width: 150px;
68
+ }
65
69
 
66
70
  .ar-table > .content > table > thead {
67
71
  background-color: var(--gray-100);
@@ -14,13 +14,49 @@
14
14
  box-shadow: 0 -5px 15px -2.5px rgba(var(--black-rgb), 0.1);
15
15
  }
16
16
 
17
- .ar-select-options > .no-options-field {
17
+ .ar-select-options > .search-field {
18
+ padding: 0.5rem;
19
+ border-bottom: solid 1px var(--gray-200);
20
+ }
21
+
22
+ .ar-select-options > ul {
23
+ width: 100%;
24
+ max-height: calc(var(--input-height) * 5);
25
+ overflow-x: hidden;
26
+ overflow-y: auto;
27
+ }
28
+ .ar-select-options > ul > li {
29
+ display: flex;
30
+ align-items: center;
31
+ gap: 0 0.5rem;
32
+ padding: 0 1rem;
33
+ height: var(--input-height);
34
+ cursor: pointer;
35
+ }
36
+ .ar-select-options > ul > li:hover {
37
+ background-color: var(--gray-200);
38
+ }
39
+ .ar-select-options > ul > li.selectedItem {
40
+ /* background-color: rgba(var(--success-rgb), 0.1); */
41
+ }
42
+ .ar-select-options > ul > li.navigate-with-arrow-keys {
43
+ background-color: var(--gray-100);
44
+ }
45
+
46
+ .ar-select-options > .no-options-field,
47
+ .ar-select-options > ul > li > .no-options-field {
48
+ width: 100%;
18
49
  padding: 0.5rem 1rem;
19
50
  }
20
- .ar-select-options > .no-options-field > .text {
51
+ .ar-select-options > ul > li > .no-options-field {
52
+ padding: 0 !important;
53
+ }
54
+ .ar-select-options > .no-options-field > .text,
55
+ .ar-select-options > ul > li > .no-options-field > .text {
21
56
  color: var(--gray-500);
22
57
  }
23
- .ar-select-options > .no-options-field > .add-item {
58
+ .ar-select-options > .no-options-field > .add-item,
59
+ .ar-select-options > ul > li > .no-options-field > .add-item {
24
60
  display: flex;
25
61
  align-items: center;
26
62
  position: relative;
@@ -31,7 +67,8 @@
31
67
  color: var(--primary);
32
68
  cursor: pointer;
33
69
  }
34
- .ar-select-options > .no-options-field > .add-item::before {
70
+ .ar-select-options > .no-options-field > .add-item::before,
71
+ .ar-select-options > ul > li > .no-options-field > .add-item::before {
35
72
  position: absolute;
36
73
  top: 50%;
37
74
  transform: translateY(-50%);
@@ -40,7 +77,8 @@
40
77
  border: solid 5px transparent;
41
78
  border-left-color: var(--primary);
42
79
  }
43
- .ar-select-options > .no-options-field > .add-item > .plus {
80
+ .ar-select-options > .no-options-field > .add-item > .plus,
81
+ .ar-select-options > ul > li > .no-options-field > .add-item > .plus {
44
82
  display: inline-block;
45
83
  position: relative;
46
84
  background-color: var(--primary);
@@ -53,35 +91,6 @@
53
91
  line-height: 1rem;
54
92
  }
55
93
 
56
- .ar-select-options > .search-field {
57
- padding: 0.5rem;
58
- border-bottom: solid 1px var(--gray-200);
59
- }
60
-
61
- .ar-select-options > ul {
62
- width: 100%;
63
- max-height: calc(var(--input-height) * 5);
64
- overflow-x: hidden;
65
- overflow-y: auto;
66
- }
67
- .ar-select-options > ul > li {
68
- display: flex;
69
- align-items: center;
70
- gap: 0 0.5rem;
71
- padding: 0 1rem;
72
- height: var(--input-height);
73
- cursor: pointer;
74
- }
75
- .ar-select-options > ul > li:hover {
76
- background-color: var(--gray-200);
77
- }
78
- .ar-select-options > ul > li.selectedItem {
79
- /* background-color: rgba(var(--success-rgb), 0.1); */
80
- }
81
- .ar-select-options > ul > li.navigate-with-arrow-keys {
82
- background-color: var(--gray-100);
83
- }
84
-
85
94
  /* .ar-select-options:is(.opened) {
86
95
  visibility: visible;
87
96
  opacity: 1;
@@ -4,20 +4,19 @@ import { IChildren } from "../../../libs/types/IGlobalProps";
4
4
  export type SearchedParam = {
5
5
  [key: string]: string;
6
6
  };
7
+ type ActionType = {
8
+ tooltip: string;
9
+ onClick: (event: React.MouseEvent<HTMLButtonElement, MouseEvent>) => void;
10
+ };
7
11
  interface IProps<T> extends IChildren {
8
12
  title?: string;
9
13
  description?: string;
10
14
  data: T[];
11
15
  columns: TableColumnType<T>[];
12
16
  actions?: {
13
- create?: {
14
- tooltip: string;
15
- onClick: (event: React.MouseEvent<HTMLButtonElement, MouseEvent>) => void;
16
- };
17
- import?: {
18
- tooltip: string;
19
- onClick: (event: React.MouseEvent<HTMLButtonElement, MouseEvent>) => void;
20
- };
17
+ create?: ActionType;
18
+ import?: ActionType;
19
+ filterClear?: ActionType;
21
20
  };
22
21
  selections?: (selectionItems: T[]) => void;
23
22
  searchedParams?: (params: SearchedParam | undefined, query: string) => void;
@@ -26,11 +25,9 @@ interface IProps<T> extends IChildren {
26
25
  perPage: number;
27
26
  onChange: (currentPage: number) => void;
28
27
  };
29
- filterCleaner?: boolean;
30
28
  config?: {
31
29
  isServerSide?: boolean;
32
30
  isSearchable?: boolean;
33
- isCleanFilter?: boolean;
34
31
  scroll?: {
35
32
  maxHeight: number;
36
33
  };
@@ -1,10 +1,13 @@
1
- import React from "react";
2
- import IProps from "./IProps";
3
1
  import "../../../assets/css/components/data-display/table/styles.css";
4
- declare const Table: {
5
- <T extends object>({ children, title, description, data, columns, actions, selections, searchedParams, pagination, filterCleaner, config, }: IProps<T>): React.JSX.Element;
6
- Action: React.FC<{
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<{
7
9
  children: React.ReactElement | React.ReactElement[];
8
10
  }>;
9
11
  };
12
+ declare const Table: TableCompoundComponents;
10
13
  export default Table;
@@ -1,17 +1,17 @@
1
1
  "use client";
2
- import React, { useCallback, useEffect, useRef, useState } from "react";
3
2
  import "../../../assets/css/components/data-display/table/styles.css";
3
+ import { ARIcon } from "../../icons";
4
+ import Button from "../../form/button";
4
5
  import Checkbox from "../../form/checkbox";
5
- import Actions from "./Actions";
6
6
  import Pagination from "../../navigation/pagination";
7
- import Button from "../../form/button";
8
- import { ARIcon } from "../../icons";
9
- const Table = function ({ children, title, description, data, columns, actions, selections, searchedParams, pagination, filterCleaner, config = { isSearchable: false }, }) {
7
+ import React, { forwardRef, useCallback, useEffect, useImperativeHandle, useRef, useState } from "react";
8
+ import Actions from "./Actions";
9
+ const TableWithRef = forwardRef(({ children, title, description, data, columns, actions, selections, searchedParams, pagination, config = { isSearchable: false }, }, ref) => {
10
10
  // refs
11
11
  let _dataLength = useRef(0);
12
12
  const _tableWrapper = useRef(null);
13
- const _tableContent = useRef(null);
14
13
  const _table = useRef(null);
14
+ const _tableContent = useRef(null);
15
15
  const _checkboxItems = useRef([]);
16
16
  const _searchTextInputs = useRef([]);
17
17
  const _searchTimeOut = useRef(null);
@@ -30,9 +30,27 @@ const Table = function ({ children, title, description, data, columns, actions,
30
30
  }
31
31
  }
32
32
  }
33
+ // Custom Attributes
34
+ useImperativeHandle(ref, () => {
35
+ const tableCurrent = _table.current;
36
+ return {
37
+ ...tableCurrent,
38
+ filterCleaner: () => {
39
+ if (config.isServerSide) {
40
+ setSearchedParams({});
41
+ pagination && pagination.onChange(1);
42
+ }
43
+ else {
44
+ setSearchedText({});
45
+ }
46
+ setCurrentPage(1);
47
+ _searchTextInputs.current.map((item) => item && (item.value = ""));
48
+ },
49
+ };
50
+ });
33
51
  // methods
34
52
  const handleScroll = () => {
35
- if (!_table.current || !_tableWrapper.current)
53
+ if (!_tableWrapper.current)
36
54
  return;
37
55
  const wrapperRect = _tableWrapper.current.getBoundingClientRect();
38
56
  const updateStickyPositions = (elements) => {
@@ -87,8 +105,8 @@ const Table = function ({ children, title, description, data, columns, actions,
87
105
  // #endregion
88
106
  });
89
107
  };
90
- const theadElements = _table.current.querySelectorAll("thead > tr");
91
- const tbodyElements = _table.current.querySelectorAll("tbody > tr");
108
+ const theadElements = _tableWrapper.current.querySelectorAll("table > thead > tr");
109
+ const tbodyElements = _tableWrapper.current.querySelectorAll("table > tbody > tr");
92
110
  requestAnimationFrame(() => {
93
111
  updateStickyPositions(theadElements);
94
112
  updateStickyPositions(tbodyElements);
@@ -102,12 +120,13 @@ const Table = function ({ children, title, description, data, columns, actions,
102
120
  return Object.entries(searchedText).every(([key, value]) => {
103
121
  const _itemValue = item[key];
104
122
  if (typeof _itemValue === "number" || typeof _itemValue === "string") {
105
- return _itemValue.toString().toLowerCase().includes(value.toLowerCase());
123
+ return _itemValue.toString().toLocaleLowerCase().includes(value.toLocaleLowerCase());
106
124
  }
107
125
  if (typeof _itemValue === "object") {
108
- deepSearch(_itemValue, searchedText);
126
+ return Object.entries(_itemValue ?? {}).some(([_, objValue]) => String(objValue).toLocaleLowerCase().includes(value.toLocaleLowerCase()));
127
+ }
128
+ if (Array.isArray(_itemValue)) {
109
129
  }
110
- // Diğer türlerdeki değerleri atla.
111
130
  return false;
112
131
  });
113
132
  };
@@ -152,18 +171,6 @@ const Table = function ({ children, title, description, data, columns, actions,
152
171
  }
153
172
  setSelectAll(allChecked);
154
173
  }, [currentPage]);
155
- // Tetikleme işlemleri için eklendi.
156
- useEffect(() => {
157
- if (config.isServerSide) {
158
- setSearchedParams({});
159
- pagination && pagination.onChange(1);
160
- }
161
- else {
162
- setSearchedText({});
163
- }
164
- setCurrentPage(1);
165
- _searchTextInputs.current.map((item) => item && (item.value = ""));
166
- }, [filterCleaner]);
167
174
  return (React.createElement("div", { ref: _tableWrapper, className: _tableClassName.map((c) => c).join(" ") },
168
175
  (title || description || actions || React.Children.count(children) > 0) && (React.createElement("div", { className: "header" },
169
176
  React.createElement("div", { className: "title" },
@@ -173,10 +180,10 @@ const Table = function ({ children, title, description, data, columns, actions,
173
180
  React.Children.count(children) > 0 && React.createElement("div", null, React.Children.map(children, (child) => child)),
174
181
  actions && (React.createElement(React.Fragment, null,
175
182
  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 })),
176
- 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 })))),
177
- config && (React.createElement(React.Fragment, null))))),
183
+ 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 })),
184
+ 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 }))))))),
178
185
  React.createElement("div", { ref: _tableContent, className: "content", onScroll: handleScroll },
179
- React.createElement("table", { ref: _table },
186
+ React.createElement("table", { ref: ref },
180
187
  React.createElement("thead", null,
181
188
  React.createElement("tr", { key: "selection" },
182
189
  selections && (React.createElement("th", { className: "selection-col sticky-left", "data-sticky-position": "left" },
@@ -195,11 +202,15 @@ const Table = function ({ children, title, description, data, columns, actions,
195
202
  let _className = [];
196
203
  if (c.config?.sticky)
197
204
  _className.push(`sticky-${c.config.sticky}`);
205
+ if (!c.config?.width)
206
+ _className.push("min-w");
198
207
  if (c.config?.alignContent) {
199
208
  _className.push(`align-content-${c.config.alignContent}`);
200
209
  }
201
210
  return (React.createElement("th", { key: `column-${cIndex}`, ...(_className.length > 0 && {
202
211
  className: `${_className.map((c) => c).join(" ")}`,
212
+ }), ...(c.config?.width && {
213
+ style: { minWidth: c.config.width },
203
214
  }), ...(c.config?.sticky && {
204
215
  "data-sticky-position": c.config.sticky,
205
216
  }) }, c.title));
@@ -274,9 +285,7 @@ const Table = function ({ children, title, description, data, columns, actions,
274
285
  _className.push(`align-content-${c.config.alignContent}`);
275
286
  if (c.config?.textWrap)
276
287
  _className.push(`text-${c.config.textWrap}`);
277
- return (React.createElement("td", { key: `cell-${index}-${cIndex}`, ...(c.config?.width && {
278
- style: { minWidth: c.config.width },
279
- }), ...(_className.length > 0 && {
288
+ return (React.createElement("td", { key: `cell-${index}-${cIndex}`, ...(_className.length > 0 && {
280
289
  className: `${_className.map((c) => c).join(" ")}`,
281
290
  }), ...(c.config?.sticky && {
282
291
  "data-sticky-position": c.config.sticky,
@@ -298,6 +307,8 @@ const Table = function ({ children, title, description, data, columns, actions,
298
307
  config.isServerSide && pagination.onChange(currentPage);
299
308
  setCurrentPage(currentPage);
300
309
  } }))))));
301
- };
302
- Table.Action = Actions;
310
+ });
311
+ // Actions'ı ekliyoruz.
312
+ const Table = TableWithRef;
313
+ Table.Actions = Actions;
303
314
  export default Table;
@@ -15,9 +15,9 @@ const Alert = ({ children, message, status = "primary", border = { radius: "sm"
15
15
  // TODO: Bu konu hakkında düşünüp karar verilecek.
16
16
  if (!emphasize)
17
17
  return message;
18
- let _lowerCaseMessage = message.toLowerCase();
18
+ let _lowerCaseMessage = message.toLocaleLowerCase();
19
19
  return emphasize.reduce((currentMessage, emphasize) => {
20
- let _lowerCaseEmphasize = emphasize.toLowerCase();
20
+ let _lowerCaseEmphasize = emphasize.toLocaleLowerCase();
21
21
  let startIndex = _lowerCaseMessage.indexOf(_lowerCaseEmphasize);
22
22
  while (startIndex !== -1) {
23
23
  const endIndex = startIndex + emphasize.length;
@@ -26,7 +26,7 @@ const Alert = ({ children, message, status = "primary", border = { radius: "sm"
26
26
  const lastValue = currentMessage.substring(endIndex);
27
27
  currentMessage = `${firstValue} <span class="ar-alert-tag">${originalTag}</span> ${lastValue}`;
28
28
  // Update the lowerCaseMessage to reflect the change
29
- _lowerCaseMessage = currentMessage.toLowerCase();
29
+ _lowerCaseMessage = currentMessage.toLocaleLowerCase();
30
30
  // Find the next occurrence of the tag
31
31
  startIndex = _lowerCaseMessage.indexOf(_lowerCaseEmphasize, startIndex + `<span class="ar-alert-tag">${originalTag}</span>`.length);
32
32
  }
@@ -20,6 +20,7 @@ const Select = ({ variant = "outlined", status, border = { radius: "sm" }, optio
20
20
  // states
21
21
  const [optionsOpen, setOptionsOpen] = useState(false);
22
22
  const [filteredOptions, setFilteredOptions] = useState([]);
23
+ const [isSearchTextEqual, setIsSearchTextEqual] = useState(false);
23
24
  const [searchText, setSearchText] = useState("");
24
25
  const [singleInputText, setSingleInputText] = useState("");
25
26
  const [navigationIndex, setNavigationIndex] = useState(0);
@@ -110,6 +111,17 @@ const Select = ({ variant = "outlined", status, border = { radius: "sm" }, optio
110
111
  }
111
112
  setOptionsOpen(false);
112
113
  };
114
+ const createField = () => {
115
+ if (!onCreate)
116
+ return;
117
+ return (React.createElement("div", { className: "no-options-field", onClick: (event) => {
118
+ event.stopPropagation();
119
+ onCreate({ value: "", text: singleInputText });
120
+ setOptionsOpen(false);
121
+ } }, options.length === 0 && (singleInputText.length === 0 || searchText.length === 0) ? (React.createElement("span", { className: "text" }, "Herhangi bir kay\u0131t bulunumad\u0131.")) : (React.createElement("span", { className: "add-item" },
122
+ React.createElement("span", { className: "plus" }, "+"),
123
+ singleInputText.length !== 0 ? singleInputText : searchText))));
124
+ };
113
125
  // Özel büyük harfe dönüştürme işlevi.
114
126
  const convertToUpperCase = (str) => {
115
127
  return str
@@ -190,7 +202,12 @@ const Select = ({ variant = "outlined", status, border = { radius: "sm" }, optio
190
202
  setFilteredOptions(options?.filter((option) => {
191
203
  if (!optionsOpen)
192
204
  return option;
193
- return option.text.toLowerCase().includes(searchText.toLowerCase());
205
+ return option.text.toLocaleLowerCase().includes(searchText.toLocaleLowerCase());
206
+ }));
207
+ setIsSearchTextEqual(options?.some((option) => {
208
+ if (!optionsOpen)
209
+ return option;
210
+ return option.text.toLocaleLowerCase() == searchText.toLocaleLowerCase();
194
211
  }));
195
212
  // Arama yapılması durumunda değerleri sıfırla.
196
213
  setNavigationIndex(0);
@@ -246,22 +263,18 @@ const Select = ({ variant = "outlined", status, border = { radius: "sm" }, optio
246
263
  ReactDOM.createPortal(React.createElement("div", { ref: _options, className: "ar-select-options" },
247
264
  multiple && (React.createElement("div", { className: "search-field" },
248
265
  React.createElement(Input, { ref: _searchField, variant: "outlined", status: "light", placeholder: "Search...", value: searchText, onChange: (event) => setSearchText(event.target.value), onClick: (event) => event.stopPropagation() }))),
249
- filteredOptions.length > 0 ? (React.createElement("ul", null, filteredOptions.map((option, index) => {
250
- const isItem = multiple && value.some((_value) => _value.value === option.value);
251
- return (React.createElement("li", { key: index, ref: (element) => (_optionItems.current[index] = element), className: option === value ? "selectedItem" : "", onClick: (event) => {
252
- event.stopPropagation();
253
- handleItemSelected(option);
254
- } },
255
- multiple && React.createElement(Checkbox, { checked: isItem, status: isItem ? "primary" : "light", disabled: true }),
256
- React.createElement("span", null, option.text)));
257
- }))) : !onCreate ? (React.createElement("div", { className: "no-options-field" },
258
- React.createElement("span", { className: "text" }, "Herhangi bir kay\u0131t bulunumad\u0131."))) : (React.createElement("div", { className: "no-options-field", onClick: (event) => {
259
- event.stopPropagation();
260
- onCreate({ value: "", text: singleInputText });
261
- setOptionsOpen(false);
262
- } }, options.length === 0 && singleInputText.length === 0 && searchText.length === 0 ? (React.createElement("span", { className: "text" }, "Herhangi bir kay\u0131t bulunumad\u0131.")) : (React.createElement("span", { className: "add-item" },
263
- React.createElement("span", { className: "plus" }, "+"),
264
- singleInputText.length !== 0 ? singleInputText : searchText))))), document.body)));
266
+ filteredOptions.length > 0 ? (React.createElement("ul", null,
267
+ onCreate && !isSearchTextEqual && searchText.length > 0 && React.createElement("li", null, createField()),
268
+ filteredOptions.map((option, index) => {
269
+ const isItem = multiple && value.some((_value) => _value.value === option.value);
270
+ return (React.createElement("li", { key: index, ref: (element) => (_optionItems.current[index] = element), className: option === value ? "selectedItem" : "", onClick: (event) => {
271
+ event.stopPropagation();
272
+ handleItemSelected(option);
273
+ } },
274
+ multiple && React.createElement(Checkbox, { checked: isItem, status: isItem ? "primary" : "light", disabled: true }),
275
+ React.createElement("span", null, option.text)));
276
+ }))) : !onCreate ? (React.createElement("div", { className: "no-options-field" },
277
+ React.createElement("span", { className: "text" }, "Herhangi bir kay\u0131t bulunumad\u0131."))) : (createField())), document.body)));
265
278
  };
266
279
  Select.displayName = "Select";
267
280
  export default Select;
@@ -37,6 +37,9 @@ export type TableColumnType<T> = {
37
37
  textWrap?: "wrap" | "nowrap";
38
38
  };
39
39
  };
40
+ export type HTMLTableElementWithCustomAttributes = {
41
+ filterCleaner: () => void;
42
+ } & HTMLTableElement;
40
43
  export type StepProps = {
41
44
  title: string;
42
45
  content: React.ReactNode;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ar-design",
3
- "version": "0.1.86",
3
+ "version": "0.1.87",
4
4
  "main": "./dist/index.js",
5
5
  "module": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",