@inceptionbg/iui 2.0.19 → 2.0.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (30) hide show
  1. package/dist/index.d.ts +15 -7
  2. package/dist/index.js +1 -1
  3. package/dist/index.js.map +1 -1
  4. package/dist/iui.css +1 -1
  5. package/package.json +2 -1
  6. package/src/components/Accordions/Accordions.tsx +35 -27
  7. package/src/components/Dialog/Dialog.tsx +27 -25
  8. package/src/components/Header/Components/EnvBadge.tsx +17 -0
  9. package/src/components/Header/Header.tsx +7 -3
  10. package/src/components/Inputs/Selects/components/SelectWrapper.tsx +1 -1
  11. package/src/components/Table/components/items/TableItemActions.tsx +5 -3
  12. package/src/components/Table/contexts/TableContext.tsx +8 -5
  13. package/src/components/Table/hooks/localHooks/useLocalTableData.tsx +1 -1
  14. package/src/components/Table/hooks/localHooks/useLocalTableKeyboard.ts +3 -1
  15. package/src/components/Table/hooks/useTableEdit.tsx +9 -2
  16. package/src/components/Table/hooks/useTableSearch.ts +2 -1
  17. package/src/components/Tabs/Tabs.tsx +3 -3
  18. package/src/components/Tooltip/Tooltip.tsx +14 -81
  19. package/src/components/Wrappers/FormWrapper.tsx +1 -1
  20. package/src/index.ts +2 -0
  21. package/src/styles/common/_typography.scss +2 -2
  22. package/src/styles/components/_dialog.scss +25 -19
  23. package/src/styles/components/_header.scss +5 -0
  24. package/src/styles/components/_table.scss +1 -1
  25. package/src/styles/components/_tabs.scss +1 -1
  26. package/src/types/ITable.ts +1 -1
  27. package/src/utils/InputPatternValidation.ts +2 -2
  28. package/src/utils/objectUtils.ts +15 -5
  29. package/src/components/Inputs/Select2/Select.tsx +0 -258
  30. package/src/components/Inputs/Select2/select.scss +0 -42
@@ -1,4 +1,5 @@
1
1
  import { Dispatch, SetStateAction, useState } from 'react';
2
+ import { deletePropsThatEndsWith } from '../../../utils/objectUtils';
2
3
 
