ar-design 0.1.66 → 0.1.68

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.
@@ -1,8 +1,9 @@
1
1
  .ar-select-options {
2
2
  position: absolute;
3
3
  background-color: var(--white);
4
- border: solid 1px var(--gray-200);
5
- border-radius: var(--border-radius-lg);
4
+ /* border: solid 1px var(--gray-200); */
5
+ border-radius: var(--border-radius-sm);
6
+ box-shadow: 0 0 15px -2.5px rgba(var(--black-rgb), 0.1);
6
7
  overflow: hidden;
7
8
  z-index: 101;
8
9
  transition: visibility 250ms, opacity 250ms, transform 250ms ease-in-out;
@@ -14,6 +15,45 @@
14
15
  box-shadow: 0 -5px 15px -2.5px rgba(var(--black-rgb), 0.1);
15
16
  }
16
17
 
18
+ .ar-select-options > .no-options-field {
19
+ padding: 0.5rem 1rem;
20
+ }
21
+ .ar-select-options > .no-options-field > .text {
22
+ color: var(--gray-500);
23
+ }
24
+ .ar-select-options > .no-options-field > .add-item {
25
+ display: flex;
26
+ align-items: center;
27
+ position: relative;
28
+ background-color: rgba(var(--primary-rgb), 0.05);
29
+ padding: 0.25rem 0.5rem;
30
+ border-radius: var(--border-radius-sm);
31
+ border-left: solid 2px var(--primary);
32
+ color: var(--primary);
33
+ cursor: pointer;
34
+ }
35
+ .ar-select-options > .no-options-field > .add-item::before {
36
+ position: absolute;
37
+ top: 50%;
38
+ transform: translateY(-50%);
39
+ left: 0;
40
+ content: "";
41
+ border: solid 5px transparent;
42
+ border-left-color: var(--primary);
43
+ }
44
+ .ar-select-options > .no-options-field > .add-item > .plus {
45
+ display: inline-block;
46
+ position: relative;
47
+ background-color: var(--primary);
48
+ min-width: 1rem;
49
+ height: 1rem;
50
+ margin-right: 0.25rem;
51
+ border-radius: var(--border-radius-pill);
52
+ color: var(--white);
53
+ text-align: center;
54
+ line-height: 1rem;
55
+ }
56
+
17
57
  .ar-select-options > .search-field {
18
58
  padding: 0.5rem;
19
59
  border-bottom: solid 1px var(--gray-200);
@@ -18,10 +18,11 @@
18
18
  display: inline-flex;
19
19
  justify-content: center;
20
20
  align-items: center;
21
+ cursor: pointer;
21
22
  }
