@inceptionbg/iui 2.0.22 → 2.0.24

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 (237) hide show
  1. package/dist/NoAccessPage-CJisyKrk.js +2 -0
  2. package/dist/{NoAccessPage-BmizYfw0.js.map → NoAccessPage-CJisyKrk.js.map} +1 -1
  3. package/dist/NotFoundPage-BeRit0kr.js +2 -0
  4. package/dist/{NotFoundPage-Cv544vAr.js.map → NotFoundPage-BeRit0kr.js.map} +1 -1
  5. package/dist/icons/index.d.ts +3 -1
  6. package/dist/icons/index.js +1 -1
  7. package/dist/index.d.ts +452 -408
  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/GridTable/GridTable.tsx +1 -1
  12. package/idea/Menu/Menu.tsx +5 -3
  13. package/idea/Menu/MenuItem.tsx +3 -2
  14. package/idea/Menu/hooks/useMenuControl.ts +1 -1
  15. package/idea/Menu.tsx +3 -2
  16. package/idea/NoAccessInfo.tsx +1 -1
  17. package/idea/Table/Components/Edit/ItemActionsMenu.tsx +2 -1
  18. package/idea/Table/Components/Edit/ItemEditOptionsButtons.tsx +1 -1
  19. package/idea/Table/Components/Edit/TableEditRow.tsx +3 -2
  20. package/idea/Table/Components/FilterItem.tsx +2 -2
  21. package/idea/Table/Components/Header/TableHeader.tsx +3 -2
  22. package/idea/Table/Components/Header/TableHeaderRow.tsx +2 -2
  23. package/idea/Table/Components/Print/CustomTablePrint.tsx +3 -2
  24. package/idea/Table/Components/SetSortList.tsx +2 -2
  25. package/idea/Table/Components/SetTableFilter.tsx +3 -2
  26. package/idea/Table/Components/TableFooter.tsx +6 -4
  27. package/idea/Table/Components/TableOptions.tsx +3 -2
  28. package/idea/Table/Table.tsx +3 -2
  29. package/idea/Table/hooks/useTableKeyboard.ts +2 -2
  30. package/package.json +1 -1
  31. package/src/assets/icons/duotone/faBell.ts +17 -17
  32. package/src/assets/icons/duotone/faCircleUser.ts +17 -17
  33. package/src/assets/icons/index.ts +25 -24
  34. package/src/assets/icons/light/faArrowDownShortWide.ts +15 -15
  35. package/src/assets/icons/light/faArrowDownWideShort.ts +15 -15
  36. package/src/assets/icons/light/faArrowLeft.ts +5 -5
  37. package/src/assets/icons/light/faArrowRight.ts +5 -5
  38. package/src/assets/icons/light/faArrowUpArrowDown.ts +15 -15
  39. package/src/assets/icons/light/faArrowUpRightFromSquare.ts +15 -15
  40. package/src/assets/icons/light/faArrowsToLine.ts +15 -15
  41. package/src/assets/icons/light/faArrowsUpDown.ts +15 -15
  42. package/src/assets/icons/light/faBell.ts +15 -15
  43. package/src/assets/icons/light/faBookmark.ts +15 -15
  44. package/src/assets/icons/light/faBookmarkSlash.ts +15 -15
  45. package/src/assets/icons/light/faCalendarPlus.ts +15 -15
  46. package/src/assets/icons/light/faCheck.ts +15 -15
  47. package/src/assets/icons/light/faChevronDown.ts +15 -15
  48. package/src/assets/icons/light/faChevronRight.ts +15 -15
  49. package/src/assets/icons/light/faCircleInfo.ts +15 -15
  50. package/src/assets/icons/light/faCircleXmark.ts +15 -15
  51. package/src/assets/icons/light/faClipboardCheck.ts +15 -15
  52. package/src/assets/icons/light/faClockRotateLeft.ts +15 -15
  53. package/src/assets/icons/light/faEllipsisVertical.ts +15 -15
  54. package/src/assets/icons/light/faEnvelope.ts +15 -15
  55. package/src/assets/icons/light/faEye.ts +15 -15
  56. package/src/assets/icons/light/faEyeSlash.ts +15 -15
  57. package/src/assets/icons/light/faFilter.ts +15 -15
  58. package/src/assets/icons/light/faGear.ts +15 -15
  59. package/src/assets/icons/light/faHouse.ts +15 -15
  60. package/src/assets/icons/light/faIdBadge.ts +15 -15
  61. package/src/assets/icons/light/faLineColumns.ts +15 -15
  62. package/src/assets/icons/light/faLink.ts +15 -15
  63. package/src/assets/icons/light/faMagnifyingGlass.ts +15 -15
  64. package/src/assets/icons/light/faPen.ts +15 -15
  65. package/src/assets/icons/light/faPrint.ts +15 -15
  66. package/src/assets/icons/light/faQuestion.ts +15 -15
  67. package/src/assets/icons/light/faRotateRight.ts +15 -15
  68. package/src/assets/icons/light/faTrashCan.ts +15 -15
  69. package/src/assets/icons/light/faTriangleExclamation.ts +15 -15
  70. package/src/assets/icons/light/faXmark.ts +15 -15
  71. package/src/assets/icons/regular/faArrowLeft.ts +15 -15
  72. package/src/assets/icons/regular/faArrowRightArrowLeft.ts +15 -15
  73. package/src/assets/icons/regular/faCircleCheck.ts +15 -15
  74. package/src/assets/icons/regular/faCircleExclamation.ts +15 -15
  75. package/src/assets/icons/regular/faCircleInfo.ts +15 -15
  76. package/src/assets/icons/regular/faFileArrowDown.ts +15 -15
  77. package/src/assets/icons/regular/faFilterCircleXmark.ts +15 -15
  78. package/src/assets/icons/regular/faTriangleExclamation.ts +15 -15
  79. package/src/assets/icons/solid/faAngleLeft.ts +15 -15
  80. package/src/assets/icons/solid/faAngleRight.ts +15 -15
  81. package/src/assets/icons/solid/faArrowDownWideShort.ts +15 -15
  82. package/src/assets/icons/solid/faCaretDown.ts +15 -15
  83. package/src/assets/icons/solid/faCheck.ts +15 -15
  84. package/src/assets/icons/solid/faEllipsisVertical.ts +15 -15
  85. package/src/assets/icons/solid/faEnvelopeDot.ts +15 -15
  86. package/src/assets/icons/solid/faFilter.ts +15 -15
  87. package/src/assets/icons/solid/faFloppyDisk.ts +15 -15
  88. package/src/assets/icons/solid/faGripDotsVertical.ts +15 -15
  89. package/src/assets/icons/solid/faListUl.ts +15 -15
  90. package/src/assets/icons/solid/faMinus.ts +15 -15
  91. package/src/assets/icons/solid/faPlus.ts +15 -15
  92. package/src/assets/icons/solid/faPrint.ts +15 -15
  93. package/src/assets/icons/solid/faRotateRight.ts +15 -15
  94. package/src/assets/icons/solid/faXmark.ts +15 -15
  95. package/src/components/Accordions/Accordions.tsx +75 -74
  96. package/src/components/Alert/Alert.tsx +31 -31
  97. package/src/components/Badge/DotBadge.tsx +16 -16
  98. package/src/components/Badge/NotificationBadge.tsx +29 -29
  99. package/src/components/Badge/PillBadge.tsx +13 -13
  100. package/src/components/Button/Button.tsx +56 -56
  101. package/src/components/Button/IconButton.tsx +51 -51
  102. package/src/components/Button/SplitButton.tsx +91 -91
  103. package/src/components/Dashboard/Dashboard.tsx +9 -9
  104. package/src/components/Dashboard/DashboardWidget.tsx +44 -44
  105. package/src/components/Dashboard/FastLinksWidget/FastLinksWidget.tsx +37 -37
  106. package/src/components/Dialog/Dialog.tsx +166 -162
  107. package/src/components/Dialog/components/DialogFooter.tsx +100 -98
  108. package/src/components/Header/Components/EnvBadge.tsx +17 -17
  109. package/src/components/Header/Components/ModuleSelect.tsx +68 -68
  110. package/src/components/Header/Components/Notifications.tsx +202 -208
  111. package/src/components/Header/Components/UserMenu.tsx +52 -52
  112. package/src/components/Header/Header.tsx +37 -36
  113. package/src/components/Helper/Collapse.tsx +53 -52
  114. package/src/components/Inputs/Checkbox.tsx +53 -53
  115. package/src/components/Inputs/CurrencyInput.tsx +124 -123
  116. package/src/components/Inputs/DateInput/DateInput.tsx +184 -183
  117. package/src/components/Inputs/DateInput/components/DatePartInput.tsx +159 -158
  118. package/src/components/Inputs/InputWrapper.tsx +95 -95
  119. package/src/components/Inputs/NumberInput.tsx +86 -86
  120. package/src/components/Inputs/PasswordInput.tsx +40 -39
  121. package/src/components/Inputs/PhoneInput/PhoneInput.tsx +108 -0
  122. package/src/components/Inputs/PhoneInput/utils/countryCode.ts +20 -0
  123. package/src/components/Inputs/Radio.tsx +59 -59
  124. package/src/components/Inputs/RadioGroup.tsx +48 -48
  125. package/src/components/Inputs/RadioLarge.tsx +39 -39
  126. package/src/components/Inputs/SearchInput.tsx +46 -45
  127. package/src/components/Inputs/Selects/Select.tsx +17 -17
  128. package/src/components/Inputs/Selects/components/CustomSelectComponents.tsx +20 -19
  129. package/src/components/Inputs/Selects/components/SelectWrapper.tsx +118 -118
  130. package/src/components/Inputs/Selects/utils/selectStyles.ts +101 -101
  131. package/src/components/Inputs/TextAreaInput.tsx +68 -67
  132. package/src/components/Inputs/TextInput.tsx +100 -99
  133. package/src/components/Inputs/TimeInput/TimeInput.tsx +81 -81
  134. package/src/components/List/List.tsx +21 -20
  135. package/src/components/List/ListItem.tsx +70 -69
  136. package/src/components/Loader/Loader.tsx +59 -53
  137. package/src/components/Loader/ProgressBar.tsx +41 -41
  138. package/src/components/Menu/Menu.tsx +81 -80
  139. package/src/components/Menu/MenuItem.tsx +46 -46
  140. package/src/components/Menu/NewMenu.tsx +63 -63
  141. package/src/components/Menu/hooks/useMenuPosition.tsx +116 -115
  142. package/src/components/Pullover/Pullover.tsx +197 -196
  143. package/src/components/Router/Router.tsx +52 -51
  144. package/src/components/Sidebar/AddButton.tsx +22 -22
  145. package/src/components/Sidebar/Sidebar.tsx +85 -83
  146. package/src/components/Sidebar/SidebarItem.tsx +84 -84
  147. package/src/components/Sidebar/types/ISidebar.ts +28 -28
  148. package/src/components/Table/Table.tsx +259 -258
  149. package/src/components/Table/components/columns/ColumnsList.tsx +60 -59
  150. package/src/components/Table/components/columns/TableColumnsEdit.tsx +114 -112
  151. package/src/components/Table/components/edit/TableEditRow.tsx +78 -77
  152. package/src/components/Table/components/filters/FilterItem.tsx +15 -15
  153. package/src/components/Table/components/filters/TableFilters.tsx +126 -125
  154. package/src/components/Table/components/footer/TableFooter.tsx +126 -124
  155. package/src/components/Table/components/header/TableHeader.tsx +40 -40
  156. package/src/components/Table/components/header/TableHeaderRow.tsx +57 -57
  157. package/src/components/Table/components/items/TableItemActions.tsx +78 -78
  158. package/src/components/Table/components/print/TablePrint.tsx +200 -199
  159. package/src/components/Table/components/select/TableSelect.tsx +50 -49
  160. package/src/components/Table/components/sort/TableSort.tsx +73 -72
  161. package/src/components/Table/components/templates/CreateTemplateDialog.tsx +58 -48
  162. package/src/components/Table/components/templates/TableTemplates.tsx +65 -112
  163. package/src/components/Table/components/templates/TemplatesPullover.tsx +88 -0
  164. package/src/components/Table/contexts/TableContext.tsx +116 -123
  165. package/src/components/Table/hooks/localHooks/useLocalTableColumns.tsx +70 -70
  166. package/src/components/Table/hooks/localHooks/useLocalTableData.tsx +84 -84
  167. package/src/components/Table/hooks/localHooks/useLocalTableKeyboard.ts +176 -177
  168. package/src/components/Table/hooks/localHooks/useLocalTablePagination.ts +12 -12
  169. package/src/components/Table/hooks/useTableColumns.ts +34 -34
  170. package/src/components/Table/hooks/useTableEdit.tsx +140 -140
  171. package/src/components/Table/hooks/useTableFilterFields.tsx +150 -150
  172. package/src/components/Table/hooks/useTablePagination.ts +19 -19
  173. package/src/components/Table/hooks/useTablePrint.ts +83 -83
  174. package/src/components/Table/hooks/useTableSearch.ts +31 -30
  175. package/src/components/Table/hooks/useTableSelect.ts +19 -19
  176. package/src/components/Table/hooks/useTableSort.ts +8 -8
  177. package/src/components/Tabs/Tabs.tsx +68 -67
  178. package/src/components/Tooltip/Tooltip.tsx +191 -200
  179. package/src/components/Tree/Tree.tsx +22 -22
  180. package/src/components/Tree/TreeItem.tsx +57 -56
  181. package/src/components/Wrappers/AppLayout.tsx +17 -17
  182. package/src/components/Wrappers/ConditionalWrapper.tsx +10 -10
  183. package/src/components/Wrappers/FormWrapper.tsx +84 -83
  184. package/src/components/Wrappers/PageLayout.tsx +156 -155
  185. package/src/hooks/useBackgroundClose.ts +19 -18
  186. package/src/hooks/useGetFocusableElements.ts +43 -42
  187. package/src/hooks/useIsMenuOpen.ts +11 -11
  188. package/src/hooks/useLocalPopoverControl.ts +32 -32
  189. package/src/hooks/useOnEsc.ts +14 -14
  190. package/src/hooks/usePopupControl.ts +22 -22
  191. package/src/hooks/useZendesk.ts +21 -21
  192. package/src/index.ts +379 -382
  193. package/src/pages/NoAccessPage.tsx +27 -27
  194. package/src/pages/NotFoundPage.tsx +26 -26
  195. package/src/styles/common/helpers/_size.scss +0 -3
  196. package/src/styles/components/_accordions.scss +2 -1
  197. package/src/styles/components/_buttonSplit.scss +4 -29
  198. package/src/styles/components/_dialog.scss +2 -2
  199. package/src/styles/components/_input.scss +9 -0
  200. package/src/styles/components/_page.scss +2 -3
  201. package/src/types/IBasic.ts +32 -31
  202. package/src/types/ICountryCode.ts +5 -0
  203. package/src/types/IError.ts +5 -5
  204. package/src/types/IHeader.ts +40 -40
  205. package/src/types/IInfo.ts +1 -1
  206. package/src/types/IKeyboard.ts +33 -33
  207. package/src/types/IMenu.ts +19 -19
  208. package/src/types/INotifications.ts +15 -15
  209. package/src/types/IPopup.ts +17 -17
  210. package/src/types/IRouter.ts +6 -6
  211. package/src/types/ISelect.ts +54 -54
  212. package/src/types/ITab.ts +1 -1
  213. package/src/types/ITable.ts +290 -279
  214. package/src/types/ITree.ts +6 -6
  215. package/src/utils/InputPatternValidation.ts +12 -12
  216. package/src/utils/dateUtils.ts +32 -32
  217. package/src/utils/fileUtils.ts +177 -177
  218. package/src/utils/i18n/i18nIUICyrilic.ts +119 -116
  219. package/src/utils/i18n/i18nIUILatin.ts +120 -117
  220. package/src/utils/i18n/i18nIUIMe.ts +118 -115
  221. package/src/utils/icons.ts +13 -13
  222. package/src/utils/localStorageHelper.ts +24 -24
  223. package/src/utils/logoUtils.ts +7 -7
  224. package/src/utils/numberUtils.ts +21 -21
  225. package/src/utils/objectUtils.ts +114 -114
  226. package/src/utils/popupUtils.ts +82 -82
  227. package/src/utils/rootDir.ts +1 -1
  228. package/src/utils/stringUtils.ts +18 -18
  229. package/src/utils/tableUtils.ts +130 -130
  230. package/src/utils/toasts.ts +6 -6
  231. package/src/utils/urlUtils.ts +4 -4
  232. package/tsconfig.json +1 -0
  233. package/dist/NoAccessPage-BmizYfw0.js +0 -2
  234. package/dist/NotFoundPage-Cv544vAr.js +0 -2
  235. package/src/components/Dialog/hooks/useDialogKeyboard.ts +0 -42
  236. package/src/components/Inputs/Select2/Select.tsx +0 -258
  237. package/src/components/Inputs/Select2/select.scss +0 -42
