react-better-html 1.1.11 → 1.1.12
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.js +2 -2
- package/dist/components/Chip.d.ts +20 -0
- package/dist/components/Chip.js +20 -0
- package/dist/components/Dropdown.d.ts +36 -0
- package/dist/components/Dropdown.js +157 -0
- package/dist/components/InputField.d.ts +33 -0
- package/dist/components/InputField.js +146 -0
- package/dist/components/ToggleInput.d.ts +19 -0
- package/dist/components/ToggleInput.js +122 -0
- package/dist/constants/icons.js +50 -0
- package/dist/index.d.ts +5 -1
- package/dist/index.js +9 -1
- package/dist/types/icon.d.ts +1 -1
- package/dist/utils/hooks.d.ts +14 -1
- package/dist/utils/hooks.js +67 -3
- package/package.json +1 -1
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { ComponentPropWithRef } from "../types/components";
|
|
2
|
+
import { OmitProps } from "../types/app";
|
|
3
|
+
type ChipProps = {
|
|
4
|
+
text: string;
|
|
5
|
+
/** @default theme.colors.textPrimary */
|
|
6
|
+
color?: string;
|
|
7
|
+
/** @default backgroundSecondary */
|
|
8
|
+
backgroundColor?: string;
|
|
9
|
+
/** @default theme.styles.borderRadius / 1.3 */
|
|
10
|
+
borderRadius?: number;
|
|
11
|
+
};
|
|
12
|
+
type ChipComponentType = {
|
|
13
|
+
(props: ComponentPropWithRef<HTMLDivElement, ChipProps>): React.ReactElement;
|
|
14
|
+
circle: (props: ComponentPropWithRef<HTMLDivElement, OmitProps<ChipProps, "borderRadius">>) => React.ReactElement;
|
|
15
|
+
};
|
|
16
|
+
declare const ChipComponent: ChipComponentType;
|
|
17
|
+
declare const Chip: typeof ChipComponent & {
|
|
18
|
+
circle: typeof ChipComponent.circle;
|
|
19
|
+
};
|
|
20
|
+
export default Chip;
|
|
@@ -0,0 +1,20 @@
|
|
|
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 Div_1 = __importDefault(require("./Div"));
|
|
9
|
+
const Text_1 = __importDefault(require("./Text"));
|
|
10
|
+
const BetterHtmlProvider_1 = require("./BetterHtmlProvider");
|
|
11
|
+
const ChipComponent = (0, react_1.forwardRef)(function Chip({ text, color, backgroundColor, borderRadius }, ref) {
|
|
12
|
+
const theme = (0, BetterHtmlProvider_1.useTheme)();
|
|
13
|
+
return ((0, jsx_runtime_1.jsx)(Div_1.default, { width: "fit-content", backgroundColor: backgroundColor ?? theme.colors.backgroundSecondary, borderRadius: borderRadius ?? theme.styles.borderRadius / 1.3, paddingBlock: theme.styles.gap, paddingInline: theme.styles.space, ref: ref, children: (0, jsx_runtime_1.jsx)(Text_1.default, { color: color ?? theme.colors.textPrimary, children: text }) }));
|
|
14
|
+
});
|
|
15
|
+
ChipComponent.circle = (0, react_1.forwardRef)(function Circle(props, ref) {
|
|
16
|
+
return (0, jsx_runtime_1.jsx)(ChipComponent, { borderRadius: 999, ref: ref, ...props });
|
|
17
|
+
});
|
|
18
|
+
const Chip = (0, react_1.memo)(ChipComponent);
|
|
19
|
+
Chip.circle = ChipComponent.circle;
|
|
20
|
+
exports.default = Chip;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { ComponentPropWithRef } from "../types/components";
|
|
2
|
+
import { OmitProps } from "../types/app";
|
|
3
|
+
import { IconName } from "../types/icon";
|
|
4
|
+
import { DivProps } from "./Div";
|
|
5
|
+
export type DropdownOption<Value, Data = unknown> = {
|
|
6
|
+
label: string;
|
|
7
|
+
value: Value;
|
|
8
|
+
disabled?: boolean;
|
|
9
|
+
searchValues?: string[];
|
|
10
|
+
data?: Data;
|
|
11
|
+
};
|
|
12
|
+
type DropdownProps<Value, Data> = {
|
|
13
|
+
label?: string;
|
|
14
|
+
errorText?: string;
|
|
15
|
+
infoText?: string;
|
|
16
|
+
required?: boolean;
|
|
17
|
+
disabled?: boolean;
|
|
18
|
+
options: DropdownOption<Value, Data>[];
|
|
19
|
+
value?: Value;
|
|
20
|
+
placeholder?: string;
|
|
21
|
+
leftIcon?: IconName;
|
|
22
|
+
withSearch?: boolean;
|
|
23
|
+
withDebounce?: boolean;
|
|
24
|
+
/** @default 0.5s */
|
|
25
|
+
debounceDelay?: number;
|
|
26
|
+
debounceIsLoading?: number;
|
|
27
|
+
onChange?: (value: Value | undefined) => void;
|
|
28
|
+
onChangeSearch?: (query: string) => void;
|
|
29
|
+
renderOption?: (option: DropdownOption<Value, Data>, index: number) => React.ReactNode;
|
|
30
|
+
} & OmitProps<DivProps<unknown>, "onChange">;
|
|
31
|
+
type DropdownComponentType = {
|
|
32
|
+
<Value, Data>(props: ComponentPropWithRef<HTMLDivElement, DropdownProps<Value, Data>>): React.ReactElement;
|
|
33
|
+
};
|
|
34
|
+
declare const DropdownComponent: DropdownComponentType;
|
|
35
|
+
declare const Dropdown: typeof DropdownComponent & {};
|
|
36
|
+
export default Dropdown;
|
|
@@ -0,0 +1,157 @@
|
|
|
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 hooks_1 = require("../utils/hooks");
|
|
9
|
+
const hooks_2 = require("../utils/hooks");
|
|
10
|
+
const Text_1 = __importDefault(require("./Text"));
|
|
11
|
+
const Div_1 = __importDefault(require("./Div"));
|
|
12
|
+
const InputField_1 = __importDefault(require("./InputField"));
|
|
13
|
+
const Icon_1 = __importDefault(require("./Icon"));
|
|
14
|
+
const Button_1 = __importDefault(require("./Button"));
|
|
15
|
+
const BetterHtmlProvider_1 = require("./BetterHtmlProvider");
|
|
16
|
+
const Loader_1 = __importDefault(require("./Loader"));
|
|
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, onChange, onChangeSearch, renderOption, ...props }, ref) {
|
|
18
|
+
const theme = (0, BetterHtmlProvider_1.useTheme)();
|
|
19
|
+
const dropdownHolderRef = (0, react_1.useRef)(null);
|
|
20
|
+
const inputRef = (0, react_1.useRef)(null);
|
|
21
|
+
const [isOpen, setIsOpen] = (0, hooks_1.useBooleanState)();
|
|
22
|
+
const [isOpenLate, setIsOpenLate] = (0, hooks_1.useBooleanState)();
|
|
23
|
+
const [isFocused, setIsFocused] = (0, hooks_1.useBooleanState)();
|
|
24
|
+
const [searchQuery, setSearchQuery] = (0, react_1.useState)("");
|
|
25
|
+
const [_, debouncedSearchQuery, setDebouncedSearchQuery, isLoadingDebouncedSearchQuery] = (0, hooks_2.useDebounceState)("", debounceDelay);
|
|
26
|
+
const [focusedOptionIndex, setFocusedOptionIndex] = (0, react_1.useState)();
|
|
27
|
+
const [internalValue, setInternalValue] = (0, react_1.useState)();
|
|
28
|
+
const value = controlledValue ?? internalValue;
|
|
29
|
+
const filteredOptions = (0, react_1.useMemo)(() => {
|
|
30
|
+
if (!searchQuery)
|
|
31
|
+
return options;
|
|
32
|
+
const query = searchQuery.toLowerCase();
|
|
33
|
+
return options.filter((option) => option.label.toLowerCase().includes(query) ||
|
|
34
|
+
option.searchValues?.some((value) => value.toLowerCase().includes(query)));
|
|
35
|
+
}, [options, searchQuery]);
|
|
36
|
+
const onKeyDownInputField = (0, react_1.useCallback)((event) => {
|
|
37
|
+
if (event.key === "Enter" || (!withSearch && event.key === " ")) {
|
|
38
|
+
event.preventDefault();
|
|
39
|
+
if (!disabled) {
|
|
40
|
+
setIsOpen.toggle();
|
|
41
|
+
if (isOpen && filteredOptions.length > 0 && focusedOptionIndex !== undefined) {
|
|
42
|
+
const option = filteredOptions[focusedOptionIndex];
|
|
43
|
+
if (!option.disabled) {
|
|
44
|
+
if (controlledValue === undefined)
|
|
45
|
+
setInternalValue(option.value);
|
|
46
|
+
onChange?.(option.value);
|
|
47
|
+
setIsOpen.setFalse();
|
|
48
|
+
inputRef.current?.blur();
|
|
49
|
+
setSearchQuery("");
|
|
50
|
+
setFocusedOptionIndex(undefined);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
else if (event.key === "Escape") {
|
|
56
|
+
setIsOpen.setFalse();
|
|
57
|
+
setFocusedOptionIndex(undefined);
|
|
58
|
+
}
|
|
59
|
+
else if (event.key === "ArrowDown") {
|
|
60
|
+
event.preventDefault();
|
|
61
|
+
if (!isOpen)
|
|
62
|
+
setIsOpen.setTrue();
|
|
63
|
+
if (filteredOptions.length > 0) {
|
|
64
|
+
setFocusedOptionIndex((oldValue) => oldValue === undefined ? 0 : (oldValue + 1) % filteredOptions.length);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
else if (event.key === "ArrowUp") {
|
|
68
|
+
event.preventDefault();
|
|
69
|
+
if (!isOpen)
|
|
70
|
+
setIsOpen.setTrue();
|
|
71
|
+
if (filteredOptions.length > 0) {
|
|
72
|
+
setFocusedOptionIndex((oldValue) => oldValue === undefined
|
|
73
|
+
? filteredOptions.length - 1
|
|
74
|
+
: (oldValue - 1 + filteredOptions.length) % filteredOptions.length);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}, [disabled, withSearch, isOpen, filteredOptions, focusedOptionIndex, controlledValue, onChange]);
|
|
78
|
+
const onClickOption = (0, react_1.useCallback)((option) => {
|
|
79
|
+
if (!option.disabled) {
|
|
80
|
+
if (controlledValue === undefined)
|
|
81
|
+
setInternalValue(option.value);
|
|
82
|
+
onChange?.(option.value);
|
|
83
|
+
setIsOpen.setFalse();
|
|
84
|
+
inputRef.current?.blur();
|
|
85
|
+
setSearchQuery("");
|
|
86
|
+
setFocusedOptionIndex(undefined);
|
|
87
|
+
}
|
|
88
|
+
}, [onChange, controlledValue]);
|
|
89
|
+
const onClickClearButton = (0, react_1.useCallback)((event) => {
|
|
90
|
+
event.stopPropagation();
|
|
91
|
+
if (controlledValue === undefined)
|
|
92
|
+
setInternalValue(undefined);
|
|
93
|
+
onChange?.(undefined);
|
|
94
|
+
setIsOpen.setFalse();
|
|
95
|
+
inputRef.current?.blur();
|
|
96
|
+
setSearchQuery("");
|
|
97
|
+
setFocusedOptionIndex(undefined);
|
|
98
|
+
}, [controlledValue, onChange]);
|
|
99
|
+
const onChangeValue = (0, react_1.useCallback)((newValue) => {
|
|
100
|
+
setSearchQuery(newValue);
|
|
101
|
+
if (withDebounce)
|
|
102
|
+
setDebouncedSearchQuery(newValue);
|
|
103
|
+
else
|
|
104
|
+
onChangeSearch?.(newValue);
|
|
105
|
+
}, [withDebounce, onChangeSearch]);
|
|
106
|
+
const selectedOption = (0, react_1.useMemo)(() => options.find((option) => option.value === value), [options, value]);
|
|
107
|
+
(0, react_1.useEffect)(() => {
|
|
108
|
+
if (isOpen) {
|
|
109
|
+
setIsOpenLate.setTrue();
|
|
110
|
+
if (withSearch && inputRef.current)
|
|
111
|
+
inputRef.current.focus();
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
const timeout = setTimeout(setIsOpenLate.setFalse, 0.2 * 1000);
|
|
115
|
+
return () => {
|
|
116
|
+
clearTimeout(timeout);
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
}, [isOpen, withSearch]);
|
|
120
|
+
(0, react_1.useEffect)(() => {
|
|
121
|
+
setFocusedOptionIndex(undefined);
|
|
122
|
+
}, [filteredOptions]);
|
|
123
|
+
(0, react_1.useEffect)(() => {
|
|
124
|
+
const handleClickOutside = (event) => {
|
|
125
|
+
if (dropdownHolderRef.current && !dropdownHolderRef.current.contains(event.target)) {
|
|
126
|
+
setIsOpen.setFalse();
|
|
127
|
+
setSearchQuery("");
|
|
128
|
+
setFocusedOptionIndex(undefined);
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
if (isOpen) {
|
|
132
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
133
|
+
}
|
|
134
|
+
return () => {
|
|
135
|
+
document.removeEventListener("mousedown", handleClickOutside);
|
|
136
|
+
};
|
|
137
|
+
}, [isOpen]);
|
|
138
|
+
(0, react_1.useEffect)(() => {
|
|
139
|
+
if (!withDebounce)
|
|
140
|
+
return;
|
|
141
|
+
onChangeSearch?.(debouncedSearchQuery);
|
|
142
|
+
}, [withDebounce, onChangeSearch, debouncedSearchQuery]);
|
|
143
|
+
const displayValue = withSearch && isFocused ? searchQuery : selectedOption?.label ?? "";
|
|
144
|
+
const withClearButton = isOpen && selectedOption;
|
|
145
|
+
return ((0, jsx_runtime_1.jsx)(Div_1.default.column, { 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) => {
|
|
146
|
+
const isSelected = option.value === value;
|
|
147
|
+
const isDisabled = option.disabled;
|
|
148
|
+
const isFocused = index === focusedOptionIndex;
|
|
149
|
+
return ((0, jsx_runtime_1.jsx)(Div_1.default, { color: isDisabled
|
|
150
|
+
? theme.colors.textSecondary + "80"
|
|
151
|
+
: isSelected
|
|
152
|
+
? theme.colors.base
|
|
153
|
+
: theme.colors.textPrimary, backgroundColor: isSelected ? theme.colors.primary : theme.colors.backgroundContent, filter: isFocused ? (isDisabled ? "brightness(0.95)" : "brightness(0.9)") : undefined, filterHover: focusedOptionIndex === undefined && !isDisabled ? "brightness(0.9)" : undefined, cursor: isDisabled ? "not-allowed" : "pointer", padding: `${theme.styles.space / 2}px ${theme.styles.space + theme.styles.gap}px`, value: option, onClickWithValue: onClickOption, onMouseMove: () => setFocusedOptionIndex(undefined), role: "option", "aria-selected": isSelected, "aria-disabled": isDisabled, children: renderOption ? renderOption(option, index) : (0, jsx_runtime_1.jsx)(Text_1.default, { children: option.label }) }, JSON.stringify(option)));
|
|
154
|
+
})) : ((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: "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" })] })] }) }));
|
|
155
|
+
});
|
|
156
|
+
const Dropdown = (0, react_1.memo)(DropdownComponent);
|
|
157
|
+
exports.default = Dropdown;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { ComponentHoverStyle, ComponentPropWithRef, ComponentStyle } from "../types/components";
|
|
3
|
+
import { OmitProps } from "../types/app";
|
|
4
|
+
import { IconName } from "../types/icon";
|
|
5
|
+
type InputFieldProps = {
|
|
6
|
+
label?: string;
|
|
7
|
+
errorText?: string;
|
|
8
|
+
infoText?: string;
|
|
9
|
+
leftIcon?: IconName;
|
|
10
|
+
rightIcon?: IconName;
|
|
11
|
+
insideInputFieldComponent?: React.ReactNode;
|
|
12
|
+
withDebounce?: boolean;
|
|
13
|
+
/** @default 0.5s */
|
|
14
|
+
debounceDelay?: number;
|
|
15
|
+
onChangeValue?: (value: string) => void;
|
|
16
|
+
onClickRightIcon?: () => void;
|
|
17
|
+
} & OmitProps<React.ComponentProps<"input">, "style"> & ComponentStyle & ComponentHoverStyle;
|
|
18
|
+
type InputFieldComponentType = {
|
|
19
|
+
(props: ComponentPropWithRef<HTMLInputElement, InputFieldProps>): React.ReactElement;
|
|
20
|
+
multiline: (props: ComponentPropWithRef<HTMLTextAreaElement, TextareaFieldProps>) => React.ReactElement;
|
|
21
|
+
email: (props: ComponentPropWithRef<HTMLInputElement, InputFieldProps>) => React.ReactElement;
|
|
22
|
+
password: (props: ComponentPropWithRef<HTMLInputElement, InputFieldProps>) => React.ReactElement;
|
|
23
|
+
search: (props: ComponentPropWithRef<HTMLInputElement, InputFieldProps>) => React.ReactElement;
|
|
24
|
+
};
|
|
25
|
+
declare const InputFieldComponent: InputFieldComponentType;
|
|
26
|
+
type TextareaFieldProps = OmitProps<InputFieldProps, "type"> & OmitProps<React.ComponentProps<"textarea">, "style">;
|
|
27
|
+
declare const InputField: typeof InputFieldComponent & {
|
|
28
|
+
multiline: typeof InputFieldComponent.multiline;
|
|
29
|
+
email: typeof InputFieldComponent.email;
|
|
30
|
+
password: typeof InputFieldComponent.password;
|
|
31
|
+
search: typeof InputFieldComponent.search;
|
|
32
|
+
};
|
|
33
|
+
export default InputField;
|
|
@@ -0,0 +1,146 @@
|
|
|
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 styled_components_1 = __importDefault(require("styled-components"));
|
|
9
|
+
const hooks_1 = require("../utils/hooks");
|
|
10
|
+
const Text_1 = __importDefault(require("./Text"));
|
|
11
|
+
const Div_1 = __importDefault(require("./Div"));
|
|
12
|
+
const Icon_1 = __importDefault(require("./Icon"));
|
|
13
|
+
const Button_1 = __importDefault(require("./Button"));
|
|
14
|
+
const BetterHtmlProvider_1 = require("./BetterHtmlProvider");
|
|
15
|
+
const InputElement = styled_components_1.default.input.withConfig({
|
|
16
|
+
shouldForwardProp: (prop) => !["theme", "withLeftIcon", "withRightIcon", "normalStyle", "hoverStyle"].includes(prop),
|
|
17
|
+
}) `
|
|
18
|
+
position: relative;
|
|
19
|
+
width: 100%;
|
|
20
|
+
font-family: ${(props) => props.theme.styles.fontFamily};
|
|
21
|
+
font-size: 16px;
|
|
22
|
+
line-height: 20px;
|
|
23
|
+
color: ${(props) => props.theme.colors.textPrimary};
|
|
24
|
+
background: ${(props) => props.theme.colors.backgroundContent};
|
|
25
|
+
border: 1px solid ${(props) => props.theme.colors.border};
|
|
26
|
+
border-radius: ${(props) => props.theme.styles.borderRadius}px;
|
|
27
|
+
outline: none;
|
|
28
|
+
padding: ${(props) => `${(props.theme.styles.space + props.theme.styles.gap) / 2}px ${props.theme.styles.space + props.theme.styles.gap}px`};
|
|
29
|
+
padding-left: ${(props) => props.withLeftIcon ? `${props.theme.styles.space + 16 + props.theme.styles.space - 1}px` : undefined};
|
|
30
|
+
padding-right: ${(props) => props.withRightIcon ? `${props.theme.styles.space + 16 + props.theme.styles.space - 1}px` : undefined};
|
|
31
|
+
transition: ${(props) => props.theme.styles.transition};
|
|
32
|
+
|
|
33
|
+
&::placeholder {
|
|
34
|
+
color: ${(props) => props.theme.colors.textSecondary}80;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
&:focus {
|
|
38
|
+
border-color: ${(props) => props.theme.colors.primary};
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
&:disabled {
|
|
42
|
+
filter: brightness(0.9);
|
|
43
|
+
cursor: not-allowed;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
&.react-better-html-dropdown {
|
|
47
|
+
padding-right: ${(props) => props.theme.styles.space + 16 + props.theme.styles.space - 1}px;
|
|
48
|
+
|
|
49
|
+
&.react-better-html-dropdown-open {
|
|
50
|
+
border-bottom-left-radius: 0px;
|
|
51
|
+
border-bottom-right-radius: 0px;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
${(props) => props.normalStyle}
|
|
56
|
+
|
|
57
|
+
&:hover {
|
|
58
|
+
${(props) => props.hoverStyle}
|
|
59
|
+
}
|
|
60
|
+
`;
|
|
61
|
+
const TextareaElement = styled_components_1.default.textarea.withConfig({
|
|
62
|
+
shouldForwardProp: (prop) => !["normalStyle", "hoverStyle"].includes(prop),
|
|
63
|
+
}) `
|
|
64
|
+
width: 100%;
|
|
65
|
+
min-height: 3lh;
|
|
66
|
+
max-height: 8lh;
|
|
67
|
+
font-family: ${(props) => props.theme.styles.fontFamily};
|
|
68
|
+
font-size: 16px;
|
|
69
|
+
line-height: 20px;
|
|
70
|
+
color: ${(props) => props.theme.colors.textPrimary};
|
|
71
|
+
background: ${(props) => props.theme.colors.backgroundContent};
|
|
72
|
+
border: 1px solid ${(props) => props.theme.colors.border};
|
|
73
|
+
border-radius: ${(props) => props.theme.styles.borderRadius}px;
|
|
74
|
+
outline: none;
|
|
75
|
+
padding: ${(props) => `${(props.theme.styles.gap + props.theme.styles.space) / 2}px ${props.theme.styles.space + props.theme.styles.gap}px`};
|
|
76
|
+
resize: vertical;
|
|
77
|
+
transition: border-color ${(props) => props.theme.styles.transition};
|
|
78
|
+
|
|
79
|
+
&::placeholder {
|
|
80
|
+
color: ${(props) => props.theme.colors.textSecondary}80;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
&:focus {
|
|
84
|
+
border-color: ${(props) => props.theme.colors.primary};
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
${(props) => props.normalStyle}
|
|
88
|
+
|
|
89
|
+
&:hover {
|
|
90
|
+
${(props) => props.hoverStyle}
|
|
91
|
+
}
|
|
92
|
+
`;
|
|
93
|
+
const InputFieldComponent = (0, react_1.forwardRef)(function InputField({ label, errorText, infoText, leftIcon, rightIcon, insideInputFieldComponent, withDebounce, debounceDelay = 0.5, onChange, onChangeValue, onClickRightIcon, required, ...props }, ref) {
|
|
94
|
+
const theme = (0, BetterHtmlProvider_1.useTheme)();
|
|
95
|
+
const [_, debouncedValue, setDebouncedValue] = (0, hooks_1.useDebounceState)(props.value?.toString() ?? "", debounceDelay);
|
|
96
|
+
const styledComponentStylesWithoutExcluded = (0, hooks_1.useStyledComponentStyles)(props, theme, true);
|
|
97
|
+
const styledComponentStylesWithExcluded = (0, hooks_1.useComponentPropsWithExcludedStyle)(props);
|
|
98
|
+
const dataProps = (0, hooks_1.useComponentPropsWithPrefix)(props, "data");
|
|
99
|
+
const ariaProps = (0, hooks_1.useComponentPropsWithPrefix)(props, "aria");
|
|
100
|
+
const restProps = (0, hooks_1.useComponentPropsWithoutStyle)(props);
|
|
101
|
+
const onChangeElement = (0, react_1.useCallback)((event) => {
|
|
102
|
+
const newValue = event.target.value;
|
|
103
|
+
if (withDebounce) {
|
|
104
|
+
onChange?.(event);
|
|
105
|
+
setDebouncedValue(newValue);
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
onChange?.(event);
|
|
109
|
+
onChangeValue?.(newValue);
|
|
110
|
+
}
|
|
111
|
+
}, [onChange, onChangeValue, withDebounce]);
|
|
112
|
+
(0, react_1.useEffect)(() => {
|
|
113
|
+
if (!withDebounce)
|
|
114
|
+
return;
|
|
115
|
+
onChangeValue?.(debouncedValue);
|
|
116
|
+
}, [withDebounce, onChangeValue, debouncedValue]);
|
|
117
|
+
return ((0, jsx_runtime_1.jsxs)(Div_1.default.column, { width: "100%", gap: theme.styles.gap / 2, ...styledComponentStylesWithExcluded, children: [label && ((0, jsx_runtime_1.jsxs)(Text_1.default, { as: "label", height: 16, fontSize: 14, color: errorText ? theme.colors.error : theme.colors.textSecondary, children: [label, required && ((0, jsx_runtime_1.jsxs)(Text_1.default, { as: "span", fontSize: 16, color: theme.colors.error, children: [" ", "*"] }))] })), (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, 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
|
+
});
|
|
119
|
+
InputFieldComponent.multiline = (0, react_1.forwardRef)(function Textarea({ label, errorText, infoText, onChange, onChangeValue, required, ...props }, ref) {
|
|
120
|
+
const theme = (0, BetterHtmlProvider_1.useTheme)();
|
|
121
|
+
const styledComponentStyles = (0, hooks_1.useStyledComponentStyles)(props, theme);
|
|
122
|
+
const dataProps = (0, hooks_1.useComponentPropsWithPrefix)(props, "data");
|
|
123
|
+
const ariaProps = (0, hooks_1.useComponentPropsWithPrefix)(props, "aria");
|
|
124
|
+
const restProps = (0, hooks_1.useComponentPropsWithoutStyle)(props);
|
|
125
|
+
const onChangeElement = (0, react_1.useCallback)((event) => {
|
|
126
|
+
onChange?.(event);
|
|
127
|
+
onChangeValue?.(event.target.value);
|
|
128
|
+
}, [onChange, onChangeValue]);
|
|
129
|
+
return ((0, jsx_runtime_1.jsxs)(Div_1.default.column, { gap: theme.styles.gap / 2, children: [label && ((0, jsx_runtime_1.jsxs)(Text_1.default, { as: "label", fontSize: 14, color: errorText ? theme.colors.error : theme.colors.textSecondary, children: [label, required && ((0, jsx_runtime_1.jsxs)(Text_1.default, { as: "span", fontSize: 16, color: theme.colors.error, children: [" ", "*"] }))] })), (0, jsx_runtime_1.jsx)(TextareaElement, { theme: theme, 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
|
+
});
|
|
131
|
+
InputFieldComponent.email = (0, react_1.forwardRef)(function Email({ ...props }, ref) {
|
|
132
|
+
return ((0, jsx_runtime_1.jsx)(InputFieldComponent, { type: "email", placeholder: "your@email.here", autoComplete: "email", autoCorrect: "off", autoCapitalize: "off", ref: ref, ...props }));
|
|
133
|
+
});
|
|
134
|
+
InputFieldComponent.password = (0, react_1.forwardRef)(function Email({ ...props }, ref) {
|
|
135
|
+
const [isPassword, setIsPassword] = (0, hooks_1.useBooleanState)(true);
|
|
136
|
+
return ((0, jsx_runtime_1.jsx)(InputFieldComponent, { type: isPassword ? "password" : "text", placeholder: "******", rightIcon: isPassword ? "eye" : "eyeDashed", onClickRightIcon: setIsPassword.toggle, autoComplete: "current-password", autoCorrect: "off", autoCapitalize: "off", ref: ref, ...props }));
|
|
137
|
+
});
|
|
138
|
+
InputFieldComponent.search = (0, react_1.forwardRef)(function Email({ ...props }, ref) {
|
|
139
|
+
return (0, jsx_runtime_1.jsx)(InputFieldComponent, { leftIcon: "magnifyingGlass", placeholder: "Search...", ref: ref, ...props });
|
|
140
|
+
});
|
|
141
|
+
const InputField = (0, react_1.memo)(InputFieldComponent);
|
|
142
|
+
InputField.multiline = InputFieldComponent.multiline;
|
|
143
|
+
InputField.email = InputFieldComponent.email;
|
|
144
|
+
InputField.password = InputFieldComponent.password;
|
|
145
|
+
InputField.search = InputFieldComponent.search;
|
|
146
|
+
exports.default = InputField;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { ComponentHoverStyle, ComponentPropWithRef, ComponentStyle } from "../types/components";
|
|
2
|
+
import { OmitProps } from "../types/app";
|
|
3
|
+
export type ToggleInputRef = {};
|
|
4
|
+
type InternalToggleInputProps<Value> = {
|
|
5
|
+
label?: string;
|
|
6
|
+
text?: string;
|
|
7
|
+
errorText?: string;
|
|
8
|
+
infoText?: string;
|
|
9
|
+
value?: Value;
|
|
10
|
+
onChange?: (checked: boolean, value?: Value) => void;
|
|
11
|
+
} & OmitProps<React.ComponentProps<"input">, "style" | "value" | "ref" | "onChange" | "name"> & ComponentStyle & ComponentHoverStyle;
|
|
12
|
+
type ToggleInputProps<Value> = ComponentPropWithRef<ToggleInputRef, OmitProps<InternalToggleInputProps<Value>, "type">>;
|
|
13
|
+
type ToggleInputComponentType = <Value>(props: ToggleInputProps<Value>) => React.ReactElement;
|
|
14
|
+
declare const _default: {
|
|
15
|
+
checkbox: ToggleInputComponentType;
|
|
16
|
+
radiobutton: ToggleInputComponentType;
|
|
17
|
+
switch: ToggleInputComponentType;
|
|
18
|
+
};
|
|
19
|
+
export default _default;
|
|
@@ -0,0 +1,122 @@
|
|
|
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 styled_components_1 = __importDefault(require("styled-components"));
|
|
9
|
+
const hooks_1 = require("../utils/hooks");
|
|
10
|
+
const Text_1 = __importDefault(require("./Text"));
|
|
11
|
+
const Div_1 = __importDefault(require("./Div"));
|
|
12
|
+
const Icon_1 = __importDefault(require("./Icon"));
|
|
13
|
+
const BetterHtmlProvider_1 = require("./BetterHtmlProvider");
|
|
14
|
+
const InputElement = styled_components_1.default.input.withConfig({
|
|
15
|
+
shouldForwardProp: (prop) => !["theme", "normalStyle", "hoverStyle"].includes(prop),
|
|
16
|
+
}) `
|
|
17
|
+
position: relative;
|
|
18
|
+
appearance: none;
|
|
19
|
+
width: 24px;
|
|
20
|
+
height: 24px;
|
|
21
|
+
background-color: ${(props) => props.theme.colors.backgroundContent};
|
|
22
|
+
border: 1px solid ${(props) => props.theme.colors.border};
|
|
23
|
+
border-radius: ${(props) => props.theme.styles.borderRadius / 2}px;
|
|
24
|
+
cursor: pointer;
|
|
25
|
+
transition: ${(props) => props.theme.styles.transition};
|
|
26
|
+
flex-shrink: 0;
|
|
27
|
+
|
|
28
|
+
&[type="radio"] {
|
|
29
|
+
border-radius: 999px;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
&:checked {
|
|
33
|
+
background-color: ${(props) => props.theme.colors.primary};
|
|
34
|
+
border-color: ${(props) => props.theme.colors.primary};
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
&:disabled {
|
|
38
|
+
filter: brightness(0.9);
|
|
39
|
+
cursor: not-allowed;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
${(props) => props.normalStyle}
|
|
43
|
+
|
|
44
|
+
&:hover {
|
|
45
|
+
${(props) => props.hoverStyle}
|
|
46
|
+
}
|
|
47
|
+
`;
|
|
48
|
+
const SwitchElement = styled_components_1.default.div.withConfig({
|
|
49
|
+
shouldForwardProp: (prop) => !["theme", "checked", "disabled", "normalStyle", "hoverStyle"].includes(prop),
|
|
50
|
+
}) `
|
|
51
|
+
position: relative;
|
|
52
|
+
width: 36px;
|
|
53
|
+
height: 20px;
|
|
54
|
+
background-color: ${(props) => (props.checked ? props.theme.colors.primary : props.theme.colors.border)};
|
|
55
|
+
border-radius: 10px;
|
|
56
|
+
cursor: ${(props) => (props.disabled ? "not-allowed" : "pointer")};
|
|
57
|
+
opacity: ${(props) => (props.disabled ? 0.5 : 1)};
|
|
58
|
+
transition: ${(props) => props.theme.styles.transition};
|
|
59
|
+
|
|
60
|
+
&::before {
|
|
61
|
+
content: "";
|
|
62
|
+
position: absolute;
|
|
63
|
+
width: 16px;
|
|
64
|
+
height: 16px;
|
|
65
|
+
background-color: white;
|
|
66
|
+
border-radius: 50%;
|
|
67
|
+
top: 2px;
|
|
68
|
+
left: 2px;
|
|
69
|
+
transition: ${(props) => props.theme.styles.transition};
|
|
70
|
+
transform: translateX(${(props) => (props.checked ? "16px" : "0")});
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
${(props) => props.normalStyle}
|
|
74
|
+
|
|
75
|
+
&:hover {
|
|
76
|
+
${(props) => props.hoverStyle}
|
|
77
|
+
}
|
|
78
|
+
`;
|
|
79
|
+
const ToggleInputComponent = (0, react_1.forwardRef)(function ToggleInput({ label, text, errorText, infoText, value, onChange, checked: controlledChecked, required, ...props }, ref) {
|
|
80
|
+
const theme = (0, BetterHtmlProvider_1.useTheme)();
|
|
81
|
+
const styledComponentStyles = (0, hooks_1.useStyledComponentStyles)(props, theme, true);
|
|
82
|
+
const styledComponentStylesWithExcluded = (0, hooks_1.useComponentPropsWithExcludedStyle)(props);
|
|
83
|
+
const dataProps = (0, hooks_1.useComponentPropsWithPrefix)(props, "data");
|
|
84
|
+
const ariaProps = (0, hooks_1.useComponentPropsWithPrefix)(props, "aria");
|
|
85
|
+
const restProps = (0, hooks_1.useComponentPropsWithoutStyle)(props);
|
|
86
|
+
const [internalChecked, setInternalChecked] = (0, react_1.useState)(false);
|
|
87
|
+
const onChangeElement = (0, react_1.useCallback)((event) => {
|
|
88
|
+
const newValue = event.target.checked;
|
|
89
|
+
if (controlledChecked === undefined)
|
|
90
|
+
setInternalChecked(newValue);
|
|
91
|
+
onChange?.(newValue, value);
|
|
92
|
+
}, [onChange, controlledChecked, value, props.type]);
|
|
93
|
+
const checked = controlledChecked ?? internalChecked;
|
|
94
|
+
return ((0, jsx_runtime_1.jsxs)(Div_1.default.column, { width: "100%", gap: theme.styles.gap / 2, ...styledComponentStylesWithExcluded, children: [label && ((0, jsx_runtime_1.jsxs)(Text_1.default, { as: "label", height: 16, fontSize: 14, color: errorText ? theme.colors.error : theme.colors.textSecondary, children: [label, required && ((0, jsx_runtime_1.jsxs)(Text_1.default, { as: "span", fontSize: 16, color: theme.colors.error, children: [" ", "*"] }))] })), (0, jsx_runtime_1.jsxs)(Div_1.default.row, { alignItems: "center", gap: theme.styles.gap, children: [(0, jsx_runtime_1.jsxs)(Div_1.default.row, { position: "relative", alignItems: "center", children: [(0, jsx_runtime_1.jsx)(InputElement, { theme: theme, type: props.type ?? "checkbox", checked: checked, onChange: onChangeElement, ...styledComponentStyles, ...dataProps, ...ariaProps, ...restProps }), props.type === "checkbox" ? ((0, jsx_runtime_1.jsx)(Icon_1.default, { name: "check", position: "absolute", top: "50%", left: "50%", color: theme.colors.base, size: 14, transform: `translate(-50%, -50%)${checked ? "" : " scale(0.4)"}`, opacity: checked ? 1 : 0, pointerEvents: "none", transition: theme.styles.transition })) : props.type === "radio" ? ((0, jsx_runtime_1.jsx)(Div_1.default, { position: "absolute", width: 10, height: 10, top: "50%", left: "50%", backgroundColor: theme.colors.base, borderRadius: 999, transform: `translate(-50%, -50%)${checked ? "" : " scale(0.4)"}`, opacity: checked ? 1 : 0, pointerEvents: "none" })) : undefined] }), text && (0, jsx_runtime_1.jsx)(Text_1.default, { children: text })] }), (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 }))] }));
|
|
95
|
+
});
|
|
96
|
+
exports.default = {
|
|
97
|
+
checkbox: (0, react_1.forwardRef)(function Checkbox(props, ref) {
|
|
98
|
+
return (0, jsx_runtime_1.jsx)(ToggleInputComponent, { type: "checkbox", ref: ref, ...props });
|
|
99
|
+
}),
|
|
100
|
+
radiobutton: (0, react_1.forwardRef)(function RadioButton(props, ref) {
|
|
101
|
+
return (0, jsx_runtime_1.jsx)(ToggleInputComponent, { type: "radio", ref: ref, ...props });
|
|
102
|
+
}),
|
|
103
|
+
switch: (0, react_1.forwardRef)(function Switch({ label, errorText, infoText, disabled, onChange, checked: controlledChecked, required, ...props }, ref) {
|
|
104
|
+
const theme = (0, BetterHtmlProvider_1.useTheme)();
|
|
105
|
+
const styledComponentStyles = (0, hooks_1.useStyledComponentStyles)(props, theme, true);
|
|
106
|
+
const styledComponentStylesWithExcluded = (0, hooks_1.useComponentPropsWithExcludedStyle)(props);
|
|
107
|
+
const dataProps = (0, hooks_1.useComponentPropsWithPrefix)(props, "data");
|
|
108
|
+
const ariaProps = (0, hooks_1.useComponentPropsWithPrefix)(props, "aria");
|
|
109
|
+
const restProps = (0, hooks_1.useComponentPropsWithoutStyle)(props);
|
|
110
|
+
const [internalChecked, setInternalChecked] = (0, hooks_1.useBooleanState)();
|
|
111
|
+
const checked = controlledChecked ?? internalChecked;
|
|
112
|
+
const onClickElement = (0, react_1.useCallback)(() => {
|
|
113
|
+
if (disabled)
|
|
114
|
+
return;
|
|
115
|
+
const newValue = !checked;
|
|
116
|
+
if (controlledChecked === undefined)
|
|
117
|
+
setInternalChecked.setState(newValue);
|
|
118
|
+
onChange?.(newValue);
|
|
119
|
+
}, [disabled, checked, onChange, controlledChecked]);
|
|
120
|
+
return ((0, jsx_runtime_1.jsxs)(Div_1.default.column, { width: "100%", gap: theme.styles.gap / 2, ...styledComponentStylesWithExcluded, children: [label && ((0, jsx_runtime_1.jsxs)(Text_1.default, { as: "label", height: 16, fontSize: 14, color: errorText ? theme.colors.error : theme.colors.textSecondary, children: [label, required && ((0, jsx_runtime_1.jsxs)(Text_1.default, { as: "span", fontSize: 16, color: theme.colors.error, children: [" ", "*"] }))] })), (0, jsx_runtime_1.jsx)(Div_1.default.row, { alignItems: "center", gap: theme.styles.gap, children: (0, jsx_runtime_1.jsx)(SwitchElement, { theme: theme, checked: checked, disabled: disabled ?? false, onClick: onClickElement, ...styledComponentStyles, ...dataProps, ...ariaProps, ...restProps }) }), (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 }))] }));
|
|
121
|
+
}),
|
|
122
|
+
};
|
package/dist/constants/icons.js
CHANGED
|
@@ -32,4 +32,54 @@ exports.icons = {
|
|
|
32
32
|
},
|
|
33
33
|
],
|
|
34
34
|
},
|
|
35
|
+
chevronDown: {
|
|
36
|
+
width: 512,
|
|
37
|
+
height: 512,
|
|
38
|
+
paths: [
|
|
39
|
+
{
|
|
40
|
+
d: "M233.4 406.6c12.5 12.5 32.8 12.5 45.3 0l192-192c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0L256 338.7 86.6 169.4c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3l192 192z",
|
|
41
|
+
type: "fill",
|
|
42
|
+
},
|
|
43
|
+
],
|
|
44
|
+
},
|
|
45
|
+
eye: {
|
|
46
|
+
width: 576,
|
|
47
|
+
height: 512,
|
|
48
|
+
paths: [
|
|
49
|
+
{
|
|
50
|
+
d: "M288 32c-80.8 0-145.5 36.8-192.6 80.6C48.6 156 17.3 208 2.5 243.7c-3.3 7.9-3.3 16.7 0 24.6C17.3 304 48.6 356 95.4 399.4C142.5 443.2 207.2 480 288 480s145.5-36.8 192.6-80.6c46.8-43.5 78.1-95.4 93-131.1c3.3-7.9 3.3-16.7 0-24.6c-14.9-35.7-46.2-87.7-93-131.1C433.5 68.8 368.8 32 288 32zM144 256a144 144 0 1 1 288 0 144 144 0 1 1 -288 0zm144-64c0 35.3-28.7 64-64 64c-7.1 0-13.9-1.2-20.3-3.3c-5.5-1.8-11.9 1.6-11.7 7.4c.3 6.9 1.3 13.8 3.2 20.7c13.7 51.2 66.4 81.6 117.6 67.9s81.6-66.4 67.9-117.6c-11.1-41.5-47.8-69.4-88.6-71.1c-5.8-.2-9.2 6.1-7.4 11.7c2.1 6.4 3.3 13.2 3.3 20.3z",
|
|
51
|
+
type: "fill",
|
|
52
|
+
},
|
|
53
|
+
],
|
|
54
|
+
},
|
|
55
|
+
eyeDashed: {
|
|
56
|
+
width: 640,
|
|
57
|
+
height: 512,
|
|
58
|
+
paths: [
|
|
59
|
+
{
|
|
60
|
+
d: "M38.8 5.1C28.4-3.1 13.3-1.2 5.1 9.2S-1.2 34.7 9.2 42.9l592 464c10.4 8.2 25.5 6.3 33.7-4.1s6.3-25.5-4.1-33.7L525.6 386.7c39.6-40.6 66.4-86.1 79.9-118.4c3.3-7.9 3.3-16.7 0-24.6c-14.9-35.7-46.2-87.7-93-131.1C465.5 68.8 400.8 32 320 32c-68.2 0-125 26.3-169.3 60.8L38.8 5.1zM223.1 149.5C248.6 126.2 282.7 112 320 112c79.5 0 144 64.5 144 144c0 24.9-6.3 48.3-17.4 68.7L408 294.5c8.4-19.3 10.6-41.4 4.8-63.3c-11.1-41.5-47.8-69.4-88.6-71.1c-5.8-.2-9.2 6.1-7.4 11.7c2.1 6.4 3.3 13.2 3.3 20.3c0 10.2-2.4 19.8-6.6 28.3l-90.3-70.8zM373 389.9c-16.4 6.5-34.3 10.1-53 10.1c-79.5 0-144-64.5-144-144c0-6.9 .5-13.6 1.4-20.2L83.1 161.5C60.3 191.2 44 220.8 34.5 243.7c-3.3 7.9-3.3 16.7 0 24.6c14.9 35.7 46.2 87.7 93 131.1C174.5 443.2 239.2 480 320 480c47.8 0 89.9-12.9 126.2-32.5L373 389.9z",
|
|
61
|
+
type: "fill",
|
|
62
|
+
},
|
|
63
|
+
],
|
|
64
|
+
},
|
|
65
|
+
magnifyingGlass: {
|
|
66
|
+
width: 512,
|
|
67
|
+
height: 512,
|
|
68
|
+
paths: [
|
|
69
|
+
{
|
|
70
|
+
d: "M416 208c0 45.9-14.9 88.3-40 122.7L502.6 457.4c12.5 12.5 12.5 32.8 0 45.3s-32.8 12.5-45.3 0L330.7 376c-34.4 25.2-76.8 40-122.7 40C93.1 416 0 322.9 0 208S93.1 0 208 0S416 93.1 416 208zM208 352a144 144 0 1 0 0-288 144 144 0 1 0 0 288z",
|
|
71
|
+
type: "fill",
|
|
72
|
+
},
|
|
73
|
+
],
|
|
74
|
+
},
|
|
75
|
+
check: {
|
|
76
|
+
width: 448,
|
|
77
|
+
height: 512,
|
|
78
|
+
paths: [
|
|
79
|
+
{
|
|
80
|
+
d: "M438.6 105.4c12.5 12.5 12.5 32.8 0 45.3l-256 256c-12.5 12.5-32.8 12.5-45.3 0l-128-128c-12.5-12.5-12.5-32.8 0-45.3s32.8-12.5 45.3 0L160 338.7 393.4 105.4c12.5-12.5 32.8-12.5 45.3 0z",
|
|
81
|
+
type: "fill",
|
|
82
|
+
},
|
|
83
|
+
],
|
|
84
|
+
},
|
|
35
85
|
};
|
package/dist/index.d.ts
CHANGED
|
@@ -7,6 +7,10 @@ import Button from "./components/Button";
|
|
|
7
7
|
import Divider from "./components/Divider";
|
|
8
8
|
import Modal, { type ModalRef } from "./components/Modal";
|
|
9
9
|
import PageHolder from "./components/PageHolder";
|
|
10
|
+
import Chip from "./components/Chip";
|
|
11
|
+
import InputField from "./components/InputField";
|
|
12
|
+
import Dropdown from "./components/Dropdown";
|
|
13
|
+
import ToggleInput from "./components/ToggleInput";
|
|
10
14
|
import { useBetterHtmlContext, useTheme, useLoader, useLoaderControls } from "./components/BetterHtmlProvider";
|
|
11
15
|
import { usePageResize, useMediaQuery } from "./utils/hooks";
|
|
12
|
-
export { Div, Text, Loader, Icon, Image, Button, Divider, Modal, ModalRef, PageHolder, useBetterHtmlContext, useTheme, useLoader, useLoaderControls, usePageResize, useMediaQuery, };
|
|
16
|
+
export { Div, Text, Loader, Icon, Image, Button, Divider, Modal, ModalRef, PageHolder, Chip, InputField, Dropdown, ToggleInput, useBetterHtmlContext, useTheme, useLoader, useLoaderControls, usePageResize, useMediaQuery, };
|
package/dist/index.js
CHANGED
|
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.useMediaQuery = exports.usePageResize = exports.useLoaderControls = exports.useLoader = exports.useTheme = exports.useBetterHtmlContext = exports.PageHolder = exports.Modal = exports.Divider = exports.Button = exports.Image = exports.Icon = exports.Loader = exports.Text = exports.Div = void 0;
|
|
6
|
+
exports.useMediaQuery = exports.usePageResize = exports.useLoaderControls = exports.useLoader = exports.useTheme = exports.useBetterHtmlContext = exports.ToggleInput = exports.Dropdown = exports.InputField = exports.Chip = exports.PageHolder = exports.Modal = exports.Divider = exports.Button = exports.Image = exports.Icon = exports.Loader = exports.Text = exports.Div = void 0;
|
|
7
7
|
const Div_1 = __importDefault(require("./components/Div"));
|
|
8
8
|
exports.Div = Div_1.default;
|
|
9
9
|
const Text_1 = __importDefault(require("./components/Text"));
|
|
@@ -22,6 +22,14 @@ const Modal_1 = __importDefault(require("./components/Modal"));
|
|
|
22
22
|
exports.Modal = Modal_1.default;
|
|
23
23
|
const PageHolder_1 = __importDefault(require("./components/PageHolder"));
|
|
24
24
|
exports.PageHolder = PageHolder_1.default;
|
|
25
|
+
const Chip_1 = __importDefault(require("./components/Chip"));
|
|
26
|
+
exports.Chip = Chip_1.default;
|
|
27
|
+
const InputField_1 = __importDefault(require("./components/InputField"));
|
|
28
|
+
exports.InputField = InputField_1.default;
|
|
29
|
+
const Dropdown_1 = __importDefault(require("./components/Dropdown"));
|
|
30
|
+
exports.Dropdown = Dropdown_1.default;
|
|
31
|
+
const ToggleInput_1 = __importDefault(require("./components/ToggleInput"));
|
|
32
|
+
exports.ToggleInput = ToggleInput_1.default;
|
|
25
33
|
const BetterHtmlProvider_1 = require("./components/BetterHtmlProvider");
|
|
26
34
|
Object.defineProperty(exports, "useBetterHtmlContext", { enumerable: true, get: function () { return BetterHtmlProvider_1.useBetterHtmlContext; } });
|
|
27
35
|
Object.defineProperty(exports, "useTheme", { enumerable: true, get: function () { return BetterHtmlProvider_1.useTheme; } });
|
package/dist/types/icon.d.ts
CHANGED
package/dist/utils/hooks.d.ts
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import { ComponentHoverStyle, ComponentStyle } from "../types/components";
|
|
2
2
|
import { Theme } from "../types/theme";
|
|
3
|
-
export declare function useStyledComponentStyles(props: ComponentStyle & ComponentHoverStyle, theme?: Theme
|
|
3
|
+
export declare function useStyledComponentStyles(props: ComponentStyle & ComponentHoverStyle, theme?: Theme,
|
|
4
|
+
/** @default false */
|
|
5
|
+
excludeProps?: boolean): {
|
|
4
6
|
normalStyle: ComponentStyle;
|
|
5
7
|
hoverStyle: ComponentStyle;
|
|
6
8
|
};
|
|
7
9
|
export declare function useComponentPropsWithPrefix<Props extends Record<string, any>, Prefix extends string>(props: Props, prefix: Prefix): Record<`${Prefix}-${string}`, any>;
|
|
10
|
+
export declare function useComponentPropsWithExcludedStyle<Props extends Record<string, any>>(props: Props): Partial<Props>;
|
|
8
11
|
export declare function useComponentPropsWithoutStyle<Props extends Record<string, any>>(props: Props): Partial<Props>;
|
|
9
12
|
export declare function usePageResize(): {
|
|
10
13
|
width: number;
|
|
@@ -26,3 +29,13 @@ export declare function useMediaQuery(): {
|
|
|
26
29
|
size1500: boolean;
|
|
27
30
|
size1600: boolean;
|
|
28
31
|
};
|
|
32
|
+
export declare function useBooleanState(initialValue?: boolean): [
|
|
33
|
+
state: boolean,
|
|
34
|
+
actions: {
|
|
35
|
+
setState: React.Dispatch<React.SetStateAction<boolean>>;
|
|
36
|
+
setTrue: () => void;
|
|
37
|
+
setFalse: () => void;
|
|
38
|
+
toggle: () => void;
|
|
39
|
+
}
|
|
40
|
+
];
|
|
41
|
+
export declare function useDebounceState<Value>(initialValue: Value, delay?: number): [value: Value, debouncedValue: Value, setValue: React.Dispatch<React.SetStateAction<Value>>, isLoading: boolean];
|
package/dist/utils/hooks.js
CHANGED
|
@@ -2,21 +2,54 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.useStyledComponentStyles = useStyledComponentStyles;
|
|
4
4
|
exports.useComponentPropsWithPrefix = useComponentPropsWithPrefix;
|
|
5
|
+
exports.useComponentPropsWithExcludedStyle = useComponentPropsWithExcludedStyle;
|
|
5
6
|
exports.useComponentPropsWithoutStyle = useComponentPropsWithoutStyle;
|
|
6
7
|
exports.usePageResize = usePageResize;
|
|
7
8
|
exports.useMediaQuery = useMediaQuery;
|
|
9
|
+
exports.useBooleanState = useBooleanState;
|
|
10
|
+
exports.useDebounceState = useDebounceState;
|
|
8
11
|
const react_1 = require("react");
|
|
9
12
|
const cssProps = Object.keys(document.documentElement.style).reduce((previousValue, currentValue) => {
|
|
10
13
|
previousValue[currentValue.toLowerCase()] = true;
|
|
11
14
|
previousValue[`${currentValue}Hover`.toLowerCase()] = true;
|
|
12
15
|
return previousValue;
|
|
13
16
|
}, {});
|
|
14
|
-
|
|
15
|
-
|
|
17
|
+
const cssPropsToExclude = [
|
|
18
|
+
"position",
|
|
19
|
+
"top",
|
|
20
|
+
"right",
|
|
21
|
+
"bottom",
|
|
22
|
+
"left",
|
|
23
|
+
"width",
|
|
24
|
+
"height",
|
|
25
|
+
"minWidth",
|
|
26
|
+
"minHeight",
|
|
27
|
+
"maxWidth",
|
|
28
|
+
"maxHeight",
|
|
29
|
+
"margin",
|
|
30
|
+
"marginTop",
|
|
31
|
+
"marginBottom",
|
|
32
|
+
"marginLeft",
|
|
33
|
+
"marginRight",
|
|
34
|
+
"marginBlock",
|
|
35
|
+
"marginInline",
|
|
36
|
+
"marginBlockStart",
|
|
37
|
+
"marginBlockEnd",
|
|
38
|
+
"marginInlineStart",
|
|
39
|
+
"marginInlineEnd",
|
|
40
|
+
"marginTrim",
|
|
41
|
+
"zIndex",
|
|
42
|
+
];
|
|
43
|
+
function useStyledComponentStyles(props, theme,
|
|
44
|
+
/** @default false */
|
|
45
|
+
excludeProps) {
|
|
46
|
+
return (0, react_1.useMemo)(() => {
|
|
16
47
|
const normalStyle = {};
|
|
17
48
|
const hoverStyle = {};
|
|
18
49
|
let haveHover = false;
|
|
19
50
|
for (const key in props) {
|
|
51
|
+
if (excludeProps && cssPropsToExclude.includes(key))
|
|
52
|
+
continue;
|
|
20
53
|
if (key.endsWith("Hover")) {
|
|
21
54
|
haveHover = true;
|
|
22
55
|
const normalKey = key.slice(0, -5);
|
|
@@ -35,7 +68,6 @@ function useStyledComponentStyles(props, theme) {
|
|
|
35
68
|
hoverStyle,
|
|
36
69
|
};
|
|
37
70
|
}, [props, theme]);
|
|
38
|
-
return styles;
|
|
39
71
|
}
|
|
40
72
|
function useComponentPropsWithPrefix(props, prefix) {
|
|
41
73
|
return (0, react_1.useMemo)(() => {
|
|
@@ -48,6 +80,15 @@ function useComponentPropsWithPrefix(props, prefix) {
|
|
|
48
80
|
return returnValue;
|
|
49
81
|
}, [props, prefix]);
|
|
50
82
|
}
|
|
83
|
+
function useComponentPropsWithExcludedStyle(props) {
|
|
84
|
+
return (0, react_1.useMemo)(() => Object.keys(props).reduce((previousValue, currentValue) => {
|
|
85
|
+
const key = currentValue;
|
|
86
|
+
if (!cssPropsToExclude.includes(key))
|
|
87
|
+
return previousValue;
|
|
88
|
+
previousValue[key] = props[key];
|
|
89
|
+
return previousValue;
|
|
90
|
+
}, {}), [props]);
|
|
91
|
+
}
|
|
51
92
|
function useComponentPropsWithoutStyle(props) {
|
|
52
93
|
return (0, react_1.useMemo)(() => Object.keys(props).reduce((previousValue, currentValue) => {
|
|
53
94
|
if (!cssProps[currentValue.toLowerCase()])
|
|
@@ -92,3 +133,26 @@ function useMediaQuery() {
|
|
|
92
133
|
size1600: width <= 1600,
|
|
93
134
|
};
|
|
94
135
|
}
|
|
136
|
+
function useBooleanState(initialValue = false) {
|
|
137
|
+
const [state, setState] = (0, react_1.useState)(initialValue);
|
|
138
|
+
const setTrue = (0, react_1.useCallback)(() => setState(true), []);
|
|
139
|
+
const setFalse = (0, react_1.useCallback)(() => setState(false), []);
|
|
140
|
+
const toggle = (0, react_1.useCallback)(() => setState((oldValue) => !oldValue), []);
|
|
141
|
+
return [state, { setState, setTrue, setFalse, toggle }];
|
|
142
|
+
}
|
|
143
|
+
function useDebounceState(initialValue, delay = 0.5) {
|
|
144
|
+
const [value, setValue] = (0, react_1.useState)(initialValue);
|
|
145
|
+
const [debouncedValue, setDebouncedValue] = (0, react_1.useState)(initialValue);
|
|
146
|
+
const [isLoading, setIsLoading] = useBooleanState();
|
|
147
|
+
(0, react_1.useEffect)(() => {
|
|
148
|
+
setIsLoading.setTrue();
|
|
149
|
+
const timer = setTimeout(() => {
|
|
150
|
+
setDebouncedValue(value);
|
|
151
|
+
setIsLoading.setFalse();
|
|
152
|
+
}, delay * 1000);
|
|
153
|
+
return () => {
|
|
154
|
+
clearTimeout(timer);
|
|
155
|
+
};
|
|
156
|
+
}, [value, delay]);
|
|
157
|
+
return [value, debouncedValue, setValue, isLoading];
|
|
158
|
+
}
|