@inceptionbg/iui 2.0.5 → 2.0.7

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 (257) hide show
  1. package/dist/{NoAccessPage-C6nBt-PN.js → NoAccessPage-BozT_Suz.js} +2 -2
  2. package/dist/{NoAccessPage-C6nBt-PN.js.map → NoAccessPage-BozT_Suz.js.map} +1 -1
  3. package/dist/{NotFoundPage-DatmJOrr.js → NotFoundPage-WWiekDef.js} +2 -2
  4. package/dist/{NotFoundPage-DatmJOrr.js.map → NotFoundPage-WWiekDef.js.map} +1 -1
  5. package/dist/icons/index.d.ts +43 -0
  6. package/dist/icons/index.js +1 -0
  7. package/dist/index.d.ts +32 -20
  8. package/dist/index.js +1 -1
  9. package/dist/index.js.map +1 -1
  10. package/dist/iui.css +1 -1
  11. package/idea/Menu/Menu.tsx +119 -0
  12. package/idea/Menu/MenuItem.tsx +74 -0
  13. package/idea/Menu/hooks/useMenuControl.ts +13 -0
  14. package/idea/Menu.tsx +132 -0
  15. package/idea/NoAccessInfo.tsx +193 -0
  16. package/idea/Notifications.tsx +245 -0
  17. package/idea/Table2/Components/Columns/ColumnsList.tsx +56 -0
  18. package/idea/Table2/Components/Columns/SetColumnsList.tsx +107 -0
  19. package/idea/Table2/Components/Edit/ItemActionsMenu.tsx +87 -0
  20. package/idea/Table2/Components/Edit/ItemEditOptionsButtons.tsx +32 -0
  21. package/idea/Table2/Components/Edit/TableEditRow.tsx +56 -0
  22. package/idea/Table2/Components/FilterItem.tsx +20 -0
  23. package/idea/Table2/Components/Header/TableHeader.tsx +35 -0
  24. package/idea/Table2/Components/Header/TableHeaderRow.tsx +37 -0
  25. package/idea/Table2/Components/Print/CustomTablePrint.tsx +119 -0
  26. package/idea/Table2/Components/Print/TablePrint.tsx +208 -0
  27. package/idea/Table2/Components/SetSortList.tsx +33 -0
  28. package/idea/Table2/Components/SetTableFilter.tsx +90 -0
  29. package/idea/Table2/Components/TableFooter.tsx +107 -0
  30. package/idea/Table2/Components/TableOptions.tsx +211 -0
  31. package/idea/Table2/Components/Templates/TemplateCreate.tsx +75 -0
  32. package/idea/Table2/Components/Templates/TemplateCreateDefault.tsx +45 -0
  33. package/idea/Table2/Components/Templates/TemplateList.tsx +167 -0
  34. package/idea/Table2/Components/Templates/repo/TemplateRepo.ts +51 -0
  35. package/idea/Table2/Table.tsx +657 -0
  36. package/idea/Table2/_table.scss +300 -0
  37. package/idea/Table2/hooks/useDefaultTemplate.ts +22 -0
  38. package/idea/Table2/hooks/useTableKeyboard.ts +115 -0
  39. package/package.json +9 -4
  40. package/rollup.config.js +80 -0
  41. package/src/assets/icons/duotone/faCircleUser.ts +17 -0
  42. package/src/assets/icons/index.ts +20 -0
  43. package/src/assets/icons/light/faArrowDownShortWide.ts +15 -0
  44. package/src/assets/icons/light/faArrowDownWideShort.ts +15 -0
  45. package/src/assets/icons/light/faArrowUpArrowDown.ts +15 -0
  46. package/src/assets/icons/light/faArrowUpRightFromSquare.ts +15 -0
  47. package/src/assets/icons/light/faArrowsToLine.ts +15 -0
  48. package/src/assets/icons/light/faArrowsUpDown.ts +15 -0
  49. package/src/assets/icons/light/faCalendarPlus.ts +15 -0
  50. package/src/assets/icons/light/faCheck.ts +15 -0
  51. package/src/assets/icons/light/faChevronDown.ts +15 -0
  52. package/src/assets/icons/light/faChevronRight.ts +15 -0
  53. package/src/assets/icons/light/faCircleInfo.ts +15 -0
  54. package/src/assets/icons/light/faCircleXmark.ts +15 -0
  55. package/src/assets/icons/light/faClockRotateLeft.ts +15 -0
  56. package/src/assets/icons/light/faEllipsisVertical.ts +15 -0
  57. package/src/assets/icons/light/faEye.ts +15 -0
  58. package/src/assets/icons/light/faEyeSlash.ts +15 -0
  59. package/src/assets/icons/light/faFilter.ts +15 -0
  60. package/src/assets/icons/light/faGear.ts +15 -0
  61. package/src/assets/icons/light/faHouse.ts +15 -0
  62. package/src/assets/icons/light/faIdBadge.ts +15 -0
  63. package/src/assets/icons/light/faLineColumns.ts +15 -0
  64. package/src/assets/icons/light/faLink.ts +15 -0
  65. package/src/assets/icons/light/faMagnifyingGlass.ts +15 -0
  66. package/src/assets/icons/light/faPenField.ts +15 -0
  67. package/src/assets/icons/light/faPrint.ts +15 -0
  68. package/src/assets/icons/light/faQuestion.ts +15 -0
  69. package/src/assets/icons/light/faRotateRight.ts +15 -0
  70. package/src/assets/icons/light/faTrashCan.ts +15 -0
  71. package/src/assets/icons/light/faTriangleExclamation.ts +15 -0
  72. package/src/assets/icons/light/faXmark.ts +15 -0
  73. package/src/assets/icons/regular/faArrowLeft.ts +15 -0
  74. package/src/assets/icons/regular/faArrowRightArrowLeft.ts +15 -0
  75. package/src/assets/icons/regular/faCircleCheck.ts +15 -0
  76. package/src/assets/icons/regular/faCircleExclamation.ts +15 -0
  77. package/src/assets/icons/regular/faCircleInfo.ts +15 -0
  78. package/src/assets/icons/regular/faFileArrowDown.ts +15 -0
  79. package/src/assets/icons/regular/faFilterCircleXmark.ts +15 -0
  80. package/src/assets/icons/regular/faTriangleExclamation.ts +15 -0
  81. package/src/assets/icons/solid/faAngleLeft.ts +15 -0
  82. package/src/assets/icons/solid/faAngleRight.ts +15 -0
  83. package/src/assets/icons/solid/faArrowDownWideShort.ts +15 -0
  84. package/src/assets/icons/solid/faCaretDown.ts +15 -0
  85. package/src/assets/icons/solid/faCheck.ts +15 -0
  86. package/src/assets/icons/solid/faEllipsisVertical.ts +15 -0
  87. package/src/assets/icons/solid/faFilter.ts +15 -0
  88. package/src/assets/icons/solid/faFloppyDisk.ts +15 -0
  89. package/src/assets/icons/solid/faGripDotsVertical.ts +15 -0
  90. package/src/assets/icons/solid/faListUl.ts +15 -0
  91. package/src/assets/icons/solid/faMagnifyingGlass.ts +15 -0
  92. package/src/assets/icons/solid/faMinus.ts +15 -0
  93. package/src/assets/icons/solid/faPlus.ts +15 -0
  94. package/src/assets/icons/solid/faPrint.ts +15 -0
  95. package/src/assets/icons/solid/faRotateRight.ts +15 -0
  96. package/src/assets/icons/solid/faXmark.ts +15 -0
  97. package/src/assets/images/logo/mts.svg +5703 -0
  98. package/src/assets/images/logo/paperless.svg +21 -0
  99. package/src/assets/images/logo/pismonosa.png +0 -0
  100. package/src/assets/images/not-found.svg +19 -0
  101. package/src/components/Accordions/Accordions.tsx +64 -0
  102. package/src/components/Alert/Alert.tsx +31 -0
  103. package/src/components/Badge/DotBadge.tsx +16 -0
  104. package/src/components/Badge/NotificationBadge.tsx +29 -0
  105. package/src/components/Badge/PillBadge.tsx +13 -0
  106. package/src/components/Button/Button.tsx +56 -0
  107. package/src/components/Button/IconButton.tsx +49 -0
  108. package/src/components/Dashboard/Dashboard.tsx +9 -0
  109. package/src/components/Dashboard/DashboardWidget.tsx +44 -0
  110. package/src/components/Dashboard/FastLinksWidget/FastLinksWidget.tsx +37 -0
  111. package/src/components/Dialog/DeleteItemDialog.tsx +52 -0
  112. package/src/components/Dialog/Dialog.tsx +226 -0
  113. package/src/components/Dialog/hooks/useDialogKeyboard.ts +41 -0
  114. package/src/components/Dialog/hooks/useDialogObserver.ts +21 -0
  115. package/src/components/Header/Components/ModuleSelect.tsx +55 -0
  116. package/src/components/Header/Components/UserMenu.tsx +52 -0
  117. package/src/components/Header/Header.tsx +31 -0
  118. package/src/components/Helper/Collapse.tsx +52 -0
  119. package/src/components/Inputs/Checkbox.tsx +53 -0
  120. package/src/components/Inputs/CurrencyInput.tsx +123 -0
  121. package/src/components/Inputs/DateInput/DateInput.tsx +177 -0
  122. package/src/components/Inputs/DateInput/components/DatePartInput.tsx +154 -0
  123. package/src/components/Inputs/InputWrapper.tsx +90 -0
  124. package/src/components/Inputs/NumberInput.tsx +83 -0
  125. package/src/components/Inputs/PasswordInput.tsx +38 -0
  126. package/src/components/Inputs/Radio.tsx +59 -0
  127. package/src/components/Inputs/RadioGroup.tsx +48 -0
  128. package/src/components/Inputs/RadioLarge.tsx +39 -0
  129. package/src/components/Inputs/SearchInput.tsx +40 -0
  130. package/src/components/Inputs/Select2/Select.tsx +224 -0
  131. package/src/components/Inputs/Select2/select.scss +43 -0
  132. package/src/components/Inputs/Selects/Select.tsx +17 -0
  133. package/src/components/Inputs/Selects/components/CustomSelectComponents.tsx +19 -0
  134. package/src/components/Inputs/Selects/components/SelectWrapper.tsx +126 -0
  135. package/src/components/Inputs/Selects/utils/selectStyles.ts +104 -0
  136. package/src/components/Inputs/TextAreaInput.tsx +67 -0
  137. package/src/components/Inputs/TextInput.tsx +98 -0
  138. package/src/components/Inputs/TimeInput/TimeInput.tsx +81 -0
  139. package/src/components/Loader/Loader.tsx +53 -0
  140. package/src/components/Menu/Menu.tsx +68 -0
  141. package/src/components/Menu/MenuItem.tsx +47 -0
  142. package/src/components/Menu/NewMenu.tsx +66 -0
  143. package/src/components/Menu/hooks/useMenuPosition.tsx +80 -0
  144. package/src/components/Pullover/Pullover.tsx +89 -0
  145. package/src/components/Router/Router.tsx +51 -0
  146. package/src/components/Sidebar/AddButton.tsx +22 -0
  147. package/src/components/Sidebar/Sidebar.tsx +81 -0
  148. package/src/components/Sidebar/SidebarItem.tsx +84 -0
  149. package/src/components/Sidebar/types/ISidebar.ts +28 -0
  150. package/src/components/Table/Components/Columns/ColumnsList.tsx +61 -0
  151. package/src/components/Table/Components/Columns/SetColumnsList.tsx +113 -0
  152. package/src/components/Table/Components/Edit/ItemActionsMenu.tsx +84 -0
  153. package/src/components/Table/Components/Edit/ItemEditOptionsButtons.tsx +31 -0
  154. package/src/components/Table/Components/Edit/TableEditRow.tsx +56 -0
  155. package/src/components/Table/Components/FilterItem.tsx +20 -0
  156. package/src/components/Table/Components/Header/TableHeader.tsx +45 -0
  157. package/src/components/Table/Components/Header/TableHeaderRow.tsx +37 -0
  158. package/src/components/Table/Components/Print/CustomTablePrint.tsx +114 -0
  159. package/src/components/Table/Components/Print/TablePrint.tsx +207 -0
  160. package/src/components/Table/Components/SetSortList.tsx +30 -0
  161. package/src/components/Table/Components/SetTableFilter.tsx +90 -0
  162. package/src/components/Table/Components/TableFooter.tsx +135 -0
  163. package/src/components/Table/Components/TableOptions.tsx +226 -0
  164. package/src/components/Table/Components/Templates/TemplateCreate.tsx +80 -0
  165. package/src/components/Table/Components/Templates/TemplateCreateDefault.tsx +45 -0
  166. package/src/components/Table/Components/Templates/TemplateList.tsx +167 -0
  167. package/src/components/Table/Components/Templates/repo/TemplateRepo.ts +53 -0
  168. package/src/components/Table/Table.tsx +527 -0
  169. package/src/components/Table/hooks/useDefaultTemplate.ts +20 -0
  170. package/src/components/Table/hooks/useTableKeyboard.ts +138 -0
  171. package/src/components/Table/hooks/useTableSelect.ts +11 -0
  172. package/src/components/Tabs/Tabs.tsx +66 -0
  173. package/src/components/Tooltip/Tooltip.tsx +133 -0
  174. package/src/components/Tree/Tree.tsx +22 -0
  175. package/src/components/Tree/TreeItem.tsx +56 -0
  176. package/src/components/Wrappers/AppLayout.tsx +17 -0
  177. package/src/components/Wrappers/ConditionalWrapper.tsx +10 -0
  178. package/src/components/Wrappers/FormWrapper.tsx +81 -0
  179. package/src/components/Wrappers/PageLayout.tsx +152 -0
  180. package/src/hooks/useBackgroundClose.ts +18 -0
  181. package/src/hooks/useIsMenuOpen.ts +11 -0
  182. package/src/hooks/useOnEsc.ts +14 -0
  183. package/src/hooks/useZendesk.ts +21 -0
  184. package/src/index.ts +324 -0
  185. package/src/pages/NoAccessPage.tsx +27 -0
  186. package/src/pages/NotFoundPage.tsx +26 -0
  187. package/src/styles/App.scss +43 -0
  188. package/src/styles/common/_animations.scss +64 -0
  189. package/src/styles/common/_typography.scss +88 -0
  190. package/src/styles/common/helpers/_base.scss +55 -0
  191. package/src/styles/common/helpers/_color.scss +7 -0
  192. package/src/styles/common/helpers/_display.scss +85 -0
  193. package/src/styles/common/helpers/_size.scss +25 -0
  194. package/src/styles/common/maps/_align.scss +21 -0
  195. package/src/styles/common/maps/_info-types.scss +1 -0
  196. package/src/styles/common/maps/_spacing.scss +78 -0
  197. package/src/styles/common/maps/_text.scss +14 -0
  198. package/src/styles/components/_accordions.scss +46 -0
  199. package/src/styles/components/_alert.scss +23 -0
  200. package/src/styles/components/_badge.scss +76 -0
  201. package/src/styles/components/_button.scss +138 -0
  202. package/src/styles/components/_card.scss +24 -0
  203. package/src/styles/components/_dialog.scss +111 -0
  204. package/src/styles/components/_form.scss +8 -0
  205. package/src/styles/components/_header.scss +109 -0
  206. package/src/styles/components/_input.scss +158 -0
  207. package/src/styles/components/_inputCheckbox.scss +105 -0
  208. package/src/styles/components/_inputDateTime.scss +161 -0
  209. package/src/styles/components/_inputRadio.scss +83 -0
  210. package/src/styles/components/_inputSelect.scss +6 -0
  211. package/src/styles/components/_loader.scss +44 -0
  212. package/src/styles/components/_menu-v2.scss +67 -0
  213. package/src/styles/components/_menu.scss +53 -0
  214. package/src/styles/components/_page.scss +62 -0
  215. package/src/styles/components/_portal.scss +8 -0
  216. package/src/styles/components/_print.scss +87 -0
  217. package/src/styles/components/_pullover.scss +43 -0
  218. package/src/styles/components/_scrollbar.scss +18 -0
  219. package/src/styles/components/_sidebar.scss +206 -0
  220. package/src/styles/components/_smallComponents.scss +23 -0
  221. package/src/styles/components/_table.scss +270 -0
  222. package/src/styles/components/_tabs.scss +33 -0
  223. package/src/styles/components/_tooltip.scss +48 -0
  224. package/src/styles/components/_tree.scss +21 -0
  225. package/src/styles/components/_widget.scss +90 -0
  226. package/src/styles/pages/_fullScreenPage.scss +64 -0
  227. package/src/styles/variables/_bp.scss +5 -0
  228. package/src/styles/variables/_variables.scss +130 -0
  229. package/src/types/Base/custom.d.ts +9 -0
  230. package/src/types/IBasic.ts +31 -0
  231. package/src/types/IError.ts +5 -0
  232. package/src/types/IHeader.ts +34 -0
  233. package/src/types/IInfo.ts +1 -0
  234. package/src/types/IKeyboard.ts +37 -0
  235. package/src/types/IMenu.ts +18 -0
  236. package/src/types/IRouter.ts +6 -0
  237. package/src/types/ISelect.ts +52 -0
  238. package/src/types/ITab.ts +10 -0
  239. package/src/types/ITable.ts +249 -0
  240. package/src/types/ITree.ts +6 -0
  241. package/src/utils/DateUtils.ts +32 -0
  242. package/src/utils/InputPatternValidation.ts +12 -0
  243. package/src/utils/LocalStorageHelper.ts +24 -0
  244. package/src/utils/NumberUtils.ts +21 -0
  245. package/src/utils/ObjectUtils.ts +85 -0
  246. package/src/utils/RootDir.ts +1 -0
  247. package/src/utils/StringUtils.ts +18 -0
  248. package/src/utils/TableUtils.ts +130 -0
  249. package/src/utils/Toasts.ts +6 -0
  250. package/src/utils/UrlUtils.ts +4 -0
  251. package/src/utils/fileUtils.ts +176 -0
  252. package/src/utils/i18n/i18nIUICyrilic.ts +90 -0
  253. package/src/utils/i18n/i18nIUILatin.ts +90 -0
  254. package/src/utils/i18n/i18nIUIMe.ts +88 -0
  255. package/src/utils/icons.ts +13 -0
  256. package/tsconfig.icons.json +5 -0
  257. package/tsconfig.json +19 -0