@@ -1,200 +1,191 @@
1
- import clsx from 'clsx';
2
- import {
3
- cloneElement,
4
- Dispatch,
5
- FC,
6
- ReactElement,
7
- Ref,
8
- SetStateAction,
9
- useEffect,
10
- useRef,
11
- useState,
12
- } from 'react';
13
- import { createPortal } from 'react-dom';
14
- import { rootDir } from '../../utils/rootDir';
15
-
16
- export type TooltipPosition = 'left' | 'right' | 'top' | 'bottom';
17
-
18
- interface Props {
19
- label?: string;
20
- position?: TooltipPosition;
21
- disabled?: boolean;
22
- singleLine?: boolean;
23
- className?: string;
24
- children: ReactElement;
25
- ref?: Ref<HTMLElement> | null;
26
- }
27
-
28
- export const Tooltip: FC<Props> = ({
29
- label,
30
- position = 'top',
31
- disabled,
32
- singleLine,
33
- className,
34
- children,
35
- ref,
36
- }) => {
37
- const [newPosition, setNewPosition] = useState<TooltipPosition | ''>('');
38
-
39
- const internalRef = useRef<HTMLElement>(null);
40
- const tooltipRef = useRef<HTMLDivElement>(null);
41
-
42
- useEffect(() => {
43
- if (!disabled && !!label) {
44
- const getContainer = () => {
45
- if (ref && 'current' in ref) {
46
- return ref.current;
47
- }
48
- return internalRef.current;
49
- };
50
-
51
- const container = getContainer();
52
- const tooltip = tooltipRef.current;
53
-
54
- const onMouseEnter = () => {
55
- if (container && tooltip) {
56
- setAbsolutePosition(container, tooltip, position, setNewPosition);
57
- tooltip.classList.add('visible');
58
- }
59
- };
60
- const onMouseLeave = () => tooltip?.classList.remove('visible');
61
-
62
- if (container) {
63
- container.addEventListener('mouseenter', onMouseEnter);
64
- container.addEventListener('mouseleave', onMouseLeave);
65
-
66
- return () => {
67
- container.removeEventListener('mouseenter', onMouseEnter);
68
- container.removeEventListener('mouseleave', onMouseLeave);
69
- };
70
- }
71
- }
72
- }, [disabled, label, position, ref]);
73
-
74
- return !!label && !disabled ? (
75
- <>
76
- {/* @ts-ignore */}
77
- {cloneElement(children, { ref: ref || internalRef })}
78
- {createPortal(
79
- <div
80
- ref={tooltipRef}
81
- className={clsx('tooltip-container', className, {
82
- 'no-wrap': singleLine,
83
- })}
84
- >
85
- <div className="tooltip">
86
- <div className={clsx('arrow', newPosition || position)} />
87
- <div>{label}</div>
88
- </div>
89
- </div>,
90
- rootDir
91
- )}
92
- </>
93
- ) : (
94
- children
95
- );
96
- };
97
-
98
- const setAbsolutePosition = (
99
- containerEl: HTMLElement,
100
- targetEl: HTMLDivElement,
101
- position: TooltipPosition,
102
- setNewPosition: Dispatch<SetStateAction<TooltipPosition | ''>>
103
- ) => {
104
- const containerRect = containerEl.getBoundingClientRect();
105
- const tooltipRect = targetEl.getBoundingClientRect();
106
- const margin = 16; // Distance from container
107
- const screenPadding = 8; // Minimum distance from screen edges
108
-
109
- 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(
113
- containerRect.left + containerRect.width / 2 - tooltipRect.width / 2
114
- );
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
- const reverse =
125
- position === 'top' ? top < 0 : bottom + tooltipRect.height > window.innerHeight;
126
-
127
- setNewPosition(reverse ? (position === 'bottom' ? 'top' : 'bottom') : '');
128
-
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`;
142
- targetEl.style.left = `${leftCenter}px`;
143
- } 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`;
171
- } 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`;
199
- }
200
- };
1
+ import type { Dispatch, FC, ReactElement, Ref, SetStateAction } from 'react';
2
+ import { cloneElement, useEffect, useRef, useState } from 'react';
3
+ import clsx from 'clsx';
4
+ import { createPortal } from 'react-dom';
5
+ import { rootDir } from '../../utils/rootDir';
6
+
7
+ export type TooltipPosition = 'left' | 'right' | 'top' | 'bottom';
8
+
9
+ interface Props {
10
+ label?: string;
11
+ position?: TooltipPosition;
12
+ disabled?: boolean;
13
+ singleLine?: boolean;
14
+ className?: string;
15
+ children: ReactElement;
16
+ ref?: Ref<HTMLElement> | null;
17
+ }
18
+
19
+ export const Tooltip: FC<Props> = ({
20
+ label,
21
+ position = 'top',
22
+ disabled,
23
+ singleLine,
24
+ className,
25
+ children,
26
+ ref,
27
+ }) => {
28
+ const [newPosition, setNewPosition] = useState<TooltipPosition | ''>('');
29
+
30
+ const internalRef = useRef<HTMLElement>(null);
31
+ const tooltipRef = useRef<HTMLDivElement>(null);
32
+
33
+ useEffect(() => {
34
+ if (!disabled && !!label) {
35
+ const getContainer = () => {
36
+ if (ref && 'current' in ref) {
37
+ return ref.current;
38
+ }
39
+ return internalRef.current;
40
+ };
41
+
42
+ const container = getContainer();
43
+ const tooltip = tooltipRef.current;
44
+
45
+ const onMouseEnter = () => {
46
+ if (container && tooltip) {
47
+ setAbsolutePosition(container, tooltip, position, setNewPosition);
48
+ tooltip.classList.add('visible');
49
+ }
50
+ };
51
+ const onMouseLeave = () => tooltip?.classList.remove('visible');
52
+
53
+ if (container) {
54
+ container.addEventListener('mouseenter', onMouseEnter);
55
+ container.addEventListener('mouseleave', onMouseLeave);
56
+
57
+ return () => {
58
+ container.removeEventListener('mouseenter', onMouseEnter);
59
+ container.removeEventListener('mouseleave', onMouseLeave);
60
+ };
61
+ }
62
+ }
63
+ }, [disabled, label, position, ref]);
64
+
65
+ return !!label && !disabled ? (
66
+ <>
67
+ {/* @ts-ignore */}
68
+ {cloneElement(children, { ref: ref || internalRef })}
69
+ {createPortal(
70
+ <div
71
+ ref={tooltipRef}
72
+ className={clsx('tooltip-container', className, {
73
+ 'no-wrap': singleLine,
74
+ })}
75
+ >
76
+ <div className="tooltip">
77
+ <div className={clsx('arrow', newPosition || position)} />
78
+ <div>{label}</div>
79
+ </div>
80
+ </div>,
81
+ rootDir
82
+ )}
83
+ </>
84
+ ) : (
85
+ children
86
+ );
87
+ };
88
+
89
+ const setAbsolutePosition = (
90
+ containerEl: HTMLElement,
91
+ targetEl: HTMLDivElement,
92
+ position: TooltipPosition,
93
+ setNewPosition: Dispatch<SetStateAction<TooltipPosition | ''>>
94
+ ) => {
95
+ const containerRect = containerEl.getBoundingClientRect();
96
+ const tooltipRect = targetEl.getBoundingClientRect();
97
+ const margin = 16; // Distance from container
98
+ const screenPadding = 8; // Minimum distance from screen edges
99
+
100
+ if (position === 'bottom' || position === 'top') {
101
+ const bottom = Math.floor(containerRect.bottom + margin);
102
+ const top = Math.floor(containerRect.top - tooltipRect.height - margin);
103
+ let leftCenter = Math.floor(
104
+ containerRect.left + containerRect.width / 2 - tooltipRect.width / 2
105
+ );
106
+
107
+ // Check if tooltip overflows horizontally and adjust
108
+ if (leftCenter < screenPadding) {
109
+ targetEl.style.width = `${tooltipRect.width + leftCenter}px`;
110
+ leftCenter = screenPadding;
111
+ } else if (leftCenter + tooltipRect.width > window.innerWidth - screenPadding) {
112
+ leftCenter = window.innerWidth - tooltipRect.width - screenPadding;
113
+ }
114
+
115
+ const reverse =
116
+ position === 'top' ? top < 0 : bottom + tooltipRect.height > window.innerHeight;
117
+
118
+ setNewPosition(reverse ? (position === 'bottom' ? 'top' : 'bottom') : '');
119
+
120
+ let finalTop =
121
+ position === 'bottom' ? (reverse ? top : bottom) : reverse ? bottom : top;
122
+
123
+ // Ensure tooltip doesn't go above screen
124
+ if (finalTop < screenPadding) {
125
+ finalTop = screenPadding;
126
+ }
127
+ // Ensure tooltip doesn't go below screen
128
+ if (finalTop + tooltipRect.height > window.innerHeight - screenPadding) {
129
+ finalTop = window.innerHeight - tooltipRect.height - screenPadding;
130
+ }
131
+
132
+ targetEl.style.top = `${finalTop}px`;
133
+ targetEl.style.left = `${leftCenter}px`;
134
+ } else if (position === 'right') {
135
+ let finalTop = Math.floor(
136
+ containerRect.top + containerRect.height / 2 - tooltipRect.height / 2
137
+ );
138
+ let finalLeft = Math.floor(containerRect.right + margin);
139
+
140
+ // Check if tooltip overflows vertically and adjust
141
+ if (finalTop < screenPadding) {
142
+ finalTop = screenPadding;
143
+ } else if (finalTop + tooltipRect.height > window.innerHeight - screenPadding) {
144
+ finalTop = window.innerHeight - tooltipRect.height - screenPadding;
145
+ }
146
+
147
+ // Check if tooltip overflows to the right and flip to left
148
+ if (finalLeft + tooltipRect.width > window.innerWidth - screenPadding) {
149
+ finalLeft = Math.floor(containerRect.left - tooltipRect.width - margin);
150
+ setNewPosition('left');
151
+
152
+ // If it still overflows on the left, position it at the edge
153
+ if (finalLeft < screenPadding) {
154
+ finalLeft = screenPadding;
155
+ }
156
+ } else {
157
+ setNewPosition('');
158
+ }
159
+
160
+ targetEl.style.top = `${finalTop}px`;
161
+ targetEl.style.left = `${finalLeft}px`;
162
+ } else if (position === 'left') {
163
+ let finalTop = Math.floor(
164
+ containerRect.top + containerRect.height / 2 - tooltipRect.height / 2
165
+ );
166
+ let finalLeft = Math.floor(containerRect.left - tooltipRect.width - margin);
167
+
168
+ // Check if tooltip overflows vertically and adjust
169
+ if (finalTop < screenPadding) {
170
+ finalTop = screenPadding;
171
+ } else if (finalTop + tooltipRect.height > window.innerHeight - screenPadding) {
172
+ finalTop = window.innerHeight - tooltipRect.height - screenPadding;
173
+ }
174
+
175
+ // Check if tooltip overflows to the left and flip to right
176
+ if (finalLeft < screenPadding) {
177
+ finalLeft = Math.floor(containerRect.right + margin);
178
+ setNewPosition('right');
179
+
180
+ // If it still overflows on the right, position it at the edge
181
+ if (finalLeft + tooltipRect.width > window.innerWidth - screenPadding) {
182
+ finalLeft = window.innerWidth - tooltipRect.width - screenPadding;
183
+ }
184
+ } else {
185
+ setNewPosition('');
186
+ }
187
+
188
+ targetEl.style.top = `${finalTop}px`;
189
+ targetEl.style.left = `${finalLeft}px`;
190
+ }
191
+ };
@@ -1,22 +1,22 @@
1
- import { FC } from 'react';
2
- import { TreeItem } from './TreeItem';
3
- import { ITreeItem } from '../../types/ITree';
4
-
5
- interface Props {
6
- data: ITreeItem[];
7
- selectedItemUuid?: string;
8
- onClick: (itemUuid: string) => void;
9
- }
10
-
11
- export const Tree: FC<Props> = ({ data, selectedItemUuid, onClick }) => (
12
- <div>
13
- {data.map(item => (
14
- <TreeItem
15
- key={item.uuid}
16
- item={item}
17
- onClick={onClick}
18
- selectedItemUuid={selectedItemUuid}
19
- />
20
- ))}
21
- </div>
22
- );
1
+ import type { FC } from 'react';
2
+ import type { ITreeItem } from '../../types/ITree';
3
+ import { TreeItem } from './TreeItem';
4
+
5
+ interface Props {
6
+ data: ITreeItem[];
7
+ selectedItemUuid?: string;
8
+ onClick: (itemUuid: string) => void;
9
+ }
10
+
11
+ export const Tree: FC<Props> = ({ data, selectedItemUuid, onClick }) => (
12
+ <div>
13
+ {data.map(item => (
14
+ <TreeItem
15
+ key={item.uuid}
16
+ item={item}
17
+ onClick={onClick}
18
+ selectedItemUuid={selectedItemUuid}
19
+ />
20
+ ))}
21
+ </div>
22
+ );
@@ -1,56 +1,57 @@
1
- import { FC, useState } from 'react';
2
- import { ITreeItem } from '../../types/ITree';
3
- import clsx from 'clsx';
4
- import { IconButton } from '../Button/IconButton';
5
- import { Collapse } from '../Helper/Collapse';
6
- import { faChevronRight } from '../../assets/icons';
7
-
8
- interface Props {
9
- item: ITreeItem;
10
- onClick: (itemUuid: string) => void;
11
- selectedItemUuid?: string;
12
- className?: string;
13
- }
14
-
15
- export const TreeItem: FC<Props> = ({ item, onClick, selectedItemUuid, className }) => {
16
- const [isOpen, setIsOpen] = useState(false);
17
-
18
- const hasChildren = !!item.children?.length;
19
- return (
20
- <div className={clsx('tree-item', className)}>
21
- <div className="flex align-center">
22
- <div className="extendable-icon">
23
- {hasChildren && (
24
- <IconButton
25
- icon={faChevronRight}
26
- onClick={() => setIsOpen(!isOpen)}
27
- size="s"
28
- className={clsx('rotate', { rotate90: isOpen })}
29
- />
30
- )}
31
- </div>
32
- <div
33
- className={clsx('tree-item-name clickable', {
34
- active: selectedItemUuid === item.uuid,
35
- })}
36
- onClick={() => onClick(item.uuid)}
37
- >
38
- {item.name}
39
- </div>
40
- </div>
41
- {hasChildren && (
42
- <Collapse isOpen={isOpen}>
43
- {item.children?.map((child: ITreeItem) => (
44
- <TreeItem
45
- key={child.uuid}
46
- item={child}
47
- onClick={onClick}
48
- className={clsx('ml-3', className)}
49
- selectedItemUuid={selectedItemUuid}
50
- />
51
- ))}
52
- </Collapse>
53
- )}
54
- </div>
55
- );
56
- };
1
+ import type { FC } from 'react';
2
+ import type { ITreeItem } from '../../types/ITree';
3
+ import { useState } from 'react';
4
+ import clsx from 'clsx';
5
+ import { faChevronRight } from '../../assets/icons';
6
+ import { IconButton } from '../Button/IconButton';
7
+ import { Collapse } from '../Helper/Collapse';
8
+
9
+ interface Props {
10
+ item: ITreeItem;
11
+ onClick: (itemUuid: string) => void;
12
+ selectedItemUuid?: string;
13
+ className?: string;
14
+ }
15
+
16
+ export const TreeItem: FC<Props> = ({ item, onClick, selectedItemUuid, className }) => {
17
+ const [isOpen, setIsOpen] = useState(false);
18
+
19
+ const hasChildren = !!item.children?.length;
20
+ return (
21
+ <div className={clsx('tree-item', className)}>
22
+ <div className="flex align-center">
23
+ <div className="extendable-icon">
24
+ {hasChildren && (
25
+ <IconButton
26
+ icon={faChevronRight}
27
+ onClick={() => setIsOpen(!isOpen)}
28
+ size="s"
29
+ className={clsx('rotate', { rotate90: isOpen })}
30
+ />
31
+ )}
32
+ </div>
33
+ <div
34
+ className={clsx('tree-item-name clickable', {
35
+ active: selectedItemUuid === item.uuid,
36
+ })}
37
+ onClick={() => onClick(item.uuid)}
38
+ >
39
+ {item.name}
40
+ </div>
41
+ </div>
42
+ {hasChildren && (
43
+ <Collapse isOpen={isOpen}>
44
+ {item.children?.map((child: ITreeItem) => (
45
+ <TreeItem
46
+ key={child.uuid}
47
+ item={child}
48
+ onClick={onClick}
49
+ className={clsx('ml-3', className)}
50
+ selectedItemUuid={selectedItemUuid}
51
+ />
52
+ ))}
53
+ </Collapse>
54
+ )}
55
+ </div>
56
+ );
57
+ };
@@ -1,17 +1,17 @@
1
- import { ComponentProps, FC, ReactNode } from 'react';
2
- import { Header } from '../Header/Header';
3
- import { Sidebar } from '../Sidebar/Sidebar';
4
-
5
- interface Props {
6
- header: ComponentProps<typeof Header>;
7
- sidebar: ComponentProps<typeof Sidebar>;
8
- children: ReactNode;
9
- }
10
-
11
- export const AppLayout: FC<Props> = ({ header, sidebar, children }) => (
12
- <div className="app-layout">
13
- <Header {...header} />
14
- <Sidebar {...sidebar} />
15
- <div className="app-content">{children}</div>
16
- </div>
17
- );
1
+ import type { ComponentProps, FC, ReactNode } from 'react';
2
+ import { Header } from '../Header/Header';
3
+ import { Sidebar } from '../Sidebar/Sidebar';
4
+
5
+ interface Props {
6
+ header: ComponentProps<typeof Header>;
7
+ sidebar: ComponentProps<typeof Sidebar>;
8
+ children: ReactNode;
9
+ }
10
+
11
+ export const AppLayout: FC<Props> = ({ header, sidebar, children }) => (
12
+ <div className="app-layout">
13
+ <Header {...header} />
14
+ <Sidebar {...sidebar} />
15
+ <div className="app-content">{children}</div>
16
+ </div>
17
+ );
@@ -1,10 +1,10 @@
1
- import { FC, ReactNode } from 'react';
2
-
3
- interface Props {
4
- condition: boolean;
5
- wrapper: (children: ReactNode) => ReactNode;
6
- children: ReactNode;
7
- }
8
-
9
- export const ConditionalWrapper: FC<Props> = ({ condition, wrapper, children }) =>
10
- condition ? wrapper(children) : children;
1
+ import type { FC, ReactNode } from 'react';
2
+
3
+ interface Props {
4
+ condition: boolean;
5
+ wrapper: (children: ReactNode) => ReactNode;
6
+ children: ReactNode;
7
+ }
8
+
9
+ export const ConditionalWrapper: FC<Props> = ({ condition, wrapper, children }) =>
10
+ condition ? wrapper(children) : children;