@arkyn/components 1.2.4 → 1.3.0

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.
Files changed (40) hide show
  1. package/dist/bundle.js +1053 -767
  2. package/dist/bundle.umd.cjs +11 -11
  3. package/dist/components/Checkbox/index.d.ts +5 -0
  4. package/dist/components/Checkbox/index.d.ts.map +1 -0
  5. package/dist/components/Checkbox/index.js +20 -0
  6. package/dist/components/Input/CpfCpnjInput/getConfig.d.ts +1 -1
  7. package/dist/components/Input/CpfCpnjInput/getConfig.d.ts.map +1 -1
  8. package/dist/components/Input/CpfCpnjInput/getConfig.js +12 -1
  9. package/dist/components/Input/CpfCpnjInput/index.d.ts.map +1 -1
  10. package/dist/components/Input/CpfCpnjInput/index.js +2 -2
  11. package/dist/components/Input/CurrencyInput/index.js +1 -1
  12. package/dist/components/Input/MaskInput/getConfig.js +1 -1
  13. package/dist/components/Input/MaskInput/index.d.ts.map +1 -1
  14. package/dist/components/Input/MaskInput/index.js +34 -58
  15. package/dist/components/Select/getConfig.d.ts +313 -0
  16. package/dist/components/Select/getConfig.d.ts.map +1 -0
  17. package/dist/components/Select/getConfig.js +30 -0
  18. package/dist/components/Select/index.d.ts +5 -0
  19. package/dist/components/Select/index.d.ts.map +1 -0
  20. package/dist/components/Select/index.js +71 -0
  21. package/dist/components/Select/utils/morpheme.d.ts +4 -0
  22. package/dist/components/Select/utils/morpheme.d.ts.map +1 -0
  23. package/dist/components/Select/utils/morpheme.js +10 -0
  24. package/dist/index.d.ts +2 -0
  25. package/dist/index.d.ts.map +1 -1
  26. package/dist/index.js +2 -0
  27. package/dist/style.css +1 -1
  28. package/package.json +6 -6
  29. package/src/components/Checkbox/index.tsx +52 -0
  30. package/src/components/Checkbox/styles.css +66 -0
  31. package/src/components/Input/CpfCpnjInput/getConfig.tsx +15 -0
  32. package/src/components/Input/CpfCpnjInput/index.tsx +3 -4
  33. package/src/components/Input/CurrencyInput/index.tsx +1 -1
  34. package/src/components/Input/MaskInput/getConfig.tsx +1 -1
  35. package/src/components/Input/MaskInput/index.tsx +81 -68
  36. package/src/components/Select/getConfig.tsx +52 -0
  37. package/src/components/Select/index.tsx +161 -0
  38. package/src/components/Select/styles.css +305 -0
  39. package/src/components/Select/utils/morpheme.tsx +19 -0
  40. package/src/index.ts +2 -0
