ar-design 0.3.7 → 0.3.8

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,4 +1,11 @@
1
- import { IBorder, IColors, IUpperCase, IValidation, IVariant } from "../../../libs/types/IGlobalProps";
2
- interface IProps extends IVariant, IColors, IBorder, IUpperCase, IValidation, Omit<React.InputHTMLAttributes<HTMLInputElement>, "children" | "size" | "color" | "type"> {
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 = ({ ...attributes }) => {
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 [value, setValue] = useState("");
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.replace(/\./g, "").replace(",", ".");
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
- let formatted = numberValue === 0 && cleanedValue === "" ? "" : formatter(isDecimals).format(numberValue);
28
- // if (isDecimals) {
29
- // const [_, digits] = formatted.split(",");
30
- // if (digits && digits.length > 2) formatted = formatted.slice(0, -1);
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
- setTimeout(() => {
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 handleClick = () => {
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
- return;
67
- if (attributes.value !== undefined && attributes.value !== "") {
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
- }, [attributes.value]);
74
- return (React.createElement(Input, { ref: _input, ...attributes, value: value ?? attributes.value ?? "", onChange: (event) => {
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 (attributes.disabled)
82
+ if (disabled)
77
83
  return;
78
- (() => {
79
- handleChange(event);
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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ar-design",
3
- "version": "0.3.7",
3
+ "version": "0.3.8",
4
4
  "main": "./dist/index.js",
5
5
  "module": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",