ar-design 0.1.34 → 0.1.36
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/assets/css/components/form/select/select.css +9 -2
- package/dist/assets/css/components/navigation/steps/steps.css +3 -0
- package/dist/assets/css/core/variants/outlined/outlined.css +8 -8
- package/dist/components/data-display/table/IProps.d.ts +2 -1
- package/dist/components/data-display/table/index.js +2 -2
- package/dist/components/form/date-picker/index.js +4 -9
- package/dist/components/form/input/IProps.d.ts +2 -6
- package/dist/components/form/input/index.js +1 -1
- package/dist/components/form/select/Props.d.ts +3 -4
- package/dist/components/form/select/index.js +15 -17
- package/dist/components/navigation/steps/index.js +0 -2
- package/dist/libs/core/application/hooks/index.d.ts +2 -12
- package/dist/libs/core/application/hooks/index.js +46 -46
- package/dist/libs/infrastructure/shared/Utils.d.ts +1 -0
- package/dist/libs/infrastructure/shared/Utils.js +11 -0
- package/dist/libs/types/IGlobalProps.d.ts +6 -0
- package/dist/libs/types/index.d.ts +1 -0
- package/package.json +1 -1
|
@@ -10,7 +10,8 @@
|
|
|
10
10
|
|
|
11
11
|
.ar-select-wrapper > .ar-select > .angel-down {
|
|
12
12
|
position: absolute;
|
|
13
|
-
top:
|
|
13
|
+
top: calc(var(--input-height) / 2);
|
|
14
|
+
transform: translateY(-50%);
|
|
14
15
|
right: 0.5rem;
|
|
15
16
|
width: 0.75rem;
|
|
16
17
|
height: 0.75rem;
|
|
@@ -44,7 +45,7 @@
|
|
|
44
45
|
|
|
45
46
|
.ar-select-wrapper > .ar-select > .button-clear {
|
|
46
47
|
position: absolute;
|
|
47
|
-
top:
|
|
48
|
+
top: calc(var(--input-height) / 2);
|
|
48
49
|
transform: translateY(-50%);
|
|
49
50
|
right: 2rem;
|
|
50
51
|
background-color: rgba(var(--black-rgb), 0.25);
|
|
@@ -100,4 +101,10 @@
|
|
|
100
101
|
border-radius: var(--border-radius-sm);
|
|
101
102
|
}
|
|
102
103
|
|
|
104
|
+
.ar-select-wrapper > .ar-select > .validation {
|
|
105
|
+
color: var(--danger);
|
|
106
|
+
font-size: 0.8rem;
|
|
107
|
+
font-weight: 600;
|
|
108
|
+
}
|
|
109
|
+
|
|
103
110
|
@import url("./options.css");
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/* #region PRIMARY */
|
|
2
2
|
.outlined:not(.disabled).primary {
|
|
3
3
|
border-color: var(--primary);
|
|
4
|
-
color: var(--primary);
|
|
4
|
+
/* color: var(--primary); */
|
|
5
5
|
}
|
|
6
6
|
.outlined:not(.disabled).primary:hover {
|
|
7
7
|
border-color: rgba(var(--primary-rgb), 0.5);
|
|
@@ -23,7 +23,7 @@ input[type="checkbox"]:checked + span > .ar-checkbox.outlined:not(.disabled).pri
|
|
|
23
23
|
/* #region SECONDARY */
|
|
24
24
|
.outlined:not(.disabled).secondary {
|
|
25
25
|
border-color: var(--secondary);
|
|
26
|
-
color: var(--secondary);
|
|
26
|
+
/* color: var(--secondary); */
|
|
27
27
|
}
|
|
28
28
|
.outlined:not(.disabled).secondary:hover {
|
|
29
29
|
border-color: rgba(var(--secondary-rgb), 0.5);
|
|
@@ -45,7 +45,7 @@ input[type="checkbox"]:checked + span > .ar-checkbox.outlined:not(.disabled).sec
|
|
|
45
45
|
/* #region SUCCESS */
|
|
46
46
|
.outlined:not(.disabled).success {
|
|
47
47
|
border-color: var(--success);
|
|
48
|
-
color: var(--success);
|
|
48
|
+
/* color: var(--success); */
|
|
49
49
|
}
|
|
50
50
|
.outlined:not(.disabled).success:hover {
|
|
51
51
|
border-color: rgba(var(--success-rgb), 0.5);
|
|
@@ -67,7 +67,7 @@ input[type="checkbox"]:checked + span > .ar-checkbox.outlined:not(.disabled).suc
|
|
|
67
67
|
/* #region WARNING */
|
|
68
68
|
.outlined:not(.disabled).warning {
|
|
69
69
|
border-color: var(--warning);
|
|
70
|
-
color: var(--warning);
|
|
70
|
+
/* color: var(--warning); */
|
|
71
71
|
}
|
|
72
72
|
.outlined:not(.disabled).warning:hover {
|
|
73
73
|
border-color: rgba(var(--warning-rgb), 0.5);
|
|
@@ -89,7 +89,7 @@ input[type="checkbox"]:checked + span > .ar-checkbox.outlined:not(.disabled).war
|
|
|
89
89
|
/* #region DANGER */
|
|
90
90
|
.outlined:not(.disabled).danger {
|
|
91
91
|
border-color: var(--danger);
|
|
92
|
-
color: var(--danger);
|
|
92
|
+
/* color: var(--danger); */
|
|
93
93
|
}
|
|
94
94
|
.outlined:not(.disabled).danger:hover {
|
|
95
95
|
border-color: rgba(var(--danger-rgb), 0.5);
|
|
@@ -111,7 +111,7 @@ input[type="checkbox"]:checked + span > .ar-checkbox.outlined:not(.disabled).dan
|
|
|
111
111
|
/* #region INFORMATION */
|
|
112
112
|
.outlined:not(.disabled).information {
|
|
113
113
|
border-color: var(--information);
|
|
114
|
-
color: var(--information);
|
|
114
|
+
/* color: var(--information); */
|
|
115
115
|
}
|
|
116
116
|
.outlined:not(.disabled).information:hover {
|
|
117
117
|
border-color: rgba(var(--information-rgb), 0.5);
|
|
@@ -133,7 +133,7 @@ input[type="checkbox"]:checked + span > .ar-checkbox.outlined:not(.disabled).inf
|
|
|
133
133
|
/* #region DARK */
|
|
134
134
|
.outlined:not(.disabled).dark {
|
|
135
135
|
border-color: var(--dark);
|
|
136
|
-
color: var(--dark);
|
|
136
|
+
/* color: var(--dark); */
|
|
137
137
|
}
|
|
138
138
|
.outlined:not(.disabled).dark:hover {
|
|
139
139
|
border-color: rgba(var(--dark-rgb), 0.5);
|
|
@@ -155,7 +155,7 @@ input[type="checkbox"]:checked + span > .ar-checkbox.outlined:not(.disabled).dar
|
|
|
155
155
|
/* #region LIGHT */
|
|
156
156
|
.outlined:not(.disabled).light {
|
|
157
157
|
border-color: var(--light);
|
|
158
|
-
color: var(--dark);
|
|
158
|
+
/* color: var(--dark); */
|
|
159
159
|
}
|
|
160
160
|
.outlined:not(.disabled).light:hover {
|
|
161
161
|
border-color: rgba(var(--light-rgb), 0.5);
|
|
@@ -136,8 +136,8 @@ const Table = function ({ children, data, columns, selections, pagination, confi
|
|
|
136
136
|
}, [currentPage]);
|
|
137
137
|
return (React.createElement("div", { ref: _tableWrapper, className: _tableClassName.map((c) => c).join(" ") },
|
|
138
138
|
React.createElement("div", { className: "header" },
|
|
139
|
-
React.createElement("div", null,
|
|
140
|
-
React.createElement(Input, { placeholder: "Ara", onChange: (event) => setSearchedText(event.target.value.toLowerCase()) })),
|
|
139
|
+
config?.isSearchable && (React.createElement("div", null,
|
|
140
|
+
React.createElement(Input, { placeholder: "Ara", onChange: (event) => setSearchedText(event.target.value.toLowerCase()) }))),
|
|
141
141
|
React.createElement("div", null, React.Children.map(children, (child) => child))),
|
|
142
142
|
React.createElement("div", { ref: _tableContent, className: "content", onScroll: handleOnScroll },
|
|
143
143
|
React.createElement("table", { ref: _table },
|
|
@@ -45,10 +45,7 @@ const DatePicker = ({ onChange, isClock, ...attributes }) => {
|
|
|
45
45
|
const [minutes, setMinutes] = useState();
|
|
46
46
|
const [dateTrigger, setDateTrigger] = useState(false);
|
|
47
47
|
const [timeTrigger, setTimeTrigger] = useState(false);
|
|
48
|
-
let [calendarClassName, setCalendarClassName] = useState([
|
|
49
|
-
"calendar-wrapper",
|
|
50
|
-
"closed",
|
|
51
|
-
]);
|
|
48
|
+
let [calendarClassName, setCalendarClassName] = useState(["calendar-wrapper", "closed"]);
|
|
52
49
|
// states => Selected Date
|
|
53
50
|
const [currentYear, setCurrentYear] = useState(_currentDate.getFullYear());
|
|
54
51
|
const [currentMonth, setCurrentMonth] = useState(_currentDate.getMonth());
|
|
@@ -195,9 +192,7 @@ const DatePicker = ({ onChange, isClock, ...attributes }) => {
|
|
|
195
192
|
}, [dateTrigger, calendarOpen]);
|
|
196
193
|
useEffect(() => {
|
|
197
194
|
const generateList = (count, current, setFunc) => {
|
|
198
|
-
const items = Array.from({ length: count }, (_, i) => (React.createElement("li", { ref: (element) => count === 24
|
|
199
|
-
? (_hoursLiElements.current[i] = element)
|
|
200
|
-
: (_minutesLiElements.current[i] = element), key: i, ...(current === i ? { className: "selection-time" } : {}), onClick: () => {
|
|
195
|
+
const items = Array.from({ length: count }, (_, i) => (React.createElement("li", { ref: (element) => count === 24 ? (_hoursLiElements.current[i] = element) : (_minutesLiElements.current[i] = element), key: i, ...(current === i ? { className: "selection-time" } : {}), onClick: () => {
|
|
201
196
|
if (count === 24) {
|
|
202
197
|
setTimeTrigger((prev) => !prev);
|
|
203
198
|
_hours.current = i;
|
|
@@ -277,12 +272,12 @@ const DatePicker = ({ onChange, isClock, ...attributes }) => {
|
|
|
277
272
|
setDateTrigger((prev) => !prev);
|
|
278
273
|
} }, "‹")),
|
|
279
274
|
React.createElement("div", { className: "selects" },
|
|
280
|
-
React.createElement(Select, {
|
|
275
|
+
React.createElement(Select, { variant: "borderless", value: { value: _month.current, text: String(_month.current) }, options: months, onChange: (option) => {
|
|
281
276
|
_month.current = option?.value;
|
|
282
277
|
updateDateInput(_year.current, _month.current, _day.current);
|
|
283
278
|
setDateTrigger((prev) => !prev);
|
|
284
279
|
}, placeholder: "Ay" }),
|
|
285
|
-
React.createElement(Select, { variant: "borderless",
|
|
280
|
+
React.createElement(Select, { variant: "borderless", value: { value: _year.current, text: String(_year.current) }, options: years, onChange: (option) => {
|
|
286
281
|
_year.current = option?.value;
|
|
287
282
|
updateDateInput(_year.current, _month.current, _day.current);
|
|
288
283
|
setDateTrigger((prev) => !prev);
|
|
@@ -1,17 +1,13 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import IButtonProps from "../button/IProps";
|
|
3
3
|
import { Variants } from "../../../libs/types";
|
|
4
|
-
import { IGlobalProps } from "../../../libs/types/IGlobalProps";
|
|
5
|
-
interface IProps extends Omit<IGlobalProps, "children" | "disabled">, Omit<React.InputHTMLAttributes<HTMLInputElement>, "children" | "size"
|
|
4
|
+
import { IGlobalProps, IValidation } from "../../../libs/types/IGlobalProps";
|
|
5
|
+
interface IProps extends Omit<IGlobalProps, "children" | "disabled">, Omit<React.InputHTMLAttributes<HTMLInputElement>, "children" | "size">, IValidation {
|
|
6
6
|
button?: IButtonProps;
|
|
7
7
|
addon?: {
|
|
8
8
|
variant?: Variants;
|
|
9
9
|
before?: string | number;
|
|
10
10
|
after?: string | number;
|
|
11
11
|
};
|
|
12
|
-
validation?: {
|
|
13
|
-
text: string | string[] | React.JSX.Element[] | null;
|
|
14
|
-
scrollTo?: boolean;
|
|
15
|
-
};
|
|
16
12
|
}
|
|
17
13
|
export default IProps;
|
|
@@ -9,7 +9,7 @@ const Input = forwardRef(({ variant = "outlined", status = "light", size = "norm
|
|
|
9
9
|
const _addonBeforeClassName = ["addon-before"];
|
|
10
10
|
const _addonAfterClassName = ["addon-after"];
|
|
11
11
|
const _inputClassName = [];
|
|
12
|
-
_inputClassName.push(...Utils.GetClassName(variant, validation?.text ? "danger" : status, border, size, icon, attributes.className));
|
|
12
|
+
_inputClassName.push(...Utils.GetClassName(variant, !Utils.IsNullOrEmpty(validation?.text) ? "danger" : status, border, size, icon, attributes.className));
|
|
13
13
|
// addon className
|
|
14
14
|
if (addon) {
|
|
15
15
|
_wrapperClassName.push("addon");
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Variants, Option, Status } from "../../../libs/types";
|
|
2
|
-
import { IGlobalProps } from "../../../libs/types/IGlobalProps";
|
|
2
|
+
import { IGlobalProps, IValidation } from "../../../libs/types/IGlobalProps";
|
|
3
3
|
interface IMultiple {
|
|
4
4
|
status?: {
|
|
5
5
|
color?: Status;
|
|
@@ -8,14 +8,12 @@ interface IMultiple {
|
|
|
8
8
|
color?: Status;
|
|
9
9
|
};
|
|
10
10
|
};
|
|
11
|
-
defaultValueIndex?: number[];
|
|
12
11
|
value: Option[];
|
|
13
12
|
onChange: (option: Option[]) => void;
|
|
14
13
|
multiple: true;
|
|
15
14
|
}
|
|
16
15
|
interface ISingle {
|
|
17
16
|
status?: Status;
|
|
18
|
-
defaultValueIndex?: number;
|
|
19
17
|
value: Option | undefined;
|
|
20
18
|
onChange: (option: Option | undefined) => void;
|
|
21
19
|
multiple?: false;
|
|
@@ -24,5 +22,6 @@ export type Props = {
|
|
|
24
22
|
options: Option[];
|
|
25
23
|
onCreate?: (option: Option) => void;
|
|
26
24
|
placeholder?: string;
|
|
27
|
-
|
|
25
|
+
disabled?: boolean;
|
|
26
|
+
} & (IMultiple | ISingle) & Omit<IGlobalProps, "status"> & IValidation;
|
|
28
27
|
export {};
|
|
@@ -5,9 +5,10 @@ import "../../../assets/css/components/form/select/select.css";
|
|
|
5
5
|
import Chip from "../../data-display/chip";
|
|
6
6
|
import Checkbox from "../checkbox";
|
|
7
7
|
import Paragraph from "../../data-display/typography/paragraph/Paragraph";
|
|
8
|
-
|
|
8
|
+
import Utils from "../../../libs/infrastructure/shared/Utils";
|
|
9
|
+
const Select = ({ variant = "outlined", status, border = { radius: "sm" }, options, value, onChange, onCreate, multiple, placeholder, disabled, validation, }) => {
|
|
10
|
+
const _selectionClassName = ["selections"];
|
|
9
11
|
// refs
|
|
10
|
-
let _selectionClassName = "selections";
|
|
11
12
|
const _arSelect = useRef(null);
|
|
12
13
|
const _singleInput = useRef(null);
|
|
13
14
|
const _multipleInput = useRef(null);
|
|
@@ -23,13 +24,7 @@ const Select = ({ variant = "outlined", status, border = { radius: "sm" }, optio
|
|
|
23
24
|
const [searchText, setSearchText] = useState("");
|
|
24
25
|
const [singleInputText, setSingleInputText] = useState("");
|
|
25
26
|
const [navigationIndex, setNavigationIndex] = useState(0);
|
|
26
|
-
|
|
27
|
-
if (variant)
|
|
28
|
-
_selectionClassName += ` ${variant}`;
|
|
29
|
-
_selectionClassName += multiple ? ` ${status?.color || "light"}` : status || "light";
|
|
30
|
-
// border
|
|
31
|
-
_selectionClassName += ` border-radius-${border.radius}`;
|
|
32
|
-
_selectionClassName += ` border-style-solid}`;
|
|
27
|
+
_selectionClassName.push(...Utils.GetClassName(variant, !Utils.IsNullOrEmpty(validation?.text) ? "danger" : "light", border, undefined, undefined, undefined));
|
|
33
28
|
// methods
|
|
34
29
|
const handleClickOutSide = (event) => {
|
|
35
30
|
const target = event.target;
|
|
@@ -134,7 +129,7 @@ const Select = ({ variant = "outlined", status, border = { radius: "sm" }, optio
|
|
|
134
129
|
// }
|
|
135
130
|
if (_singleInput.current) {
|
|
136
131
|
_singleInput.current.value = "";
|
|
137
|
-
_singleInput.current.placeholder = value?.text ||
|
|
132
|
+
_singleInput.current.placeholder = value?.text || placeholder || "";
|
|
138
133
|
}
|
|
139
134
|
}
|
|
140
135
|
// Options açıldıktan 100ms sonra arama kutusuna otomatik olarak focus oluyor.
|
|
@@ -166,7 +161,7 @@ const Select = ({ variant = "outlined", status, border = { radius: "sm" }, optio
|
|
|
166
161
|
else {
|
|
167
162
|
if (_singleInput.current) {
|
|
168
163
|
_singleInput.current.value = value?.text ?? "";
|
|
169
|
-
_singleInput.current.placeholder =
|
|
164
|
+
_singleInput.current.placeholder = placeholder ?? "";
|
|
170
165
|
}
|
|
171
166
|
}
|
|
172
167
|
setOptionsClassName((prev) => [...prev, direction, "closed"]);
|
|
@@ -205,8 +200,8 @@ const Select = ({ variant = "outlined", status, border = { radius: "sm" }, optio
|
|
|
205
200
|
}, [navigationIndex]);
|
|
206
201
|
return (React.createElement("div", { ref: _arSelect, className: "ar-select-wrapper" },
|
|
207
202
|
React.createElement("div", { ref: _multipleInput, className: "ar-select" },
|
|
208
|
-
multiple ? (React.createElement("div", { className: _selectionClassName, onClick: () => setOptionsOpen((x) => !x) },
|
|
209
|
-
React.createElement("div", { className: "items" }, value.length > 0 ? (value.map((_value, index) => (React.createElement(Chip, { key: index, variant: status?.selected?.variant || "filled", status: status?.selected?.color || status?.color, text: _value.text })))) : (React.createElement("span",
|
|
203
|
+
multiple ? (React.createElement("div", { className: _selectionClassName.map((c) => c).join(" "), onClick: () => setOptionsOpen((x) => !x) },
|
|
204
|
+
React.createElement("div", { className: "items" }, value.length > 0 ? (value.map((_value, index) => (React.createElement(Chip, { key: index, variant: status?.selected?.variant || "filled", status: status?.selected?.color || status?.color, text: _value.text })))) : (React.createElement("span", { className: "placeholder" }, placeholder))))) : (React.createElement(Input, { ref: _singleInput, variant: variant, status: !Utils.IsNullOrEmpty(validation?.text) ? "danger" : status, border: { radius: border.radius }, onClick: () => {
|
|
210
205
|
setOptionsOpen((prev) => !prev);
|
|
211
206
|
setSingleInputText("");
|
|
212
207
|
}, onChange: (event) => {
|
|
@@ -216,15 +211,18 @@ const Select = ({ variant = "outlined", status, border = { radius: "sm" }, optio
|
|
|
216
211
|
if (event.key === "Enter")
|
|
217
212
|
return;
|
|
218
213
|
setSearchText(event.currentTarget.value);
|
|
219
|
-
}, placeholder:
|
|
220
|
-
React.createElement("span", { className: `button-clear ${!
|
|
214
|
+
}, placeholder: placeholder, disabled: disabled })),
|
|
215
|
+
React.createElement("span", { className: `button-clear ${!disabled && (multiple ? value.length > 0 : value) ? "opened" : "closed"}`, onClick: (event) => {
|
|
216
|
+
if (disabled)
|
|
217
|
+
return;
|
|
221
218
|
event.stopPropagation();
|
|
222
219
|
handleCleanSelection();
|
|
223
220
|
} }),
|
|
224
221
|
React.createElement("span", { className: `angel-down ${optionsOpen ? "opened" : "closed"}`, onClick: (event) => {
|
|
225
222
|
event.stopPropagation();
|
|
226
223
|
setOptionsOpen((x) => !x);
|
|
227
|
-
} })
|
|
224
|
+
} }),
|
|
225
|
+
validation?.text && React.createElement("span", { className: "validation" }, validation.text)),
|
|
228
226
|
React.createElement("div", { ref: _options, className: optionsClassName.map((c) => c).join(" ") },
|
|
229
227
|
multiple && (React.createElement("div", { className: "search-field" },
|
|
230
228
|
React.createElement(Input, { ref: _searchField, variant: "outlined", status: "light", placeholder: "Search...", onKeyUp: (event) => {
|
|
@@ -237,7 +235,7 @@ const Select = ({ variant = "outlined", status, border = { radius: "sm" }, optio
|
|
|
237
235
|
React.createElement("span", null, option.text)));
|
|
238
236
|
}))) : !onCreate ? (React.createElement(Paragraph, { color: "gray-500", align: "center" }, "Herhangi bir kay\u0131t bulunumad\u0131!")) : (React.createElement("span", { style: { padding: "1rem", cursor: "pointer" }, onClick: () => {
|
|
239
237
|
onCreate({ value: "", text: singleInputText });
|
|
240
|
-
|
|
238
|
+
handleItemSelected({ value: "", text: singleInputText });
|
|
241
239
|
} }, options.length === 0 && singleInputText.length === 0
|
|
242
240
|
? "Herhangi bir kayıt bulunumadı!"
|
|
243
241
|
: `${singleInputText} Ekle`)))));
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
import React, { useState } from "react";
|
|
3
3
|
import "../../../assets/css/components/navigation/steps/steps.css";
|
|
4
4
|
import Typography from "../../data-display/typography";
|
|
5
|
-
import Divider from "../../data-display/divider";
|
|
6
5
|
const { Title } = Typography;
|
|
7
6
|
const Steps = ({ steps = [], onChange }) => {
|
|
8
7
|
// states
|
|
@@ -35,7 +34,6 @@ const Steps = ({ steps = [], onChange }) => {
|
|
|
35
34
|
index + 1),
|
|
36
35
|
React.createElement(Title, { Level: "h3" }, step.title))));
|
|
37
36
|
})),
|
|
38
|
-
React.createElement(Divider, null),
|
|
39
37
|
React.createElement("div", { className: "content" }, steps.map((step, index) => currentStep === index && step.content))));
|
|
40
38
|
};
|
|
41
39
|
export default Steps;
|
|
@@ -39,18 +39,8 @@ export declare const useNotification: () => {
|
|
|
39
39
|
status: Status;
|
|
40
40
|
}) => void;
|
|
41
41
|
};
|
|
42
|
-
type Error = {
|
|
43
|
-
[key: string]: string;
|
|
44
|
-
type: string;
|
|
45
|
-
}[];
|
|
46
42
|
export declare const useValidation: <TData extends object>(data: TData, params: ValidationProperties<TData>[]) => {
|
|
47
|
-
|
|
43
|
+
onSubmit: (callback: (result: boolean) => void) => void;
|
|
48
44
|
setSubmit: import("react").Dispatch<import("react").SetStateAction<boolean>>;
|
|
49
|
-
|
|
50
|
-
setSuccess: import("react").Dispatch<import("react").SetStateAction<boolean>>;
|
|
51
|
-
message: string | null;
|
|
52
|
-
setMessage: import("react").Dispatch<import("react").SetStateAction<string | null>>;
|
|
53
|
-
errors: Error;
|
|
54
|
-
showErrors: (errors: Error, field: string) => string[] | null;
|
|
45
|
+
errors: Partial<{ [key in keyof TData]: string; }>;
|
|
55
46
|
};
|
|
56
|
-
export {};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useContext, useEffect, useState } from "react";
|
|
1
|
+
import { useContext, useEffect, useRef, useState } from "react";
|
|
2
2
|
import { ConfigContext } from "../contexts/Config";
|
|
3
3
|
import { NotificationContext } from "../contexts/Notification";
|
|
4
4
|
import Utils from "../../../infrastructure/shared/Utils";
|
|
@@ -22,66 +22,66 @@ export const useNotification = () => {
|
|
|
22
22
|
return { notification };
|
|
23
23
|
};
|
|
24
24
|
export const useValidation = function (data, params) {
|
|
25
|
-
//
|
|
25
|
+
// refs
|
|
26
|
+
const _errors = useRef({});
|
|
27
|
+
// states
|
|
28
|
+
const [errors, setErrors] = useState({});
|
|
26
29
|
const [submit, setSubmit] = useState(false);
|
|
27
|
-
const [success, setSuccess] = useState(true);
|
|
28
|
-
const [message, setMessage] = useState(null);
|
|
29
|
-
const [errors, setErrors] = useState([]);
|
|
30
30
|
// methods
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
31
|
+
const onSubmit = (callback) => {
|
|
32
|
+
setSubmit(true);
|
|
33
|
+
setTimeout(() => {
|
|
34
|
+
let result = true;
|
|
35
|
+
if (!data || Object.keys(data).length === 0 || params.length === 0)
|
|
36
|
+
result = false;
|
|
37
|
+
if (Object.keys(_errors.current).length > 0)
|
|
38
|
+
result = false;
|
|
39
|
+
callback(result);
|
|
40
|
+
}, 0);
|
|
41
|
+
};
|
|
42
|
+
const setError = (key, message) => {
|
|
43
|
+
setErrors((prev) => ({ ...prev, [key]: message }));
|
|
44
|
+
_errors.current = { ..._errors.current, [key]: message };
|
|
36
45
|
};
|
|
37
46
|
// useEffects
|
|
38
47
|
useEffect(() => {
|
|
39
|
-
if (!
|
|
48
|
+
if (!submit)
|
|
40
49
|
return;
|
|
41
|
-
setErrors(
|
|
50
|
+
setErrors({});
|
|
51
|
+
_errors.current = {};
|
|
42
52
|
params.forEach((param) => {
|
|
43
53
|
const value = data[param.key];
|
|
44
54
|
param.shape?.forEach((s) => {
|
|
45
|
-
if (
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
value && value.length < s.value
|
|
50
|
-
? setErrors((errors) => [
|
|
51
|
-
...errors,
|
|
52
|
-
{
|
|
53
|
-
[param.key]: Utils.StringFormat(s.message, s.value, 4),
|
|
54
|
-
type: s.type,
|
|
55
|
-
},
|
|
56
|
-
])
|
|
57
|
-
: null;
|
|
58
|
-
}
|
|
59
|
-
if (s.type === "maximum") {
|
|
60
|
-
value && value.length > s.value
|
|
61
|
-
? setErrors((errors) => [
|
|
62
|
-
...errors,
|
|
63
|
-
{
|
|
64
|
-
[param.key]: Utils.StringFormat(s.message, s.value),
|
|
65
|
-
type: s.type,
|
|
66
|
-
},
|
|
67
|
-
])
|
|
68
|
-
: null;
|
|
55
|
+
if (param.where) {
|
|
56
|
+
if (s.type === "required" && param.where(data)) {
|
|
57
|
+
Utils.IsNullOrEmpty(value) ? setError(param.key, s.message) : null;
|
|
58
|
+
}
|
|
69
59
|
}
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
60
|
+
else {
|
|
61
|
+
if (s.type === "required") {
|
|
62
|
+
Utils.IsNullOrEmpty(value) ? setError(param.key, s.message) : null;
|
|
63
|
+
}
|
|
64
|
+
if (s.type === "minimum") {
|
|
65
|
+
value && value.length < s.value
|
|
66
|
+
? setError(param.key, Utils.StringFormat(s.message, s.value))
|
|
67
|
+
: null;
|
|
68
|
+
}
|
|
69
|
+
if (s.type === "maximum") {
|
|
70
|
+
value && value.length > s.value
|
|
71
|
+
? setError(param.key, Utils.StringFormat(s.message, s.value))
|
|
72
|
+
: null;
|
|
73
|
+
}
|
|
74
|
+
if (s.type === "email") {
|
|
75
|
+
const regex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/.test(value);
|
|
76
|
+
!regex && Utils.IsNullOrEmpty(value) ? setError(param.key, s.message) : null;
|
|
77
|
+
}
|
|
73
78
|
}
|
|
74
79
|
});
|
|
75
80
|
});
|
|
76
|
-
}, [data]);
|
|
81
|
+
}, [submit, data]);
|
|
77
82
|
return {
|
|
78
|
-
|
|
83
|
+
onSubmit,
|
|
79
84
|
setSubmit,
|
|
80
|
-
success,
|
|
81
|
-
setSuccess,
|
|
82
|
-
message,
|
|
83
|
-
setMessage,
|
|
84
85
|
errors,
|
|
85
|
-
showErrors,
|
|
86
86
|
};
|
|
87
87
|
};
|
|
@@ -2,6 +2,7 @@ import { Border, Icon, Sizes, Status, Variants } from "../../types";
|
|
|
2
2
|
declare class Utils {
|
|
3
3
|
GetClassName: (variant?: Variants, status?: Status, border?: Border, size?: Sizes, icon?: Icon, className?: string) => string[];
|
|
4
4
|
StringFormat: (value: string, ...args: any[]) => string;
|
|
5
|
+
IsNullOrEmpty: (value: unknown) => boolean;
|
|
5
6
|
}
|
|
6
7
|
declare const _default: Utils;
|
|
7
8
|
export default _default;
|
|
@@ -19,5 +19,16 @@ class Utils {
|
|
|
19
19
|
return typeof args[index] !== "undefined" ? args[index] : match;
|
|
20
20
|
});
|
|
21
21
|
};
|
|
22
|
+
IsNullOrEmpty = (value) => {
|
|
23
|
+
if (value === null || value === undefined)
|
|
24
|
+
return true;
|
|
25
|
+
if (typeof value === "string" && value.trim() === "")
|
|
26
|
+
return true;
|
|
27
|
+
if (typeof value === "object" && value !== null && Object.keys(value).length === 0)
|
|
28
|
+
return true;
|
|
29
|
+
if (Array.isArray(value) && value.length === 0)
|
|
30
|
+
return true;
|
|
31
|
+
return false;
|
|
32
|
+
};
|
|
22
33
|
}
|
|
23
34
|
export default new Utils();
|