@@ -0,0 +1,52 @@
1
+ import { CheckboxProps } from "@arkyn/types";
2
+ import { Check } from "lucide-react";
3
+ import { useState } from "react";
4
+
5
+ import { useFormController } from "../Form/FormController";
6
+ import "./styles.css";
7
+
8
+ function Checkbox(props: CheckboxProps) {
9
+ const {
10
+ name,
11
+ className: baseClassName = "",
12
+ size = "md",
13
+ isError: defaultIsError,
14
+ defaultChecked = false,
15
+ checked: baseChecked = null,
16
+ onCheck,
17
+ value,
18
+ ...rest
19
+ } = props;
20
+
21
+ const { id, inputRef, error } = useFormController();
22
+ const isError = defaultIsError || !!error;
23
+
24
+ const [isChecked, setIsChecked] = useState(defaultChecked || false);
25
+ const currentChecked =
26
+ typeof baseChecked === "boolean" ? baseChecked : isChecked;
27
+
28
+ const className = `arkyn_checkbox ${size} ${isError ? "error" : ""} ${
29
+ currentChecked ? "checked" : ""
30
+ } ${baseClassName}`;
31
+
32
+ function handleCheck() {
33
+ const defaultChecked = isChecked;
34
+ setIsChecked(!defaultChecked);
35
+ onCheck && onCheck(!defaultChecked ? value || "checked" : "");
36
+ }
37
+
38
+ return (
39
+ <div className={className} onClick={handleCheck} {...rest}>
40
+ <input
41
+ type="hidden"
42
+ name={name}
43
+ id={id}
44
+ ref={inputRef}
45
+ value={currentChecked ? value || "checked" : ""}
46
+ />
47
+ <Check />
48
+ </div>
49
+ );
50
+ }
51
+
52
+ export { Checkbox };
@@ -0,0 +1,66 @@
1
+ .arkyn_checkbox {
2
+ display: flex;
3
+ align-items: center;
4
+ justify-content: center;
5
+
6
+ border: 2px solid var(--secondary-400);
7
+ background-color: var(--secondary-100);
8
+ }
9
+
10
+ .arkyn_checkbox:hover {
11
+ cursor: pointer;
12
+ }
13
+
14
+ .arkyn_checkbox svg {
15
+ display: none;
16
+ stroke-width: 3px;
17
+ }
18
+
19
+ /* SIZE */
20
+ .arkyn_checkbox.sm {
21
+ height: 16px;
22
+ width: 16px;
23
+ border-radius: 2px;
24
+ }
25
+
26
+ .arkyn_checkbox.sm svg {
27
+ min-height: 12px;
28
+ min-width: 12px;
29
+ }
30
+
31
+ .arkyn_checkbox.md {
32
+ height: 20px;
33
+ width: 20px;
34
+ border-radius: 4px;
35
+ }
36
+
37
+ .arkyn_checkbox.md svg {
38
+ min-height: 14px;
39
+ min-width: 14px;
40
+ }
41
+
42
+ .arkyn_checkbox.lg {
43
+ height: 24px;
44
+ width: 24px;
45
+ border-radius: 6px;
46
+ }
47
+
48
+ .arkyn_checkbox.lg svg {
49
+ min-height: 14px;
50
+ min-width: 14px;
51
+ }
52
+
53
+ /* CHECKED */
54
+ .arkyn_checkbox.checked {
55
+ background-color: var(--primary-500);
56
+ border-color: var(--primary-500);
57
+ }
58
+
59
+ .arkyn_checkbox.checked svg {
60
+ display: unset;
61
+ color: #fff;
62
+ }
63
+
64
+ .arkyn_checkbox.error {
65
+ border-color: var(--danger-500);
66
+ }
@@ -2,6 +2,7 @@ import type { CpfCnpjInputProps } from "@arkyn/types";
2
2
  import { Loader2 } from "lucide-react";
3
3
 
4
4
  import { morpheme } from "../utils/morpheme";
5
+ import { MAX_LENGTH, TYPES, applyMask, clear, getMask } from "./utils";
5
6
 
