next-helios-fe 1.8.105 → 1.8.107

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.
@@ -62,21 +62,20 @@ export const MultipleSelect: React.FC<MultipleSelectProps> = ({
62
62
  onRemove,
63
63
  ...rest
64
64
  }) => {
65
- const [tempValue, setTempValue] = useState<string[]>([]);
66
- const [openDropdown, setOpenDropdown] = useState(false);
67
- const [dropdownWidth, setDropdownWidth] = useState<number>(0);
68
- const [dropdownHeight, setDropdownHeight] = useState<number>(0);
69
- const fakeInputRef = useRef<HTMLDivElement>(null);
70
65
  const itemContainerRef = useRef<HTMLDivElement>(null);
71
66
  const inputRef = useRef<HTMLInputElement>(null);
72
67
  const dropdownRef = useRef<HTMLButtonElement>(null);
68
+ const [tempValue, setTempValue] = useState<string[]>([]);
69
+ const [openDropdown, setOpenDropdown] = useState(false);
70
+ const [inputHeight, setInputHeight] = useState<number>(0);
71
+ const [dropdownWidth, setDropdownWidth] = useState<number>(0);
73
72
  const width = options?.width === "fit" ? "w-fit" : "w-full";
74
73
  const height =
75
74
  options?.height === "short"
76
- ? "py-0.5"
75
+ ? "py-[3.5px]"
77
76
  : options?.height === "high"
78
- ? "py-1.5"
79
- : "py-1";
77
+ ? "py-[7.5px]"
78
+ : "py-[5px]";
80
79
 
81
80
  useEffect(() => {
82
81
  document.addEventListener("mousedown", (e) => {
@@ -84,6 +83,16 @@ export const MultipleSelect: React.FC<MultipleSelectProps> = ({
84
83
  setOpenDropdown(false);
85
84
  }
86
85
  });
86
+
87
+ const observer = new ResizeObserver((entries) => {
88
+ for (let entry of entries) {
89
+ setInputHeight(entry.contentRect.height);
90
+ }
91
+ });
92
+
93
+ observer.observe(itemContainerRef.current!);
94
+
95
+ return () => observer.disconnect();
87
96
  }, []);
88
97
 
89
98
  useEffect(() => {
@@ -107,211 +116,221 @@ export const MultipleSelect: React.FC<MultipleSelectProps> = ({
107
116
  }, [tempValue]);
108
117
 
109
118
  return (
110
- <div className="flex flex-row-reverse items-end">
111
- <label className={`flex flex-col gap-2 ${width}`}>
112
- {(label || description) && (
113
- <div className="flex justify-between items-center gap-2">
114
- {label && (
115
- <span
116
- className={`text-sm select-none ${
117
- required && "after:content-['*'] after:ml-1 after:text-danger"
118
- }`}
119
- >
120
- {label}
121
- </span>
122
- )}
123
- {description && (
124
- <Tooltip content={description}>
125
- <Icon
126
- icon="octicon:info-16"
127
- className="text-sm text-primary-dark"
128
- />
129
- </Tooltip>
130
- )}
131
- </div>
132
- )}
133
- <div className="relative flex items-center">
134
- <input
135
- ref={inputRef}
136
- type="text"
137
- className="absolute bottom-0 -z-10 w-full border-0 rounded-md focus:ring-0"
138
- disabled={disabled ?? false}
139
- />
140
- <div
141
- ref={fakeInputRef}
142
- className={`group/button flex justify-between items-center gap-2 w-full min-h-10 px-4 border rounded-md caret-transparent focus:outline-none focus:ring-1 focus:ring-primary focus:shadow focus:shadow-primary focus:border-primary-dark ${height} ${
143
- disabled
144
- ? "bg-secondary-light cursor-default pointer-events-none"
145
- : "bg-secondary-bg cursor-pointer"
146
- } ${
147
- openDropdown
148
- ? "outline-none ring-1 ring-primary shadow shadow-primary border-primary-dark"
149
- : "border-default"
150
- }`}
151
- onClick={(e) => {
152
- e.preventDefault();
153
- onClick && onClick();
154
- setOpenDropdown(true);
155
- dropdownRef.current?.click();
156
- setDropdownWidth(
157
- fakeInputRef?.current?.getBoundingClientRect()?.width || 0
158
- );
159
- setDropdownHeight(
160
- fakeInputRef?.current?.getBoundingClientRect()?.height || 0
161
- );
162
- }}
163
- {...rest}
164
- >
165
- {!tempValue || tempValue?.length === 0 ? (
166
- <span
167
- className={`text-silent select-none duration-300 ${
168
- openDropdown ? "translate-x-1" : "translate-x-0"
169
- }`}
170
- >
171
- {placeholder}
172
- </span>
173
- ) : (
174
- <div
175
- ref={itemContainerRef}
176
- className="flex flex-wrap gap-2 w-full h-min pointer-events-none invisible"
177
- >
178
- {tempValue?.map((item) => {
179
- return (
180
- <div
181
- key={item}
182
- className="flex items-center gap-2 px-2 py-0.5 rounded-md bg-primary text-white cursor-default pointer-events-auto"
183
- >
184
- <span>{menus.find((i) => i.value === item)?.label}</span>
185
- <div className="cursor-pointer">
186
- <Icon icon="pajamas:close" />
187
- </div>
188
- </div>
119
+ <div className="relative">
120
+ <div className="flex flex-row-reverse items-end">
121
+ <label className={`flex flex-col gap-2 ${width}`}>
122
+ {(label || description) && (
123
+ <div className="flex justify-between items-center gap-2">
124
+ {label && (
125
+ <span
126
+ className={`text-sm select-none ${
127
+ required &&
128
+ "after:content-['*'] after:ml-1 after:text-danger"
129
+ }`}
130
+ >
131
+ {label}
132
+ </span>
133
+ )}
134
+ {description && (
135
+ <Tooltip content={description}>
136
+ <Icon
137
+ icon="octicon:info-16"
138
+ className="text-sm text-primary-dark"
139
+ />
140
+ </Tooltip>
141
+ )}
142
+ </div>
143
+ )}
144
+ <div className="relative flex items-center">
145
+ <div className="relative flex items-center w-full cursor-pointer">
146
+ <input
147
+ ref={inputRef}
148
+ type="text"
149
+ className="w-full ps-4 pe-14 border border-default rounded-md bg-secondary-bg text-transparent cursor-pointer caret-transparent duration-150 placeholder:duration-300 placeholder:text-silent 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-disabled disabled:cursor-default"
150
+ style={{
151
+ height:
152
+ tempValue.length !== 0
153
+ ? inputHeight +
154
+ (options?.height === "short"
155
+ ? 7
156
+ : options?.height === "high"
157
+ ? 15
158
+ : 10)
159
+ : options?.height === "short"
160
+ ? 35
161
+ : options?.height === "high"
162
+ ? 43
163
+ : 39,
164
+ }}
165
+ placeholder={placeholder}
166
+ required={required}
167
+ disabled={disabled}
168
+ value={tempValue.join(", ")}
169
+ onChange={(e) => {}}
170
+ onClick={(e) => {
171
+ e.preventDefault();
172
+ setOpenDropdown(true);
173
+ dropdownRef.current?.click();
174
+ setDropdownWidth(
175
+ inputRef?.current?.getBoundingClientRect()?.width || 0
189
176
  );
190
- })}
191
- </div>
192
- )}
193
- {!options?.disableDropdown && (
194
- <div className="ms-auto text-xl text-disabled pointer-events-none">
177
+ }}
178
+ onKeyDown={(e) => {
179
+ if (e.key === "Enter") {
180
+ e.preventDefault();
181
+ inputRef.current?.click();
182
+ }
183
+ }}
184
+ />
185
+ <div className="absolute right-4 text-xl text-disabled pointer-events-none">
195
186
  <Icon
196
187
  icon={`gravity-ui:chevron-${openDropdown ? "up" : "down"}`}
197
188
  />
198
189
  </div>
199
- )}
190
+ </div>
200
191
  </div>
201
- <div
202
- className="absolute left-4 flex flex-wrap gap-2 h-min pointer-events-none"
203
- style={{ width: itemContainerRef.current?.clientWidth }}
204
- >
205
- {tempValue?.map((item) => {
206
- return (
207
- <div
208
- key={item}
209
- className={`flex items-center gap-2 px-2 py-0.5 rounded-md text-white select-none cursor-default pointer-events-auto ${
210
- disabled ||
211
- menus.find((i) => i.value === item)?.disableUnselect
212
- ? "bg-secondary"
213
- : "bg-primary"
214
- }`}
192
+ </label>
193
+ {!options?.disableDropdown && (
194
+ <div className="w-0 overflow-hidden">
195
+ <Dropdown
196
+ placement="bottom-start"
197
+ dismissOnClick={false}
198
+ trigger={
199
+ <button
200
+ type="button"
201
+ ref={dropdownRef}
202
+ className="w-0"
203
+ style={{
204
+ height:
205
+ tempValue.length !== 0
206
+ ? inputHeight +
207
+ (options?.height === "short"
208
+ ? 7
209
+ : options?.height === "high"
210
+ ? 15
211
+ : 10)
212
+ : options?.height === "short"
213
+ ? 35
214
+ : options?.height === "high"
215
+ ? 43
216
+ : 39,
217
+ }}
218
+ tabIndex={-1}
219
+ disabled={disabled ?? false}
215
220
  >
216
- <span>{menus.find((i) => i.value === item)?.label}</span>
217
- <button
218
- disabled={
219
- disabled ||
220
- menus.find((i) => i.value === item)?.disableUnselect
221
+ 1
222
+ </button>
223
+ }
224
+ >
225
+ {menus.length === 0 ? (
226
+ <Dropdown.Item
227
+ onKeyDown={(e) => {
228
+ if (e.key === "Escape") {
229
+ e.preventDefault();
230
+ inputRef.current?.focus();
231
+ setOpenDropdown(false);
221
232
  }
222
- onClick={() => {
223
- setTempValue(tempValue.filter((i) => i !== item));
224
- if (onChange) {
225
- onChange({
226
- target: {
227
- value: tempValue.filter((i) => i !== item),
228
- },
229
- } as any);
230
- }
231
- if (onRemove) {
232
- onRemove({
233
- target: {
234
- value: item,
235
- },
236
- });
237
- }
238
- }}
233
+ }}
234
+ >
235
+ <div
236
+ className="flex justify-center"
237
+ style={{ width: dropdownWidth - 43 }}
239
238
  >
240
- <Icon icon="pajamas:close" />
241
- </button>
242
- </div>
243
- );
244
- })}
239
+ <span>No data found</span>
240
+ </div>
241
+ </Dropdown.Item>
242
+ ) : (
243
+ menus.map((item, index) => {
244
+ return (
245
+ <Dropdown.Item
246
+ key={index}
247
+ active={
248
+ tempValue?.find((i) => i === item.value) ? true : false
249
+ }
250
+ as={item.variant || "button"}
251
+ disabled={item.disabled ?? false}
252
+ onClick={() => {
253
+ setTempValue([...tempValue, item.value]);
254
+ if (onChange) {
255
+ onChange({
256
+ target: { value: [...tempValue, item.value] },
257
+ } as any);
258
+ }
259
+ if (onSelect) {
260
+ onSelect({
261
+ target: { value: item.value },
262
+ });
263
+ }
264
+ }}
265
+ onKeyDown={(e) => {
266
+ if (e.key === "Escape") {
267
+ e.preventDefault();
268
+ inputRef.current?.focus();
269
+ setOpenDropdown(false);
270
+ }
271
+ }}
272
+ >
273
+ <div
274
+ className="flex justify-between items-center gap-4"
275
+ style={{ width: dropdownWidth - 43 }}
276
+ >
277
+ <span>{item.label}</span>
278
+ {labelComponent ? labelComponent(item) : ""}
279
+ </div>
280
+ </Dropdown.Item>
281
+ );
282
+ })
283
+ )}
284
+ </Dropdown>
245
285
  </div>
246
- </div>
247
- </label>
248
- {!options?.disableDropdown && (
249
- <div className="w-0 overflow-hidden">
250
- <Dropdown
251
- placement="bottom-start"
252
- dismissOnClick={false}
253
- trigger={
286
+ )}
287
+ </div>
288
+ <div
289
+ ref={itemContainerRef}
290
+ className={`absolute bottom-0 ps-4 pe-12 flex flex-wrap gap-2 w-full h-min pointer-events-none ${height}`}
291
+ >
292
+ {tempValue?.map((item) => {
293
+ return (
294
+ <div
295
+ key={item}
296
+ className={`flex items-center gap-2 px-2 py-0.5 rounded-md text-white select-none cursor-default pointer-events-auto ${
297
+ disabled || menus.find((i) => i.value === item)?.disableUnselect
298
+ ? "bg-secondary"
299
+ : "bg-primary"
300
+ }`}
301
+ >
302
+ <span>{menus.find((i) => i.value === item)?.label}</span>
254
303
  <button
255
304
  type="button"
256
- ref={dropdownRef}
257
- className="w-0 my-0.5"
258
- style={{
259
- height: dropdownHeight,
260
- }}
305
+ disabled={
306
+ disabled ||
307
+ menus.find((i) => i.value === item)?.disableUnselect
308
+ }
261
309
  tabIndex={-1}
262
- disabled={disabled ?? false}
310
+ onClick={() => {
311
+ setTempValue(tempValue.filter((i) => i !== item));
312
+ if (onChange) {
313
+ onChange({
314
+ target: {
315
+ value: tempValue.filter((i) => i !== item),
316
+ },
317
+ } as any);
318
+ }
319
+ if (onRemove) {
320
+ onRemove({
321
+ target: {
322
+ value: item,
323
+ },
324
+ });
325
+ }
326
+ }}
263
327
  >
264
- 1
328
+ <Icon icon="pajamas:close" />
265
329
  </button>
266
- }
267
- >
268
- {menus.length === 0 ? (
269
- <Dropdown.Item>
270
- <div
271
- className="flex justify-center"
272
- style={{ width: dropdownWidth - 43 }}
273
- >
274
- <span>No data found</span>
275
- </div>
276
- </Dropdown.Item>
277
- ) : (
278
- menus.map((item, index) => {
279
- return (
280
- <Dropdown.Item
281
- key={index}
282
- active={
283
- tempValue?.find((i) => i === item.value) ? true : false
284
- }
285
- as={item.variant || "button"}
286
- disabled={item.disabled ?? false}
287
- onClick={() => {
288
- setTempValue([...tempValue, item.value]);
289
- if (onChange) {
290
- onChange({
291
- target: { value: [...tempValue, item.value] },
292
- } as any);
293
- }
294
- if (onSelect) {
295
- onSelect({
296
- target: { value: item.value },
297
- });
298
- }
299
- }}
300
- >
301
- <div
302
- className="flex justify-between items-center gap-4"
303
- style={{ width: dropdownWidth - 43 }}
304
- >
305
- <span>{item.label}</span>
306
- {labelComponent ? labelComponent(item) : ""}
307
- </div>
308
- </Dropdown.Item>
309
- );
310
- })
311
- )}
312
- </Dropdown>
313
- </div>
314
- )}
330
+ </div>
331
+ );
332
+ })}
333
+ </div>
315
334
  </div>
316
335
  );
317
336
  };
@@ -114,6 +114,7 @@ export const Rating: React.FC<RatingProps> = ({
114
114
  <input
115
115
  type="text"
116
116
  className={`absolute top-0 w-full border-0 bg-transparent text-transparent caret-transparent pointer-events-none focus:ring-0 ${height}`}
117
+ tabIndex={-1}
117
118
  required={rest.required}
118
119
  readOnly
119
120
  value={tempValue}
@@ -103,11 +103,7 @@ export const Select: React.FC<SelectProps> = ({
103
103
  <input
104
104
  ref={inputRef}
105
105
  type="text"
106
- className={`w-full ps-4 pe-14 border rounded-md bg-secondary-bg cursor-pointer caret-transparent placeholder:duration-300 placeholder:text-silent 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-disabled disabled:cursor-default ${height} ${
107
- openDropdown
108
- ? "placeholder:translate-x-1 outline-none ring-1 ring-primary shadow shadow-primary border-primary-dark"
109
- : "border-default placeholder:translate-x-0"
110
- }`}
106
+ className={`w-full ps-4 pe-14 border border-default rounded-md bg-secondary-bg cursor-pointer caret-transparent placeholder:duration-300 placeholder:text-silent 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-disabled disabled:cursor-default ${height}`}
111
107
  placeholder={placeholder}
112
108
  required={rest.required}
113
109
  disabled={rest.disabled}
@@ -125,6 +121,12 @@ export const Select: React.FC<SelectProps> = ({
125
121
  inputRef?.current?.getBoundingClientRect()?.width || 0
126
122
  );
127
123
  }}
124
+ onKeyDown={(e) => {
125
+ if (e.key === "Enter") {
126
+ e.preventDefault();
127
+ inputRef.current?.click();
128
+ }
129
+ }}
128
130
  />
129
131
  <div className="absolute right-4 text-xl text-disabled pointer-events-none">
130
132
  <Icon icon={`gravity-ui:chevron-${openDropdown ? "up" : "down"}`} />
@@ -154,7 +156,15 @@ export const Select: React.FC<SelectProps> = ({
154
156
  }
155
157
  >
156
158
  {menus.length === 0 ? (
157
- <Dropdown.Item>
159
+ <Dropdown.Item
160
+ onKeyDown={(e) => {
161
+ if (e.key === "Escape") {
162
+ e.preventDefault();
163
+ inputRef.current?.focus();
164
+ setOpenDropdown(false);
165
+ }
166
+ }}
167
+ >
158
168
  <div
159
169
  className="flex justify-center"
160
170
  style={{ width: dropdownWidth - 43 }}
@@ -177,6 +187,15 @@ export const Select: React.FC<SelectProps> = ({
177
187
  target: { value: item.value } as HTMLSelectElement,
178
188
  } as any);
179
189
  }
190
+ setOpenDropdown(false);
191
+ inputRef.current?.focus();
192
+ }}
193
+ onKeyDown={(e) => {
194
+ if (e.key === "Escape") {
195
+ e.preventDefault();
196
+ inputRef.current?.focus();
197
+ setOpenDropdown(false);
198
+ }
180
199
  }}
181
200
  >
182
201
  <div
@@ -383,7 +383,7 @@ export const Table: TableComponentProps = ({
383
383
  <input
384
384
  type="search"
385
385
  className="w-full border-x-0 border-b border-t-0 border-default bg-secondary-bg px-6 pb-0.5 pt-0 text-sm font-normal placeholder:translate-x-0 placeholder:text-silent placeholder:duration-300 focus:border-primary-dark focus:outline-none focus:ring-0 focus:placeholder:translate-x-1 disabled:bg-secondary-light disabled:text-disabled [&::-webkit-search-cancel-button]:appearance-none"
386
- placeholder="search.."
386
+ placeholder="Search..."
387
387
  value={
388
388
  filter?.find((filterItem) => filterItem.key === item.key)
389
389
  ?.value || ""
@@ -638,7 +638,7 @@ export const Table: TableComponentProps = ({
638
638
  {options?.toolbar?.search?.show !== false && (
639
639
  <Form.Search
640
640
  options={{ width: "fit" }}
641
- placeholder="search.."
641
+ placeholder="Search..."
642
642
  value={search}
643
643
  onChange={(e) => {
644
644
  setSearch(e.target.value);