@inceptionbg/iui 2.0.25 → 2.0.26

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