6
7
  function getConfig(props: CpfCnpjInputProps, isFocused: boolean) {
7
8
  const {
@@ -15,6 +16,7 @@ function getConfig(props: CpfCnpjInputProps, isFocused: boolean) {
15
16
  leftIcon: LeftIcon,
16
17
  rightIcon: RightIcon,
17
18
  disabled,
19
+ defaultValue,
18
20
  readOnly,
19
21
  onFocus,
20
22
  onBlur,
@@ -24,6 +26,18 @@ function getConfig(props: CpfCnpjInputProps, isFocused: boolean) {
24
26
  ...rest
25
27
  } = props;
26
28
 
29
+ function parseDefault(event: string) {
30
+ let value = clear(event);
31
+ const mask = getMask(value);
32
+
33
+ let nextLength = value.length;
34
+
35
+ if (nextLength > MAX_LENGTH) return;
36
+ value = applyMask(value, TYPES[mask] as "CPF" | "CNPJ");
37
+
38
+ return value;
39
+ }
40
+
27
41
  const loadingPosition = RightIcon ? "right" : "left";
28
42
 
29
43
  const hasPrefix = !!basePrefix ? "hasPrefix" : "";
@@ -43,6 +57,7 @@ function getConfig(props: CpfCnpjInputProps, isFocused: boolean) {
43
57
  sufix: morpheme(baseSufix, iconSize, "sufix"),
44
58
  LeftIcon,
45
59
  RightIcon,
60
+ defaultValue: parseDefault(defaultValue || ""),
46
61
  disabled,
47
62
  readOnly,
48
63
  onFocus,
@@ -9,9 +9,6 @@ import { MAX_LENGTH, TYPES, applyMask, clear, getMask } from "./utils";
9
9
 
10
10
  function CpfCnpjInput(props: CpfCnpjInputProps) {
11
11
  const [isFocused, setIsFocused] = useState(false);
12
- const [inputValue, setInputValue] = useState(
13
- clear(props?.defaultValue || "")
14
- );
15
12
 
16
13
  const baseRef = useRef<HTMLInputElement>(null);
17
14
 
@@ -38,10 +35,12 @@ function CpfCnpjInput(props: CpfCnpjInputProps) {
38
35
  Spinner,
39
36
  onChange,
40
37
  value,
41
- defaultValue = "",
38
+ defaultValue,
42
39
  ...rest
43
40
  } = getConfig({ ...props, id, isError }, isFocused);
44
41
 
42
+ const [inputValue, setInputValue] = useState(defaultValue);
43
+
45
44
  const showLeftIcon = LeftIcon && !isLoading;
46
45
  const showRightIcon = RightIcon && !isLoading;
47
46
 
@@ -88,8 +88,8 @@ function CurrencyInput(props: CurrencyInputProps) {
88
88
  readOnly={readOnly}
89
89
  ref={ref}
90
90
  onFocus={handleFocus}
91
- onChange={() => {}}
92
91
  onBlur={handleBlur}
92
+ onChange={() => {}}
93
93
  {...rest}
94
94
  />
95
95
 
@@ -21,7 +21,7 @@ function getConfig(props: MaskedInputProps, isFocused: boolean) {
21
21
  title,
22
22
  style,
23
23
  onChange,
24
- showMask = true,
24
+ showMask = false,
25
25
  type,
26
26
  ...rest
27
27
  } = props;
@@ -1,80 +1,93 @@
1
1
  import type { MaskedInputProps } from "@arkyn/types";
2
- import type { FocusEvent } from "react";
2
+ import type { FocusEvent, InputHTMLAttributes } from "react";
3
3
 
4
4
  import { InputMask } from "@react-input/mask";
5
- import { useRef, useState } from "react";
5
+ import { forwardRef, useRef, useState } from "react";
6
6
 
7
7
  import { useFormController } from "../../Form/FormController";
8
- import { SimpleInput } from "../SimpleInput";
8
+ import { getConfig } from "./getConfig";
9
+
10
+ const BaseInput = forwardRef<
11
+ HTMLInputElement,
12
+ InputHTMLAttributes<HTMLInputElement>
13
+ >((props, ref) => {
14
+ return <input ref={ref} {...props} />;
15
+ });
9
16
 
10
17
  function MaskedInput(props: MaskedInputProps) {
11
- // const [isFocused, setIsFocused] = useState(false);
12
-
13
- // const baseRef = useRef<any>(null);
14
-
15
- // const { inputRef, id, error } = useFormController();
16
-
17
- // const ref = inputRef || baseRef;
18
- // const isError = props.isError || !!error;
19
-
20
- // const {
21
- // disabled,
22
- // title,
23
- // style,
24
- // className,
25
- // prefix,
26
- // sufix,
27
- // iconSize,
28
- // loadingPosition,
29
- // isLoading,
30
- // LeftIcon,
31
- // readOnly,
32
- // onFocus,
33
- // onBlur,
34
- // RightIcon,
35
- // Spinner,
36
- // ...rest
37
- // } = getConfig({ ...props, id, isError }, isFocused);
38
-
39
- // const showLeftIcon = LeftIcon && !isLoading;
40
- // const showRightIcon = RightIcon && !isLoading;
41
-
42
- // const showLeftSpinner = loadingPosition === "left" && isLoading;
43
- // const showRightSpinner = loadingPosition === "right" && isLoading;
44
-
45
- // function handleSectionClick() {
46
- // if (disabled || !ref?.current) return;
47
- // setIsFocused(true);
48
- // ref.current.focus();
49
- // }
50
-
51
- // function handleFocus(e: FocusEvent<HTMLInputElement>) {
52
- // setIsFocused(true);
53
- // if (onFocus) onFocus(e);
54
- // }
55
-
56
- // function handleBlur(e: FocusEvent<HTMLInputElement>) {
57
- // setIsFocused(false);
58
- // if (onBlur) onBlur(e);
59
- // }
18
+ const [isFocused, setIsFocused] = useState(false);
19
+
20
+ const baseRef = useRef<any>(null);
21
+
22
+ const { inputRef, id, error } = useFormController();
23
+
24
+ const ref = inputRef || baseRef;
25
+ const isError = props.isError || !!error;
26
+
27
+ const {
28
+ disabled,
29
+ title,
30
+ style,
31
+ className,
32
+ prefix,
33
+ sufix,
34
+ iconSize,
35
+ loadingPosition,
36
+ isLoading,
37
+ LeftIcon,
38
+ readOnly,
39
+ onFocus,
40
+ onBlur,
41
+ RightIcon,
42
+ Spinner,
43
+ ...rest
44
+ } = getConfig({ ...props, id, isError }, isFocused);
45
+
46
+ const showLeftIcon = LeftIcon && !isLoading;
47
+ const showRightIcon = RightIcon && !isLoading;
48
+
49
+ const showLeftSpinner = loadingPosition === "left" && isLoading;
50
+ const showRightSpinner = loadingPosition === "right" && isLoading;
51
+
52
+ function handleSectionClick() {
53
+ if (disabled || !ref?.current) return;
54
+ setIsFocused(true);
55
+ ref.current.focus();
56
+ }
57
+
58
+ function handleFocus(e: FocusEvent<HTMLInputElement>) {
59
+ setIsFocused(true);
60
+ if (onFocus) onFocus(e);
61
+ }
62
+
63
+ function handleBlur(e: FocusEvent<HTMLInputElement>) {
64
+ setIsFocused(false);
65
+ if (onBlur) onBlur(e);
66
+ }
60
67
 
61
68
  return (
62
- // <section
63
- // title={title}
64
- // style={style}
65
- // onClick={handleSectionClick}
66
- // className={className}
67
- // >
68
- // {prefix}
69
- // {showLeftSpinner && Spinner}
70
- // {showLeftIcon && <LeftIcon size={iconSize} strokeWidth={2.5} />}
71
-
72
- <InputMask component={SimpleInput} {...props} type="text" />
73
-
74
- // {showRightIcon && <RightIcon size={iconSize} strokeWidth={2.5} />}
75
- // {showRightSpinner && Spinner}
76
- // {sufix}
77
- // </section>
69
+ <section
70
+ title={title}
71
+ style={style}
72
+ onClick={handleSectionClick}
73
+ className={className}
74
+ >
75
+ {prefix}
76
+ {showLeftSpinner && Spinner}
77
+ {showLeftIcon && <LeftIcon size={iconSize} strokeWidth={2.5} />}
78
+
79
+ <InputMask
80
+ component={BaseInput}
81
+ ref={ref}
82
+ onFocus={handleFocus}
83
+ onBlur={handleBlur}
84
+ {...rest}
85
+ />
86
+
87
+ {showRightIcon && <RightIcon size={iconSize} strokeWidth={2.5} />}
88
+ {showRightSpinner && Spinner}
89
+ {sufix}
90
+ </section>
78
91
  );
79
92
  }
80
93
 
@@ -0,0 +1,52 @@
1
+ import type { SelectProps } from "@arkyn/types";
2
+ import { Loader2 } from "lucide-react";
3
+
4
+ import { morpheme } from "./utils/morpheme";
5
+
6
+ function getConfig(props: SelectProps, isFocused: boolean) {
7
+ const {
8
+ isLoading,
9
+ isError,
10
+ size = "md",
11
+ className: baseClassName = "",
12
+ variant = "solid",
13
+ prefix: basePrefix,
14
+ leftIcon: LeftIcon,
15
+ disabled,
16
+ readOnly,
17
+ onFocus,
18
+ onBlur,
19
+ title,
20
+ style,
21
+ isSearchable = false,
22
+ ...rest
23
+ } = props;
24
+
25
+ const hasPrefix = !!basePrefix ? "hasPrefix" : "";
26
+ const errored = isError ? "errored" : "";
27
+ const opacity = disabled || readOnly || isLoading ? "opacity" : "";
28
+ const focused = isFocused ? "focused" : "";
29
+
30
+ const className = `arkyn_select ${hasPrefix} ${variant} ${size} ${opacity} ${errored} ${focused} ${baseClassName}`;
31
+ const iconSizes = { md: 20, lg: 20 };
32
+ const iconSize = iconSizes[size];
33
+
34
+ return {
35
+ isLoading,
36
+ className,
37
+ prefix: morpheme(basePrefix, iconSize, "prefix"),
38
+ LeftIcon,
39
+ disabled,
40
+ readOnly,
41
+ onFocus,
42
+ onBlur,
43
+ title,
44
+ style,
45
+ isSearchable,
46
+ iconSize: iconSize,
47
+ Spinner: <Loader2 className="spinner" size={iconSize} strokeWidth={2.5} />,
48
+ ...rest,
49
+ };
50
+ }
51
+
52
+ export { getConfig };
@@ -0,0 +1,161 @@
1
+ import type { SelectProps } from "@arkyn/types";
2
+ import type { FocusEvent } from "react";
3
+
4
+ import { ArrowUp, Check, ChevronDown } from "lucide-react";
5
+ import { useRef, useState } from "react";
6
+
7
+ import { useFormController } from "../Form/FormController";
8
+ import { getConfig } from "./getConfig";
9
+
10
+ import "./styles.css";
11
+
12
+ function Select(props: SelectProps) {
13
+ const [isFocused, setIsFocused] = useState(false);
14
+ const { inputRef, id, error } = useFormController();
15
+
16
+ const baseRef = useRef<HTMLInputElement>(null);
17
+
18
+ const ref = inputRef || baseRef;
19
+ const isError = props.isError || !!error;
20
+
21
+ const {
22
+ disabled,
23
+ title,
24
+ style,
25
+ className,
26
+ prefix,
27
+ iconSize,
28
+ isLoading,
29
+ LeftIcon,
30
+ value: baseValue = null,
31
+ defaultValue = "",
32
+ readOnly,
33
+ onFocus,
34
+ onBlur,
35
+ Spinner,
36
+ name,
37
+ isSearchable,
38
+ placeholder,
39
+ onSelect,
40
+ options,
41
+ optionMaxHeight,
42
+ ...rest
43
+ } = getConfig({ ...props, id, isError }, isFocused);
44
+
45
+ const [selectedValue, setSelectedValue] = useState(defaultValue);
46
+ const [searchValue, setSearchValue] = useState("");
47
+
48
+ function handleSectionClick() {
49
+ if (disabled || !ref?.current) return;
50
+ setIsFocused(true);
51
+ ref.current.focus();
52
+ }
53
+
54
+ function handleFocus(e: FocusEvent<HTMLInputElement>) {
55
+ setIsFocused(true);
56
+ if (onFocus) onFocus(e);
57
+ }
58
+
59
+ function handleBlur() {
60
+ setIsFocused(false);
61
+
62
+ if (onBlur && ref.current) {
63
+ ref.current.blur();
64
+ }
65
+ }
66
+
67
+ const currentValue =
68
+ typeof baseValue === "string" ? baseValue : selectedValue;
69
+
70
+ const currentLabel =
71
+ options.find((option) => option.value === currentValue)?.label || "";
72
+
73
+ const placeholderDark = () => {
74
+ if (isSearchable) {
75
+ if (!isFocused && !!currentLabel) return true;
76
+ if (!isFocused && !currentLabel) return false;
77
+ if (isFocused) return false;
78
+ }
79
+
80
+ if (!isSearchable) {
81
+ if (!isFocused && !!currentLabel) return true;
82
+ if (!isFocused && !currentLabel) return false;
83
+ if (isFocused && !!currentLabel) return true;
84
+ if (isFocused && !currentLabel) return false;
85
+ }
86
+ };
87
+
88
+ const filteredOptions = options.filter((option) => {
89
+ if (isSearchable) {
90
+ return option.label.toLowerCase().includes(searchValue.toLowerCase());
91
+ } else {
92
+ return true;
93
+ }
94
+ });
95
+
96
+ return (
97
+ <>
98
+ <section
99
+ title={title}
100
+ style={style}
101
+ onClick={handleSectionClick}
102
+ className={`${className} placeholder_dark_${placeholderDark()}`}
103
+ >
104
+ {prefix}
105
+ {LeftIcon && <LeftIcon size={iconSize} strokeWidth={2.5} />}
106
+
107
+ <input
108
+ disabled={disabled || isLoading}
109
+ readOnly={!isSearchable}
110
+ value={searchValue || ""}
111
+ placeholder={currentLabel || placeholder}
112
+ ref={ref}
113
+ onFocus={handleFocus}
114
+ onBlur={() => setSearchValue("")}
115
+ {...rest}
116
+ onChange={(e) => setSearchValue(e.target.value)}
117
+ />
118
+
119
+ <input type="hidden" name={name} value={currentValue || ""} readOnly />
120
+
121
+ {isFocused && (
122
+ <ul
123
+ className="arkyn_select_content"
124
+ style={{ overflow: "auto", maxHeight: optionMaxHeight }}
125
+ >
126
+ {filteredOptions.map(({ label, value }) => (
127
+ <li
128
+ key={value}
129
+ className={currentValue === value ? "active" : ""}
130
+ onClick={() => {
131
+ if (selectedValue !== value) setSelectedValue(value);
132
+ else setSelectedValue("");
133
+ onSelect && onSelect({ label, value });
134
+ }}
135
+ >
136
+ {label} <Check />
137
+ </li>
138
+ ))}
139
+
140
+ {filteredOptions.length <= 0 && <p>Sem opções disponíveis</p>}
141
+ </ul>
142
+ )}
143
+
144
+ {!isLoading && (
145
+ <ChevronDown
146
+ className="arkyn_select_arrow"
147
+ size={iconSize}
148
+ strokeWidth={2.5}
149
+ />
150
+ )}
151
+ {isLoading && Spinner}
152
+ </section>
153
+
154
+ {isFocused && (
155
+ <aside className="arkyn_select_overlay" onClick={handleBlur} />
156
+ )}
157
+ </>
158
+ );
159
+ }
160
+
161
+ export { Select };