ar-design 0.4.24 → 0.4.26
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/components/data-display/table/IProps.d.ts +1 -0
- package/dist/components/data-display/table/body/Editable.d.ts +3 -1
- package/dist/components/data-display/table/body/Editable.js +3 -3
- package/dist/components/data-display/table/body/TBody.d.ts +11 -3
- package/dist/components/data-display/table/body/TBody.js +21 -11
- package/dist/components/data-display/table/index.js +5 -2
- package/dist/components/form/date-picker/index.js +3 -7
- package/dist/components/form/input/decimal/Decimal.js +25 -13
- package/dist/components/form/input/decimal/IProps.d.ts +1 -0
- package/dist/components/form/input/formatted-decimal/FormattedDecimal.js +30 -40
- package/package.json +1 -1
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { Errors, TableColumnType } from "../../../../libs/types";
|
|
3
|
+
import { Config } from "../IProps";
|
|
3
4
|
interface IProps<T> {
|
|
4
5
|
c: TableColumnType<T>;
|
|
5
6
|
item: T;
|
|
6
7
|
trackByValue: string;
|
|
7
8
|
onEditable: (item: T, trackByValue: string) => void;
|
|
8
9
|
validation?: Errors<T>;
|
|
10
|
+
config: Config<T>;
|
|
9
11
|
}
|
|
10
|
-
declare const Editable: <T>({ c, item, trackByValue, onEditable, validation }: IProps<T>) => React.JSX.Element | null;
|
|
12
|
+
declare const Editable: <T>({ c, item, trackByValue, onEditable, validation, config }: IProps<T>) => React.JSX.Element | null;
|
|
11
13
|
export default Editable;
|
|
@@ -3,7 +3,7 @@ import React, { useEffect, useState } from "react";
|
|
|
3
3
|
import Input from "../../../form/input";
|
|
4
4
|
import DatePicker from "../../../form/date-picker";
|
|
5
5
|
import Select from "../../../form/select";
|
|
6
|
-
const Editable = function ({ c, item, trackByValue, onEditable, validation }) {
|
|
6
|
+
const Editable = function ({ c, item, trackByValue, onEditable, validation, config }) {
|
|
7
7
|
// variables
|
|
8
8
|
const key = c.key;
|
|
9
9
|
const itemValue = item[c.key];
|
|
@@ -29,13 +29,13 @@ const Editable = function ({ c, item, trackByValue, onEditable, validation }) {
|
|
|
29
29
|
const { value } = event.target;
|
|
30
30
|
setValue(value);
|
|
31
31
|
onEditable({ ...item, [key]: value }, trackByValue);
|
|
32
|
-
}, validation: { text: _vText } }));
|
|
32
|
+
}, validation: { text: _vText }, locale: config.locale }));
|
|
33
33
|
case "input-formatted-decimal":
|
|
34
34
|
return (React.createElement(Input.FormattedDecimal, { variant: "borderless", name: c.key, value: _value, onChange: (event) => {
|
|
35
35
|
const { value } = event.target;
|
|
36
36
|
setValue(value);
|
|
37
37
|
onEditable({ ...item, [key]: value }, trackByValue);
|
|
38
|
-
}, validation: { text: _vText } }));
|
|
38
|
+
}, validation: { text: _vText }, locale: config.locale }));
|
|
39
39
|
case "date-picker":
|
|
40
40
|
return (React.createElement(DatePicker, { variant: "borderless", value: _value, onChange: (value) => {
|
|
41
41
|
setValue(value);
|
|
@@ -1,15 +1,23 @@
|
|
|
1
|
-
import React from "react";
|
|
1
|
+
import React, { Dispatch, SetStateAction } from "react";
|
|
2
2
|
import { TableColumnType } from "../../../../libs/types";
|
|
3
3
|
import { Config } from "../IProps";
|
|
4
4
|
interface IProps<T> {
|
|
5
5
|
data: T[];
|
|
6
6
|
columns: TableColumnType<T>[];
|
|
7
|
+
refs: {
|
|
8
|
+
_checkboxItems: React.MutableRefObject<(HTMLInputElement | null)[]>;
|
|
9
|
+
_selectionItems: React.MutableRefObject<T[]>;
|
|
10
|
+
};
|
|
7
11
|
states: {
|
|
12
|
+
setSelectAll: {
|
|
13
|
+
get: boolean;
|
|
14
|
+
set: Dispatch<SetStateAction<boolean>>;
|
|
15
|
+
};
|
|
8
16
|
showSubitems: {
|
|
9
17
|
get: {
|
|
10
18
|
[key: string]: boolean;
|
|
11
19
|
};
|
|
12
|
-
set:
|
|
20
|
+
set: Dispatch<React.SetStateAction<{
|
|
13
21
|
[key: string]: boolean;
|
|
14
22
|
}>>;
|
|
15
23
|
};
|
|
@@ -23,6 +31,6 @@ interface IProps<T> {
|
|
|
23
31
|
};
|
|
24
32
|
config: Config<T>;
|
|
25
33
|
}
|
|
26
|
-
declare function TBody<T extends object>({ data, columns, methods, states, config }: IProps<T>): React.JSX.Element | React.JSX.Element[];
|
|
34
|
+
declare function TBody<T extends object>({ data, columns, refs, methods, states, config }: IProps<T>): React.JSX.Element | React.JSX.Element[];
|
|
27
35
|
declare const _default: typeof TBody;
|
|
28
36
|
export default _default;
|
|
@@ -2,14 +2,12 @@ import React, { Fragment, memo, useEffect, useRef, useState } from "react";
|
|
|
2
2
|
import { ARIcon } from "../../../icons";
|
|
3
3
|
import Checkbox from "../../../form/checkbox";
|
|
4
4
|
import Editable from "./Editable";
|
|
5
|
-
function TBody({ data, columns, methods, states, config }) {
|
|
5
|
+
function TBody({ data, columns, refs, methods, states, config }) {
|
|
6
6
|
// refs
|
|
7
|
+
const _hasMeasured = useRef(false);
|
|
7
8
|
const _tBodyTR = useRef([]);
|
|
8
|
-
const _checkboxItems = useRef([]);
|
|
9
|
-
// refs -> Selection
|
|
10
|
-
const _selectionItems = useRef([]);
|
|
11
9
|
// states
|
|
12
|
-
const [
|
|
10
|
+
const [triggerForRender, setTriggerForRender] = useState(false);
|
|
13
11
|
const [rowHeights, setRowHeights] = useState([]);
|
|
14
12
|
// variables
|
|
15
13
|
const _subrowSelector = config.subrow?.selector ?? "subitems";
|
|
@@ -22,17 +20,17 @@ function TBody({ data, columns, methods, states, config }) {
|
|
|
22
20
|
_tBodyTR.current[index] = element;
|
|
23
21
|
}, ...(methods.rowBackgroundColor ? { style: { backgroundColor: methods.rowBackgroundColor(item) } } : {}), ...(methods.onDnD && data.length > 1 ? { className: "draggable", draggable: true } : {}) },
|
|
24
22
|
methods.selections && (React.createElement("td", { className: "flex justify-content-center sticky-left", "data-sticky-position": "left" },
|
|
25
|
-
React.createElement(Checkbox, { key: Date.now(), ref: (element) => (_checkboxItems.current[index] = element), variant: "filled", color: "green", checked: _selectionItems.current.some((selectionItem) => methods.trackBy?.(selectionItem) === methods.trackBy?.(item)), onChange: (event) => {
|
|
23
|
+
React.createElement(Checkbox, { key: Date.now(), ref: (element) => (refs._checkboxItems.current[index] = element), variant: "filled", color: "green", checked: refs._selectionItems.current.some((selectionItem) => methods.trackBy?.(selectionItem) === methods.trackBy?.(item)), onChange: (event) => {
|
|
26
24
|
const key = methods.trackBy?.(item);
|
|
27
25
|
if (event.target.checked) {
|
|
28
|
-
if (!_selectionItems.current.some((_item) => methods.trackBy?.(_item) === key)) {
|
|
29
|
-
_selectionItems.current = [..._selectionItems.current, item];
|
|
26
|
+
if (!refs._selectionItems.current.some((_item) => methods.trackBy?.(_item) === key)) {
|
|
27
|
+
refs._selectionItems.current = [...refs._selectionItems.current, item];
|
|
30
28
|
}
|
|
31
29
|
}
|
|
32
30
|
else {
|
|
33
|
-
_selectionItems.current = _selectionItems.current.filter((_item) => methods.trackBy?.(_item) !== key);
|
|
31
|
+
refs._selectionItems.current = refs._selectionItems.current.filter((_item) => methods.trackBy?.(_item) !== key);
|
|
34
32
|
}
|
|
35
|
-
methods.selections?.(_selectionItems.current);
|
|
33
|
+
methods.selections?.(refs._selectionItems.current);
|
|
36
34
|
setTriggerForRender((prev) => !prev);
|
|
37
35
|
} }))),
|
|
38
36
|
isHasSubitems && _subrowButton ? (React.createElement("td", null, item[_subrowSelector] && (React.createElement("div", { className: "subitem-open-button-wrapper" },
|
|
@@ -91,7 +89,7 @@ function TBody({ data, columns, methods, states, config }) {
|
|
|
91
89
|
return (React.createElement("div", { key: `last-before-${i}`, style: { left: `${i + 0.65}rem` }, className: "last-before" }));
|
|
92
90
|
}),
|
|
93
91
|
React.createElement("div", { className: "before" }))),
|
|
94
|
-
React.isValidElement(render) ? (render) : column.editable && methods.onEditable ? (React.createElement(Editable, { c: column, item: item, trackByValue: methods.trackBy?.(item) ?? "", onEditable: methods.onEditable, validation: config.validation })) : (React.createElement("span", null, render)),
|
|
92
|
+
React.isValidElement(render) ? (render) : column.editable && methods.onEditable ? (React.createElement(Editable, { c: column, item: item, trackByValue: methods.trackBy?.(item) ?? "", onEditable: methods.onEditable, validation: config.validation, config: config })) : (React.createElement("span", null, render)),
|
|
95
93
|
config.isTreeView && cIndex === 0 && (React.createElement("div", { className: "after" },
|
|
96
94
|
React.createElement("div", { className: "circle" }))))));
|
|
97
95
|
};
|
|
@@ -131,9 +129,21 @@ function TBody({ data, columns, methods, states, config }) {
|
|
|
131
129
|
};
|
|
132
130
|
// useEffects
|
|
133
131
|
useEffect(() => {
|
|
132
|
+
if (_hasMeasured.current)
|
|
133
|
+
return;
|
|
134
|
+
if (!data || data.length === 0)
|
|
135
|
+
return;
|
|
134
136
|
const heights = _tBodyTR.current.map((el) => (el ? el.getBoundingClientRect().height : 0));
|
|
135
137
|
setRowHeights(heights);
|
|
138
|
+
setTriggerForRender((prev) => !prev);
|
|
139
|
+
_hasMeasured.current = true;
|
|
136
140
|
}, [data]);
|
|
141
|
+
useEffect(() => {
|
|
142
|
+
if (Array.isArray(refs._checkboxItems.current) && refs._checkboxItems.current.length > 0) {
|
|
143
|
+
const allChecked = refs._checkboxItems.current.every((item) => item?.checked === true);
|
|
144
|
+
states.setSelectAll.set(allChecked);
|
|
145
|
+
}
|
|
146
|
+
}, [triggerForRender]);
|
|
137
147
|
return data.length > 0 ? (data.map((item, index) => React.createElement(React.Fragment, { key: index }, renderRow(item, index, 1)))) : (React.createElement("tr", null,
|
|
138
148
|
React.createElement("td", { colSpan: columns.length || 1 },
|
|
139
149
|
React.createElement("div", { className: "no-item" },
|
|
@@ -383,7 +383,7 @@ const Table = forwardRef(({ children, trackBy, title, description, data, columns
|
|
|
383
383
|
_data = _data.slice(indexOfFirstRow, indexOfLastRow);
|
|
384
384
|
}
|
|
385
385
|
return _data;
|
|
386
|
-
}, [data, searchedText, currentPage, selectedPerPage, sortConfig]);
|
|
386
|
+
}, [data, searchedText, currentPage, selectedPerPage, sortConfig, config.isServerSide]);
|
|
387
387
|
// useEffects
|
|
388
388
|
useEffect(() => {
|
|
389
389
|
if (!previousSelections || previousSelections.length === 0) {
|
|
@@ -656,7 +656,10 @@ const Table = forwardRef(({ children, trackBy, title, description, data, columns
|
|
|
656
656
|
} }))))));
|
|
657
657
|
})))),
|
|
658
658
|
React.createElement("tbody", { ref: _tBody },
|
|
659
|
-
React.createElement(TBody, { data: getData, columns: columns,
|
|
659
|
+
React.createElement(TBody, { data: getData, columns: columns, refs: { _checkboxItems: _checkboxItems, _selectionItems: _selectionItems }, states: {
|
|
660
|
+
setSelectAll: { get: selectAll, set: setSelectAll },
|
|
661
|
+
showSubitems: { get: showSubitems, set: setShowSubitems },
|
|
662
|
+
}, methods: {
|
|
660
663
|
trackBy: trackBy,
|
|
661
664
|
selections: selections,
|
|
662
665
|
onDnD: onDnD,
|
|
@@ -251,10 +251,8 @@ const DatePicker = ({ variant, color, onChange, config, validation, ...attribute
|
|
|
251
251
|
attributes.placeholder && attributes.placeholder.length > 0 && (React.createElement("label", { ref: _placeholder },
|
|
252
252
|
validation ? "* " : "",
|
|
253
253
|
attributes.placeholder)),
|
|
254
|
-
React.createElement("div", { className: "wrapper",
|
|
255
|
-
|
|
256
|
-
style: {
|
|
257
|
-
clipPath: `polygon(
|
|
254
|
+
React.createElement("div", { className: "wrapper", style: {
|
|
255
|
+
clipPath: `polygon(
|
|
258
256
|
-15px 0,
|
|
259
257
|
10px -5px,
|
|
260
258
|
10px 5px,
|
|
@@ -264,9 +262,7 @@ const DatePicker = ({ variant, color, onChange, config, validation, ...attribute
|
|
|
264
262
|
calc(100% + 5px) calc(100% + 5px),
|
|
265
263
|
-5px calc(100% + 5px)
|
|
266
264
|
)`,
|
|
267
|
-
|
|
268
|
-
}
|
|
269
|
-
: {}) },
|
|
265
|
+
} },
|
|
270
266
|
React.createElement(Input, { ref: _beginDate, variant: variant, color: color, ...attributes, value: DATE.ParseValue(String(attributes.value), config?.isClock), type: config?.isClock ? "datetime-local" : "date", onKeyDown: (event) => {
|
|
271
267
|
if (event.code === "Space")
|
|
272
268
|
event.preventDefault();
|
|
@@ -1,38 +1,50 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import React, { useRef, useState, useEffect } from "react";
|
|
2
|
+
import React, { useRef, useState, useEffect, useMemo } from "react";
|
|
3
3
|
import Input from "..";
|
|
4
|
-
const Decimal = ({ variant, color, name, value, onChange, placeholder, validation, disabled }) => {
|
|
5
|
-
// refs
|
|
4
|
+
const Decimal = ({ variant, color, name, value, onChange, placeholder, validation, disabled, locale = "tr-TR", }) => {
|
|
6
5
|
const _input = useRef(null);
|
|
7
|
-
// states
|
|
8
6
|
const [_value, setValue] = useState("");
|
|
9
7
|
// methods
|
|
8
|
+
const decimalSeparator = useMemo(() => {
|
|
9
|
+
const parts = new Intl.NumberFormat(locale).formatToParts(1.1);
|
|
10
|
+
return parts.find((p) => p.type === "decimal")?.value ?? ".";
|
|
11
|
+
}, [locale]);
|
|
10
12
|
const handleChange = (event) => {
|
|
11
13
|
let inputValue = event.target.value;
|
|
12
|
-
|
|
13
|
-
const
|
|
14
|
+
// Locale’a göre izin verilen karakterler. (rakam, decimal, -)
|
|
15
|
+
const regex = new RegExp(`[^0-9\\${decimalSeparator}-]`, "g");
|
|
16
|
+
inputValue = inputValue.replace(regex, "");
|
|
17
|
+
// Sadece başta negatif işarete izin ver.
|
|
18
|
+
if (inputValue.includes("-")) {
|
|
19
|
+
inputValue = (inputValue.startsWith("-") ? "-" : "") + inputValue.replace(/-/g, "");
|
|
20
|
+
}
|
|
21
|
+
// Tek decimal separator’a izin ver.
|
|
22
|
+
const parts = inputValue.split(decimalSeparator);
|
|
14
23
|
if (parts.length > 2) {
|
|
15
|
-
inputValue = parts[0] +
|
|
24
|
+
inputValue = parts[0] + decimalSeparator + parts.slice(1).join("");
|
|
16
25
|
}
|
|
17
26
|
setValue(inputValue);
|
|
27
|
+
// Parent’a normalize edilmiş "." decimal gönder.
|
|
28
|
+
const normalized = inputValue.replace(decimalSeparator, ".");
|
|
18
29
|
onChange?.({
|
|
19
30
|
...event,
|
|
20
31
|
target: {
|
|
21
32
|
...event.target,
|
|
22
33
|
name,
|
|
23
|
-
value:
|
|
34
|
+
value: normalized,
|
|
24
35
|
},
|
|
25
36
|
});
|
|
26
37
|
};
|
|
27
38
|
// useEffects
|
|
28
39
|
useEffect(() => {
|
|
29
|
-
if (value === undefined || value === null) {
|
|
40
|
+
if (value === undefined || value === null || value === "") {
|
|
30
41
|
setValue("");
|
|
42
|
+
return;
|
|
31
43
|
}
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
}, [value]);
|
|
44
|
+
const stringValue = String(value);
|
|
45
|
+
const localized = stringValue.replace(".", decimalSeparator);
|
|
46
|
+
setValue(localized);
|
|
47
|
+
}, [value, decimalSeparator]);
|
|
36
48
|
return (React.createElement(Input, { ref: _input, name: name, variant: variant, color: color, type: "text", inputMode: "decimal", value: _value, onChange: (e) => {
|
|
37
49
|
if (disabled)
|
|
38
50
|
return;
|
|
@@ -3,5 +3,6 @@ interface IProps extends IVariant, IColors, IBorder, IUpperCase, IValidation, IP
|
|
|
3
3
|
name: string;
|
|
4
4
|
value: string | number | readonly string[] | undefined;
|
|
5
5
|
onChange?: React.ChangeEventHandler<HTMLInputElement>;
|
|
6
|
+
locale?: Intl.LocalesArgument;
|
|
6
7
|
}
|
|
7
8
|
export default IProps;
|
|
@@ -3,12 +3,16 @@ import React, { useEffect, useMemo, useRef, useState } from "react";
|
|
|
3
3
|
import Input from "..";
|
|
4
4
|
import { NUMBER } from "../../../../libs/infrastructure/shared";
|
|
5
5
|
const FormattedDecimal = ({ variant, color, name, value, onChange, locale = "tr-TR", digits, placeholder, validation, disabled, }) => {
|
|
6
|
-
// refs
|
|
7
|
-
// const _firstLoad = useRef<boolean>(false);
|
|
8
6
|
const _input = useRef(null);
|
|
9
|
-
// states
|
|
10
7
|
const [_value, setValue] = useState("");
|
|
11
8
|
// methods
|
|
9
|
+
const getSeparators = (locale) => {
|
|
10
|
+
const parts = new Intl.NumberFormat(locale).formatToParts(1000.1);
|
|
11
|
+
const group = parts.find((p) => p.type === "group")?.value ?? ",";
|
|
12
|
+
const decimal = parts.find((p) => p.type === "decimal")?.value ?? ".";
|
|
13
|
+
return { group, decimal };
|
|
14
|
+
};
|
|
15
|
+
const getFormatter = useMemo(() => NUMBER.Decimal(locale, digits), [locale, digits]);
|
|
12
16
|
const handleClick = () => {
|
|
13
17
|
const input = _input.current;
|
|
14
18
|
if (!input)
|
|
@@ -33,48 +37,34 @@ const FormattedDecimal = ({ variant, color, name, value, onChange, locale = "tr-
|
|
|
33
37
|
};
|
|
34
38
|
const handleChange = (event) => {
|
|
35
39
|
let { value } = event.target;
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
//
|
|
41
|
-
|
|
42
|
-
const
|
|
43
|
-
|
|
44
|
-
|
|
40
|
+
const { group, decimal } = getSeparators(locale);
|
|
41
|
+
// Locale’a göre izin verilen karakterleri temizle.
|
|
42
|
+
const regex = new RegExp(`[^0-9\\${group}\\${decimal}]`, "g");
|
|
43
|
+
value = value.replace(regex, "");
|
|
44
|
+
// Normalize et (decimal her zaman "." olacak şekilde)
|
|
45
|
+
let normalized = value.replace(new RegExp(`\\${group}`, "g"), "").replace(decimal, ".");
|
|
46
|
+
const parsed = parseFloat(normalized);
|
|
47
|
+
const numericValue = isNaN(parsed) ? 0 : parsed;
|
|
48
|
+
const formatted = value === "" ? "" : getFormatter.format(numericValue);
|
|
45
49
|
setValue(formatted);
|
|
46
|
-
onChange?.({
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
}
|
|
54
|
-
else if (input.includes(",") && !input.includes(".")) {
|
|
55
|
-
// Virgül ondalık, binlik yok (fr-FR gibi)
|
|
56
|
-
return input.replace(",", ".");
|
|
57
|
-
}
|
|
58
|
-
else if (input.includes(".") && !input.includes(",")) {
|
|
59
|
-
// Nokta ondalık, binlik yok veya US format
|
|
60
|
-
return input.replace(/,/g, "");
|
|
61
|
-
}
|
|
62
|
-
else {
|
|
63
|
-
// Hiçbiri yok, zaten sayı
|
|
64
|
-
return input;
|
|
65
|
-
}
|
|
50
|
+
onChange?.({
|
|
51
|
+
...event,
|
|
52
|
+
target: {
|
|
53
|
+
...event.target,
|
|
54
|
+
name,
|
|
55
|
+
value: normalized,
|
|
56
|
+
},
|
|
57
|
+
});
|
|
66
58
|
};
|
|
67
59
|
// useEffects
|
|
68
60
|
useEffect(() => {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
// }
|
|
61
|
+
if (value === undefined || value === null || value === "") {
|
|
62
|
+
setValue("");
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
74
65
|
setValue(getFormatter.format(Number(value)));
|
|
75
|
-
}, [value]);
|
|
76
|
-
return (React.createElement(Input, { ref: _input, name: name, variant: variant, color: color, value: _value
|
|
77
|
-
// Disabled gelmesi durumunda işlem yapmasına izin verme...
|
|
66
|
+
}, [value, getFormatter]);
|
|
67
|
+
return (React.createElement(Input, { ref: _input, name: name, variant: variant, color: color, value: _value, type: "text", inputMode: "decimal", onChange: (event) => {
|
|
78
68
|
if (disabled)
|
|
79
69
|
return;
|
|
80
70
|
handleChange(event);
|