22
- .ar-steps > .steps > .item:not(:last-child) > .item-icon:has(.pending)::after,
23
- .ar-steps > .steps > .item:not(:last-child) > .item-icon:has(.in-progress)::after,
24
- .ar-steps > .steps > .item > .item-icon:has(.completed)::after {
23
+ .ar-steps > .steps > .item:not(:last-child) > .item-icon.pending::after,
24
+ .ar-steps > .steps > .item:not(:last-child) > .item-icon.in-progress::after,
25
+ .ar-steps > .steps > .item > .item-icon.completed::after {
25
26
  position: absolute;
26
27
  left: calc(50% + 1.25rem);
27
28
  transform: translateX(-50%);
@@ -30,15 +31,15 @@
30
31
  height: 4px;
31
32
  border-radius: var(--border-radius-pill);
32
33
  }
33
- .ar-steps > .steps > .item:not(:last-child) > .item-icon:has(.pending)::after {
34
+ .ar-steps > .steps > .item:not(:last-child) > .item-icon.pending::after {
34
35
  background-color: var(--gray-300);
35
36
  }
36
- .ar-steps > .steps > .item:not(:last-child) > .item-icon:has(.in-progress)::after {
37
+ .ar-steps > .steps > .item:not(:last-child) > .item-icon.in-progress::after {
37
38
  background: var(--gray-300);
38
39
  background: linear-gradient(90deg, var(--primary) 50%, var(--gray-300) 50%);
39
40
  background-color: var(--primary);
40
41
  }
41
- .ar-steps > .steps > .item > .item-icon:has(.completed)::after {
42
+ .ar-steps > .steps > .item > .item-icon.completed::after {
42
43
  background-color: var(--success);
43
44
  }
44
45
 
@@ -118,6 +119,7 @@
118
119
  flex-direction: column;
119
120
  align-items: flex-start;
120
121
  gap: 0.5rem 0;
122
+ cursor: pointer;
121
123
  }
122
124
  .ar-steps > .steps > .item > .item-informations > .step {
123
125
  color: var(--gray-500);
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  import React from "react";
3
3
  import "../../../assets/css/components/feedback/alert/alert.css";
4
- const Alert = ({ children, message, status = "primary", border = { radius: "sm" }, emphasize, }) => {
4
+ const Alert = ({ children, message, status = "primary", border = { radius: "sm" }, emphasize }) => {
5
5
  // refs
6
6
  let _className = "ar-alert";
7
7
  // status
@@ -17,8 +17,6 @@ const Alert = ({ children, message, status = "primary", border = { radius: "sm"
17
17
  return message;
18
18
  let _lowerCaseMessage = message.toLowerCase();
19
19
  return emphasize.reduce((currentMessage, emphasize) => {
20
- // TODO: ...
21
- // if (['""', " "].includes(emphasize)) return currentMessage;
22
20
  let _lowerCaseEmphasize = emphasize.toLowerCase();
23
21
  let startIndex = _lowerCaseMessage.indexOf(_lowerCaseEmphasize);
24
22
  while (startIndex !== -1) {
@@ -25,14 +25,16 @@ const Input = forwardRef(({ variant = "outlined", status = "light", size = "norm
25
25
  // useEffects
26
26
  useEffect(() => {
27
27
  if (attributes.value !== undefined)
28
- setValue(value);
28
+ setValue(attributes.value);
29
29
  }, [attributes.value]);
30
30
  return (React.createElement("div", { className: _wrapperClassName.map((c) => c).join(" ") },
31
31
  addon?.before && React.createElement("span", { className: _addonBeforeClassName.map((c) => c).join(" ") }, addon?.before),
32
32
  React.createElement("div", { className: "ar-input" },
33
33
  icon?.element && React.createElement("span", { className: "icon-element" }, icon.element),
34
- attributes.placeholder && React.createElement("label", { className: value ? "visible" : "hidden" }, attributes.placeholder),
35
- React.createElement("input", { ref: ref, ...attributes, value: attributes.value !== undefined ? attributes.value : value, size: 20, className: _inputClassName.map((c) => c).join(" "), onChange: (event) => {
34
+ attributes.placeholder && (React.createElement("label", { className: value ? "visible" : "hidden" },
35
+ validation && "* ",
36
+ attributes.placeholder)),
37
+ React.createElement("input", { ref: ref, ...attributes, placeholder: `${validation ? "* " : ""}${attributes.placeholder}`, value: attributes.value !== undefined ? attributes.value : value, size: 20, className: _inputClassName.map((c) => c).join(" "), onChange: (event) => {
36
38
  // Disabled gelmesi durumunda işlem yapmasına izin verme...
37
39
  if (attributes.disabled)
38
40
  return;
@@ -22,6 +22,7 @@ export type Props = {
22
22
  options: Option[];
23
23
  onCreate?: (option: Option) => void;
24
24
  placeholder?: string;
25
+ upperCase?: boolean;
25
26
  disabled?: boolean;
26
27
  } & (IMultiple | ISingle) & Omit<IGlobalProps, "status"> & IValidation;
27
28
  export {};
@@ -4,10 +4,9 @@ import Input from "../input";
4
4
  import "../../../assets/css/components/form/select/select.css";
5
5
  import Chip from "../../data-display/chip";
6
6
  import Checkbox from "../checkbox";
7
- import Paragraph from "../../data-display/typography/paragraph/Paragraph";
8
7
  import Utils from "../../../libs/infrastructure/shared/Utils";
9
8
  import ReactDOM from "react-dom";
10
- const Select = ({ variant = "outlined", status, border = { radius: "sm" }, options, value, onChange, onCreate, multiple, placeholder, validation, disabled, }) => {
9
+ const Select = ({ variant = "outlined", status, border = { radius: "sm" }, options, value, onChange, onCreate, multiple, placeholder, validation, upperCase, disabled, }) => {
11
10
  const _selectionClassName = ["selections"];
12
11
  // refs
13
12
  const _arSelect = useRef(null);
@@ -102,10 +101,28 @@ const Select = ({ variant = "outlined", status, border = { radius: "sm" }, optio
102
101
  else {
103
102
  if (_singleInput.current) {
104
103
  setSingleInputText("");
105
- _singleInput.current.placeholder = placeholder ?? "";
104
+ _singleInput.current.placeholder = `${validation ? "* " : ""}${placeholder ?? ""}`;
106
105
  }
107
106
  onChange(undefined);
108
107
  }
108
+ setOptionsOpen(false);
109
+ };
110
+ // Özel büyük harfe dönüştürme işlevi.
111
+ const convertToUpperCase = (str) => {
112
+ return str
113
+ .replace(/ş/g, "S")
114
+ .replace(/Ş/g, "S")
115
+ .replace(/ı/g, "I")
116
+ .replace(/I/g, "I")
117
+ .replace(/ç/g, "C")
118
+ .replace(/Ç/g, "C")
119
+ .replace(/ğ/g, "G")
120
+ .replace(/Ğ/g, "G")
121
+ .replace(/ö/g, "O")
122
+ .replace(/Ö/g, "O")
123
+ .replace(/ü/g, "U")
124
+ .replace(/Ü/g, "U")
125
+ .replace(/[a-z]/g, (match) => match.toUpperCase());
109
126
  };
110
127
  // useEffects
111
128
  useEffect(() => {
@@ -130,7 +147,7 @@ const Select = ({ variant = "outlined", status, border = { radius: "sm" }, optio
130
147
  // }
131
148
  if (_singleInput.current) {
132
149
  setSingleInputText("");
133
- _singleInput.current.placeholder = value?.text || placeholder || "";
150
+ _singleInput.current.placeholder = value?.text || `${validation ? "* " : ""}${placeholder ?? ""}` || "";
134
151
  }
135
152
  }
136
153
  // Options açıldıktan 100ms sonra arama kutusuna otomatik olarak focus oluyor.
@@ -154,7 +171,7 @@ const Select = ({ variant = "outlined", status, border = { radius: "sm" }, optio
154
171
  else {
155
172
  if (_singleInput.current) {
156
173
  setSingleInputText(value?.text ?? "");
157
- _singleInput.current.placeholder = placeholder ?? "";
174
+ _singleInput.current.placeholder = `${validation ? "* " : ""}${placeholder ?? ""}`;
158
175
  }
159
176
  }
160
177
  }
@@ -199,14 +216,18 @@ const Select = ({ variant = "outlined", status, border = { radius: "sm" }, optio
199
216
  return (React.createElement("div", { ref: _arSelect, className: "ar-select-wrapper" },
200
217
  React.createElement("div", { ref: _multipleInput, className: "ar-select" },
201
218
  multiple ? (React.createElement("div", { className: _selectionClassName.map((c) => c).join(" "), onClick: () => setOptionsOpen((x) => !x) },
202
- 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 }, value: singleInputText, onClick: () => setOptionsOpen((prev) => !prev), onChange: (event) => {
219
+ 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" },
220
+ validation ? "* " : "",
221
+ placeholder))))) : (React.createElement(Input, { ref: _singleInput, variant: variant, status: !Utils.IsNullOrEmpty(validation?.text) ? "danger" : status, border: { radius: border.radius }, value: singleInputText, onClick: () => setOptionsOpen((prev) => !prev), onChange: (event) => {
203
222
  !optionsOpen && setOptionsOpen(true);
223
+ if (upperCase)
224
+ event.target.value = convertToUpperCase(event.target.value);
204
225
  setSingleInputText(event.target.value);
205
226
  }, onKeyUp: (event) => {
206
227
  if (event.key === "Enter")
207
228
  return;
208
229
  setSearchText(event.currentTarget.value);
209
- }, placeholder: placeholder, disabled: disabled })),
230
+ }, placeholder: placeholder, validation: validation, disabled: disabled })),
210
231
  React.createElement("span", { className: `button-clear ${!disabled && (multiple ? value.length > 0 : value) ? "opened" : "closed"}`, onClick: (event) => {
211
232
  if (disabled)
212
233
  return;
@@ -217,22 +238,26 @@ const Select = ({ variant = "outlined", status, border = { radius: "sm" }, optio
217
238
  event.stopPropagation();
218
239
  setOptionsOpen((x) => !x);
219
240
  } }),
220
- validation?.text && React.createElement("span", { className: "validation" }, validation.text)),
241
+ multiple && validation && React.createElement("span", { className: "validation" }, validation.text)),
221
242
  optionsOpen &&
222
243
  ReactDOM.createPortal(React.createElement("div", { ref: _options, className: "ar-select-options" },
223
244
  multiple && (React.createElement("div", { className: "search-field" },
224
- React.createElement(Input, { ref: _searchField, variant: "outlined", status: "light", placeholder: "Search...", value: searchText, onChange: (event) => setSearchText(event.currentTarget.value) }))),
245
+ React.createElement(Input, { ref: _searchField, variant: "outlined", status: "light", placeholder: "Search...", value: searchText, onChange: (event) => setSearchText(event.currentTarget.value), onClick: (event) => event.stopPropagation() }))),
225
246
  filteredOptions.length > 0 ? (React.createElement("ul", null, filteredOptions.map((option, index) => {
226
247
  const isItem = multiple && value.some((_value) => _value.value === option.value);
227
- return (React.createElement("li", { key: index, ref: (element) => (_optionItems.current[index] = element), className: option === value ? "selectedItem" : "", onClick: () => handleItemSelected(option) },
248
+ return (React.createElement("li", { key: index, ref: (element) => (_optionItems.current[index] = element), className: option === value ? "selectedItem" : "", onClick: (event) => {
249
+ event.stopPropagation();
250
+ handleItemSelected(option);
251
+ } },
228
252
  multiple && React.createElement(Checkbox, { checked: isItem, status: isItem ? "primary" : "light", disabled: true }),
229
253
  React.createElement("span", null, option.text)));
230
- }))) : !onCreate ? (React.createElement(Paragraph, { color: "gray-500", align: "center" }, "Herhangi bir kay\u0131t bulunumad\u0131!")) : (React.createElement("span", { style: { padding: "1rem", cursor: "pointer" }, onClick: () => {
254
+ }))) : !onCreate ? (React.createElement("div", { className: "no-options-field" },
255
+ React.createElement("span", { className: "text" }, "Herhangi bir kay\u0131t bulunumad\u0131."))) : (React.createElement("div", { className: "no-options-field", onClick: () => {
231
256
  onCreate({ value: "", text: singleInputText });
232
257
  setOptionsOpen(false);
233
- } }, options.length === 0 && singleInputText.length === 0
234
- ? "Herhangi bir kayıt bulunumadı!"
235
- : `${singleInputText} Ekle`))), document.body)));
258
+ } }, options.length === 0 && singleInputText.length === 0 ? (React.createElement("span", { className: "text" }, "Herhangi bir kay\u0131t bulunumad\u0131.")) : (React.createElement("span", { className: "add-item" },
259
+ React.createElement("span", { className: "plus" }, "+"),
260
+ singleInputText))))), document.body)));
236
261
  };
237
262
  Select.displayName = "Select";
238
263
  export default Select;
@@ -0,0 +1,5 @@
1
+ import { MenuProps } from "../../../libs/types";
2
+ interface IProps {
3
+ menus: MenuProps[];
4
+ }
5
+ export default IProps;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,5 @@
1
+ import React from "react";
2
+ import IProps from "./IProps";
3
+ import "../../../assets/css/components/navigation/breadcrumb/styles.css";
4
+ declare const Breadcrumb: React.FC<IProps>;
5
+ export default Breadcrumb;
@@ -0,0 +1,31 @@
1
+ import React, { useEffect, useState } from "react";
2
+ import "../../../assets/css/components/navigation/breadcrumb/styles.css";
3
+ const Breadcrumb = ({ menus }) => {
4
+ // useState
5
+ const [pathname, setPathname] = useState("");
6
+ // const [breadcrumb, setBreadcrumb] = useState<any[]>([]);
7
+ const handleBreadcrumb = (pathname) => {
8
+ if (pathname === undefined)
9
+ pathname = window.location.pathname;
10
+ // let _menus: any, _parents: any;
11
+ if (pathname) {
12
+ // console.log(menus.filter(x=>x.));
13
+ // Recursive
14
+ // handleBreadcrumb(_menus);
15
+ }
16
+ else {
17
+ // Recursive
18
+ // handleBreadcrumb(_parents.parentId);
19
+ }
20
+ };
21
+ // useEffects
22
+ useEffect(() => {
23
+ if (menus.length === 0)
24
+ return;
25
+ handleBreadcrumb(undefined);
26
+ setPathname(window.location.pathname);
27
+ }, [menus, pathname]);
28
+ return (React.createElement("nav", { className: "ar-breadcrumb" }));
29
+ };
30
+ Breadcrumb.displayName = "Breadcrumb";
31
+ export default Breadcrumb;
@@ -1,9 +1,9 @@
1
- import { StepProps } from "../../../libs/types";
1
+ import { StepProps, ValidationProperties } from "../../../libs/types";
2
2
  import { IChildren } from "../../../libs/types/IGlobalProps";
3
3
  /**
4
4
  * Stepper component props
5
5
  */
6
- interface IProps extends IChildren {
6
+ interface IProps<TData extends object> extends IChildren {
7
7
  /**
8
8
  * Step'leri temsil eden dizisi.
9
9
  * Her bir `Step` için gerekli özellikler `StepProps` tipinde olmalıdır.
@@ -14,5 +14,12 @@ interface IProps extends IChildren {
14
14
  * @param currentStep - Kullanıcının geçerli olduğu adım numarası.
15
15
  */
16
16
  onChange: (currentStep: number) => void;
17
+ /**
18
+ * ...
19
+ */
20
+ validation?: {
21
+ data: TData;
22
+ rules: ValidationProperties<TData>[];
23
+ };
17
24
  }
18
25
  export default IProps;
@@ -1,5 +1,5 @@
1
1
  import React from "react";
2
2
  import IProps from "./IProps";
3
- import "../../../assets/css/components/navigation/steps/steps.css";
4
- declare const Steps: React.FC<IProps>;
3
+ import "../../../assets/css/components/navigation/steps/styles.css";
4
+ declare const Steps: <T extends object>({ children, steps, onChange, validation }: IProps<T>) => React.JSX.Element;
5
5
  export default Steps;
@@ -1,22 +1,29 @@
1
1
  "use client";
2
2
  import React, { useEffect, useState } from "react";
3
- import "../../../assets/css/components/navigation/steps/steps.css";
3
+ import "../../../assets/css/components/navigation/steps/styles.css";
4
4
  import Typography from "../../data-display/typography";
5
5
  import Button from "../../form/button";
6
+ import { useValidation } from "../../../libs/core/application/hooks";
6
7
  const { Title } = Typography;
7
- const Steps = ({ children, steps = [], onChange }) => {
8
+ const Steps = function ({ children, steps = [], onChange, validation }) {
8
9
  // states
9
10
  const [currentStep, setCurrentStep] = useState(0);
11
+ let _errors;
12
+ let _onSubmit;
13
+ let _setSubmit;
14
+ if (validation) {
15
+ const { errors, onSubmit, setSubmit } = useValidation(validation.data, validation.rules, currentStep + 1);
16
+ _errors = errors;
17
+ _onSubmit = onSubmit;
18
+ _setSubmit = setSubmit;
19
+ }
10
20
  // methods
11
- const changeItemIcon = (currentStep, index) => {
21
+ const getStepIconStatus = (currentStep, index) => {
12
22
  if (currentStep < index)
13
23
  return "pending";
14
- else if (currentStep === index)
24
+ if (currentStep === index)
15
25
  return "in-progress";
16
- else if (currentStep > index)
17
- return "completed";
18
- else
19
- return "";
26
+ return "completed";
20
27
  };
21
28
  // useEffects
22
29
  useEffect(() => onChange(0), []);
@@ -24,13 +31,24 @@ const Steps = ({ children, steps = [], onChange }) => {
24
31
  React.createElement("div", { className: "steps" }, steps.length > 0 &&
25
32
  steps.map((step, index) => {
26
33
  let itemIcon = ["item-icon"];
27
- itemIcon.push(changeItemIcon(currentStep, index));
34
+ itemIcon.push(getStepIconStatus(currentStep, index));
28
35
  return (React.createElement("div", { key: step.title || index, className: "item", onClick: () => {
29
- setCurrentStep(index);
30
- onChange(index);
36
+ if (validation) {
37
+ _onSubmit((result) => {
38
+ if (!result)
39
+ return;
40
+ setCurrentStep(index);
41
+ onChange(index);
42
+ _setSubmit(false);
43
+ });
44
+ }
45
+ else {
46
+ setCurrentStep(index);
47
+ onChange(index);
48
+ }
31
49
  } },
32
50
  React.createElement("div", { className: itemIcon.map((c) => c).join(" ") },
33
- React.createElement("span", { className: changeItemIcon(currentStep, index) })),
51
+ React.createElement("span", { className: getStepIconStatus(currentStep, index) })),
34
52
  React.createElement("div", { className: "item-informations" },
35
53
  React.createElement("span", { className: "step" },
36
54
  "STEP ",
@@ -38,7 +56,18 @@ const Steps = ({ children, steps = [], onChange }) => {
38
56
  React.createElement(Title, { Level: "h3" }, step.title))));
39
57
  })),
40
58
  React.createElement("div", { className: "content" },
41
- steps.map((step, index) => currentStep === index && step.content),
59
+ steps.map((step, stepIndex) => {
60
+ return (React.createElement("div", { key: stepIndex }, React.Children.map(step.content, (child) => {
61
+ if (React.isValidElement(child) && stepIndex === currentStep) {
62
+ return validation
63
+ ? React.cloneElement(child, {
64
+ errors: _errors,
65
+ })
66
+ : child;
67
+ }
68
+ return null;
69
+ })));
70
+ }),
42
71
  React.createElement("div", { className: "buttons" },
43
72
  currentStep > 0 && (React.createElement(Button, { status: "light", onClick: () => {
44
73
  setCurrentStep((prev) => prev - 1);
@@ -46,8 +75,19 @@ const Steps = ({ children, steps = [], onChange }) => {
46
75
  } }, "Geri")),
47
76
  children && children,
48
77
  currentStep < steps.length - 1 && (React.createElement(Button, { onClick: () => {
49
- setCurrentStep((prev) => prev + 1);
50
- onChange(currentStep + 1);
78
+ if (validation) {
79
+ _onSubmit((result) => {
80
+ if (!result)
81
+ return;
82
+ setCurrentStep((prev) => prev + 1);
83
+ onChange(currentStep + 1);
84
+ _setSubmit(false);
85
+ });
86
+ }
87
+ else {
88
+ setCurrentStep((prev) => prev + 1);
89
+ onChange(currentStep + 1);
90
+ }
51
91
  } }, "\u0130leri"))))));
52
92
  };
53
93
  export default Steps;
package/dist/index.d.ts CHANGED
@@ -22,8 +22,9 @@ import Alert from "./components/feedback/alert";
22
22
  import Confirm from "./components/feedback/confirm";
23
23
  import Modal from "./components/feedback/modal";
24
24
  import Progress from "./components/feedback/progress";
25
+ import Breadcrumb from "./components/navigation/breadcrumb";
25
26
  import Menu from "./components/navigation/menu";
26
27
  import Steps from "./components/navigation/steps";
27
28
  import Grid from "./components/layout/grid-system";
28
29
  import Layout from "./components/layout";
29
- export { Button, ButtonAction, ButtonGroup, Input, DatePicker, Select, Switch, Upload, Checkbox, Radio, Card, Chip, Divider, DnD, Paper, SyntaxHighlighter, Table, Tabs, Typography, Alert, Confirm, Modal, Progress, Menu, Steps, Grid, Layout, };
30
+ export { Button, ButtonAction, ButtonGroup, Input, DatePicker, Select, Switch, Upload, Checkbox, Radio, Card, Chip, Divider, DnD, Paper, SyntaxHighlighter, Table, Tabs, Typography, Alert, Confirm, Modal, Progress, Breadcrumb, Menu, Steps, Grid, Layout, };
package/dist/index.js CHANGED
@@ -26,6 +26,7 @@ import Confirm from "./components/feedback/confirm";
26
26
  import Modal from "./components/feedback/modal";
27
27
  import Progress from "./components/feedback/progress";
28
28
  // Navigation
29
+ import Breadcrumb from "./components/navigation/breadcrumb";
29
30
  import Menu from "./components/navigation/menu";
30
31
  import Steps from "./components/navigation/steps";
31
32
  // Layout
@@ -39,6 +40,6 @@ Card, Chip, Divider, DnD, Paper, SyntaxHighlighter, Table, Tabs, Typography,
39
40
  // Feedback
40
41
  Alert, Confirm, Modal, Progress,
41
42
  // Navigation
42
- Menu, Steps,
43
+ Breadcrumb, Menu, Steps,
43
44
  // Layout
44
45
  Grid, Layout, };
@@ -40,7 +40,7 @@ export declare const useNotification: () => {
40
40
  status: Status;
41
41
  }) => void;
42
42
  };
43
- export declare const useValidation: <TData extends object>(data: TData, params: ValidationProperties<TData>[]) => {
43
+ export declare const useValidation: <TData extends object>(data: TData, params: ValidationProperties<TData>[], step?: number) => {
44
44
  onSubmit: (callback: (result: boolean) => void) => void;
45
45
  setSubmit: import("react").Dispatch<import("react").SetStateAction<boolean>>;
46
46
  errors: Partial<{ [key in keyof TData]: string; }>;
@@ -30,7 +30,7 @@ export const useNotification = () => {
30
30
  };
31
31
  return { notification };
32
32
  };
33
- export const useValidation = function (data, params) {
33
+ export const useValidation = function (data, params, step) {
34
34
  // refs
35
35
  const _errors = useRef({});
36
36
  // states
@@ -43,55 +43,116 @@ export const useValidation = function (data, params) {
43
43
  let result = true;
44
44
  if (!data || Object.keys(data).length === 0 || params.length === 0)
45
45
  result = false;
46
- if (Object.keys(_errors.current).length > 0)
47
- result = false;
46
+ if (step) {
47
+ const filteredErrors = Object.fromEntries(Object.entries(_errors.current)
48
+ .filter(([key]) => key.startsWith(`${step}_`))
49
+ .map(([key, value]) => [key.replace(/^\d+_/, ""), String(value)]));
50
+ if (Object.keys(filteredErrors).length > 0)
51
+ result = false;
52
+ }
53
+ else {
54
+ if (Object.keys(_errors.current).length > 0)
55
+ result = false;
56
+ }
48
57
  callback(result);
49
58
  }, 0);
50
59
  };
51
- const setError = (key, message) => {
52
- setErrors((prev) => ({ ...prev, [key]: message }));
53
- _errors.current = { ..._errors.current, [key]: message };
60
+ const setError = (key, message, step) => {
61
+ const _key = step ? `${step}_${key}` : key;
62
+ setErrors((prev) => ({ ...prev, [_key]: message }));
63
+ _errors.current = { ..._errors.current, [_key]: message };
54
64
  };
55
- // useEffects
56
- useEffect(() => {
57
- if (!submit)
65
+ const handleParams = (param) => {
66
+ const value = data[param.key];
67
+ if (param.subkey) {
68
+ const subvalue = data[param.key];
69
+ if (param.subkey.includes(".")) {
70
+ let _data = subvalue;
71
+ const levels = param.subkey.split(".");
72
+ // "levels.length - 1" çünkü son seviyeye kadar gidip, son seviyedeki değeri alacağız.
73
+ for (let i = 0; i < levels.length; i++) {
74
+ const key = levels[i];
75
+ // Eğer `_data` undefined ya da null ise işlem bitirilsin.
76
+ if (_data === undefined || _data === null)
77
+ break;
78
+ // `key`'i _data üzerinde kullanarak yeni değeri atıyoruz.
79
+ _data = _data[key];
80
+ }
81
+ // Burada _data son seviyeye ulaşacaktır.
82
+ paramsShape(param, _data);
83
+ }
58
84
  return;
59
- setErrors({});
60
- _errors.current = {};
61
- params.forEach((param) => {
62
- const value = data[param.key];
63
- param.shape?.forEach((s) => {
64
- if (param.where) {
65
- if (s.type === "required" && param.where(data)) {
66
- Utils.IsNullOrEmpty(value) ? setError(param.key, s.message) : null;
67
- }
85
+ }
86
+ paramsShape(param, value);
87
+ };
88
+ const paramsShape = (param, value) => {
89
+ param.shape?.forEach((s) => {
90
+ if (param.where) {
91
+ if (s.type === "required" && param.where(data)) {
92
+ Utils.IsNullOrEmpty(value) ? setError(param.key, s.message, param.step) : null;
68
93
  }
69
- else {
94
+ }
95
+ else {
96
+ // Subkeys Validations
97
+ if (param.subkey) {
98
+ const levels = param.subkey.split(".");
99
+ const key = levels[levels.length - 1];
70
100
  if (s.type === "required") {
71
- Utils.IsNullOrEmpty(value) ? setError(param.key, s.message) : null;
101
+ Utils.IsNullOrEmpty(value) ? setError(key, s.message, param.step) : null;
72
102
  }
73
103
  if (s.type === "minimum") {
74
104
  value && value.length < s.value
75
- ? setError(param.key, Utils.StringFormat(s.message, s.value))
105
+ ? setError(key, Utils.StringFormat(s.message, s.value), param.step)
76
106
  : null;
77
107
  }
78
108
  if (s.type === "maximum") {
79
109
  value && value.length > s.value
80
- ? setError(param.key, Utils.StringFormat(s.message, s.value))
110
+ ? setError(key, Utils.StringFormat(s.message, s.value), param.step)
81
111
  : null;
82
112
  }
83
113
  if (s.type === "email") {
84
114
  const regex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/.test(value);
85
- !regex && Utils.IsNullOrEmpty(value) ? setError(param.key, s.message) : null;
115
+ !regex && Utils.IsNullOrEmpty(value) ? setError(key, s.message, param.step) : null;
86
116
  }
117
+ return;
118
+ }
119
+ // Keys Validations
120
+ if (s.type === "required") {
121
+ Utils.IsNullOrEmpty(value) ? setError(param.key, s.message, param.step) : null;
87
122
  }
88
- });
123
+ if (s.type === "minimum") {
124
+ value && value.length < s.value
125
+ ? setError(param.key, Utils.StringFormat(s.message, s.value), param.step)
126
+ : null;
127
+ }
128
+ if (s.type === "maximum") {
129
+ value && value.length > s.value
130
+ ? setError(param.key, Utils.StringFormat(s.message, s.value), param.step)
131
+ : null;
132
+ }
133
+ if (s.type === "email") {
134
+ const regex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/.test(value);
135
+ !regex && Utils.IsNullOrEmpty(value) ? setError(param.key, s.message, param.step) : null;
136
+ }
137
+ }
89
138
  });
139
+ };
140
+ // useEffects
141
+ useEffect(() => {
142
+ setErrors({});
143
+ _errors.current = {};
144
+ if (!submit)
145
+ return;
146
+ params.forEach((param) => handleParams(param));
90
147
  }, [submit, data]);
91
148
  return {
92
149
  onSubmit,
93
150
  setSubmit,
94
- errors,
151
+ errors: step
152
+ ? Object.fromEntries(Object.entries(errors)
153
+ .filter(([key]) => key.startsWith(`${step}_`))
154
+ .map(([key, value]) => [key.replace(/^\d+_/, ""), String(value)]))
155
+ : errors,
95
156
  };
96
157
  };
97
158
  export const useTranslation = function (currentLanguage, translations) {
@@ -68,11 +68,10 @@ class Api {
68
68
  };
69
69
  };
70
70
  Cookies = (name) => {
71
- // Eğer window mevcutsa
72
71
  if (typeof window === "undefined")
73
72
  return undefined;
74
- const cookieObject = [];
75
73
  const cookies = document.cookie.split("; ");
74
+ const cookieObject = [];
76
75
  cookies.forEach((cookie) => {
77
76
  const [key, value] = cookie.split("=");
78
77
  cookieObject.push({ key: key, value: value });
@@ -47,6 +47,8 @@ export type TabProps = {
47
47
  };
48
48
  export type ValidationProperties<T> = {
49
49
  key: keyof T;
50
+ subkey?: string;
51
+ step?: number;
50
52
  shape?: {
51
53
  type: "required" | "minimum" | "maximum" | "email";
52
54
  value?: string | number;
@@ -54,6 +56,9 @@ export type ValidationProperties<T> = {
54
56
  }[];
55
57
  where?: (param: T) => boolean;
56
58
  };
59
+ export type Errors<TData> = Partial<{
60
+ [key in keyof TData]: string;
61
+ }>;
57
62
  export type PieChartDataType = {
58
63
  value: number;
59
64
  text: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ar-design",
3
- "version": "0.1.66",
3
+ "version": "0.1.68",
4
4
  "main": "./dist/index.js",
5
5
  "module": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -42,7 +42,7 @@
42
42
  ],
43
43
  "author": "Kaan ÇETİN",
44
44
  "license": "MIT",
45
- "description": "AR Design...",
45
+ "description": "AR Design is a (react || nextjs) library.",
46
46
  "peerDependencies": {
47
47
  "react": "^18.3.1",
48
48
  "react-dom": "^18.3.1"