3
4
  export interface ITableSearchProps<T> {
4
5
  setOffset: Dispatch<SetStateAction<number>>;
@@ -17,7 +18,7 @@ export const useTableSearch = <T>({
17
18
  const onSearch = (filters: T) => {
18
19
  setOffset(0);
19
20
  resetSelectedRows?.();
20
- setSearch(filters);
21
+ setSearch(<T>deletePropsThatEndsWith(filters, 'Obj'));
21
22
  };
22
23
 
23
24
  return {
@@ -27,9 +27,9 @@ export const Tabs: FC<Props> = ({
27
27
  }) => {
28
28
  const filteredTabs = useMemo(() => tabs.filter(e => !e.hidden), [tabs]);
29
29
 
30
- const [selected, setSelected] = useState(initialValue || filteredTabs[0].value);
30
+ const [selected, setSelected] = useState(initialValue || filteredTabs[0]?.value || '');
31
31
 
32
- const activeTab = filteredTabs.find(tab => (control?.value || selected) === tab.value);
32
+ const activeTab = filteredTabs.find(tab => (control?.value ?? selected) === tab.value);
33
33
 
34
34
  return filteredTabs.length > 0 ? (
35
35
  <div className={className}>
@@ -39,7 +39,7 @@ export const Tabs: FC<Props> = ({
39
39
  id={tab.value}
40
40
  key={tab.value}
41
41
  className={clsx('iui-tab clickable', {
42
- selected: (control?.value || selected) === tab.value,
42
+ selected: (control?.value ?? selected) === tab.value,
43
43
  disabled: tab.disabled,
44
44
  'no-wrap': noWrap,
45
45
  })}
@@ -103,98 +103,31 @@ const setAbsolutePosition = (
103
103
  ) => {
104
104
  const containerRect = containerEl.getBoundingClientRect();
105
105
  const tooltipRect = targetEl.getBoundingClientRect();
106
- const margin = 16; // Distance from container
107
- const screenPadding = 8; // Minimum distance from screen edges
108
106
 
109
107
  if (position === 'bottom' || position === 'top') {
110
- const bottom = Math.floor(containerRect.bottom + margin);
111
- const top = Math.floor(containerRect.top - tooltipRect.height - margin);
112
- let leftCenter = Math.floor(
108
+ const bottom = Math.floor(containerRect.bottom + 16);
109
+ const top = Math.floor(containerRect.top - tooltipRect.height - 16);
110
+ const leftCenter = Math.floor(
113
111
  containerRect.left + containerRect.width / 2 - tooltipRect.width / 2
114
112
  );
115
-
116
- // Check if tooltip overflows horizontally and adjust
117
- if (leftCenter < screenPadding) {
118
- targetEl.style.width = `${tooltipRect.width + leftCenter}px`;
119
- leftCenter = screenPadding;
120
- } else if (leftCenter + tooltipRect.width > window.innerWidth - screenPadding) {
121
- leftCenter = window.innerWidth - tooltipRect.width - screenPadding;
122
- }
123
-
124
113
  const reverse =
125
114
  position === 'top' ? top < 0 : bottom + tooltipRect.height > window.innerHeight;
126
115
 
127
116
  setNewPosition(reverse ? (position === 'bottom' ? 'top' : 'bottom') : '');
128
117
 
129
- let finalTop =
130
- position === 'bottom' ? (reverse ? top : bottom) : reverse ? bottom : top;
131
-
132
- // Ensure tooltip doesn't go above screen
133
- if (finalTop < screenPadding) {
134
- finalTop = screenPadding;
135
- }
136
- // Ensure tooltip doesn't go below screen
137
- if (finalTop + tooltipRect.height > window.innerHeight - screenPadding) {
138
- finalTop = window.innerHeight - tooltipRect.height - screenPadding;
139
- }
140
-
141
- targetEl.style.top = `${finalTop}px`;
118
+ targetEl.style.top = `${
119
+ position === 'bottom' ? (reverse ? top : bottom) : reverse ? bottom : top
120
+ }px`;
142
121
  targetEl.style.left = `${leftCenter}px`;
143
122
  } else if (position === 'right') {
144
- let finalTop = Math.floor(
145
- containerRect.top + containerRect.height / 2 - tooltipRect.height / 2
146
- );
147
- let finalLeft = Math.floor(containerRect.right + margin);
148
-
149
- // Check if tooltip overflows vertically and adjust
150
- if (finalTop < screenPadding) {
151
- finalTop = screenPadding;
152
- } else if (finalTop + tooltipRect.height > window.innerHeight - screenPadding) {
153
- finalTop = window.innerHeight - tooltipRect.height - screenPadding;
154
- }
155
-
156
- // Check if tooltip overflows to the right and flip to left
157
- if (finalLeft + tooltipRect.width > window.innerWidth - screenPadding) {
158
- finalLeft = Math.floor(containerRect.left - tooltipRect.width - margin);
159
- setNewPosition('left');
160
-
161
- // If it still overflows on the left, position it at the edge
162
- if (finalLeft < screenPadding) {
163
- finalLeft = screenPadding;
164
- }
165
- } else {
166
- setNewPosition('');
167
- }
168
-
169
- targetEl.style.top = `${finalTop}px`;
170
- targetEl.style.left = `${finalLeft}px`;
123
+ targetEl.style.top =
124
+ Math.floor(containerRect.top + containerRect.height / 2 - tooltipRect.height / 2) +
125
+ 'px';
126
+ targetEl.style.left = Math.floor(containerRect.right + 16) + 'px';
171
127
  } else if (position === 'left') {
172
- let finalTop = Math.floor(
173
- containerRect.top + containerRect.height / 2 - tooltipRect.height / 2
174
- );
175
- let finalLeft = Math.floor(containerRect.left - tooltipRect.width - margin);
176
-
177
- // Check if tooltip overflows vertically and adjust
178
- if (finalTop < screenPadding) {
179
- finalTop = screenPadding;
180
- } else if (finalTop + tooltipRect.height > window.innerHeight - screenPadding) {
181
- finalTop = window.innerHeight - tooltipRect.height - screenPadding;
182
- }
183
-
184
- // Check if tooltip overflows to the left and flip to right
185
- if (finalLeft < screenPadding) {
186
- finalLeft = Math.floor(containerRect.right + margin);
187
- setNewPosition('right');
188
-
189
- // If it still overflows on the right, position it at the edge
190
- if (finalLeft + tooltipRect.width > window.innerWidth - screenPadding) {
191
- finalLeft = window.innerWidth - tooltipRect.width - screenPadding;
192
- }
193
- } else {
194
- setNewPosition('');
195
- }
196
-
197
- targetEl.style.top = `${finalTop}px`;
198
- targetEl.style.left = `${finalLeft}px`;
128
+ targetEl.style.top =
129
+ Math.floor(containerRect.top + containerRect.height / 2 - tooltipRect.height / 2) +
130
+ 'px';
131
+ targetEl.style.left = Math.floor(containerRect.left - tooltipRect.width - 16) + 'px';
199
132
  }
200
133
  };
@@ -67,7 +67,7 @@ export const FormWrapper: FC<IFormWrapper> = ({
67
67
  {!noAccess && (
68
68
  <Button
69
69
  label={submitButton.label ?? t('Save')}
70
- // icon={submitButton.icon}
70
+ icon={submitButton.icon}
71
71
  disabled={isLoading || submitButton.disabled}
72
72
  variant={submitButton.variant}
73
73
  color={submitButton.color}
package/src/index.ts CHANGED
@@ -173,6 +173,7 @@ import {
173
173
  deleteEmptyPropsIncludingArray,
174
174
  deleteProps,
175
175
  deletePropsThatEndsWith,
176
+ flattenTreeForSelect,
176
177
  intersectArrays,
177
178
  } from './utils/objectUtils';
178
179
  import {
@@ -345,6 +346,7 @@ export {
345
346
  setTemplateData,
346
347
  getVisibleColumnsIds,
347
348
  inputPattern,
349
+ flattenTreeForSelect,
348
350
  intersectArrays,
349
351
  maxChar,
350
352
  parseUrlSearch,
@@ -1,8 +1,8 @@
1
1
  @use '../variables/bp';
2
- @import url('https://fonts.googleapis.com/css2?family=Poppins:ital,wght@0,400;0,500;0,600;0,700;0,900;1,400;1,500;1,600;1,700;1,900&display=swap');
2
+ @import url('@fontsource-variable/ibm-plex-sans');
3
3
 
4
4
  * {
5
- font-family: 'Poppins', sans-serif;
5
+ font-family: 'IBM Plex Sans Variable', sans-serif;
6
6
  }
7
7
 
8
8
  body {
@@ -24,15 +24,22 @@ $dialog-sizes: (
24
24
  }
25
25
 
26
26
  .iui-dialog-container {
27
+ display: flex;
28
+ flex-direction: column;
29
+ gap: 24px;
27
30
  background-color: var(--background);
28
31
  border-radius: 16px;
29
32
  min-width: 400px;
30
33
  max-width: 98vw;
34
+ max-height: 95dvh;
31
35
  animation: scale-in 0.2s forwards;
32
36
  overflow: hidden;
37
+ padding: 24px;
38
+
33
39
  .iui-dialog-header {
34
40
  display: flex;
35
41
  gap: 16px;
42
+ flex-shrink: 0;
36
43
  .iui-dialog-desc {
37
44
  color: var(--text);
38
45
  word-break: break-word;
@@ -53,6 +60,18 @@ $dialog-sizes: (
53
60
  }
54
61
  }
55
62
  }
63
+ .iui-dialog-content {
64
+ display: flex;
65
+ flex-direction: column;
66
+ gap: 8px;
67
+ flex: 1;
68
+ margin-right: -24px;
69
+ padding-right: 24px;
70
+ &:not(.no-overflow) {
71
+ overflow: auto;
72
+ overscroll-behavior: none;
73
+ }
74
+ }
56
75
 
57
76
  @each $key, $value in $dialog-sizes {
58
77
  &.#{$key} {
@@ -71,28 +90,15 @@ $dialog-sizes: (
71
90
  }
72
91
  }
73
92
  }
74
- }
75
-
76
- .iui-dialog-content {
77
- display: flex;
78
- flex-direction: column;
79
- gap: 8px;
80
- max-height: 80vh;
81
- padding: 24px;
82
- &:not(.no-overflow) {
83
- overflow: auto;
84
- overscroll-behavior: none;
93
+ .iui-dialog-actions {
94
+ display: flex;
95
+ gap: 8px;
96
+ justify-content: right;
97
+ padding-top: 24px;
98
+ border-top: var(--border);
85
99
  }
86
100
  }
87
101
 
88
- .iui-dialog-actions {
89
- display: flex;
90
- gap: 8px;
91
- justify-content: right;
92
- padding: 24px;
93
- border-top: var(--border);
94
- }
95
-
96
102
  @media #{bp.$mobile} {
97
103
  .iui-dialog-container {
98
104
  height: 100dvh;
@@ -12,6 +12,11 @@
12
12
  padding-left: 8px;
13
13
  box-sizing: border-box;
14
14
  z-index: 2;
15
+ .env-badge {
16
+ color: var(--text);
17
+ font-weight: bold;
18
+ font-size: 14px;
19
+ }
15
20
  .header-button {
16
21
  height: 40px;
17
22
  width: 40px;
@@ -100,7 +100,7 @@ table {
100
100
  display: flex;
101
101
  align-items: center;
102
102
  justify-content: center;
103
- padding: 0 4px;
103
+ padding: 0 8px;
104
104
  }
105
105
 
106
106
  //// Footer ////
@@ -2,7 +2,7 @@
2
2
  display: flex;
3
3
  overflow: auto;
4
4
  border-bottom: var(--border);
5
- padding-bottom: 4px;
5
+ flex-shrink: 0;
6
6
  &::-webkit-scrollbar {
7
7
  height: 5px;
8
8
  }
@@ -97,7 +97,7 @@ export interface ITableDataItemCells {
97
97
  }
98
98
 
99
99
  export interface ITableDataActions<T = unknown> {
100
- hasEditAccess: boolean;
100
+ hasEditAccess?: boolean;
101
101
  actions?: (item?: T) => {
102
102
  label: string;
103
103
  onClick: () => void;
@@ -3,10 +3,10 @@ export const inputPattern = {
3
3
  businessCode: '^\\d{8}$',
4
4
  umcn: '^\\d{13}$',
5
5
  idCardNumber: '^\\d{9}$',
6
- phoneNumber: '^\\d{8,9}$',
6
+ phoneNumber: '^\\+\\d{11,13}$',
7
7
  port: '^\\d{4}$',
8
8
  year: '^\\d{4}$',
9
9
  number: '^\\d*$',
10
10
  strongPassword: '^.*(?=.{8,})(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[^a-zA-Z0-9]).*$',
11
- // email: '\\S+@\\S+\\.\\S+',
11
+ email: '\\S+@\\S+\\.\\S+',
12
12
  };
@@ -14,17 +14,14 @@ export const deleteProps = <T extends Record<string, any>>(
14
14
  return newObj as Partial<T>;
15
15
  };
16
16
 
17
- export const deletePropsThatEndsWith = <T extends Record<string, any>>(
18
- obj: T,
19
- endsWith: string
20
- ) => {
17
+ export const deletePropsThatEndsWith = <T>(obj: T, endsWith: string) => {
21
18
  const newObj = { ...obj };
22
19
  for (const prop in newObj) {
23
20
  if (prop.endsWith(endsWith)) {
24
21
  delete newObj[prop];
25
22
  }
26
23
  }
27
- return newObj;
24
+ return newObj as Partial<T>;
28
25
  };
29
26
 
30
27
  export const deleteEmptyProps = <T extends Record<string, any>>(obj: T): T =>
@@ -102,3 +99,16 @@ export const getNotificationValues = (
102
99
  }
103
100
  return { ...obj, [item.key]: processedValue };
104
101
  }, {});
102
+
103
+ export const flattenTreeForSelect = (items: any[], depth = 0, maxDepth = 5): any[] => {
104
+ if (!Array.isArray(items)) return [];
105
+ const indent = '\u00A0'.repeat(Math.min(depth, maxDepth) * 3);
106
+ return items.flatMap(node => [
107
+ {
108
+ value: node.uuid,
109
+ label: `${indent}${node.code ? node.code + ' - ' : ''}${node.name}`,
110
+ disabled: node.active === false || node.hasUserAccess === false,
111
+ },
112
+ ...(node.children ? flattenTreeForSelect(node.children, depth + 1, maxDepth) : []),
113
+ ]);
114
+ };
@@ -1,258 +0,0 @@
1
- import './select.scss';
2
-
3
- import { useState, useRef, useEffect, ChangeEvent, FC, UIEvent } from 'react';
4
- import clsx from 'clsx';
5
- import { InputWrapper } from '../InputWrapper';
6
- import { createPortal } from 'react-dom';
7
- import { rootDir } from '../../../utils/rootDir';
8
- import { useMenuPosition } from '../../Menu/hooks/useMenuPosition';
9
- import { IMenuPlacement } from '../../../types/IMenu';
10
-
11
- export interface OptionType {
12
- label: string;
13
- value: any;
14
- }
15
-
16
- // interface LoadOptionsParams {
17
- // inputValue: string;
18
- // loadedOptions: OptionType[];
19
- // page: number;
20
- // }
21
-
22
- interface LoadOptionsResponse {
23
- options: OptionType[];
24
- hasMore: boolean;
25
- }
26
-
27
- interface CustomSelectProps {
28
- label: string;
29
- value?: any;
30
- setValue: (option: OptionType | null) => void;
31
- required?: boolean;
32
- disabled?: boolean;
33
- isMulti?: boolean;
34
- isAsync?: boolean;
35
- isCreatable?: boolean;
36
- options?: OptionType[];
37
- placeholder?: string;
38
- loadOptions?: (
39
- inputValue: string,
40
- loadedOptions: OptionType[],
41
- params: { page: number }
42
- ) => Promise<LoadOptionsResponse>;
43
- onCreateOption?: (inputValue: string) => Promise<OptionType>;
44
- isClearable: boolean;
45
- onClearInput?: () => void;
46
- helperText?: string;
47
- errorText?: string;
48
- error?: boolean;
49
- menuPlacement?: IMenuPlacement;
50
- className?: string;
51
- // minWidth?: number;
52
- }
53
-
54
- export const Select: FC<CustomSelectProps> = ({
55
- label,
56
- value,
57
- setValue,
58
- onCreateOption,
59
- required,
60
- disabled,
61
- options = [],
62
- loadOptions,
63
- placeholder = 'Select...',
64
- isMulti,
65
- isAsync = false,
66
- isCreatable = false,
67
- isClearable = true,
68
- onClearInput,
69
- helperText,
70
- errorText,
71
- error,
72
- menuPlacement = 'bottom-left',
73
- className,
74
- // minWidth,
75
- }) => {
76
- const [inputValue, setInputValue] = useState<string | null>(null);
77
- const [dropdownVisible, setDropdownVisible] = useState(false);
78
- const [filteredOptions, setFilteredOptions] = useState<OptionType[]>([]);
79
- const [page, setPage] = useState(0);
80
- const [index, setIndex] = useState<number | null>(null);
81
- const [hasMore, setHasMore] = useState(true);
82
-
83
- const containerRef = useRef<HTMLDivElement>(null);
84
- const dropdownRef = useRef<HTMLDivElement>(null);
85
-
86
- const menuStyle = useMenuPosition({
87
- isOpen: dropdownVisible,
88
- placement: menuPlacement,
89
- containerRef,
90
- menuRef: dropdownRef,
91
- withMinWidth: true,
92
- });
93
-
94
- useEffect(() => {
95
- if (!isAsync) {
96
- const filtered = inputValue
97
- ? options.filter(opt =>
98
- opt.label.toLowerCase().includes(inputValue.toLowerCase())
99
- )
100
- : options;
101
- setFilteredOptions(filtered);
102
- }
103
- }, [inputValue, options, isAsync]);
104
-
105
- useEffect(() => {
106
- if (isAsync && loadOptions) {
107
- loadOptions(inputValue ?? '', filteredOptions, { page }).then(
108
- ({ options: newOptions, hasMore }) => {
109
- setFilteredOptions(prev => [...prev, ...newOptions]);
110
- setHasMore(hasMore);
111
- }
112
- );
113
- }
114
- // eslint-disable-next-line react-hooks/exhaustive-deps
115
- }, [page]);
116
-
117
- const handleOptionClick = (option: OptionType) => {
118
- setValue(option);
119
- setInputValue(null);
120
- setTimeout(() => {
121
- setIndex(null);
122
- // setDropdownVisible(false);
123
- });
124
- };
125
-
126
- const handleInput = (e: ChangeEvent<HTMLInputElement>) => {
127
- const inputValue = e.target.value;
128
- setInputValue(
129
- e.target.defaultValue === value?.label
130
- ? // @ts-ignore
131
- (e.nativeEvent?.data ?? '')
132
- : inputValue
133
- );
134
- // setFilteredOptions([]);
135
- setPage(0);
136
- if (isAsync && loadOptions) {
137
- loadOptions(inputValue, [], { page: 0 }).then(({ options, hasMore }) => {
138
- setFilteredOptions(options);
139
- setHasMore(hasMore);
140
- });
141
- }
142
- };
143
-
144
- const handleScroll = (e: UIEvent<HTMLDivElement>) => {
145
- const { scrollTop, scrollHeight, clientHeight } = e.currentTarget;
146
- if (scrollHeight - scrollTop === clientHeight && hasMore) {
147
- setPage(prev => prev + 1);
148
- }
149
- };
150
-
151
- const handleCreate = async () => {
152
- if (onCreateOption && inputValue?.trim()) {
153
- const newOption = await onCreateOption(inputValue);
154
- setFilteredOptions(prev => [newOption, ...prev]);
155
- setValue(newOption);
156
- setInputValue(null);
157
- setDropdownVisible(false);
158
- }
159
- };
160
-
161
- return (
162
- <div
163
- className="customSelect"
164
- onFocus={() => setDropdownVisible(true)}
165
- onBlur={() => {
166
- setDropdownVisible(false);
167
- setInputValue(null);
168
- }}
169
- >
170
- <InputWrapper
171
- label={label}
172
- required={required}
173
- disabled={disabled}
174
- // endText={endText}
175
- // endButton={endButton}
176
- onClearInput={
177
- isClearable && value
178
- ? () => {
179
- setValue(null);
180
- setInputValue('');
181
- // setSelectedOption(null);
182
- }
183
- : undefined
184
- }
185
- helperText={helperText}
186
- errorText={errorText}
187
- error={error}
188
- inputFieldRef={containerRef}
189
- className={className}
190
- >
191
- <input
192
- value={inputValue ?? value?.label ?? ''}
193
- onChange={handleInput}
194
- required={required}
195
- disabled={disabled}
196
- // onFocus={e => e.currentTarget.select()}
197
- // autoFocus={autoFocus}
198
- placeholder={value?.label || placeholder}
199
- onKeyDown={e => {
200
- if (e.key === 'ArrowUp') {
201
- e.preventDefault();
202
- if (index === null || index === 0) {
203
- setIndex(filteredOptions.length - 1);
204
- } else {
205
- setIndex(prev => prev! - 1);
206
- }
207
- } else if (e.key === 'ArrowDown') {
208
- e.preventDefault();
209
- if (index === null || index === filteredOptions.length - 1) {
210
- setIndex(0);
211
- } else {
212
- setIndex(prev => prev! + 1);
213
- dropdownRef.current?.scrollTo({ top: 20 * ((index ?? 0) + 1) });
214
- }
215
- } else if (e.key === 'Enter' && index !== null) {
216
- e.preventDefault();
217
- e.currentTarget.blur();
218
- handleOptionClick(filteredOptions[index]);
219
- } else if (e.key === 'Escape') {
220
- e.preventDefault();
221
- e.currentTarget.blur();
222
- }
223
- }}
224
- />
225
- </InputWrapper>
226
-
227
- {dropdownVisible
228
- ? createPortal(
229
- <div
230
- ref={dropdownRef}
231
- className="select-dropdown"
232
- onScroll={handleScroll}
233
- style={menuStyle}
234
- >
235
- {filteredOptions.map((option, i) => (
236
- <div
237
- key={i}
238
- className={clsx('option', { hover: index === i })}
239
- onMouseDown={() => handleOptionClick(option)}
240
- >
241
- {option.label}
242
- </div>
243
- ))}
244
- {!filteredOptions.length && <div className="option">No options</div>}
245
- {isCreatable &&
246
- inputValue &&
247
- !filteredOptions.some(opt => opt.label === inputValue) && (
248
- <div className="option createOption" onClick={handleCreate}>
249
- {`Create ${inputValue}`}
250
- </div>
251
- )}
252
- </div>,
253
- rootDir
254
- )
255
- : null}
256
- </div>
257
- );
258
- };
@@ -1,42 +0,0 @@
1
- .customSelect {
2
- position: relative;
3
- width: 300px;
4
- font-family: sans-serif;
5
-
6
- .inputWrapper {
7
- input {
8
- width: 100%;
9
- padding: 8px 12px;
10
- border: 1px solid #ccc;
11
- border-radius: 4px;
12
- font-size: 14px;
13
- }
14
- }
15
- }
16
-
17
- .select-dropdown {
18
- position: absolute;
19
- z-index: 1000;
20
- // width: 100%;
21
- min-width: 200px;
22
- max-height: 200px;
23
- overflow-y: auto;
24
- background: #fff;
25
- border: var(--border);
26
- border-radius: 8px;
27
- // border-radius: 0 0 8px 8px;
28
- margin-top: 2px;
29
- .option {
30
- padding: 8px 12px;
31
- cursor: pointer;
32
-
33
- &.hover,
34
- &:hover {
35
- background-color: #f5f5f5;
36
- }
37
- }
38
- .createOption {
39
- font-weight: bold;
40
- color: #007bff;
41
- }
42
- }