@inceptionbg/iui 2.0.23 → 2.0.25

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 (230) hide show
  1. package/dist/{NoAccessPage-BmizYfw0.js → NoAccessPage-DTPU8bP2.js} +2 -2
  2. package/dist/{NoAccessPage-BmizYfw0.js.map → NoAccessPage-DTPU8bP2.js.map} +1 -1
  3. package/dist/{NotFoundPage-Cv544vAr.js → NotFoundPage-PZunMooy.js} +2 -2
  4. package/dist/{NotFoundPage-Cv544vAr.js.map → NotFoundPage-PZunMooy.js.map} +1 -1
  5. package/dist/index.d.ts +432 -430
  6. package/dist/index.js +1 -1
  7. package/dist/index.js.map +1 -1
  8. package/dist/iui.css +1 -1
  9. package/idea/GridTable/GridTable.tsx +1 -1
  10. package/idea/Menu/Menu.tsx +5 -3
  11. package/idea/Menu/MenuItem.tsx +3 -2
  12. package/idea/Menu/hooks/useMenuControl.ts +1 -1
  13. package/idea/Menu.tsx +3 -2
  14. package/idea/NoAccessInfo.tsx +1 -1
  15. package/idea/Table/Components/Edit/ItemActionsMenu.tsx +2 -1
  16. package/idea/Table/Components/Edit/ItemEditOptionsButtons.tsx +1 -1
  17. package/idea/Table/Components/Edit/TableEditRow.tsx +3 -2
  18. package/idea/Table/Components/FilterItem.tsx +2 -2
  19. package/idea/Table/Components/Header/TableHeader.tsx +3 -2
  20. package/idea/Table/Components/Header/TableHeaderRow.tsx +2 -2
  21. package/idea/Table/Components/Print/CustomTablePrint.tsx +3 -2
  22. package/idea/Table/Components/SetSortList.tsx +2 -2
  23. package/idea/Table/Components/SetTableFilter.tsx +3 -2
  24. package/idea/Table/Components/TableFooter.tsx +6 -4
  25. package/idea/Table/Components/TableOptions.tsx +3 -2
  26. package/idea/Table/Table.tsx +3 -2
  27. package/idea/Table/hooks/useTableKeyboard.ts +2 -2
  28. package/package.json +1 -1
  29. package/src/assets/icons/duotone/faBell.ts +17 -17
  30. package/src/assets/icons/duotone/faCircleUser.ts +17 -17
  31. package/src/assets/icons/index.ts +25 -25
  32. package/src/assets/icons/light/faArrowDownShortWide.ts +15 -15
  33. package/src/assets/icons/light/faArrowDownWideShort.ts +15 -15
  34. package/src/assets/icons/light/faArrowLeft.ts +5 -5
  35. package/src/assets/icons/light/faArrowRight.ts +5 -5
  36. package/src/assets/icons/light/faArrowUpArrowDown.ts +15 -15
  37. package/src/assets/icons/light/faArrowUpRightFromSquare.ts +15 -15
  38. package/src/assets/icons/light/faArrowsToLine.ts +15 -15
  39. package/src/assets/icons/light/faArrowsUpDown.ts +15 -15
  40. package/src/assets/icons/light/faBell.ts +15 -15
  41. package/src/assets/icons/light/faBookmark.ts +15 -15
  42. package/src/assets/icons/light/faBookmarkSlash.ts +15 -15
  43. package/src/assets/icons/light/faCalendarPlus.ts +15 -15
  44. package/src/assets/icons/light/faCheck.ts +15 -15
  45. package/src/assets/icons/light/faChevronDown.ts +15 -15
  46. package/src/assets/icons/light/faChevronRight.ts +15 -15
  47. package/src/assets/icons/light/faCircleInfo.ts +15 -15
  48. package/src/assets/icons/light/faCircleXmark.ts +15 -15
  49. package/src/assets/icons/light/faClipboardCheck.ts +15 -15
  50. package/src/assets/icons/light/faClockRotateLeft.ts +15 -15
  51. package/src/assets/icons/light/faEllipsisVertical.ts +15 -15
  52. package/src/assets/icons/light/faEnvelope.ts +15 -15
  53. package/src/assets/icons/light/faEye.ts +15 -15
  54. package/src/assets/icons/light/faEyeSlash.ts +15 -15
  55. package/src/assets/icons/light/faFilter.ts +15 -15
  56. package/src/assets/icons/light/faGear.ts +15 -15
  57. package/src/assets/icons/light/faHouse.ts +15 -15
  58. package/src/assets/icons/light/faIdBadge.ts +15 -15
  59. package/src/assets/icons/light/faLineColumns.ts +15 -15
  60. package/src/assets/icons/light/faLink.ts +15 -15
  61. package/src/assets/icons/light/faMagnifyingGlass.ts +15 -15
  62. package/src/assets/icons/light/faPen.ts +15 -15
  63. package/src/assets/icons/light/faPrint.ts +15 -15
  64. package/src/assets/icons/light/faQuestion.ts +15 -15
  65. package/src/assets/icons/light/faRotateRight.ts +15 -15
  66. package/src/assets/icons/light/faTrashCan.ts +15 -15
  67. package/src/assets/icons/light/faTriangleExclamation.ts +15 -15
  68. package/src/assets/icons/light/faXmark.ts +15 -15
  69. package/src/assets/icons/regular/faArrowLeft.ts +15 -15
  70. package/src/assets/icons/regular/faArrowRightArrowLeft.ts +15 -15
  71. package/src/assets/icons/regular/faCircleCheck.ts +15 -15
  72. package/src/assets/icons/regular/faCircleExclamation.ts +15 -15
  73. package/src/assets/icons/regular/faCircleInfo.ts +15 -15
  74. package/src/assets/icons/regular/faFileArrowDown.ts +15 -15
  75. package/src/assets/icons/regular/faFilterCircleXmark.ts +15 -15
  76. package/src/assets/icons/regular/faTriangleExclamation.ts +15 -15
  77. package/src/assets/icons/solid/faAngleLeft.ts +15 -15
  78. package/src/assets/icons/solid/faAngleRight.ts +15 -15
  79. package/src/assets/icons/solid/faArrowDownWideShort.ts +15 -15
  80. package/src/assets/icons/solid/faCaretDown.ts +15 -15
  81. package/src/assets/icons/solid/faCheck.ts +15 -15
  82. package/src/assets/icons/solid/faEllipsisVertical.ts +15 -15
  83. package/src/assets/icons/solid/faEnvelopeDot.ts +15 -15
  84. package/src/assets/icons/solid/faFilter.ts +15 -15
  85. package/src/assets/icons/solid/faFloppyDisk.ts +15 -15
  86. package/src/assets/icons/solid/faGripDotsVertical.ts +15 -15
  87. package/src/assets/icons/solid/faListUl.ts +15 -15
  88. package/src/assets/icons/solid/faMinus.ts +15 -15
  89. package/src/assets/icons/solid/faPlus.ts +15 -15
  90. package/src/assets/icons/solid/faPrint.ts +15 -15
  91. package/src/assets/icons/solid/faRotateRight.ts +15 -15
  92. package/src/assets/icons/solid/faXmark.ts +15 -15
  93. package/src/components/Accordions/Accordions.tsx +75 -74
  94. package/src/components/Alert/Alert.tsx +31 -31
  95. package/src/components/Badge/DotBadge.tsx +16 -16
  96. package/src/components/Badge/NotificationBadge.tsx +29 -29
  97. package/src/components/Badge/PillBadge.tsx +13 -13
  98. package/src/components/Button/Button.tsx +56 -56
  99. package/src/components/Button/IconButton.tsx +51 -51
  100. package/src/components/Button/SplitButton.tsx +91 -91
  101. package/src/components/Dashboard/Dashboard.tsx +9 -9
  102. package/src/components/Dashboard/DashboardWidget.tsx +44 -44
  103. package/src/components/Dashboard/FastLinksWidget/FastLinksWidget.tsx +37 -37
  104. package/src/components/Dialog/Dialog.tsx +166 -164
  105. package/src/components/Dialog/components/DialogFooter.tsx +100 -98
  106. package/src/components/Header/Components/EnvBadge.tsx +17 -17
  107. package/src/components/Header/Components/ModuleSelect.tsx +68 -68
  108. package/src/components/Header/Components/Notifications.tsx +202 -208
  109. package/src/components/Header/Components/UserMenu.tsx +52 -52
  110. package/src/components/Header/Header.tsx +37 -36
  111. package/src/components/Helper/Collapse.tsx +53 -52
  112. package/src/components/Inputs/Checkbox.tsx +53 -53
  113. package/src/components/Inputs/CurrencyInput.tsx +124 -123
  114. package/src/components/Inputs/DateInput/DateInput.tsx +184 -183
  115. package/src/components/Inputs/DateInput/components/DatePartInput.tsx +159 -158
  116. package/src/components/Inputs/InputWrapper.tsx +95 -95
  117. package/src/components/Inputs/NumberInput.tsx +86 -86
  118. package/src/components/Inputs/PasswordInput.tsx +40 -39
  119. package/src/components/Inputs/PhoneInput/PhoneInput.tsx +108 -108
  120. package/src/components/Inputs/PhoneInput/utils/countryCode.ts +20 -20
  121. package/src/components/Inputs/Radio.tsx +59 -59
  122. package/src/components/Inputs/RadioGroup.tsx +48 -48
  123. package/src/components/Inputs/RadioLarge.tsx +39 -39
  124. package/src/components/Inputs/SearchInput.tsx +46 -45
  125. package/src/components/Inputs/Selects/Select.tsx +17 -17
  126. package/src/components/Inputs/Selects/components/CustomSelectComponents.tsx +19 -19
  127. package/src/components/Inputs/Selects/components/SelectWrapper.tsx +118 -118
  128. package/src/components/Inputs/Selects/utils/selectStyles.ts +101 -101
  129. package/src/components/Inputs/TextAreaInput.tsx +68 -67
  130. package/src/components/Inputs/TextInput.tsx +100 -99
  131. package/src/components/Inputs/TimeInput/TimeInput.tsx +81 -81
  132. package/src/components/List/List.tsx +21 -20
  133. package/src/components/List/ListItem.tsx +70 -69
  134. package/src/components/Loader/Loader.tsx +59 -53
  135. package/src/components/Loader/ProgressBar.tsx +41 -41
  136. package/src/components/Menu/Menu.tsx +81 -80
  137. package/src/components/Menu/MenuItem.tsx +46 -46
  138. package/src/components/Menu/NewMenu.tsx +63 -63
  139. package/src/components/Menu/hooks/useMenuPosition.tsx +116 -115
  140. package/src/components/Pullover/Pullover.tsx +197 -196
  141. package/src/components/Router/Router.tsx +52 -51
  142. package/src/components/Sidebar/AddButton.tsx +22 -22
  143. package/src/components/Sidebar/Sidebar.tsx +85 -83
  144. package/src/components/Sidebar/SidebarItem.tsx +84 -84
  145. package/src/components/Sidebar/types/ISidebar.ts +28 -28
  146. package/src/components/Table/Table.tsx +259 -258
  147. package/src/components/Table/components/columns/ColumnsList.tsx +60 -59
  148. package/src/components/Table/components/columns/TableColumnsEdit.tsx +114 -112
  149. package/src/components/Table/components/edit/TableEditRow.tsx +78 -77
  150. package/src/components/Table/components/filters/FilterItem.tsx +15 -15
  151. package/src/components/Table/components/filters/TableFilters.tsx +126 -125
  152. package/src/components/Table/components/footer/TableFooter.tsx +126 -124
  153. package/src/components/Table/components/header/TableHeader.tsx +40 -40
  154. package/src/components/Table/components/header/TableHeaderRow.tsx +57 -57
  155. package/src/components/Table/components/items/TableItemActions.tsx +78 -78
  156. package/src/components/Table/components/print/TablePrint.tsx +200 -199
  157. package/src/components/Table/components/select/TableSelect.tsx +50 -49
  158. package/src/components/Table/components/sort/TableSort.tsx +73 -72
  159. package/src/components/Table/components/templates/CreateTemplateDialog.tsx +58 -57
  160. package/src/components/Table/components/templates/TableTemplates.tsx +65 -64
  161. package/src/components/Table/components/templates/TemplatesPullover.tsx +88 -88
  162. package/src/components/Table/contexts/TableContext.tsx +116 -123
  163. package/src/components/Table/hooks/localHooks/useLocalTableColumns.tsx +70 -70
  164. package/src/components/Table/hooks/localHooks/useLocalTableData.tsx +84 -84
  165. package/src/components/Table/hooks/localHooks/useLocalTableKeyboard.ts +176 -177
  166. package/src/components/Table/hooks/localHooks/useLocalTablePagination.ts +12 -12
  167. package/src/components/Table/hooks/useTableColumns.ts +34 -34
  168. package/src/components/Table/hooks/useTableEdit.tsx +140 -140
  169. package/src/components/Table/hooks/useTableFilterFields.tsx +150 -150
  170. package/src/components/Table/hooks/useTablePagination.ts +19 -19
  171. package/src/components/Table/hooks/useTablePrint.ts +83 -83
  172. package/src/components/Table/hooks/useTableSearch.ts +31 -30
  173. package/src/components/Table/hooks/useTableSelect.ts +19 -19
  174. package/src/components/Table/hooks/useTableSort.ts +8 -8
  175. package/src/components/Tabs/Tabs.tsx +68 -67
  176. package/src/components/Tooltip/Tooltip.tsx +191 -200
  177. package/src/components/Tree/Tree.tsx +22 -22
  178. package/src/components/Tree/TreeItem.tsx +57 -56
  179. package/src/components/Wrappers/AppLayout.tsx +17 -17
  180. package/src/components/Wrappers/ConditionalWrapper.tsx +10 -10
  181. package/src/components/Wrappers/FormWrapper.tsx +84 -83
  182. package/src/components/Wrappers/PageLayout.tsx +156 -155
  183. package/src/hooks/useBackgroundClose.ts +19 -18
  184. package/src/hooks/useGetFocusableElements.ts +43 -42
  185. package/src/hooks/useIsMenuOpen.ts +11 -11
  186. package/src/hooks/useLocalPopoverControl.ts +32 -32
  187. package/src/hooks/useOnEsc.ts +14 -14
  188. package/src/hooks/usePopupControl.ts +22 -22
  189. package/src/hooks/useZendesk.ts +21 -21
  190. package/src/index.ts +379 -386
  191. package/src/pages/NoAccessPage.tsx +27 -27
  192. package/src/pages/NotFoundPage.tsx +26 -26
  193. package/src/styles/common/helpers/_size.scss +0 -3
  194. package/src/styles/components/_accordions.scss +1 -1
  195. package/src/styles/components/_buttonSplit.scss +4 -29
  196. package/src/types/IBasic.ts +32 -31
  197. package/src/types/ICountryCode.ts +5 -0
  198. package/src/types/IError.ts +5 -5
  199. package/src/types/IHeader.ts +40 -40
  200. package/src/types/IInfo.ts +1 -1
  201. package/src/types/IKeyboard.ts +33 -33
  202. package/src/types/IMenu.ts +19 -19
  203. package/src/types/INotifications.ts +15 -15
  204. package/src/types/IPopup.ts +17 -17
  205. package/src/types/IRouter.ts +6 -6
  206. package/src/types/ISelect.ts +54 -54
  207. package/src/types/ITab.ts +1 -1
  208. package/src/types/ITable.ts +290 -281
  209. package/src/types/ITree.ts +6 -6
  210. package/src/utils/InputPatternValidation.ts +12 -12
  211. package/src/utils/dateUtils.ts +32 -32
  212. package/src/utils/fileUtils.ts +177 -177
  213. package/src/utils/i18n/i18nIUICyrilic.ts +119 -119
  214. package/src/utils/i18n/i18nIUILatin.ts +120 -120
  215. package/src/utils/i18n/i18nIUIMe.ts +118 -118
  216. package/src/utils/icons.ts +13 -13
  217. package/src/utils/localStorageHelper.ts +24 -24
  218. package/src/utils/logoUtils.ts +7 -7
  219. package/src/utils/numberUtils.ts +21 -21
  220. package/src/utils/objectUtils.ts +114 -114
  221. package/src/utils/popupUtils.ts +82 -82
  222. package/src/utils/rootDir.ts +1 -1
  223. package/src/utils/stringUtils.ts +18 -18
  224. package/src/utils/tableUtils.ts +130 -130
  225. package/src/utils/toasts.ts +6 -6
  226. package/src/utils/urlUtils.ts +4 -4
  227. package/tsconfig.json +1 -0
  228. package/src/components/Dialog/hooks/useDialogKeyboard.ts +0 -42
  229. package/src/components/Inputs/Select2/Select.tsx +0 -258
  230. 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;