next-helios-fe 1.6.13 → 1.6.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,7 @@
|
|
1
1
|
"use client";
|
2
2
|
import React, { useState, useEffect, useRef } from "react";
|
3
|
+
import { Dropdown } from "../../../components";
|
3
4
|
import { Icon } from "@iconify/react";
|
4
|
-
import { createPortal } from "react-dom";
|
5
5
|
|
6
6
|
export interface SelectProps
|
7
7
|
extends React.SelectHTMLAttributes<HTMLSelectElement> {
|
@@ -27,13 +27,9 @@ export const Select: React.FC<SelectProps> = ({
|
|
27
27
|
}) => {
|
28
28
|
const [tempValue, setTempValue] = useState("");
|
29
29
|
const [openDropdown, setOpenDropdown] = useState(false);
|
30
|
-
const [position, setPosition] = useState<{
|
31
|
-
top: number;
|
32
|
-
left: number;
|
33
|
-
} | null>(null);
|
34
30
|
const [dropdownWidth, setDropdownWidth] = useState<number>(0);
|
35
|
-
const
|
36
|
-
const dropdownRef = useRef<
|
31
|
+
const inputRef = useRef<HTMLInputElement>(null);
|
32
|
+
const dropdownRef = useRef<HTMLButtonElement>(null);
|
37
33
|
const width = options?.width === "fit" ? "w-fit" : "w-full";
|
38
34
|
const height =
|
39
35
|
options?.height === "short"
|
@@ -43,51 +39,13 @@ export const Select: React.FC<SelectProps> = ({
|
|
43
39
|
: "py-1.5";
|
44
40
|
|
45
41
|
useEffect(() => {
|
46
|
-
|
47
|
-
if (
|
48
|
-
dropdownRef.current &&
|
49
|
-
!dropdownRef.current.contains(e.target as Node) &&
|
50
|
-
!triggerRef.current?.contains(e.target as Node)
|
51
|
-
) {
|
42
|
+
document.addEventListener("mousedown", (e) => {
|
43
|
+
if (e.target instanceof HTMLElement) {
|
52
44
|
setOpenDropdown(false);
|
53
45
|
}
|
54
|
-
};
|
55
|
-
|
56
|
-
document.addEventListener("mousedown", handleClickOutside);
|
57
|
-
return () => {
|
58
|
-
document.removeEventListener("mousedown", handleClickOutside);
|
59
|
-
};
|
46
|
+
});
|
60
47
|
}, []);
|
61
48
|
|
62
|
-
useEffect(() => {
|
63
|
-
if (triggerRef.current) {
|
64
|
-
const rect = triggerRef.current.getBoundingClientRect();
|
65
|
-
const dropdownHeight = dropdownRef.current?.offsetHeight || 0;
|
66
|
-
const windowHeight = window.innerHeight;
|
67
|
-
|
68
|
-
setPosition({
|
69
|
-
top: rect.bottom + window.scrollY + 10,
|
70
|
-
left: rect.left + window.scrollX,
|
71
|
-
});
|
72
|
-
|
73
|
-
setDropdownWidth(rect.width);
|
74
|
-
|
75
|
-
if (rect.bottom + dropdownHeight > windowHeight) {
|
76
|
-
setPosition((prev) =>
|
77
|
-
prev
|
78
|
-
? { ...prev, top: rect.top + window.scrollY - dropdownHeight - 10 }
|
79
|
-
: null
|
80
|
-
);
|
81
|
-
}
|
82
|
-
}
|
83
|
-
|
84
|
-
if (openDropdown) {
|
85
|
-
document.getElementById("body")!.style.overflow = "hidden";
|
86
|
-
} else {
|
87
|
-
document.getElementById("body")!.style.overflow = "auto";
|
88
|
-
}
|
89
|
-
}, [openDropdown]);
|
90
|
-
|
91
49
|
useEffect(() => {
|
92
50
|
if (rest.value || rest.value === "") {
|
93
51
|
setTempValue(rest.value as string);
|
@@ -108,24 +66,27 @@ export const Select: React.FC<SelectProps> = ({
|
|
108
66
|
}, [tempValue]);
|
109
67
|
|
110
68
|
return (
|
111
|
-
<
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
onClick={() => setOpenDropdown(!openDropdown)}
|
125
|
-
>
|
69
|
+
<div className="flex flex-row-reverse items-end">
|
70
|
+
<label className={`grid gap-2 ${width}`}>
|
71
|
+
{label && (
|
72
|
+
<span
|
73
|
+
className={`text-sm select-none ${
|
74
|
+
rest.required &&
|
75
|
+
"after:content-['*'] after:ml-1 after:text-danger"
|
76
|
+
}`}
|
77
|
+
>
|
78
|
+
{label}
|
79
|
+
</span>
|
80
|
+
)}
|
81
|
+
<div className="relative flex items-center cursor-pointer">
|
126
82
|
<input
|
83
|
+
ref={inputRef}
|
127
84
|
type="text"
|
128
|
-
className={`w-full px-4 border
|
85
|
+
className={`w-full px-4 border rounded-md bg-secondary-bg cursor-pointer caret-transparent placeholder:duration-300 placeholder:text-slate-300 focus:placeholder:translate-x-1 focus:outline-none focus:ring-1 focus:ring-primary focus:shadow focus:shadow-primary focus:border-primary-dark disabled:bg-secondary-light disabled:text-slate-400 disabled:cursor-default ${height} ${
|
86
|
+
openDropdown
|
87
|
+
? "placeholder:translate-x-1 outline-none ring-1 ring-primary shadow shadow-primary border-primary-dark"
|
88
|
+
: "border-default placeholder:translate-x-0"
|
89
|
+
}`}
|
129
90
|
placeholder={placeholder}
|
130
91
|
required={rest.required}
|
131
92
|
disabled={rest.disabled}
|
@@ -134,55 +95,67 @@ export const Select: React.FC<SelectProps> = ({
|
|
134
95
|
? menus.find((item) => item.value === tempValue)?.label
|
135
96
|
: ""
|
136
97
|
}
|
137
|
-
onClick={() =>
|
98
|
+
onClick={(e) => {
|
99
|
+
e.preventDefault();
|
100
|
+
setOpenDropdown(true);
|
101
|
+
dropdownRef.current?.click();
|
102
|
+
setDropdownWidth(
|
103
|
+
inputRef?.current?.getBoundingClientRect()?.width || 0
|
104
|
+
);
|
105
|
+
}}
|
138
106
|
/>
|
139
107
|
<div className="absolute right-4 text-xl text-slate-400 pointer-events-none">
|
140
108
|
<Icon icon={`gravity-ui:chevron-${openDropdown ? "up" : "down"}`} />
|
141
109
|
</div>
|
142
110
|
</div>
|
143
|
-
{
|
144
|
-
|
145
|
-
|
146
|
-
|
111
|
+
<select className="hidden" {...rest}>
|
112
|
+
{menus.map((item, index) => (
|
113
|
+
<option key={index} value={item.value}>
|
114
|
+
{item.label}
|
115
|
+
</option>
|
116
|
+
))}
|
117
|
+
</select>
|
118
|
+
</label>
|
119
|
+
<div className="w-0 overflow-hidden">
|
120
|
+
<Dropdown
|
121
|
+
placement="bottom-start"
|
122
|
+
trigger={
|
123
|
+
<button
|
124
|
+
type="button"
|
147
125
|
ref={dropdownRef}
|
148
|
-
className=
|
149
|
-
style={{
|
150
|
-
top: position.top,
|
151
|
-
left: position.left,
|
152
|
-
width: dropdownWidth,
|
153
|
-
}}
|
126
|
+
className={`w-0 my-0.5 ${height}`}
|
154
127
|
>
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
128
|
+
1
|
129
|
+
</button>
|
130
|
+
}
|
131
|
+
>
|
132
|
+
<div
|
133
|
+
style={{
|
134
|
+
width: dropdownWidth - 11,
|
135
|
+
}}
|
136
|
+
>
|
137
|
+
{menus.length === 0 ? (
|
138
|
+
<div className="flex justify-center">
|
139
|
+
<span className="px-4 py-1">No data found</span>
|
140
|
+
</div>
|
141
|
+
) : (
|
142
|
+
menus.map((item, index) => (
|
143
|
+
<button
|
144
|
+
key={index}
|
145
|
+
type="button"
|
146
|
+
className="min-w-40 w-full my-0.5 px-4 py-2 rounded-md text-sm text-left hover:bg-secondary-light disabled:bg-primary-transparent disabled:text-primary"
|
147
|
+
disabled={tempValue === item.value}
|
148
|
+
onClick={() => {
|
149
|
+
setTempValue(item.value);
|
150
|
+
}}
|
151
|
+
>
|
152
|
+
{item.label}
|
153
|
+
</button>
|
154
|
+
))
|
155
|
+
)}
|
156
|
+
</div>
|
157
|
+
</Dropdown>
|
178
158
|
</div>
|
179
|
-
|
180
|
-
{menus.map((item, index) => (
|
181
|
-
<option key={index} value={item.value}>
|
182
|
-
{item.label}
|
183
|
-
</option>
|
184
|
-
))}
|
185
|
-
</select>
|
186
|
-
</label>
|
159
|
+
</div>
|
187
160
|
);
|
188
161
|
};
|