ar-design 0.1.29 → 0.1.30
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/feedback/modal/modal.css +5 -1
- package/dist/assets/css/components/form/input/input.css +5 -0
- package/dist/assets/css/components/form/select/select.css +8 -0
- package/dist/components/data-display/table/index.d.ts +1 -1
- package/dist/components/data-display/table/index.js +2 -4
- package/dist/components/feedback/modal/index.js +12 -7
- package/dist/components/form/input/IProps.d.ts +4 -0
- package/dist/components/form/input/index.js +6 -5
- package/dist/components/form/select/index.js +5 -3
- package/dist/components/navigation/pagination/index.js +10 -9
- package/dist/libs/core/application/hooks/index.d.ts +17 -1
- package/dist/libs/core/application/hooks/index.js +67 -2
- package/dist/libs/infrastructure/shared/Utils.d.ts +1 -0
- package/dist/libs/infrastructure/shared/Utils.js +8 -0
- package/dist/libs/types/index.d.ts +8 -0
- package/package.json +1 -1
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
.ar-modal-wrapper {
|
|
2
2
|
position: absolute;
|
|
3
3
|
inset: 0;
|
|
4
|
+
}
|
|
5
|
+
.ar-modal-wrapper > .ar-modal-bg {
|
|
6
|
+
position: fixed;
|
|
7
|
+
inset: 0;
|
|
4
8
|
background-color: rgba(var(--black-rgb), 0.5);
|
|
5
|
-
backdrop-filter: blur(
|
|
9
|
+
backdrop-filter: blur(10px);
|
|
6
10
|
}
|
|
7
11
|
|
|
8
12
|
/* #region Open or Close */
|
|
@@ -20,6 +20,11 @@
|
|
|
20
20
|
box-sizing: border-box;
|
|
21
21
|
transition: background 250ms, border 250ms, box-shadow 250ms ease-in-out;
|
|
22
22
|
}
|
|
23
|
+
.ar-input-wrapper > .ar-input > .validation {
|
|
24
|
+
color: var(--danger);
|
|
25
|
+
font-size: 0.8rem;
|
|
26
|
+
font-weight: 600;
|
|
27
|
+
}
|
|
23
28
|
|
|
24
29
|
/* Core Css */
|
|
25
30
|
@import url("./core/icon.css");
|
|
@@ -56,6 +56,14 @@
|
|
|
56
56
|
line-height: 0.7rem;
|
|
57
57
|
cursor: pointer;
|
|
58
58
|
}
|
|
59
|
+
.ar-select-wrapper > .ar-select > .button-clear:is(.opened) {
|
|
60
|
+
visibility: visible;
|
|
61
|
+
opacity: 1;
|
|
62
|
+
}
|
|
63
|
+
.ar-select-wrapper > .ar-select > .button-clear:is(.closed) {
|
|
64
|
+
visibility: hidden;
|
|
65
|
+
opacity: 0;
|
|
66
|
+
}
|
|
59
67
|
.ar-select-wrapper > .ar-select > .button-clear::before {
|
|
60
68
|
content: "x";
|
|
61
69
|
color: var(--white);
|
|
@@ -2,7 +2,7 @@ import React from "react";
|
|
|
2
2
|
import IProps from "./IProps";
|
|
3
3
|
import "../../../assets/css/components/data-display/table/table.css";
|
|
4
4
|
declare const Table: {
|
|
5
|
-
<T extends object>({ children, data, columns, selections, pagination, config
|
|
5
|
+
<T extends object>({ children, data, columns, selections, pagination, config }: IProps<T>): React.JSX.Element;
|
|
6
6
|
Action: React.FC<{
|
|
7
7
|
children: React.ReactElement<{
|
|
8
8
|
children: React.ReactElement<import("../../form/button/IProps").default> | React.ReactElement<import("../../form/button/IProps").default>[];
|
|
@@ -5,7 +5,7 @@ import Checkbox from "../../form/checkbox";
|
|
|
5
5
|
import Actions from "./Actions";
|
|
6
6
|
import Input from "../../form/input";
|
|
7
7
|
import Pagination from "../../navigation/pagination";
|
|
8
|
-
const Table = function ({ children, data, columns, selections, pagination, config
|
|
8
|
+
const Table = function ({ children, data, columns, selections, pagination, config }) {
|
|
9
9
|
// refs
|
|
10
10
|
let _dataLength = useRef(0);
|
|
11
11
|
const _tableWrapper = useRef(null);
|
|
@@ -185,9 +185,7 @@ const Table = function ({ children, data, columns, selections, pagination, confi
|
|
|
185
185
|
else if (typeof c.key === "object") {
|
|
186
186
|
const _item = item[c.key.field];
|
|
187
187
|
if (_item && typeof _item === "object") {
|
|
188
|
-
render = c.render
|
|
189
|
-
? c.render(item)
|
|
190
|
-
: _item[c.key.nestedKey];
|
|
188
|
+
render = c.render ? c.render(item) : _item[c.key.nestedKey];
|
|
191
189
|
}
|
|
192
190
|
}
|
|
193
191
|
// Diğer durumlarda `null` döndür
|
|
@@ -13,11 +13,10 @@ const Modal = ({ children, open, title, size = "normal", footer }) => {
|
|
|
13
13
|
else
|
|
14
14
|
_modalWrapperClassName.push("closed");
|
|
15
15
|
// methods
|
|
16
|
-
const handleClickOutSide = (event) => {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
};
|
|
16
|
+
// const handleClickOutSide = (event: MouseEvent) => {
|
|
17
|
+
// const target = event.target as HTMLElement;
|
|
18
|
+
// if (_arModal.current && !_arModal.current.contains(target)) open.set(false);
|
|
19
|
+
// };
|
|
21
20
|
const handleKeys = (event) => {
|
|
22
21
|
const key = event.key;
|
|
23
22
|
if (key === "Escape")
|
|
@@ -26,16 +25,22 @@ const Modal = ({ children, open, title, size = "normal", footer }) => {
|
|
|
26
25
|
// useEffects
|
|
27
26
|
useEffect(() => {
|
|
28
27
|
if (open.get) {
|
|
29
|
-
document.addEventListener("click", handleClickOutSide);
|
|
28
|
+
// document.addEventListener("click", handleClickOutSide);
|
|
30
29
|
document.addEventListener("keydown", handleKeys);
|
|
31
30
|
// Dinleyicileri kaldır.
|
|
32
31
|
return () => {
|
|
33
|
-
document.removeEventListener("click", handleClickOutSide);
|
|
32
|
+
// document.removeEventListener("click", handleClickOutSide);
|
|
34
33
|
document.removeEventListener("keydown", handleKeys);
|
|
35
34
|
};
|
|
36
35
|
}
|
|
37
36
|
}, [open.get]);
|
|
38
37
|
return (React.createElement("div", { className: _modalWrapperClassName.map((c) => c).join(" ") },
|
|
38
|
+
React.createElement("div", { className: "ar-modal-bg", onMouseDown: (event) => {
|
|
39
|
+
event.stopPropagation();
|
|
40
|
+
const target = event.target;
|
|
41
|
+
if (_arModal.current && !_arModal.current.contains(target))
|
|
42
|
+
open.set(false);
|
|
43
|
+
} }),
|
|
39
44
|
React.createElement("div", { ref: _arModal, className: _modalClassName.map((c) => c).join(" "), role: "dialog" },
|
|
40
45
|
React.createElement("div", { className: "header" },
|
|
41
46
|
React.createElement(Title, { Level: "h3" }, title),
|
|
@@ -9,5 +9,9 @@ interface IProps extends Omit<IGlobalProps, "children" | "disabled">, Omit<React
|
|
|
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
|
+
};
|
|
12
16
|
}
|
|
13
17
|
export default IProps;
|
|
@@ -3,13 +3,13 @@ import React, { forwardRef } from "react";
|
|
|
3
3
|
import "../../../assets/css/components/form/input/input.css";
|
|
4
4
|
import Button from "../button";
|
|
5
5
|
import Utils from "../../../libs/infrastructure/shared/Utils";
|
|
6
|
-
const Input = forwardRef(({ variant = "outlined", status = "light", size = "normal", icon, border = { radius: "sm" }, button, addon, ...attributes }, ref) => {
|
|
6
|
+
const Input = forwardRef(({ variant = "outlined", status = "light", size = "normal", icon, border = { radius: "sm" }, button, addon, validation, ...attributes }, ref) => {
|
|
7
7
|
// variables
|
|
8
8
|
const _wrapperClassName = ["ar-input-wrapper"];
|
|
9
9
|
const _addonBeforeClassName = ["addon-before"];
|
|
10
10
|
const _addonAfterClassName = ["addon-after"];
|
|
11
11
|
const _inputClassName = [];
|
|
12
|
-
_inputClassName.push(...Utils.GetClassName(variant, status, border, size, icon, attributes.className));
|
|
12
|
+
_inputClassName.push(...Utils.GetClassName(variant, validation?.text ? "danger" : status, border, size, icon, attributes.className));
|
|
13
13
|
// addon className
|
|
14
14
|
if (addon) {
|
|
15
15
|
_wrapperClassName.push("addon");
|
|
@@ -21,7 +21,7 @@ const Input = forwardRef(({ variant = "outlined", status = "light", size = "norm
|
|
|
21
21
|
_addonAfterClassName.push(`border-radius-${border.radius}`);
|
|
22
22
|
}
|
|
23
23
|
return (React.createElement("div", { className: _wrapperClassName.map((c) => c).join(" ") },
|
|
24
|
-
addon?.before &&
|
|
24
|
+
addon?.before && React.createElement("span", { className: _addonBeforeClassName.map((c) => c).join(" ") }, addon?.before),
|
|
25
25
|
React.createElement("div", { className: "ar-input" },
|
|
26
26
|
icon?.element && React.createElement("span", { className: "icon-element" }, icon.element),
|
|
27
27
|
React.createElement("input", { ref: ref, ...attributes, size: 20, className: _inputClassName.map((c) => c).join(" "), onChange: (event) => {
|
|
@@ -40,8 +40,9 @@ const Input = forwardRef(({ variant = "outlined", status = "light", size = "norm
|
|
|
40
40
|
});
|
|
41
41
|
}
|
|
42
42
|
})();
|
|
43
|
-
} })
|
|
44
|
-
|
|
43
|
+
} }),
|
|
44
|
+
validation?.text && React.createElement("span", { className: "validation" }, validation.text)),
|
|
45
|
+
addon?.after && React.createElement("span", { className: _addonAfterClassName.map((c) => c).join(" ") }, addon?.after),
|
|
45
46
|
button && (React.createElement(Button, { ...button, status: status, border: { radius: border.radius }, disabled: attributes.disabled }))));
|
|
46
47
|
});
|
|
47
48
|
Input.displayName = "Input";
|
|
@@ -222,8 +222,10 @@ const Select = ({ variant = "outlined", status, border = { radius: "sm" }, optio
|
|
|
222
222
|
// Arama yapmak için kullanılan state bu kısımda dolduruluyor.
|
|
223
223
|
setSearchText(event.currentTarget.value);
|
|
224
224
|
}, placeholder: attributes.placeholder, disabled: attributes.disabled })),
|
|
225
|
-
!attributes.disabled &&
|
|
226
|
-
|
|
225
|
+
React.createElement("span", { className: `button-clear ${!attributes.disabled && (Object.keys(selection || {}).length > 0 || (multiple && selections.length > 0))
|
|
226
|
+
? "opened"
|
|
227
|
+
: "closed"}`, onClick: (event) => {
|
|
228
|
+
event.stopPropagation();
|
|
227
229
|
// Multiple
|
|
228
230
|
if (multiple) {
|
|
229
231
|
if (_searchField.current)
|
|
@@ -239,7 +241,7 @@ const Select = ({ variant = "outlined", status, border = { radius: "sm" }, optio
|
|
|
239
241
|
setSelection(undefined);
|
|
240
242
|
onChange(undefined);
|
|
241
243
|
}
|
|
242
|
-
} })
|
|
244
|
+
} }),
|
|
243
245
|
React.createElement("span", { className: `angel-down ${optionsOpen ? "opened" : "closed"}`, onClick: (event) => {
|
|
244
246
|
event.stopPropagation();
|
|
245
247
|
setOptionsOpen((x) => !x);
|
|
@@ -1,20 +1,21 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import React, { useContext, useEffect,
|
|
2
|
+
import React, { useContext, useEffect, useState } from "react";
|
|
3
3
|
import "../../../assets/css/components/navigation/pagination/pagination.css";
|
|
4
4
|
import { ConfigContext } from "../../../libs/core/application/contexts/Config";
|
|
5
5
|
const Pagination = ({ defaultCurrent = 1, totalRecords, perPage, onChange }) => {
|
|
6
6
|
// context
|
|
7
7
|
const { config } = useContext(ConfigContext);
|
|
8
|
-
// refs
|
|
9
|
-
const _totalPageCount = useRef(Math.ceil(totalRecords / (perPage ?? config.perPage))).current;
|
|
10
8
|
// states
|
|
11
9
|
const [pages, setPages] = useState([]);
|
|
12
10
|
const [currentPage, setCurrentPage] = useState(defaultCurrent);
|
|
11
|
+
const [totalPageCount, setTotalPageCount] = useState(0);
|
|
13
12
|
// useEffect
|
|
14
13
|
useEffect(() => {
|
|
15
14
|
if (totalRecords === 0)
|
|
16
15
|
return;
|
|
17
16
|
const liItems = [];
|
|
17
|
+
const _totalPageCount = Math.ceil(totalRecords / (perPage ?? config.perPage));
|
|
18
|
+
setTotalPageCount(_totalPageCount);
|
|
18
19
|
// Başlangıç ve bitiş aralığını hesapla.
|
|
19
20
|
const startPage = Math.max(1, currentPage - 1);
|
|
20
21
|
const endPage = Math.min(_totalPageCount, currentPage + 1);
|
|
@@ -58,20 +59,20 @@ const Pagination = ({ defaultCurrent = 1, totalRecords, perPage, onChange }) =>
|
|
|
58
59
|
} },
|
|
59
60
|
React.createElement("span", null, "‹")),
|
|
60
61
|
pages,
|
|
61
|
-
React.createElement("li", { className:
|
|
62
|
-
if (
|
|
62
|
+
React.createElement("li", { className: totalPageCount === currentPage ? "passive" : "", onClick: () => {
|
|
63
|
+
if (totalPageCount === currentPage)
|
|
63
64
|
return;
|
|
64
65
|
setCurrentPage((prev) => {
|
|
65
|
-
if (prev ===
|
|
66
|
+
if (prev === totalPageCount)
|
|
66
67
|
return prev;
|
|
67
68
|
return (prev += 1);
|
|
68
69
|
});
|
|
69
70
|
} },
|
|
70
71
|
React.createElement("span", null, "›")),
|
|
71
|
-
React.createElement("li", { className:
|
|
72
|
-
if (
|
|
72
|
+
React.createElement("li", { className: totalPageCount === currentPage ? "passive" : "", onClick: () => {
|
|
73
|
+
if (totalPageCount === currentPage)
|
|
73
74
|
return;
|
|
74
|
-
setCurrentPage(
|
|
75
|
+
setCurrentPage(totalPageCount);
|
|
75
76
|
} },
|
|
76
77
|
React.createElement("span", null, "»")))));
|
|
77
78
|
};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Status } from "../contexts/Notification";
|
|
2
|
+
import { ValidationProperties } from "../../../types";
|
|
2
3
|
export declare const useLayout: () => {
|
|
3
4
|
config: {
|
|
4
5
|
layout: {
|
|
@@ -32,9 +33,24 @@ export declare const useLayout: () => {
|
|
|
32
33
|
}>>;
|
|
33
34
|
};
|
|
34
35
|
export declare const useNotification: () => {
|
|
35
|
-
notification: ({ title, message, status
|
|
36
|
+
notification: ({ title, message, status }: {
|
|
36
37
|
title: string;
|
|
37
38
|
message?: string;
|
|
38
39
|
status: Status;
|
|
39
40
|
}) => void;
|
|
40
41
|
};
|
|
42
|
+
type Error = {
|
|
43
|
+
[key: string]: string;
|
|
44
|
+
type: string;
|
|
45
|
+
}[];
|
|
46
|
+
export declare const useValidation: <TData extends object>(data: TData, params: ValidationProperties<TData>[]) => {
|
|
47
|
+
submit: boolean;
|
|
48
|
+
setSubmit: import("react").Dispatch<import("react").SetStateAction<boolean>>;
|
|
49
|
+
success: boolean;
|
|
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;
|
|
55
|
+
};
|
|
56
|
+
export {};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { useContext } from "react";
|
|
1
|
+
import { useContext, useEffect, useState } from "react";
|
|
2
2
|
import { ConfigContext } from "../contexts/Config";
|
|
3
3
|
import { NotificationContext } from "../contexts/Notification";
|
|
4
|
+
import Utils from "../../../infrastructure/shared/Utils";
|
|
4
5
|
export const useLayout = () => {
|
|
5
6
|
const context = useContext(ConfigContext);
|
|
6
7
|
if (!context) {
|
|
@@ -12,7 +13,7 @@ export const useNotification = () => {
|
|
|
12
13
|
// contexts
|
|
13
14
|
const { setTitle, setMessage, setStatus, setTrigger } = useContext(NotificationContext);
|
|
14
15
|
// methods
|
|
15
|
-
const notification = ({ title, message, status
|
|
16
|
+
const notification = ({ title, message, status }) => {
|
|
16
17
|
setTitle && setTitle(title);
|
|
17
18
|
setMessage && setMessage(message ?? "");
|
|
18
19
|
setStatus && setStatus(status);
|
|
@@ -20,3 +21,67 @@ export const useNotification = () => {
|
|
|
20
21
|
};
|
|
21
22
|
return { notification };
|
|
22
23
|
};
|
|
24
|
+
export const useValidation = function (data, params) {
|
|
25
|
+
// useStates
|
|
26
|
+
const [submit, setSubmit] = useState(false);
|
|
27
|
+
const [success, setSuccess] = useState(true);
|
|
28
|
+
const [message, setMessage] = useState(null);
|
|
29
|
+
const [errors, setErrors] = useState([]);
|
|
30
|
+
// methods
|
|
31
|
+
const showErrors = (errors, field) => {
|
|
32
|
+
const _errors = errors.filter((error) => error[field]);
|
|
33
|
+
if (_errors.length === 0)
|
|
34
|
+
return null;
|
|
35
|
+
return _errors.map((error) => error[field]);
|
|
36
|
+
};
|
|
37
|
+
// useEffects
|
|
38
|
+
useEffect(() => {
|
|
39
|
+
if (!data || Object.keys(data).length === 0 || params.length === 0)
|
|
40
|
+
return;
|
|
41
|
+
setErrors([]);
|
|
42
|
+
params.forEach((param) => {
|
|
43
|
+
const value = data[param.key];
|
|
44
|
+
param.shape?.forEach((s) => {
|
|
45
|
+
if (s.type === "required") {
|
|
46
|
+
!value ? setErrors((errors) => [...errors, { [param.key]: s.message, type: s.type }]) : null;
|
|
47
|
+
}
|
|
48
|
+
if (s.type === "minimum") {
|
|
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;
|
|
69
|
+
}
|
|
70
|
+
if (s.type === "email") {
|
|
71
|
+
const regex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/.test(value);
|
|
72
|
+
!regex && value ? setErrors((errors) => [...errors, { [param.key]: s.message, type: s.type }]) : null;
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
}, [data]);
|
|
77
|
+
return {
|
|
78
|
+
submit,
|
|
79
|
+
setSubmit,
|
|
80
|
+
success,
|
|
81
|
+
setSuccess,
|
|
82
|
+
message,
|
|
83
|
+
setMessage,
|
|
84
|
+
errors,
|
|
85
|
+
showErrors,
|
|
86
|
+
};
|
|
87
|
+
};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
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
|
+
StringFormat: (value: string, ...args: any[]) => string;
|
|
4
5
|
}
|
|
5
6
|
declare const _default: Utils;
|
|
6
7
|
export default _default;
|
|
@@ -11,5 +11,13 @@ class Utils {
|
|
|
11
11
|
classNames.push(className);
|
|
12
12
|
return classNames;
|
|
13
13
|
};
|
|
14
|
+
StringFormat = (value, ...args) => {
|
|
15
|
+
if (args[0].length === 0)
|
|
16
|
+
return value;
|
|
17
|
+
return value.replace(/{(\d+)}/g, (match, number) => {
|
|
18
|
+
const index = parseInt(number, 10);
|
|
19
|
+
return typeof args[index] !== "undefined" ? args[index] : match;
|
|
20
|
+
});
|
|
21
|
+
};
|
|
14
22
|
}
|
|
15
23
|
export default new Utils();
|
|
@@ -39,3 +39,11 @@ export type StepProps = {
|
|
|
39
39
|
title: string;
|
|
40
40
|
content: React.ReactNode;
|
|
41
41
|
};
|
|
42
|
+
export type ValidationProperties<T> = {
|
|
43
|
+
key: keyof T;
|
|
44
|
+
shape?: {
|
|
45
|
+
type: "required" | "minimum" | "maximum" | "email";
|
|
46
|
+
value?: string | number;
|
|
47
|
+
message: string;
|
|
48
|
+
}[];
|
|
49
|
+
};
|