ar-design 0.3.7 → 0.3.9
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/Editable.d.ts +3 -2
- package/dist/components/data-display/table/Editable.js +7 -11
- package/dist/components/data-display/table/IProps.d.ts +1 -1
- package/dist/components/data-display/table/index.js +13 -13
- package/dist/components/form/input-number/IProps.d.ts +9 -2
- package/dist/components/form/input-number/index.js +60 -72
- package/dist/libs/types/IGlobalProps.d.ts +12 -0
- package/package.json +1 -1
|
@@ -3,7 +3,8 @@ import { TableColumnType } from "../../../libs/types";
|
|
|
3
3
|
interface IProps<T> {
|
|
4
4
|
c: TableColumnType<T>;
|
|
5
5
|
item: T;
|
|
6
|
-
|
|
6
|
+
index: number;
|
|
7
|
+
onEditable: (item: T, index: number) => void;
|
|
7
8
|
}
|
|
8
|
-
declare const Editable: <T>({ c, item, onEditable }: IProps<T>) => React.JSX.Element | null;
|
|
9
|
+
declare const Editable: <T>({ c, item, index, onEditable }: IProps<T>) => React.JSX.Element | null;
|
|
9
10
|
export default Editable;
|
|
@@ -3,7 +3,7 @@ import React, { 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, onEditable }) {
|
|
6
|
+
const Editable = function ({ c, item, index, onEditable }) {
|
|
7
7
|
const key = c.key;
|
|
8
8
|
const itemValue = item[c.key];
|
|
9
9
|
const selectItem = c.editable?.options?.find((x) => x.value === itemValue);
|
|
@@ -12,30 +12,26 @@ const Editable = function ({ c, item, onEditable }) {
|
|
|
12
12
|
: [];
|
|
13
13
|
// states
|
|
14
14
|
const [value, setValue] = useState(itemValue);
|
|
15
|
-
const [selectionItem, setSelectionItem] = useState(selectItem);
|
|
16
|
-
const [selectionItems, setSelectionItems] = useState(selectItems);
|
|
17
15
|
switch (c.editable?.type) {
|
|
18
16
|
case "string":
|
|
19
17
|
case "number":
|
|
20
18
|
return (React.createElement(Input, { variant: "borderless", value: value, onChange: (event) => {
|
|
21
19
|
const { value } = event.target;
|
|
22
20
|
setValue(value);
|
|
23
|
-
onEditable({ ...item, [key]: c.editable?.type === "number" ? Number(value) : value });
|
|
21
|
+
onEditable({ ...item, [key]: c.editable?.type === "number" ? Number(value) : value }, index);
|
|
24
22
|
} }));
|
|
25
23
|
case "date-picker":
|
|
26
24
|
return (React.createElement(DatePicker, { variant: "borderless", value: value, onChange: (value) => {
|
|
27
25
|
setValue(value);
|
|
28
|
-
onEditable({ ...item, [key]: value });
|
|
26
|
+
onEditable({ ...item, [key]: value }, index);
|
|
29
27
|
} }));
|
|
30
28
|
case "single-select":
|
|
31
|
-
return (React.createElement(Select, { variant: "borderless", value:
|
|
32
|
-
|
|
33
|
-
onEditable({ ...item, [key]: option?.value });
|
|
29
|
+
return (React.createElement(Select, { variant: "borderless", value: selectItem, options: c.editable.options, onClick: async () => await c.editable?.method?.(), onChange: (option) => {
|
|
30
|
+
onEditable({ ...item, [key]: option?.value }, index);
|
|
34
31
|
} }));
|
|
35
32
|
case "multiple-select":
|
|
36
|
-
return (React.createElement(Select, { variant: "borderless", value:
|
|
37
|
-
|
|
38
|
-
onEditable({ ...item, [key]: options.map((option) => option.value) });
|
|
33
|
+
return (React.createElement(Select, { variant: "borderless", value: selectItems, options: c.editable.options, onClick: async () => await c.editable?.method?.(), onChange: (options) => {
|
|
34
|
+
onEditable({ ...item, [key]: options.map((option) => option.value) }, index);
|
|
39
35
|
}, multiple: true }));
|
|
40
36
|
default:
|
|
41
37
|
return null;
|
|
@@ -142,7 +142,7 @@ interface IProps<T> extends IChildren {
|
|
|
142
142
|
* @param operator - Kullanılan filtre operatörü.
|
|
143
143
|
*/
|
|
144
144
|
searchedParams?: (params: SearchedParam | null, query: string, operator: FilterOperator) => void;
|
|
145
|
-
onEditable?: (item: T) => void;
|
|
145
|
+
onEditable?: (item: T, index: number) => void;
|
|
146
146
|
/**
|
|
147
147
|
* Sayfalama ayarları.
|
|
148
148
|
*/
|
|
@@ -38,6 +38,8 @@ const Table = forwardRef(({ children, title, description, data, columns, actions
|
|
|
38
38
|
const _searchTimeOut = useRef(null);
|
|
39
39
|
// refs -> Filter
|
|
40
40
|
const _filterButton = useRef([]);
|
|
41
|
+
// refs -> Previous Selection Items
|
|
42
|
+
const _hasInitialized = useRef(false);
|
|
41
43
|
// variables
|
|
42
44
|
const _subrowOpenAutomatically = config.subrow?.openAutomatically ?? false;
|
|
43
45
|
const _subrowSelector = config.subrow?.selector ?? "subitems";
|
|
@@ -399,7 +401,7 @@ const Table = forwardRef(({ children, title, description, data, columns, actions
|
|
|
399
401
|
return (React.createElement("div", { key: `last-before-${i}`, style: { left: `${i + 0.65}rem` }, className: "last-before" }));
|
|
400
402
|
}),
|
|
401
403
|
React.createElement("div", { className: "before" }))),
|
|
402
|
-
React.isValidElement(render) ? (render) : c.editable && onEditable ? (React.createElement(Editable, { c: c, item: item, onEditable: onEditable })) : (render),
|
|
404
|
+
React.isValidElement(render) ? (render) : c.editable && onEditable ? (React.createElement(Editable, { c: c, item: item, index: index, onEditable: onEditable })) : (render),
|
|
403
405
|
config.isTreeView && cIndex === 0 && (React.createElement("div", { className: "after" },
|
|
404
406
|
React.createElement("div", { className: "circle" }))))));
|
|
405
407
|
};
|
|
@@ -426,13 +428,14 @@ const Table = forwardRef(({ children, title, description, data, columns, actions
|
|
|
426
428
|
};
|
|
427
429
|
// useEffects
|
|
428
430
|
useEffect(() => {
|
|
429
|
-
|
|
430
|
-
|
|
431
|
+
if (_hasInitialized.current)
|
|
432
|
+
return;
|
|
431
433
|
if (previousSelections && previousSelections.length > 0) {
|
|
432
434
|
const validSelections = data.filter((item) => previousSelections.some((selected) => JSON.stringify(selected) === JSON.stringify(item)));
|
|
433
435
|
setSelectionItems(validSelections);
|
|
436
|
+
_hasInitialized.current = true; // sadece bir kez ayarla
|
|
434
437
|
}
|
|
435
|
-
}, [previousSelections]);
|
|
438
|
+
}, [previousSelections, data]);
|
|
436
439
|
useEffect(() => {
|
|
437
440
|
if (config?.isServerSide && searchedParams) {
|
|
438
441
|
const searchRecord = {};
|
|
@@ -475,15 +478,12 @@ const Table = forwardRef(({ children, title, description, data, columns, actions
|
|
|
475
478
|
pagination.onChange(1);
|
|
476
479
|
}, [checkboxSelectedParams]);
|
|
477
480
|
useEffect(() => {
|
|
478
|
-
if (
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
return;
|
|
485
|
-
if (_checkboxItems.current.length > 0) {
|
|
486
|
-
setSelectAll(_checkboxItems.current.every((item) => item?.checked === true));
|
|
481
|
+
if (typeof selections === "function" && Array.isArray(selectionItems)) {
|
|
482
|
+
selections(selectionItems);
|
|
483
|
+
}
|
|
484
|
+
if (Array.isArray(_checkboxItems.current) && _checkboxItems.current.length > 0) {
|
|
485
|
+
const allChecked = _checkboxItems.current.every((item) => item?.checked === true);
|
|
486
|
+
setSelectAll(allChecked);
|
|
487
487
|
}
|
|
488
488
|
}, [selectionItems, currentPage]);
|
|
489
489
|
useEffect(() => {
|
|
@@ -1,4 +1,11 @@
|
|
|
1
|
-
import { IBorder, IColors, IUpperCase, IValidation, IVariant } from "../../../libs/types/IGlobalProps";
|
|
2
|
-
interface IProps extends IVariant, IColors, IBorder, IUpperCase, IValidation,
|
|
1
|
+
import { IBorder, IColors, IDisabled, IPlaceholder, IUpperCase, IValidation, IVariant } from "../../../libs/types/IGlobalProps";
|
|
2
|
+
interface IProps extends IVariant, IColors, IBorder, IUpperCase, IValidation, IPlaceholder, IDisabled {
|
|
3
|
+
name: string;
|
|
4
|
+
value: string | number | readonly string[] | undefined;
|
|
5
|
+
onChange?: React.ChangeEventHandler<HTMLInputElement>;
|
|
6
|
+
digits?: {
|
|
7
|
+
minimum?: number;
|
|
8
|
+
maximum?: number;
|
|
9
|
+
};
|
|
3
10
|
}
|
|
4
11
|
export default IProps;
|
|
@@ -1,99 +1,87 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import React, { useEffect, useMemo, useRef, useState } from "react";
|
|
3
3
|
import Input from "../input";
|
|
4
|
-
const InputNumber = ({
|
|
4
|
+
const InputNumber = ({ name, value, onChange, digits, placeholder, disabled }) => {
|
|
5
5
|
// refs
|
|
6
6
|
const _firstLoad = useRef(false);
|
|
7
7
|
const _input = useRef(null);
|
|
8
|
-
const _caretPosition = useRef(null);
|
|
9
|
-
const _isInputTouch = useRef(false);
|
|
10
8
|
// states
|
|
11
|
-
const [
|
|
9
|
+
const [_value, setValue] = useState("");
|
|
12
10
|
// methods
|
|
11
|
+
const handleClick = () => {
|
|
12
|
+
const input = _input.current;
|
|
13
|
+
if (!input)
|
|
14
|
+
return;
|
|
15
|
+
const caret = input.selectionStart ?? 0;
|
|
16
|
+
input.setSelectionRange(caret, caret + 1);
|
|
17
|
+
};
|
|
18
|
+
const handleKeyUp = (event) => {
|
|
19
|
+
const input = _input.current;
|
|
20
|
+
if (!input)
|
|
21
|
+
return;
|
|
22
|
+
const caret = input.selectionStart ?? 0;
|
|
23
|
+
if (event.code === "ArrowRight") {
|
|
24
|
+
input.setSelectionRange(caret, caret + 1);
|
|
25
|
+
}
|
|
26
|
+
else if (event.code === "ArrowLeft" && caret > 0) {
|
|
27
|
+
input.setSelectionRange(caret - 1, caret);
|
|
28
|
+
}
|
|
29
|
+
else if (["ArrowUp", "ArrowDown"].includes(event.code)) {
|
|
30
|
+
input.setSelectionRange(caret, caret + 1);
|
|
31
|
+
}
|
|
32
|
+
};
|
|
13
33
|
const handleChange = (event) => {
|
|
14
34
|
let { value } = event.target;
|
|
15
|
-
const caret = _input.current?.selectionStart ?? 0;
|
|
16
|
-
_caretPosition.current = caret;
|
|
17
|
-
if (value.length === 0)
|
|
18
|
-
_isInputTouch.current = false;
|
|
19
35
|
// Temizle.
|
|
20
36
|
const cleanedValue = (value = value.replace(/[^0-9,]/g, ""));
|
|
21
37
|
// Numara olarak çevir.
|
|
22
|
-
const normalized = value
|
|
23
|
-
const parsed = parseFloat(normalized);
|
|
24
|
-
const numberValue = isNaN(parsed) ? 0 : parsed;
|
|
25
|
-
// Formatla ve Kullanıcı , (virgül) girdiyse kuruş göster.
|
|
38
|
+
const normalized = parseCurrencySmart(value);
|
|
26
39
|
const isDecimals = cleanedValue.includes(",");
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
//
|
|
30
|
-
|
|
31
|
-
// }
|
|
40
|
+
const parsedDecimal = parseFloat(normalized);
|
|
41
|
+
const newValue = isNaN(parsedDecimal) ? 0 : parsedDecimal;
|
|
42
|
+
// Formatla ve Kullanıcı , (virgül) girdiyse kuruş göster.
|
|
43
|
+
let formatted = newValue === 0 && cleanedValue === "" ? "" : getFormatter(isDecimals).format(newValue);
|
|
32
44
|
setValue(formatted);
|
|
33
|
-
|
|
34
|
-
requestAnimationFrame(() => {
|
|
35
|
-
if (!_input.current || _caretPosition.current == null)
|
|
36
|
-
return;
|
|
37
|
-
if (isDecimals)
|
|
38
|
-
_isInputTouch.current = false;
|
|
39
|
-
_caretPosition.current += formatted.length > value.length && !_isInputTouch.current ? 1 : 0;
|
|
40
|
-
_input.current?.setSelectionRange(_caretPosition.current, _caretPosition.current);
|
|
41
|
-
});
|
|
42
|
-
}, 0);
|
|
45
|
+
onChange?.({ ...event, target: { ...event.target, name: name, value: normalized } });
|
|
43
46
|
};
|
|
44
|
-
const
|
|
45
|
-
const caret = _input.current?.selectionStart ?? 0;
|
|
46
|
-
_caretPosition.current = caret;
|
|
47
|
-
if (_input.current && _input.current.value.length > 3)
|
|
48
|
-
_isInputTouch.current = true;
|
|
49
|
-
};
|
|
50
|
-
const handleKeyUp = (event) => {
|
|
51
|
-
if (!["ArrowUp", "ArrowRight", "ArrowDown", "ArrowLeft"].includes(event.code))
|
|
52
|
-
return;
|
|
53
|
-
if (_input.current && _input.current.value.length > 3)
|
|
54
|
-
_isInputTouch.current = true;
|
|
55
|
-
};
|
|
56
|
-
const formatter = useMemo(() => {
|
|
47
|
+
const getFormatter = useMemo(() => {
|
|
57
48
|
return (isDecimals) => new Intl.NumberFormat("tr-TR", {
|
|
58
49
|
style: "decimal",
|
|
59
|
-
minimumFractionDigits: 0,
|
|
60
|
-
maximumFractionDigits: isDecimals ? 2 : 0,
|
|
50
|
+
minimumFractionDigits: digits?.minimum ?? 0,
|
|
51
|
+
maximumFractionDigits: isDecimals ? digits?.maximum ?? 2 : 0,
|
|
61
52
|
});
|
|
62
|
-
}, []);
|
|
53
|
+
}, [digits]);
|
|
54
|
+
const parseCurrencySmart = (input) => {
|
|
55
|
+
if (input.includes(",") && input.includes(".")) {
|
|
56
|
+
// Nokta binlik, virgül ondalık (tr-TR, de-DE gibi)
|
|
57
|
+
return input.replace(/\./g, "").replace(",", ".");
|
|
58
|
+
}
|
|
59
|
+
else if (input.includes(",") && !input.includes(".")) {
|
|
60
|
+
// Virgül ondalık, binlik yok (fr-FR gibi)
|
|
61
|
+
return input.replace(",", ".");
|
|
62
|
+
}
|
|
63
|
+
else if (input.includes(".") && !input.includes(",")) {
|
|
64
|
+
// Nokta ondalık, binlik yok veya US format
|
|
65
|
+
return input.replace(/,/g, "");
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
// Hiçbiri yok, zaten sayı
|
|
69
|
+
return input;
|
|
70
|
+
}
|
|
71
|
+
};
|
|
63
72
|
// useEffects
|
|
64
73
|
useEffect(() => {
|
|
65
|
-
if (_firstLoad.current)
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
const isDecimals = String(attributes.value).includes(",");
|
|
69
|
-
let formatted = formatter(isDecimals).format(parseFloat(String(attributes.value)));
|
|
70
|
-
setValue(formatted == "NaN" ? "" : formatted);
|
|
74
|
+
if (!_firstLoad.current && value !== undefined && value !== "") {
|
|
75
|
+
const isDecimals = String(value).includes(".");
|
|
76
|
+
setValue(getFormatter(isDecimals).format(Number(value)));
|
|
71
77
|
_firstLoad.current = true;
|
|
72
78
|
}
|
|
73
|
-
}, [
|
|
74
|
-
return (React.createElement(Input, { ref: _input,
|
|
79
|
+
}, [value]);
|
|
80
|
+
return (React.createElement(Input, { ref: _input, name: name, value: _value ?? "", type: "text", inputMode: "decimal", onChange: (event) => {
|
|
75
81
|
// Disabled gelmesi durumunda işlem yapmasına izin verme...
|
|
76
|
-
if (
|
|
82
|
+
if (disabled)
|
|
77
83
|
return;
|
|
78
|
-
(
|
|
79
|
-
|
|
80
|
-
})();
|
|
81
|
-
(() => {
|
|
82
|
-
if (attributes.onChange) {
|
|
83
|
-
const { value } = event.target;
|
|
84
|
-
const newValue = value.replaceAll(".", "");
|
|
85
|
-
attributes.onChange({
|
|
86
|
-
...event,
|
|
87
|
-
target: {
|
|
88
|
-
...event.target,
|
|
89
|
-
id: event.target.id,
|
|
90
|
-
name: event.target.name,
|
|
91
|
-
value: newValue,
|
|
92
|
-
type: event.target.type,
|
|
93
|
-
},
|
|
94
|
-
});
|
|
95
|
-
}
|
|
96
|
-
})();
|
|
97
|
-
}, onClick: handleClick, onKeyUp: handleKeyUp, type: "text", inputMode: "decimal" }));
|
|
84
|
+
handleChange(event);
|
|
85
|
+
}, onClick: handleClick, onKeyUp: handleKeyUp, placeholder: placeholder }));
|
|
98
86
|
};
|
|
99
87
|
export default InputNumber;
|
|
@@ -180,6 +180,18 @@ export interface IValidation {
|
|
|
180
180
|
scrollTo?: boolean;
|
|
181
181
|
};
|
|
182
182
|
}
|
|
183
|
+
export interface IPlaceholder {
|
|
184
|
+
/**
|
|
185
|
+
* Bileşenin ne için olduğunu belirlemek için kullanılır.
|
|
186
|
+
*
|
|
187
|
+
* ```jsx
|
|
188
|
+
* <Component placeholder="...">
|
|
189
|
+
* Example
|
|
190
|
+
* </Component>
|
|
191
|
+
* ```
|
|
192
|
+
*/
|
|
193
|
+
placeholder?: string;
|
|
194
|
+
}
|
|
183
195
|
export interface IDisabled {
|
|
184
196
|
/**
|
|
185
197
|
* Bileşenin pasif (devre dışı) olup olmadığını belirtmek için kullanılır.
|