react-better-html 1.1.33 → 1.1.35
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/Button.d.ts +1 -0
- package/dist/components/Button.js +2 -2
- package/dist/components/Dropdown.d.ts +5 -2
- package/dist/components/Dropdown.js +4 -4
- package/dist/components/InputField.d.ts +2 -0
- package/dist/components/InputField.js +54 -2
- package/dist/components/Label.d.ts +8 -0
- package/dist/components/Label.js +14 -0
- package/dist/constants/countries.d.ts +2 -0
- package/dist/constants/countries.js +1481 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.js +3 -1
- package/dist/types/countries.d.ts +7 -0
- package/dist/types/countries.js +2 -0
- package/package.json +1 -1
|
@@ -104,7 +104,7 @@ const ButtonElement = styled_components_1.default.button.withConfig({
|
|
|
104
104
|
${(props) => props.hoverStyle}
|
|
105
105
|
}
|
|
106
106
|
`;
|
|
107
|
-
const ButtonComponent = function Button({ href, text, value, icon, iconPosition = "left", iconColor, iconSize, image, imagePosition = "left", imageWidth, imageHeight, loaderName, loaderSize, isLoading, disabled, isSmall, isSubmit, onClick, onClickWithValue, ...props }) {
|
|
107
|
+
const ButtonComponent = function Button({ href, text, value, download, icon, iconPosition = "left", iconColor, iconSize, image, imagePosition = "left", imageWidth, imageHeight, loaderName, loaderSize, isLoading, disabled, isSmall, isSubmit, onClick, onClickWithValue, ...props }) {
|
|
108
108
|
const theme = (0, BetterHtmlProvider_1.useTheme)();
|
|
109
109
|
const isLoadingHook = (0, BetterHtmlProvider_1.useLoader)(loaderName);
|
|
110
110
|
const betterHtmlContext = (0, BetterHtmlProvider_1.useBetterHtmlContext)();
|
|
@@ -122,7 +122,7 @@ const ButtonComponent = function Button({ href, text, value, icon, iconPosition
|
|
|
122
122
|
}, [onClick, onClickWithValue, value]);
|
|
123
123
|
const iconComponent = icon ? ((0, jsx_runtime_1.jsx)(Div_1.default.row, { height: 20, alignItems: "center", justifyContent: "center", children: (0, jsx_runtime_1.jsx)(Icon_1.default, { name: icon, color: iconColor ?? props.color ?? theme.colors.base, size: iconSize ?? parseInt(styledComponentStyles.normalStyle.fontSize?.toString() ?? "16") }) })) : undefined;
|
|
124
124
|
const imageComponent = image ? ((0, jsx_runtime_1.jsx)(Image_1.default, { name: image, color: iconColor ?? props.color ?? theme.colors.base, width: imageWidth ?? parseInt(styledComponentStyles.normalStyle.fontSize?.toString() ?? "16"), height: imageHeight })) : undefined;
|
|
125
|
-
return ((0, jsx_runtime_1.jsxs)(ButtonElement, { as: (href ? "a" : "button"), theme: theme, isSmall: isSmall, withText: text !== undefined, isLoading: isLoadingElement, disabled: disabled, href: href, type: isSubmit && !isLoadingElement ? "submit" : "button", onClick: !disabled && !isLoadingElement ? onClickElement : undefined, ...styledComponentStyles, ...dataProps, ...ariaProps, ...restProps, children: [(0, jsx_runtime_1.jsxs)(Div_1.default.row, { alignItems: "center", justifyContent: "center", gap: 10, pointerEvents: "none", opacity: isLoadingElement ? 0 : 1, transition: theme.styles.transition, children: [iconPosition === "left" && iconComponent, imagePosition === "left" && imageComponent, text, iconPosition === "right" && iconComponent, imagePosition === "right" && imageComponent] }), (0, jsx_runtime_1.jsx)(Div_1.default.row, { position: "absolute", width: "100%", height: "100%", top: 0, left: 0, pointerEvents: "none", alignItems: "center", justifyContent: "center", opacity: isLoadingElement ? 1 : 0, transition: theme.styles.transition, children: (0, jsx_runtime_1.jsx)(Loader_1.default, { color: props.color ?? theme.colors.base, size: loaderSize, disabled: !isLoadingElement }) })] }));
|
|
125
|
+
return ((0, jsx_runtime_1.jsxs)(ButtonElement, { as: (href ? "a" : "button"), theme: theme, isSmall: isSmall, withText: text !== undefined, isLoading: isLoadingElement, disabled: disabled, href: href, download: download, type: isSubmit && !isLoadingElement ? "submit" : "button", onClick: !disabled && !isLoadingElement ? onClickElement : undefined, ...styledComponentStyles, ...dataProps, ...ariaProps, ...restProps, children: [(0, jsx_runtime_1.jsxs)(Div_1.default.row, { alignItems: "center", justifyContent: "center", gap: 10, pointerEvents: "none", opacity: isLoadingElement ? 0 : 1, transition: theme.styles.transition, children: [iconPosition === "left" && iconComponent, imagePosition === "left" && imageComponent, text, iconPosition === "right" && iconComponent, imagePosition === "right" && imageComponent] }), (0, jsx_runtime_1.jsx)(Div_1.default.row, { position: "absolute", width: "100%", height: "100%", top: 0, left: 0, pointerEvents: "none", alignItems: "center", justifyContent: "center", opacity: isLoadingElement ? 1 : 0, transition: theme.styles.transition, children: (0, jsx_runtime_1.jsx)(Loader_1.default, { color: props.color ?? theme.colors.base, size: loaderSize, disabled: !isLoadingElement }) })] }));
|
|
126
126
|
};
|
|
127
127
|
ButtonComponent.secondary = function Secondary({ className, ...props }) {
|
|
128
128
|
const theme = (0, BetterHtmlProvider_1.useTheme)();
|
|
@@ -3,8 +3,8 @@ import { AnyOtherString, OmitProps } from "../types/app";
|
|
|
3
3
|
import { IconName } from "../types/icon";
|
|
4
4
|
import { DivProps } from "./Div";
|
|
5
5
|
export type DropdownOption<Value, Data = unknown> = {
|
|
6
|
-
label: string;
|
|
7
6
|
value: Value;
|
|
7
|
+
label: string;
|
|
8
8
|
disabled?: boolean;
|
|
9
9
|
searchValues?: string[];
|
|
10
10
|
data?: Data;
|
|
@@ -17,10 +17,13 @@ export type DropdownProps<Value, Data> = {
|
|
|
17
17
|
disabled?: boolean;
|
|
18
18
|
options: DropdownOption<Value, Data>[];
|
|
19
19
|
value?: Value;
|
|
20
|
+
defaultValue?: Value;
|
|
20
21
|
placeholder?: string;
|
|
21
22
|
leftIcon?: IconName | AnyOtherString;
|
|
23
|
+
inputFieldClassName?: string;
|
|
22
24
|
withSearch?: boolean;
|
|
23
25
|
withDebounce?: boolean;
|
|
26
|
+
withoutClearButton?: boolean;
|
|
24
27
|
/** @default 0.5s */
|
|
25
28
|
debounceDelay?: number;
|
|
26
29
|
debounceIsLoading?: boolean;
|
|
@@ -28,7 +31,7 @@ export type DropdownProps<Value, Data> = {
|
|
|
28
31
|
onChange?: (value: Value | undefined) => void;
|
|
29
32
|
onChangeSearch?: (query: string) => void;
|
|
30
33
|
renderOption?: (option: DropdownOption<Value, Data>, index: number, isSelected: boolean) => React.ReactNode;
|
|
31
|
-
} & OmitProps<DivProps<unknown>, "onChange">;
|
|
34
|
+
} & OmitProps<DivProps<unknown>, "onChange" | "defaultChecked">;
|
|
32
35
|
type DropdownComponentType = {
|
|
33
36
|
<Value, Data>(props: ComponentPropWithRef<HTMLDivElement, DropdownProps<Value, Data>>): React.ReactElement;
|
|
34
37
|
};
|
|
@@ -14,7 +14,7 @@ const Icon_1 = __importDefault(require("./Icon"));
|
|
|
14
14
|
const Button_1 = __importDefault(require("./Button"));
|
|
15
15
|
const Loader_1 = __importDefault(require("./Loader"));
|
|
16
16
|
const BetterHtmlProvider_1 = require("./BetterHtmlProvider");
|
|
17
|
-
const DropdownComponent = (0, react_1.forwardRef)(function Dropdown({ label, errorText, infoText, required, disabled, options, value: controlledValue, placeholder = "Select an option", leftIcon, withSearch, withDebounce, debounceDelay = 0.5, debounceIsLoading, debounceMinimumSymbolsRequired, onChange, onChangeSearch, renderOption, ...props }, ref) {
|
|
17
|
+
const DropdownComponent = (0, react_1.forwardRef)(function Dropdown({ label, errorText, infoText, required, disabled, options, value: controlledValue, defaultValue, placeholder = "Select an option", leftIcon, inputFieldClassName, withSearch, withDebounce, withoutClearButton, debounceDelay = 0.5, debounceIsLoading, debounceMinimumSymbolsRequired, onChange, onChangeSearch, renderOption, ...props }, ref) {
|
|
18
18
|
const theme = (0, BetterHtmlProvider_1.useTheme)();
|
|
19
19
|
const dropdownHolderRef = (0, react_1.useRef)(null);
|
|
20
20
|
const inputRef = (0, react_1.useRef)(null);
|
|
@@ -24,7 +24,7 @@ const DropdownComponent = (0, react_1.forwardRef)(function Dropdown({ label, err
|
|
|
24
24
|
const [searchQuery, setSearchQuery] = (0, react_1.useState)("");
|
|
25
25
|
const [_, debouncedSearchQuery, setDebouncedSearchQuery, isLoadingDebouncedSearchQuery] = (0, hooks_2.useDebounceState)("", debounceDelay);
|
|
26
26
|
const [focusedOptionIndex, setFocusedOptionIndex] = (0, react_1.useState)();
|
|
27
|
-
const [internalValue, setInternalValue] = (0, react_1.useState)();
|
|
27
|
+
const [internalValue, setInternalValue] = (0, react_1.useState)(defaultValue);
|
|
28
28
|
const value = controlledValue ?? internalValue;
|
|
29
29
|
const filteredOptions = (0, react_1.useMemo)(() => {
|
|
30
30
|
if (!searchQuery)
|
|
@@ -141,7 +141,7 @@ const DropdownComponent = (0, react_1.forwardRef)(function Dropdown({ label, err
|
|
|
141
141
|
}, [withDebounce, onChangeSearch, debouncedSearchQuery]);
|
|
142
142
|
const displayValue = withSearch && isFocused ? searchQuery : selectedOption?.label ?? "";
|
|
143
143
|
const withClearButton = isOpen && selectedOption;
|
|
144
|
-
return ((0, jsx_runtime_1.jsx)(Div_1.default.column, { width: "100%", position: "relative", userSelect: "none", ...props, ref: dropdownHolderRef, children: (0, jsx_runtime_1.jsxs)(Div_1.default.row, { position: "relative", width: "100%", children: [(0, jsx_runtime_1.jsx)(InputField_1.default, { label: label, errorText: errorText, infoText: infoText, required: required, disabled: disabled, readOnly: !withSearch, value: displayValue, placeholder: withSearch ? (selectedOption ? selectedOption.label : placeholder) : placeholder, leftIcon: leftIcon, className: `react-better-html-dropdown${isOpen ? " react-better-html-dropdown-open" : ""}`, zIndex: isOpen || isOpenLate ? 1001 : undefined, onClick: !disabled ? setIsOpen.toggle : undefined, onFocus: setIsFocused.setTrue, onBlur: setIsFocused.setFalse, onKeyDown: onKeyDownInputField, onChangeValue: withSearch ? onChangeValue : undefined, insideInputFieldComponent: (0, jsx_runtime_1.jsx)(Div_1.default, { position: "absolute", top: "100%", left: 0, width: "100%", maxHeight: 300, backgroundColor: theme.colors.backgroundContent, border: `1px solid ${isFocused ? theme.colors.primary : theme.colors.border}`, borderTop: "none", borderBottomLeftRadius: theme.styles.borderRadius, borderBottomRightRadius: theme.styles.borderRadius, boxShadow: "0px 10px 20px #00000020", zIndex: 1000, overflowY: "auto", opacity: !isOpen ? 0 : undefined, pointerEvents: !isOpen ? "none" : undefined, transform: `translateY(${!isOpen ? -10 : 0}px)`, transition: theme.styles.transition, role: "listbox", "aria-label": label, children: isLoadingDebouncedSearchQuery || debounceIsLoading ? ((0, jsx_runtime_1.jsx)(Div_1.default, { padding: `${theme.styles.space / 2}px ${theme.styles.space + theme.styles.gap}px`, children: (0, jsx_runtime_1.jsx)(Loader_1.default.text, {}) })) : filteredOptions.length ? (filteredOptions.map((option, index) => {
|
|
144
|
+
return ((0, jsx_runtime_1.jsx)(Div_1.default.column, { width: "100%", position: "relative", userSelect: "none", ...props, ref: dropdownHolderRef, children: (0, jsx_runtime_1.jsxs)(Div_1.default.row, { position: "relative", width: "100%", children: [(0, jsx_runtime_1.jsx)(InputField_1.default, { label: label, errorText: errorText, infoText: infoText, required: required, disabled: disabled, readOnly: !withSearch, value: displayValue, placeholder: withSearch ? (selectedOption ? selectedOption.label : placeholder) : placeholder, leftIcon: leftIcon, className: `react-better-html-dropdown${isOpen ? " react-better-html-dropdown-open" : ""}${inputFieldClassName ? ` ${inputFieldClassName}` : ""}`, zIndex: isOpen || isOpenLate ? 1001 : undefined, onClick: !disabled ? setIsOpen.toggle : undefined, onFocus: setIsFocused.setTrue, onBlur: setIsFocused.setFalse, onKeyDown: onKeyDownInputField, onChangeValue: withSearch ? onChangeValue : undefined, insideInputFieldComponent: (0, jsx_runtime_1.jsx)(Div_1.default, { position: "absolute", top: "100%", left: 0, width: "100%", maxHeight: 300, backgroundColor: theme.colors.backgroundContent, border: `1px solid ${isFocused ? theme.colors.primary : theme.colors.border}`, borderTop: "none", borderBottomLeftRadius: theme.styles.borderRadius, borderBottomRightRadius: theme.styles.borderRadius, boxShadow: "0px 10px 20px #00000020", zIndex: 1000, overflowY: "auto", opacity: !isOpen ? 0 : undefined, pointerEvents: !isOpen ? "none" : undefined, transform: `translateY(${!isOpen ? -10 : 0}px)`, transition: theme.styles.transition, role: "listbox", "aria-label": label, children: isLoadingDebouncedSearchQuery || debounceIsLoading ? ((0, jsx_runtime_1.jsx)(Div_1.default, { padding: `${theme.styles.space / 2}px ${theme.styles.space + theme.styles.gap}px`, children: (0, jsx_runtime_1.jsx)(Loader_1.default.text, {}) })) : filteredOptions.length ? (filteredOptions.map((option, index) => {
|
|
145
145
|
const isSelected = option.value === value;
|
|
146
146
|
const isDisabled = option.disabled;
|
|
147
147
|
const isFocused = index === focusedOptionIndex;
|
|
@@ -153,7 +153,7 @@ const DropdownComponent = (0, react_1.forwardRef)(function Dropdown({ label, err
|
|
|
153
153
|
})) : ((0, jsx_runtime_1.jsx)(Div_1.default, { padding: `${theme.styles.space / 2}px ${theme.styles.space + theme.styles.gap}px`, children: (0, jsx_runtime_1.jsx)(Text_1.default.unknown, { textAlign: "left", children: debounceMinimumSymbolsRequired !== undefined &&
|
|
154
154
|
searchQuery.length < debounceMinimumSymbolsRequired
|
|
155
155
|
? `Enter at least ${debounceMinimumSymbolsRequired} characters`
|
|
156
|
-
: "No options" }) })) }), role: "combobox", "aria-expanded": isOpen, "aria-controls": "dropdown-list", "aria-haspopup": "listbox", "aria-label": label, ref: inputRef }), (0, jsx_runtime_1.jsxs)(Div_1.default.row, { position: "absolute", top: 46 / 2 + (label ? 16 + theme.styles.gap / 2 : 0), right: theme.styles.space + 1, alignItems: "center", gap: theme.styles.gap, transform: "translateY(-50%)", pointerEvents: "none", filter: disabled ? "brightness(0.9)" : undefined, opacity: disabled ? 0.6 : undefined, zIndex: isOpen || isOpenLate ? 1001 : undefined, children: [(0, jsx_runtime_1.jsx)(Button_1.default.icon, { icon: "XMark", position: "relative", size: 10, iconSize: 14, opacity: !withClearButton ? 0 : undefined, pointerEvents: withClearButton ? "all" : undefined, onClick: onClickClearButton, disabled: !withClearButton }), (0, jsx_runtime_1.jsx)(Icon_1.default, { name: "chevronDown", position: "relative", size: 16, color: theme.colors.textSecondary, transform: `rotate(${isOpen ? 180 : 0}deg)`, transition: theme.styles.transition, pointerEvents: "none" })] })] }) }));
|
|
156
|
+
: "No options" }) })) }), role: "combobox", "aria-expanded": isOpen, "aria-controls": "dropdown-list", "aria-haspopup": "listbox", "aria-label": label, ref: inputRef }), (0, jsx_runtime_1.jsxs)(Div_1.default.row, { position: "absolute", top: 46 / 2 + (label ? 16 + theme.styles.gap / 2 : 0), right: theme.styles.space + 1, alignItems: "center", gap: theme.styles.gap, transform: "translateY(-50%)", pointerEvents: "none", filter: disabled ? "brightness(0.9)" : undefined, opacity: disabled ? 0.6 : undefined, zIndex: isOpen || isOpenLate ? 1001 : undefined, children: [!withoutClearButton && ((0, jsx_runtime_1.jsx)(Button_1.default.icon, { icon: "XMark", position: "relative", size: 10, iconSize: 14, opacity: !withClearButton ? 0 : undefined, pointerEvents: withClearButton ? "all" : undefined, onClick: onClickClearButton, disabled: !withClearButton })), (0, jsx_runtime_1.jsx)(Icon_1.default, { name: "chevronDown", position: "relative", size: 16, color: theme.colors.textSecondary, transform: `rotate(${isOpen ? 180 : 0}deg)`, transition: theme.styles.transition, pointerEvents: "none" })] })] }) }));
|
|
157
157
|
});
|
|
158
158
|
const Dropdown = (0, react_1.memo)(DropdownComponent);
|
|
159
159
|
exports.default = Dropdown;
|
|
@@ -21,6 +21,7 @@ type InputFieldComponentType = {
|
|
|
21
21
|
email: (props: ComponentPropWithRef<HTMLInputElement, InputFieldProps>) => React.ReactElement;
|
|
22
22
|
password: (props: ComponentPropWithRef<HTMLInputElement, InputFieldProps>) => React.ReactElement;
|
|
23
23
|
search: (props: ComponentPropWithRef<HTMLInputElement, InputFieldProps>) => React.ReactElement;
|
|
24
|
+
phoneNumber: (props: ComponentPropWithRef<HTMLInputElement, OmitProps<InputFieldProps, "type">>) => React.ReactElement;
|
|
24
25
|
};
|
|
25
26
|
declare const InputFieldComponent: InputFieldComponentType;
|
|
26
27
|
export type TextareaFieldProps = OmitProps<InputFieldProps, "type"> & OmitProps<React.ComponentProps<"textarea">, "style" | "ref">;
|
|
@@ -29,5 +30,6 @@ declare const InputField: typeof InputFieldComponent & {
|
|
|
29
30
|
email: typeof InputFieldComponent.email;
|
|
30
31
|
password: typeof InputFieldComponent.password;
|
|
31
32
|
search: typeof InputFieldComponent.search;
|
|
33
|
+
phoneNumber: typeof InputFieldComponent.phoneNumber;
|
|
32
34
|
};
|
|
33
35
|
export default InputField;
|
|
@@ -6,11 +6,15 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
7
7
|
const react_1 = require("react");
|
|
8
8
|
const styled_components_1 = __importDefault(require("styled-components"));
|
|
9
|
+
const countries_1 = require("../constants/countries");
|
|
9
10
|
const hooks_1 = require("../utils/hooks");
|
|
10
11
|
const Text_1 = __importDefault(require("./Text"));
|
|
11
12
|
const Div_1 = __importDefault(require("./Div"));
|
|
12
13
|
const Icon_1 = __importDefault(require("./Icon"));
|
|
13
14
|
const Button_1 = __importDefault(require("./Button"));
|
|
15
|
+
const Label_1 = __importDefault(require("./Label"));
|
|
16
|
+
const Dropdown_1 = __importDefault(require("./Dropdown"));
|
|
17
|
+
const Image_1 = __importDefault(require("./Image"));
|
|
14
18
|
const BetterHtmlProvider_1 = require("./BetterHtmlProvider");
|
|
15
19
|
const InputElement = styled_components_1.default.input.withConfig({
|
|
16
20
|
shouldForwardProp: (prop) => !["theme", "withLeftIcon", "withRightIcon", "normalStyle", "hoverStyle"].includes(prop),
|
|
@@ -43,6 +47,17 @@ const InputElement = styled_components_1.default.input.withConfig({
|
|
|
43
47
|
cursor: not-allowed;
|
|
44
48
|
}
|
|
45
49
|
|
|
50
|
+
&.react-better-html-phone-number-holder {
|
|
51
|
+
border-right: none;
|
|
52
|
+
border-top-right-radius: 0px;
|
|
53
|
+
border-bottom-right-radius: 0px;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
&.react-better-html-phone-number {
|
|
57
|
+
border-top-left-radius: 0px;
|
|
58
|
+
border-bottom-left-radius: 0px;
|
|
59
|
+
}
|
|
60
|
+
|
|
46
61
|
&.react-better-html-dropdown {
|
|
47
62
|
padding-right: ${(props) => props.theme.styles.space + 16 + props.theme.styles.space - 1}px;
|
|
48
63
|
|
|
@@ -114,7 +129,7 @@ const InputFieldComponent = (0, react_1.forwardRef)(function InputField({ label,
|
|
|
114
129
|
return;
|
|
115
130
|
onChangeValue?.(debouncedValue);
|
|
116
131
|
}, [withDebounce, onChangeValue, debouncedValue]);
|
|
117
|
-
return ((0, jsx_runtime_1.jsxs)(Div_1.default.column, { width: "100%", gap: theme.styles.gap / 2, ...styledComponentStylesWithExcluded, children: [label && (
|
|
132
|
+
return ((0, jsx_runtime_1.jsxs)(Div_1.default.column, { width: "100%", gap: theme.styles.gap / 2, ...styledComponentStylesWithExcluded, children: [label && (0, jsx_runtime_1.jsx)(Label_1.default, { text: label, required: required, isError: !!errorText }), (0, jsx_runtime_1.jsxs)(Div_1.default, { position: "relative", width: "100%", children: [leftIcon && ((0, jsx_runtime_1.jsx)(Icon_1.default, { name: leftIcon, position: "absolute", top: 46 / 2, left: theme.styles.space + 1, transform: "translateY(-50%)", pointerEvents: "none", zIndex: 1002 })), (0, jsx_runtime_1.jsx)(InputElement, { theme: theme, withLeftIcon: leftIcon !== undefined, withRightIcon: rightIcon !== undefined, required: required, placeholder: placeholder ?? label, onChange: onChangeElement, ...styledComponentStylesWithoutExcluded, ...dataProps, ...ariaProps, ...restProps, ref: ref }), rightIcon ? (onClickRightIcon ? ((0, jsx_runtime_1.jsx)(Button_1.default.icon, { icon: rightIcon, position: "absolute", top: 46 / 2, right: theme.styles.space + 1 - theme.styles.space / 2, transform: "translateY(-50%)", onClick: onClickRightIcon })) : ((0, jsx_runtime_1.jsx)(Icon_1.default, { name: rightIcon, position: "absolute", top: 46 / 2, right: theme.styles.space + 1, transform: "translateY(-50%)", pointerEvents: "none" }))) : undefined, insideInputFieldComponent] }), (errorText || infoText) && ((0, jsx_runtime_1.jsx)(Text_1.default, { as: "span", display: "block", fontSize: 14, color: errorText ? theme.colors.error : theme.colors.textSecondary, children: errorText || infoText }))] }));
|
|
118
133
|
});
|
|
119
134
|
InputFieldComponent.multiline = (0, react_1.forwardRef)(function Textarea({ label, errorText, infoText, onChange, onChangeValue, required, ...props }, ref) {
|
|
120
135
|
const theme = (0, BetterHtmlProvider_1.useTheme)();
|
|
@@ -126,7 +141,7 @@ InputFieldComponent.multiline = (0, react_1.forwardRef)(function Textarea({ labe
|
|
|
126
141
|
onChange?.(event);
|
|
127
142
|
onChangeValue?.(event.target.value);
|
|
128
143
|
}, [onChange, onChangeValue]);
|
|
129
|
-
return ((0, jsx_runtime_1.jsxs)(Div_1.default.column, { gap: theme.styles.gap / 2, children: [label && (
|
|
144
|
+
return ((0, jsx_runtime_1.jsxs)(Div_1.default.column, { gap: theme.styles.gap / 2, children: [label && (0, jsx_runtime_1.jsx)(Label_1.default, { text: label, required: required, isError: !!errorText }), (0, jsx_runtime_1.jsx)(TextareaElement, { theme: theme, required: required, onChange: onChangeElement, ...styledComponentStyles, ...dataProps, ...ariaProps, ...restProps, ref: ref }), (errorText || infoText) && ((0, jsx_runtime_1.jsx)(Text_1.default, { as: "span", display: "block", marginTop: theme.styles.gap / 2, color: errorText ? theme.colors.error : theme.colors.textSecondary, fontSize: 14, children: errorText || infoText }))] }));
|
|
130
145
|
});
|
|
131
146
|
InputFieldComponent.email = (0, react_1.forwardRef)(function Email({ ...props }, ref) {
|
|
132
147
|
return ((0, jsx_runtime_1.jsx)(InputFieldComponent, { type: "email", placeholder: "your@email.here", autoComplete: "email", autoCorrect: "off", autoCapitalize: "off", ref: ref, ...props }));
|
|
@@ -138,9 +153,46 @@ InputFieldComponent.password = (0, react_1.forwardRef)(function Email({ ...props
|
|
|
138
153
|
InputFieldComponent.search = (0, react_1.forwardRef)(function Email({ ...props }, ref) {
|
|
139
154
|
return (0, jsx_runtime_1.jsx)(InputFieldComponent, { leftIcon: "magnifyingGlass", placeholder: "Search...", ref: ref, ...props });
|
|
140
155
|
});
|
|
156
|
+
InputFieldComponent.phoneNumber = (0, react_1.forwardRef)(function Email({ value, onChangeValue, ...props }, ref) {
|
|
157
|
+
const theme = (0, BetterHtmlProvider_1.useTheme)();
|
|
158
|
+
const [dropdownValue, setDropdownValue] = (0, react_1.useState)();
|
|
159
|
+
const [inputFieldValue, setInputFieldValue] = (0, react_1.useState)(value?.toString() ?? "");
|
|
160
|
+
const renderOption = (0, react_1.useCallback)((option, index, isSelected) => ((0, jsx_runtime_1.jsxs)(Div_1.default.row, { alignItems: "center", gap: theme.styles.gap, children: [(0, jsx_runtime_1.jsx)(Image_1.default, { src: `https://flagcdn.com/w80/${option.data?.code.toString().toLowerCase()}.webp`, width: 20 }), (0, jsx_runtime_1.jsx)(Text_1.default, { children: option.label })] })), []);
|
|
161
|
+
const onChangeValueElement = (0, react_1.useCallback)((value) => {
|
|
162
|
+
const readyValue = value.replace(/\D/g, "");
|
|
163
|
+
setInputFieldValue(readyValue);
|
|
164
|
+
onChangeValue?.(dropdownValue ? `+${dropdownValue}${readyValue}` : readyValue);
|
|
165
|
+
}, [onChangeValue, dropdownValue]);
|
|
166
|
+
const options = (0, react_1.useMemo)(() => countries_1.countries.map((country) => ({
|
|
167
|
+
value: country.phoneNumberExtension,
|
|
168
|
+
label: `+${country.phoneNumberExtension}`,
|
|
169
|
+
data: country,
|
|
170
|
+
})), []);
|
|
171
|
+
const defaultValue = (0, react_1.useMemo)(() => {
|
|
172
|
+
const thisTimeZone = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
173
|
+
const initialDefaultValue = options.find((option) => option.data?.timeZone === thisTimeZone)?.value ?? "";
|
|
174
|
+
setDropdownValue(initialDefaultValue);
|
|
175
|
+
return initialDefaultValue;
|
|
176
|
+
}, [options]);
|
|
177
|
+
(0, react_1.useEffect)(() => {
|
|
178
|
+
if (value === undefined || value === null)
|
|
179
|
+
return;
|
|
180
|
+
const newValue = value.toString();
|
|
181
|
+
const country = countries_1.countries.find((country) => country.phoneNumberExtension ===
|
|
182
|
+
newValue.slice(newValue.startsWith("+") ? 1 : 0, country.phoneNumberExtension.length + (newValue.startsWith("+") ? 1 : 0)));
|
|
183
|
+
if (!country) {
|
|
184
|
+
setInputFieldValue(newValue);
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
setDropdownValue(country.phoneNumberExtension);
|
|
188
|
+
setInputFieldValue(newValue.slice(country?.phoneNumberExtension.length + 1));
|
|
189
|
+
}, [value]);
|
|
190
|
+
return ((0, jsx_runtime_1.jsxs)(Div_1.default.row, { children: [(0, jsx_runtime_1.jsx)(Dropdown_1.default, { options: options, renderOption: renderOption, width: 130, withSearch: true, placeholder: "+00", inputFieldClassName: "react-better-html-phone-number-holder", defaultValue: defaultValue, value: dropdownValue, onChange: setDropdownValue, withoutClearButton: true }), (0, jsx_runtime_1.jsx)(InputFieldComponent, { placeholder: "Phone number", className: "react-better-html-phone-number", value: inputFieldValue, onChangeValue: onChangeValueElement, ref: ref, ...props })] }));
|
|
191
|
+
});
|
|
141
192
|
const InputField = (0, react_1.memo)(InputFieldComponent);
|
|
142
193
|
InputField.multiline = InputFieldComponent.multiline;
|
|
143
194
|
InputField.email = InputFieldComponent.email;
|
|
144
195
|
InputField.password = InputFieldComponent.password;
|
|
145
196
|
InputField.search = InputFieldComponent.search;
|
|
197
|
+
InputField.phoneNumber = InputFieldComponent.phoneNumber;
|
|
146
198
|
exports.default = InputField;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
type LabelProps = {
|
|
2
|
+
text?: string;
|
|
3
|
+
required?: boolean;
|
|
4
|
+
isError?: boolean;
|
|
5
|
+
};
|
|
6
|
+
declare function Label({ text, required, isError }: LabelProps): import("react/jsx-runtime").JSX.Element;
|
|
7
|
+
declare const _default: import("react").MemoExoticComponent<typeof Label>;
|
|
8
|
+
export default _default;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
7
|
+
const react_1 = require("react");
|
|
8
|
+
const Text_1 = __importDefault(require("./Text"));
|
|
9
|
+
const BetterHtmlProvider_1 = require("./BetterHtmlProvider");
|
|
10
|
+
function Label({ text, required, isError }) {
|
|
11
|
+
const theme = (0, BetterHtmlProvider_1.useTheme)();
|
|
12
|
+
return ((0, jsx_runtime_1.jsxs)(Text_1.default, { as: "label", height: 16, fontSize: 14, color: isError ? theme.colors.error : theme.colors.textSecondary, children: [text, required && ((0, jsx_runtime_1.jsxs)(Text_1.default, { as: "span", fontSize: 16, color: theme.colors.error, children: [" ", "*"] }))] }));
|
|
13
|
+
}
|
|
14
|
+
exports.default = (0, react_1.memo)(Label);
|