@@ -0,0 +1,224 @@
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
+
7
+ export interface OptionType {
8
+ label: string;
9
+ value: any;
10
+ }
11
+
12
+ // interface LoadOptionsParams {
13
+ // inputValue: string;
14
+ // loadedOptions: OptionType[];
15
+ // page: number;
16
+ // }
17
+
18
+ interface LoadOptionsResponse {
19
+ options: OptionType[];
20
+ hasMore: boolean;
21
+ }
22
+
23
+ interface CustomSelectProps {
24
+ label: string;
25
+ value?: any;
26
+ setValue: (option: OptionType | null) => void;
27
+ required?: boolean;
28
+ disabled?: boolean;
29
+ // isMulti?: boolean;
30
+ isAsync?: boolean;
31
+ isCreatable?: boolean;
32
+ options?: OptionType[];
33
+ loadOptions?: (
34
+ inputValue: string,
35
+ loadedOptions: OptionType[],
36
+ params: { page: number }
37
+ ) => Promise<LoadOptionsResponse>;
38
+ onCreateOption?: (inputValue: string) => Promise<OptionType>;
39
+ placeholder?: string;
40
+ isClearable: boolean;
41
+ // minWidth?: number;
42
+ }
43
+
44
+ export const Select: FC<CustomSelectProps> = ({
45
+ label,
46
+ value,
47
+ setValue,
48
+ onCreateOption,
49
+ required,
50
+ disabled,
51
+ options = [],
52
+ loadOptions,
53
+ isAsync = false,
54
+ isCreatable = false,
55
+ isClearable = true,
56
+ // isMulti,
57
+ // minWidth,
58
+ placeholder = 'Select...',
59
+ }) => {
60
+ const [inputValue, setInputValue] = useState<string | null>(null);
61
+ const [dropdownVisible, setDropdownVisible] = useState(false);
62
+ const [filteredOptions, setFilteredOptions] = useState<OptionType[]>([]);
63
+ const [page, setPage] = useState(0);
64
+ const [index, setIndex] = useState<number | null>(null);
65
+ const [hasMore, setHasMore] = useState(true);
66
+
67
+ const dropdownRef = useRef<HTMLDivElement>(null);
68
+
69
+ useEffect(() => {
70
+ if (!isAsync) {
71
+ const filtered = inputValue
72
+ ? options.filter(opt =>
73
+ opt.label.toLowerCase().includes(inputValue.toLowerCase())
74
+ )
75
+ : options;
76
+ setFilteredOptions(filtered);
77
+ }
78
+ }, [inputValue, options, isAsync]);
79
+
80
+ useEffect(() => {
81
+ if (isAsync && loadOptions) {
82
+ loadOptions(inputValue ?? '', filteredOptions, { page }).then(
83
+ ({ options: newOptions, hasMore }) => {
84
+ setFilteredOptions(prev => [...prev, ...newOptions]);
85
+ setHasMore(hasMore);
86
+ }
87
+ );
88
+ }
89
+ // eslint-disable-next-line react-hooks/exhaustive-deps
90
+ }, [page]);
91
+
92
+ const handleOptionClick = (option: OptionType) => {
93
+ setValue(option);
94
+ setInputValue(null);
95
+ setTimeout(() => {
96
+ setIndex(null);
97
+ setDropdownVisible(false);
98
+ });
99
+ };
100
+
101
+ const handleInput = (e: ChangeEvent<HTMLInputElement>) => {
102
+ const inputValue = e.target.value;
103
+ setInputValue(
104
+ e.target.defaultValue === value?.label
105
+ ? // @ts-ignore
106
+ e.nativeEvent?.data ?? ''
107
+ : inputValue
108
+ );
109
+ // setFilteredOptions([]);
110
+ setPage(0);
111
+ if (isAsync && loadOptions) {
112
+ loadOptions(inputValue, [], { page: 0 }).then(({ options, hasMore }) => {
113
+ setFilteredOptions(options);
114
+ setHasMore(hasMore);
115
+ });
116
+ }
117
+ };
118
+
119
+ const handleScroll = (e: UIEvent<HTMLDivElement>) => {
120
+ const { scrollTop, scrollHeight, clientHeight } = e.currentTarget;
121
+ if (scrollHeight - scrollTop === clientHeight && hasMore) {
122
+ setPage(prev => prev + 1);
123
+ }
124
+ };
125
+
126
+ const handleCreate = async () => {
127
+ if (onCreateOption && inputValue?.trim()) {
128
+ const newOption = await onCreateOption(inputValue);
129
+ setFilteredOptions(prev => [newOption, ...prev]);
130
+ setValue(newOption);
131
+ setInputValue(null);
132
+ setDropdownVisible(false);
133
+ }
134
+ };
135
+
136
+ return (
137
+ <div
138
+ className="customSelect"
139
+ onFocus={() => setDropdownVisible(true)}
140
+ onBlur={() => {
141
+ setDropdownVisible(false);
142
+ setInputValue(null);
143
+ }}
144
+ >
145
+ <InputWrapper
146
+ label={label}
147
+ required={required}
148
+ disabled={disabled}
149
+ // endText={endText}
150
+ // endButton={endButton}
151
+ onClearInput={
152
+ isClearable && value
153
+ ? () => {
154
+ setValue(null);
155
+ setInputValue('');
156
+ // setSelectedOption(null);
157
+ }
158
+ : undefined
159
+ }
160
+ // helperText={helperText}
161
+ // errorText={errorText}
162
+ // error={error}
163
+ // className={className}
164
+ >
165
+ <input
166
+ value={inputValue ?? value?.label ?? ''}
167
+ onChange={handleInput}
168
+ required={required}
169
+ disabled={disabled}
170
+ // onFocus={e => e.currentTarget.select()}
171
+ // autoFocus={autoFocus}
172
+ placeholder={value?.label || placeholder}
173
+ onKeyDown={e => {
174
+ if (e.key === 'ArrowUp') {
175
+ e.preventDefault();
176
+ if (index === null || index === 0) {
177
+ setIndex(filteredOptions.length - 1);
178
+ } else {
179
+ setIndex(prev => prev! - 1);
180
+ }
181
+ } else if (e.key === 'ArrowDown') {
182
+ e.preventDefault();
183
+ if (index === null || index === filteredOptions.length - 1) {
184
+ setIndex(0);
185
+ } else {
186
+ setIndex(prev => prev! + 1);
187
+ dropdownRef.current?.scrollTo({ top: 20 * ((index ?? 0) + 1) });
188
+ }
189
+ } else if (e.key === 'Enter' && index !== null) {
190
+ e.preventDefault();
191
+ e.currentTarget.blur();
192
+ handleOptionClick(options[index]);
193
+ } else if (e.key === 'Escape') {
194
+ e.preventDefault();
195
+ e.currentTarget.blur();
196
+ }
197
+ }}
198
+ />
199
+ </InputWrapper>
200
+
201
+ {dropdownVisible && (
202
+ <div ref={dropdownRef} className="dropdown" onScroll={handleScroll}>
203
+ {filteredOptions.map((option, i) => (
204
+ <div
205
+ key={i}
206
+ className={clsx('option', { hover: index === i })}
207
+ onMouseDown={() => handleOptionClick(option)}
208
+ >
209
+ {option.label}
210
+ </div>
211
+ ))}
212
+ {!filteredOptions.length && <div className="option">No options</div>}
213
+ {isCreatable &&
214
+ inputValue &&
215
+ !filteredOptions.some(opt => opt.label === inputValue) && (
216
+ <div className="option createOption" onClick={handleCreate}>
217
+ {`Create ${inputValue}`}
218
+ </div>
219
+ )}
220
+ </div>
221
+ )}
222
+ </div>
223
+ );
224
+ };
@@ -0,0 +1,43 @@
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
+ .dropdown {
17
+ position: absolute;
18
+ z-index: 1000;
19
+ width: 100%;
20
+ max-height: 200px;
21
+ overflow-y: auto;
22
+ background: #fff;
23
+ border: var(--border);
24
+ border-radius: 8px;
25
+ // border-radius: 0 0 8px 8px;
26
+ margin-top: 2px;
27
+ }
28
+
29
+ .option {
30
+ padding: 8px 12px;
31
+ cursor: pointer;
32
+
33
+ &.hover,
34
+ &:hover {
35
+ background-color: #f5f5f5;
36
+ }
37
+ }
38
+
39
+ .createOption {
40
+ font-weight: bold;
41
+ color: #007bff;
42
+ }
43
+ }
@@ -0,0 +1,17 @@
1
+ import { FC } from 'react';
2
+ import { SelectWrapper } from './components/SelectWrapper';
3
+ import type {
4
+ AsyncSelectProps,
5
+ BasicSelectProps,
6
+ CreatableSelectProps,
7
+ } from '../../../types/ISelect';
8
+
9
+ export const Select: FC<Omit<BasicSelectProps, 'variant'>> = props => (
10
+ <SelectWrapper {...props} variant="basic" />
11
+ );
12
+ export const SelectAsyncPaginate: FC<Omit<AsyncSelectProps, 'variant'>> = props => (
13
+ <SelectWrapper {...props} variant="async" />
14
+ );
15
+ export const SelectCreatable: FC<Omit<CreatableSelectProps, 'variant'>> = props => (
16
+ <SelectWrapper {...props} variant="async-creatable" />
17
+ );
@@ -0,0 +1,19 @@
1
+ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
2
+ import { GroupBase, components } from 'react-select';
3
+ import { type SelectComponents as ISelectComponents } from 'react-select/dist/declarations/src/components';
4
+ import { faChevronDown, faCircleXmark } from '../../../../assets/icons';
5
+
6
+ export const CustomSelectComponents: Partial<
7
+ ISelectComponents<unknown, boolean, GroupBase<unknown>>
8
+ > = {
9
+ DropdownIndicator: props => (
10
+ <components.DropdownIndicator {...props}>
11
+ <FontAwesomeIcon icon={faChevronDown} className="icon" />
12
+ </components.DropdownIndicator>
13
+ ),
14
+ ClearIndicator: props => (
15
+ <components.ClearIndicator {...props}>
16
+ <FontAwesomeIcon icon={faCircleXmark} className="icon" />
17
+ </components.ClearIndicator>
18
+ ),
19
+ };
@@ -0,0 +1,126 @@
1
+ import { forwardRef, useRef } from 'react';
2
+ import ReactSelect from 'react-select';
3
+ import { AsyncPaginate } from 'react-select-async-paginate';
4
+ import AsyncCreatableSelect from 'react-select/async-creatable';
5
+ import { InputWrapper } from '../../InputWrapper';
6
+ import { CustomSelectComponents } from './CustomSelectComponents';
7
+ import { createSelectStyles } from '../utils/selectStyles';
8
+ import { useTranslation } from 'react-i18next';
9
+ import type {
10
+ AsyncSelectProps,
11
+ BasicSelectProps,
12
+ CreatableSelectProps,
13
+ } from '../../../../types/ISelect';
14
+
15
+ export type ISelectProps = BasicSelectProps | AsyncSelectProps | CreatableSelectProps;
16
+
17
+ export const SelectWrapper = forwardRef<any, ISelectProps>((props, forwardedRef) => {
18
+ const ref = useRef(null);
19
+ const { t } = useTranslation();
20
+
21
+ const {
22
+ variant,
23
+ label,
24
+ required,
25
+ disabled,
26
+ helperText,
27
+ error,
28
+ errorText,
29
+ className,
30
+ minWidth,
31
+ menuWidth,
32
+ value,
33
+ isMulti,
34
+ onChange,
35
+ placeholder,
36
+ isClearable = true,
37
+ isOpen,
38
+ onMenuOpen,
39
+ onMenuClose,
40
+ openDirection = 'auto',
41
+ formatOptionLabel,
42
+ autoFocus,
43
+ closeMenuOnSelect,
44
+ noOptionsMessage,
45
+ } = props;
46
+
47
+ const commonProps = {
48
+ value: value ?? (isMulti ? [] : null),
49
+ components: CustomSelectComponents,
50
+ onChange,
51
+ placeholder,
52
+ styles: createSelectStyles({ menuWidth }),
53
+ isDisabled: disabled,
54
+ isOptionDisabled: (option: any) => option.disabled,
55
+ isClearable,
56
+ isMulti,
57
+ menuIsOpen: isOpen,
58
+ menuPlacement: openDirection,
59
+ menuPortalTarget: document.querySelector('body'),
60
+ ref: forwardedRef ?? ref,
61
+ autoFocus,
62
+ noOptionsMessage: () => noOptionsMessage || 'Nema opcija',
63
+ onMenuOpen,
64
+ onMenuClose,
65
+ closeMenuOnSelect: closeMenuOnSelect ?? !isMulti,
66
+ formatOptionLabel,
67
+ };
68
+
69
+ const renderSelect = () => {
70
+ switch (variant) {
71
+ case 'basic':
72
+ return <ReactSelect {...commonProps} options={props.options} />;
73
+ case 'async':
74
+ return (
75
+ <AsyncPaginate
76
+ {...commonProps}
77
+ loadOptions={props.loadOptions}
78
+ defaultOptions={props.defaultData ?? true}
79
+ />
80
+ );
81
+ case 'async-creatable':
82
+ return (
83
+ <AsyncCreatableSelect
84
+ {...commonProps}
85
+ loadOptions={props.loadOptions}
86
+ defaultOptions={props.defaultData ?? true}
87
+ onCreateOption={props.onCreate}
88
+ formatCreateLabel={(inputValue: string) => (
89
+ <p>{`${t('FreeText')} "${inputValue}"`}</p>
90
+ )}
91
+ />
92
+ );
93
+ default:
94
+ return null;
95
+ }
96
+ };
97
+
98
+ return (
99
+ <InputWrapper
100
+ label={label}
101
+ required={required}
102
+ disabled={disabled}
103
+ helperText={helperText}
104
+ error={error}
105
+ errorText={errorText}
106
+ className={className}
107
+ minWidth={minWidth}
108
+ heightAuto
109
+ >
110
+ {renderSelect()}
111
+ {required && !disabled && (
112
+ <input
113
+ className="fake-input"
114
+ required
115
+ tabIndex={-1}
116
+ autoComplete="off"
117
+ value={(isMulti ? commonProps.value[0]?.value : commonProps.value?.value) ?? ''}
118
+ onChange={() => {}}
119
+ // onFocus={() =>
120
+ // ((forwardedRef as MutableRefObject<any>) ?? ref).current?.focus()
121
+ // }
122
+ />
123
+ )}
124
+ </InputWrapper>
125
+ );
126
+ });
@@ -0,0 +1,104 @@
1
+ import { StylesConfig } from 'react-select';
2
+
3
+ export const createSelectStyles = ({
4
+ fontSize = 16,
5
+ menuWidth,
6
+ }: {
7
+ fontSize?: number;
8
+ menuWidth?: 'fit-content' | 'max-content' | number;
9
+ }) =>
10
+ ({
11
+ control: provided => ({
12
+ ...provided,
13
+ border: 'none',
14
+ borderWidth: 0,
15
+ boxShadow: 'none',
16
+ width: '100%',
17
+ // minHeight: size === 's' ? 12 : 36,
18
+ }),
19
+ container: provided => ({
20
+ ...provided,
21
+ width: '100%',
22
+ }),
23
+ valueContainer: provided => ({
24
+ ...provided,
25
+ fontSize,
26
+ padding: '6px 0 6px 12px',
27
+ // fontSize: /*size === 's' ? 12 : */ 14,
28
+ // padding: /*size === 's' ? '0 4px' : */ state.isMulti ? '8px 14px' : '10px 14px',
29
+ gap: 4,
30
+ width: '100%',
31
+ }),
32
+ singleValue: provided => ({
33
+ ...provided,
34
+ margin: 0,
35
+ }),
36
+ multiValue: provided => ({
37
+ ...provided,
38
+ backgroundColor: 'unset',
39
+ border: '1px solid var(--neutral-300)',
40
+ borderRadius: 8,
41
+ margin: 0,
42
+ overflow: 'hidden',
43
+ }),
44
+ multiValueLabel: (provided, state) => ({
45
+ ...provided,
46
+ padding: state.isDisabled ? '4px 8px' : provided.padding,
47
+ }),
48
+ multiValueRemove: (provided, state) => ({
49
+ ...provided,
50
+ display: state.isDisabled ? 'none' : provided.display,
51
+ boxSizing: 'content-box',
52
+ color: 'var(--text-disabled)',
53
+ }),
54
+ menu: provided => ({
55
+ ...provided,
56
+ width: menuWidth || '100%',
57
+ minWidth: '100%',
58
+ borderRadius: 8,
59
+ boxShadow: `0px 5px 5px -3px rgb(0 0 0 / 20%), 0px 8px 10px 1px rgba(0, 0, 0, 0.14),
60
+ 0px 3px 14px 2px rgba(0, 0, 0, 0.12);`,
61
+ }),
62
+ menuPortal: provided => ({ ...provided, zIndex: 1001 }),
63
+ input: provided => ({
64
+ ...provided,
65
+ padding: 0,
66
+ margin: 0,
67
+ // height: size === 's' ? 24 : 36,
68
+ }),
69
+ option: (provided, state) => ({
70
+ ...provided,
71
+ fontSize,
72
+ // fontSize: /*size === 's' ? 12 : */ 14,
73
+ // padding: size === 's' ? 4 : provided.padding,
74
+ backgroundColor: state.isSelected
75
+ ? 'var(--primary) !important'
76
+ : state.isFocused
77
+ ? '#eee !important'
78
+ : 'inherit',
79
+ }),
80
+ noOptionsMessage: provided => ({
81
+ ...provided,
82
+ fontSize,
83
+ // fontSize: /*size === 's' ? 12 : */ 14,
84
+ fontStyle: 'italic',
85
+ textAlign: 'left',
86
+ cursor: 'default',
87
+ }),
88
+ placeholder: provided => ({
89
+ ...provided,
90
+ whiteSpace: 'nowrap',
91
+ fontStyle: 'italic',
92
+ color: '#00000050',
93
+ fontWeight: 400,
94
+ userSelect: 'none',
95
+ margin: 0,
96
+ }),
97
+ indicatorSeparator: () => ({ display: 'none' }),
98
+ dropdownIndicator: (provided, state) => ({
99
+ ...provided,
100
+ // padding: size === 's' ? '4px' : provided.padding,
101
+ transition: 'all .2s ease',
102
+ transform: state.selectProps.menuIsOpen ? 'rotate(180deg)' : null,
103
+ }),
104
+ } as StylesConfig);
@@ -0,0 +1,67 @@
1
+ import { FC, InputHTMLAttributes, Ref, useState } from 'react';
2
+ import { InputWrapper } from './InputWrapper';
3
+ import clsx from 'clsx';
4
+
5
+ export interface ITextAreaInputProps {
6
+ label: string;
7
+ value?: string;
8
+ setValue: (value: string) => void;
9
+ required?: boolean;
10
+ disabled?: boolean;
11
+ autoFocus?: boolean;
12
+ rows?: number;
13
+ resize?: boolean;
14
+ placeholder?: string;
15
+ helperText?: string;
16
+ errorText?: string;
17
+ className?: string;
18
+ inputProps?: InputHTMLAttributes<HTMLTextAreaElement>;
19
+ error?: boolean;
20
+ ref?: Ref<HTMLTextAreaElement>;
21
+ }
22
+
23
+ export const TextAreaInput: FC<ITextAreaInputProps> = ({
24
+ label,
25
+ value,
26
+ setValue,
27
+ required,
28
+ disabled,
29
+ autoFocus,
30
+ rows = 4,
31
+ resize,
32
+ placeholder,
33
+ helperText,
34
+ errorText,
35
+ className,
36
+ inputProps,
37
+ error,
38
+ ref,
39
+ }) => {
40
+ const [isAutoFill, setIsAutoFill] = useState(false);
41
+ return (
42
+ <InputWrapper
43
+ label={label}
44
+ required={required}
45
+ helperText={helperText}
46
+ errorText={errorText}
47
+ className={className}
48
+ error={error}
49
+ heightAuto
50
+ >
51
+ <textarea
52
+ ref={ref}
53
+ autoFocus={autoFocus}
54
+ onFocus={() => isAutoFill && setIsAutoFill(false)}
55
+ className={clsx({ resize })}
56
+ placeholder={required && placeholder ? `${placeholder} *` : placeholder}
57
+ value={value || ''}
58
+ onChange={e => setValue(e.target.value)}
59
+ rows={rows}
60
+ required={required}
61
+ disabled={disabled}
62
+ onAnimationStart={() => setIsAutoFill(true)}
63
+ {...inputProps}
64
+ />
65
+ </InputWrapper>
66
+ );
67
+ };
@@ -0,0 +1,98 @@
1
+ import { IconDefinition } from '@fortawesome/fontawesome-svg-core';
2
+ import { FC, FocusEventHandler, InputHTMLAttributes, Ref, useState } from 'react';
3
+ import { InputWrapper } from './InputWrapper';
4
+
5
+ export interface ITextInputProps {
6
+ id?: string;
7
+ label?: string;
8
+ value?: string;
9
+ setValue?: (value: string) => void;
10
+ required?: boolean;
11
+ disabled?: boolean;
12
+ endText?: string;
13
+ endButton?: {
14
+ icon: IconDefinition;
15
+ onClick: () => void;
16
+ disabled?: boolean;
17
+ };
18
+ isClearable?: boolean;
19
+ onClear?: () => void;
20
+ autoFocus?: boolean;
21
+ placeholder?: string;
22
+ pattern?: string;
23
+ helperText?: string;
24
+ errorText?: string;
25
+ onBlur?: FocusEventHandler<HTMLInputElement>;
26
+ onFocus?: FocusEventHandler<HTMLInputElement>;
27
+ error?: boolean;
28
+ inputProps?: InputHTMLAttributes<HTMLInputElement>;
29
+ className?: string;
30
+ ref?: Ref<HTMLInputElement>;
31
+ }
32
+
33
+ export const TextInput: FC<ITextInputProps> = ({
34
+ id,
35
+ label,
36
+ value,
37
+ setValue,
38
+ required,
39
+ disabled,
40
+ endText,
41
+ endButton,
42
+ isClearable = true,
43
+ onClear,
44
+ autoFocus,
45
+ placeholder,
46
+ pattern,
47
+ helperText,
48
+ errorText,
49
+ onBlur,
50
+ onFocus,
51
+ error,
52
+ inputProps,
53
+ className,
54
+ ref,
55
+ }) => {
56
+ const [isAutoFill, setIsAutoFill] = useState(false);
57
+ return (
58
+ <InputWrapper
59
+ label={label}
60
+ required={required}
61
+ disabled={disabled}
62
+ endText={endText}
63
+ endButton={endButton}
64
+ onClearInput={
65
+ isClearable && value
66
+ ? () => {
67
+ setValue?.('');
68
+ onClear?.();
69
+ }
70
+ : undefined
71
+ }
72
+ helperText={helperText}
73
+ errorText={errorText}
74
+ // error={error || !!(pattern && value && !new RegExp(pattern).test(value))}
75
+ error={error}
76
+ className={className}
77
+ >
78
+ <input
79
+ id={id}
80
+ ref={ref}
81
+ autoFocus={autoFocus}
82
+ onFocus={e => {
83
+ isAutoFill && setIsAutoFill(false);
84
+ onFocus?.(e);
85
+ }}
86
+ onBlur={onBlur}
87
+ placeholder={placeholder}
88
+ value={value || ''}
89
+ onChange={setValue ? e => setValue(e.target.value) : undefined}
90
+ required={required}
91
+ disabled={disabled}
92
+ onAnimationStart={() => setIsAutoFill(true)}
93
+ pattern={pattern}
94
+ {...inputProps}
95
+ />
96
+ </InputWrapper>
97
+ );
98
+ };