@inceptionbg/iui 2.0.5 → 2.0.6

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 (253) hide show
  1. package/dist/icons/index.d.ts +43 -0
  2. package/dist/icons/index.js +1 -0
  3. package/dist/index.d.ts +24 -15
  4. package/dist/index.js +1 -1
  5. package/dist/index.js.map +1 -1
  6. package/dist/iui.css +1 -1
  7. package/idea/Menu/Menu.tsx +119 -0
  8. package/idea/Menu/MenuItem.tsx +74 -0
  9. package/idea/Menu/hooks/useMenuControl.ts +13 -0
  10. package/idea/Menu.tsx +132 -0
  11. package/idea/NoAccessInfo.tsx +193 -0
  12. package/idea/Notifications.tsx +245 -0
  13. package/idea/Table2/Components/Columns/ColumnsList.tsx +56 -0
  14. package/idea/Table2/Components/Columns/SetColumnsList.tsx +107 -0
  15. package/idea/Table2/Components/Edit/ItemActionsMenu.tsx +87 -0
  16. package/idea/Table2/Components/Edit/ItemEditOptionsButtons.tsx +32 -0
  17. package/idea/Table2/Components/Edit/TableEditRow.tsx +56 -0
  18. package/idea/Table2/Components/FilterItem.tsx +20 -0
  19. package/idea/Table2/Components/Header/TableHeader.tsx +35 -0
  20. package/idea/Table2/Components/Header/TableHeaderRow.tsx +37 -0
  21. package/idea/Table2/Components/Print/CustomTablePrint.tsx +119 -0
  22. package/idea/Table2/Components/Print/TablePrint.tsx +208 -0
  23. package/idea/Table2/Components/SetSortList.tsx +33 -0
  24. package/idea/Table2/Components/SetTableFilter.tsx +90 -0
  25. package/idea/Table2/Components/TableFooter.tsx +107 -0
  26. package/idea/Table2/Components/TableOptions.tsx +211 -0
  27. package/idea/Table2/Components/Templates/TemplateCreate.tsx +75 -0
  28. package/idea/Table2/Components/Templates/TemplateCreateDefault.tsx +45 -0
  29. package/idea/Table2/Components/Templates/TemplateList.tsx +167 -0
  30. package/idea/Table2/Components/Templates/repo/TemplateRepo.ts +51 -0
  31. package/idea/Table2/Table.tsx +657 -0
  32. package/idea/Table2/_table.scss +300 -0
  33. package/idea/Table2/hooks/useDefaultTemplate.ts +22 -0
  34. package/idea/Table2/hooks/useTableKeyboard.ts +115 -0
  35. package/package.json +8 -4
  36. package/rollup.config.js +80 -0
  37. package/src/assets/icons/duotone/faCircleUser.ts +17 -0
  38. package/src/assets/icons/index.ts +20 -0
  39. package/src/assets/icons/light/faArrowDownShortWide.ts +15 -0
  40. package/src/assets/icons/light/faArrowDownWideShort.ts +15 -0
  41. package/src/assets/icons/light/faArrowUpArrowDown.ts +15 -0
  42. package/src/assets/icons/light/faArrowUpRightFromSquare.ts +15 -0
  43. package/src/assets/icons/light/faArrowsToLine.ts +15 -0
  44. package/src/assets/icons/light/faArrowsUpDown.ts +15 -0
  45. package/src/assets/icons/light/faCalendarPlus.ts +15 -0
  46. package/src/assets/icons/light/faCheck.ts +15 -0
  47. package/src/assets/icons/light/faChevronDown.ts +15 -0
  48. package/src/assets/icons/light/faChevronRight.ts +15 -0
  49. package/src/assets/icons/light/faCircleInfo.ts +15 -0
  50. package/src/assets/icons/light/faCircleXmark.ts +15 -0
  51. package/src/assets/icons/light/faClockRotateLeft.ts +15 -0
  52. package/src/assets/icons/light/faEllipsisVertical.ts +15 -0
  53. package/src/assets/icons/light/faEye.ts +15 -0
  54. package/src/assets/icons/light/faEyeSlash.ts +15 -0
  55. package/src/assets/icons/light/faFilter.ts +15 -0
  56. package/src/assets/icons/light/faGear.ts +15 -0
  57. package/src/assets/icons/light/faHouse.ts +15 -0
  58. package/src/assets/icons/light/faIdBadge.ts +15 -0
  59. package/src/assets/icons/light/faLineColumns.ts +15 -0
  60. package/src/assets/icons/light/faLink.ts +15 -0
  61. package/src/assets/icons/light/faMagnifyingGlass.ts +15 -0
  62. package/src/assets/icons/light/faPenField.ts +15 -0
  63. package/src/assets/icons/light/faPrint.ts +15 -0
  64. package/src/assets/icons/light/faQuestion.ts +15 -0
  65. package/src/assets/icons/light/faRotateRight.ts +15 -0
  66. package/src/assets/icons/light/faTrashCan.ts +15 -0
  67. package/src/assets/icons/light/faTriangleExclamation.ts +15 -0
  68. package/src/assets/icons/light/faXmark.ts +15 -0
  69. package/src/assets/icons/regular/faArrowLeft.ts +15 -0
  70. package/src/assets/icons/regular/faArrowRightArrowLeft.ts +15 -0
  71. package/src/assets/icons/regular/faCircleCheck.ts +15 -0
  72. package/src/assets/icons/regular/faCircleExclamation.ts +15 -0
  73. package/src/assets/icons/regular/faCircleInfo.ts +15 -0
  74. package/src/assets/icons/regular/faFileArrowDown.ts +15 -0
  75. package/src/assets/icons/regular/faFilterCircleXmark.ts +15 -0
  76. package/src/assets/icons/regular/faTriangleExclamation.ts +15 -0
  77. package/src/assets/icons/solid/faAngleLeft.ts +15 -0
  78. package/src/assets/icons/solid/faAngleRight.ts +15 -0
  79. package/src/assets/icons/solid/faArrowDownWideShort.ts +15 -0
  80. package/src/assets/icons/solid/faCaretDown.ts +15 -0
  81. package/src/assets/icons/solid/faCheck.ts +15 -0
  82. package/src/assets/icons/solid/faEllipsisVertical.ts +15 -0
  83. package/src/assets/icons/solid/faFilter.ts +15 -0
  84. package/src/assets/icons/solid/faFloppyDisk.ts +15 -0
  85. package/src/assets/icons/solid/faGripDotsVertical.ts +15 -0
  86. package/src/assets/icons/solid/faListUl.ts +15 -0
  87. package/src/assets/icons/solid/faMagnifyingGlass.ts +15 -0
  88. package/src/assets/icons/solid/faMinus.ts +15 -0
  89. package/src/assets/icons/solid/faPlus.ts +15 -0
  90. package/src/assets/icons/solid/faPrint.ts +15 -0
  91. package/src/assets/icons/solid/faRotateRight.ts +15 -0
  92. package/src/assets/icons/solid/faXmark.ts +15 -0
  93. package/src/assets/images/logo/mts.svg +5703 -0
  94. package/src/assets/images/logo/paperless.svg +21 -0
  95. package/src/assets/images/logo/pismonosa.png +0 -0
  96. package/src/assets/images/not-found.svg +19 -0
  97. package/src/components/Accordions/Accordions.tsx +64 -0
  98. package/src/components/Alert/Alert.tsx +31 -0
  99. package/src/components/Badge/DotBadge.tsx +16 -0
  100. package/src/components/Badge/NotificationBadge.tsx +29 -0
  101. package/src/components/Badge/PillBadge.tsx +13 -0
  102. package/src/components/Button/Button.tsx +56 -0
  103. package/src/components/Button/IconButton.tsx +49 -0
  104. package/src/components/Dashboard/Dashboard.tsx +9 -0
  105. package/src/components/Dashboard/DashboardWidget.tsx +44 -0
  106. package/src/components/Dashboard/FastLinksWidget/FastLinksWidget.tsx +37 -0
  107. package/src/components/Dialog/DeleteItemDialog.tsx +52 -0
  108. package/src/components/Dialog/Dialog.tsx +226 -0
  109. package/src/components/Dialog/hooks/useDialogKeyboard.ts +41 -0
  110. package/src/components/Dialog/hooks/useDialogObserver.ts +21 -0
  111. package/src/components/Header/Components/ModuleSelect.tsx +55 -0
  112. package/src/components/Header/Components/UserMenu.tsx +44 -0
  113. package/src/components/Header/Header.tsx +36 -0
  114. package/src/components/Helper/Collapse.tsx +52 -0
  115. package/src/components/Inputs/Checkbox.tsx +53 -0
  116. package/src/components/Inputs/CurrencyInput.tsx +123 -0
  117. package/src/components/Inputs/DateInput/DateInput.tsx +176 -0
  118. package/src/components/Inputs/DateInput/components/DatePartInput.tsx +154 -0
  119. package/src/components/Inputs/InputWrapper.tsx +90 -0
  120. package/src/components/Inputs/NumberInput.tsx +83 -0
  121. package/src/components/Inputs/PasswordInput.tsx +38 -0
  122. package/src/components/Inputs/Radio.tsx +59 -0
  123. package/src/components/Inputs/RadioGroup.tsx +48 -0
  124. package/src/components/Inputs/RadioLarge.tsx +39 -0
  125. package/src/components/Inputs/SearchInput.tsx +40 -0
  126. package/src/components/Inputs/Select2/Select.tsx +224 -0
  127. package/src/components/Inputs/Select2/select.scss +43 -0
  128. package/src/components/Inputs/Selects/Select.tsx +17 -0
  129. package/src/components/Inputs/Selects/components/CustomSelectComponents.tsx +19 -0
  130. package/src/components/Inputs/Selects/components/SelectWrapper.tsx +126 -0
  131. package/src/components/Inputs/Selects/utils/selectStyles.ts +104 -0
  132. package/src/components/Inputs/TextAreaInput.tsx +67 -0
  133. package/src/components/Inputs/TextInput.tsx +98 -0
  134. package/src/components/Inputs/TimeInput/TimeInput.tsx +81 -0
  135. package/src/components/Loader/Loader.tsx +53 -0
  136. package/src/components/Menu/Menu.tsx +68 -0
  137. package/src/components/Menu/MenuItem.tsx +47 -0
  138. package/src/components/Menu/NewMenu.tsx +66 -0
  139. package/src/components/Menu/hooks/useMenuPosition.tsx +80 -0
  140. package/src/components/Pullover/Pullover.tsx +89 -0
  141. package/src/components/Router/Router.tsx +51 -0
  142. package/src/components/Sidebar/AddButton.tsx +22 -0
  143. package/src/components/Sidebar/Sidebar.tsx +81 -0
  144. package/src/components/Sidebar/SidebarItem.tsx +84 -0
  145. package/src/components/Sidebar/types/ISidebar.ts +28 -0
  146. package/src/components/Table/Components/Columns/ColumnsList.tsx +61 -0
  147. package/src/components/Table/Components/Columns/SetColumnsList.tsx +113 -0
  148. package/src/components/Table/Components/Edit/ItemActionsMenu.tsx +84 -0
  149. package/src/components/Table/Components/Edit/ItemEditOptionsButtons.tsx +31 -0
  150. package/src/components/Table/Components/Edit/TableEditRow.tsx +56 -0
  151. package/src/components/Table/Components/FilterItem.tsx +20 -0
  152. package/src/components/Table/Components/Header/TableHeader.tsx +45 -0
  153. package/src/components/Table/Components/Header/TableHeaderRow.tsx +37 -0
  154. package/src/components/Table/Components/Print/CustomTablePrint.tsx +114 -0
  155. package/src/components/Table/Components/Print/TablePrint.tsx +207 -0
  156. package/src/components/Table/Components/SetSortList.tsx +30 -0
  157. package/src/components/Table/Components/SetTableFilter.tsx +90 -0
  158. package/src/components/Table/Components/TableFooter.tsx +135 -0
  159. package/src/components/Table/Components/TableOptions.tsx +226 -0
  160. package/src/components/Table/Components/Templates/TemplateCreate.tsx +80 -0
  161. package/src/components/Table/Components/Templates/TemplateCreateDefault.tsx +45 -0
  162. package/src/components/Table/Components/Templates/TemplateList.tsx +167 -0
  163. package/src/components/Table/Components/Templates/repo/TemplateRepo.ts +53 -0
  164. package/src/components/Table/Table.tsx +527 -0
  165. package/src/components/Table/hooks/useDefaultTemplate.ts +20 -0
  166. package/src/components/Table/hooks/useTableKeyboard.ts +138 -0
  167. package/src/components/Table/hooks/useTableSelect.ts +11 -0
  168. package/src/components/Tabs/Tabs.tsx +66 -0
  169. package/src/components/Tooltip/Tooltip.tsx +133 -0
  170. package/src/components/Tree/Tree.tsx +22 -0
  171. package/src/components/Tree/TreeItem.tsx +56 -0
  172. package/src/components/Wrappers/AppLayout.tsx +17 -0
  173. package/src/components/Wrappers/ConditionalWrapper.tsx +10 -0
  174. package/src/components/Wrappers/FormWrapper.tsx +81 -0
  175. package/src/components/Wrappers/PageLayout.tsx +152 -0
  176. package/src/hooks/useBackgroundClose.ts +18 -0
  177. package/src/hooks/useIsMenuOpen.ts +11 -0
  178. package/src/hooks/useOnEsc.ts +14 -0
  179. package/src/hooks/useZendesk.ts +21 -0
  180. package/src/index.ts +324 -0
  181. package/src/pages/NoAccessPage.tsx +27 -0
  182. package/src/pages/NotFoundPage.tsx +26 -0
  183. package/src/styles/App.scss +43 -0
  184. package/src/styles/common/_animations.scss +64 -0
  185. package/src/styles/common/_typography.scss +88 -0
  186. package/src/styles/common/helpers/_base.scss +55 -0
  187. package/src/styles/common/helpers/_color.scss +7 -0
  188. package/src/styles/common/helpers/_display.scss +85 -0
  189. package/src/styles/common/helpers/_size.scss +25 -0
  190. package/src/styles/common/maps/_align.scss +21 -0
  191. package/src/styles/common/maps/_info-types.scss +1 -0
  192. package/src/styles/common/maps/_spacing.scss +78 -0
  193. package/src/styles/common/maps/_text.scss +14 -0
  194. package/src/styles/components/_accordions.scss +46 -0
  195. package/src/styles/components/_alert.scss +23 -0
  196. package/src/styles/components/_badge.scss +76 -0
  197. package/src/styles/components/_button.scss +138 -0
  198. package/src/styles/components/_card.scss +24 -0
  199. package/src/styles/components/_dialog.scss +111 -0
  200. package/src/styles/components/_form.scss +8 -0
  201. package/src/styles/components/_header.scss +109 -0
  202. package/src/styles/components/_input.scss +158 -0
  203. package/src/styles/components/_inputCheckbox.scss +105 -0
  204. package/src/styles/components/_inputDateTime.scss +161 -0
  205. package/src/styles/components/_inputRadio.scss +83 -0
  206. package/src/styles/components/_inputSelect.scss +6 -0
  207. package/src/styles/components/_loader.scss +44 -0
  208. package/src/styles/components/_menu-v2.scss +67 -0
  209. package/src/styles/components/_menu.scss +53 -0
  210. package/src/styles/components/_page.scss +62 -0
  211. package/src/styles/components/_portal.scss +8 -0
  212. package/src/styles/components/_print.scss +87 -0
  213. package/src/styles/components/_pullover.scss +43 -0
  214. package/src/styles/components/_scrollbar.scss +18 -0
  215. package/src/styles/components/_sidebar.scss +206 -0
  216. package/src/styles/components/_smallComponents.scss +23 -0
  217. package/src/styles/components/_table.scss +270 -0
  218. package/src/styles/components/_tabs.scss +33 -0
  219. package/src/styles/components/_tooltip.scss +48 -0
  220. package/src/styles/components/_tree.scss +21 -0
  221. package/src/styles/components/_widget.scss +90 -0
  222. package/src/styles/pages/_fullScreenPage.scss +64 -0
  223. package/src/styles/variables/_bp.scss +5 -0
  224. package/src/styles/variables/_variables.scss +130 -0
  225. package/src/types/Base/custom.d.ts +9 -0
  226. package/src/types/IBasic.ts +31 -0
  227. package/src/types/IError.ts +5 -0
  228. package/src/types/IHeader.ts +24 -0
  229. package/src/types/IInfo.ts +1 -0
  230. package/src/types/IKeyboard.ts +37 -0
  231. package/src/types/IMenu.ts +18 -0
  232. package/src/types/IRouter.ts +6 -0
  233. package/src/types/ISelect.ts +52 -0
  234. package/src/types/ITab.ts +10 -0
  235. package/src/types/ITable.ts +249 -0
  236. package/src/types/ITree.ts +6 -0
  237. package/src/utils/DateUtils.ts +32 -0
  238. package/src/utils/InputPatternValidation.ts +12 -0
  239. package/src/utils/LocalStorageHelper.ts +24 -0
  240. package/src/utils/NumberUtils.ts +21 -0
  241. package/src/utils/ObjectUtils.ts +85 -0
  242. package/src/utils/RootDir.ts +1 -0
  243. package/src/utils/StringUtils.ts +18 -0
  244. package/src/utils/TableUtils.ts +130 -0
  245. package/src/utils/Toasts.ts +6 -0
  246. package/src/utils/UrlUtils.ts +4 -0
  247. package/src/utils/fileUtils.ts +176 -0
  248. package/src/utils/i18n/i18nIUICyrilic.ts +90 -0
  249. package/src/utils/i18n/i18nIUILatin.ts +90 -0
  250. package/src/utils/i18n/i18nIUIMe.ts +88 -0
  251. package/src/utils/icons.ts +13 -0
  252. package/tsconfig.icons.json +5 -0
  253. package/tsconfig.json +19 -0
@@ -0,0 +1,81 @@
1
+ import clsx from 'clsx';
2
+ import { FC } from 'react';
3
+ import { InputWrapper } from '../InputWrapper';
4
+
5
+ export interface ITimeInputProps {
6
+ time: string;
7
+ setTime: (newTime: string) => void;
8
+ label?: string;
9
+ disabled?: boolean;
10
+ required?: boolean;
11
+ isClearable?: boolean;
12
+ className?: string;
13
+ }
14
+
15
+ export const TimeInput: FC<ITimeInputProps> = ({
16
+ time = '00:00',
17
+ setTime,
18
+ label,
19
+ disabled,
20
+ required,
21
+ isClearable = true,
22
+ className,
23
+ }) => {
24
+ const [hours, minutes] = time.split(':').map(t => t.padStart(2, '0'));
25
+
26
+ const handleChange = (e: string, type: 'hh' | 'mm') => {
27
+ let value = isNaN(+e) || e === '-1' ? '00' : e.replace(/\D/g, '');
28
+ if (value.length > 2) {
29
+ value = value.substring(1);
30
+ }
31
+
32
+ if (type === 'hh') {
33
+ const newHours = Math.min(23, parseInt(value) || 0)
34
+ .toString()
35
+ .padStart(2, '0');
36
+ setTime(`${newHours}:${minutes}`);
37
+ } else {
38
+ const newMinutes = Math.min(59, parseInt(value) || 0)
39
+ .toString()
40
+ .padStart(2, '0');
41
+ setTime(`${hours}:${newMinutes}`);
42
+ }
43
+ };
44
+
45
+ return (
46
+ <InputWrapper
47
+ label={label}
48
+ required={required}
49
+ disabled={disabled}
50
+ onClearInput={isClearable && time && !disabled ? () => setTime('00:00') : undefined}
51
+ className={clsx(className, 'time-input-wrapper')}
52
+ >
53
+ <div className="time-input">
54
+ <input
55
+ type="number"
56
+ value={hours}
57
+ onChange={e => handleChange(e.target.value, 'hh')}
58
+ onClick={e => {
59
+ const input = e.target as HTMLInputElement;
60
+ input.select();
61
+ }}
62
+ disabled={disabled}
63
+ required={required}
64
+ style={{ textAlign: 'right' }}
65
+ />
66
+ <span className="fs-m">:</span>
67
+ <input
68
+ type="number"
69
+ value={minutes}
70
+ onChange={e => handleChange(e.target.value, 'mm')}
71
+ onClick={e => {
72
+ const input = e.target as HTMLInputElement;
73
+ input.select();
74
+ }}
75
+ disabled={disabled}
76
+ required={required}
77
+ />
78
+ </div>
79
+ </InputWrapper>
80
+ );
81
+ };
@@ -0,0 +1,53 @@
1
+ import { Children, FC, ReactElement, ReactNode, cloneElement } from 'react';
2
+ import clsx from 'clsx';
3
+
4
+ interface Props {
5
+ isLoading: boolean;
6
+ isFullPage?: boolean;
7
+ classNameLoader?: string;
8
+ children?: ReactElement<{ className: string; children: ReactElement | ReactNode }>;
9
+ }
10
+
11
+ export const Loader: FC<Props> = ({ isLoading, isFullPage, classNameLoader, children }) =>
12
+ children ? (
13
+ Children.map(children, child =>
14
+ cloneElement(child, {
15
+ className: clsx(child.props.className, { relative: isLoading }),
16
+ children: (
17
+ <>
18
+ {child.props.children}
19
+ {isLoading && (
20
+ <div className={clsx('loader', classNameLoader)}>
21
+ <span className="spinner" />
22
+ </div>
23
+ )}
24
+ </>
25
+ ),
26
+ })
27
+ )
28
+ ) : isLoading ? (
29
+ <div className={`${isFullPage ? 'full-page-loader' : 'empty-loader'} relative`}>
30
+ <div className={clsx('loader', classNameLoader)}>
31
+ <span className="spinner" />
32
+ </div>
33
+ </div>
34
+ ) : (
35
+ <></>
36
+ );
37
+
38
+ export const FullScreenLoader: FC<{ isLoading: boolean }> = ({ isLoading }) =>
39
+ isLoading ? (
40
+ <div className="full-screen-loader">
41
+ <div className="loader">
42
+ <span className="spinner" />
43
+ </div>
44
+ </div>
45
+ ) : null;
46
+
47
+ export const LazyLoader: FC = () => (
48
+ <div className="lazy-loader">
49
+ <div className="loader">
50
+ <span className="spinner" />
51
+ </div>
52
+ </div>
53
+ );
@@ -0,0 +1,68 @@
1
+ import clsx from 'clsx';
2
+ import { FC, ReactNode, RefObject, useRef } from 'react';
3
+ import { createPortal } from 'react-dom';
4
+ import { rootDir } from '../../utils/RootDir';
5
+ import { useMenuPosition } from './hooks/useMenuPosition';
6
+ import { useBackgroundClose } from '../../hooks/useBackgroundClose';
7
+ import { MenuItem } from './MenuItem';
8
+ import { IMenuItem, IMenuPlacement } from '../../types/IMenu';
9
+
10
+ interface Props {
11
+ isOpen: boolean;
12
+ onClose: () => void;
13
+ renderButton: (ref: RefObject<any>) => ReactNode;
14
+ items?: IMenuItem[];
15
+ placement?: IMenuPlacement;
16
+ size?: 's' | 'm' | 'l';
17
+ className?: string;
18
+ classNameItem?: string;
19
+ children?: ReactNode;
20
+ }
21
+
22
+ export const Menu: FC<Props> = ({
23
+ isOpen,
24
+ onClose,
25
+ renderButton,
26
+ items,
27
+ placement = 'bottom-left',
28
+ size,
29
+ className,
30
+ classNameItem,
31
+ children,
32
+ }) => {
33
+ const menuRef = useRef<HTMLDivElement>(null);
34
+ const portalRef = useRef<HTMLDivElement>(null);
35
+ const containerRef = useRef<Element>(null);
36
+
37
+ const menuStyle = useMenuPosition({
38
+ isOpen,
39
+ placement,
40
+ containerRef,
41
+ menuRef,
42
+ });
43
+
44
+ useBackgroundClose({ portalRef, disabled: !isOpen, handleClose: onClose });
45
+
46
+ return (
47
+ <>
48
+ {renderButton(containerRef)}
49
+ {isOpen
50
+ ? createPortal(
51
+ <div ref={portalRef} className="portal-background">
52
+ <div
53
+ ref={menuRef}
54
+ className={clsx('iui-menu', className, size)}
55
+ style={menuStyle}
56
+ >
57
+ {items?.map(item => (
58
+ <MenuItem {...item} key={item.label} className={classNameItem} />
59
+ ))}
60
+ {children}
61
+ </div>
62
+ </div>,
63
+ rootDir
64
+ )
65
+ : null}
66
+ </>
67
+ );
68
+ };
@@ -0,0 +1,47 @@
1
+ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
2
+ import clsx from 'clsx';
3
+ import { ConditionalWrapper } from '../Wrappers/ConditionalWrapper.js';
4
+ import { Link } from 'react-router';
5
+ import { NotificationBadge } from '../Badge/NotificationBadge.js';
6
+ import { IMenuItem } from '../../types/IMenu.js';
7
+ import { FC } from 'react';
8
+
9
+ export const MenuItem: FC<IMenuItem> = ({
10
+ label,
11
+ icon,
12
+ iconRotation,
13
+ onClick,
14
+ to,
15
+ badge,
16
+ disabled,
17
+ hidden,
18
+ withDevider,
19
+ className,
20
+ }) =>
21
+ hidden ? null : (
22
+ <div>
23
+ <ConditionalWrapper
24
+ condition={!disabled && !!to}
25
+ wrapper={children => <Link to={to!}>{children}</Link>}
26
+ >
27
+ <div
28
+ className={clsx(className, {
29
+ 'iui-menu-item': !className,
30
+ clickable: !!onClick || !!to,
31
+ disabled,
32
+ 'with-devider': withDevider,
33
+ })}
34
+ onClick={disabled ? undefined : onClick}
35
+ >
36
+ {icon && (
37
+ <div className="menu-item-icon">
38
+ <FontAwesomeIcon icon={icon} rotation={iconRotation} />
39
+ </div>
40
+ )}
41
+ <NotificationBadge number={badge} size="s" className="menu-item-badge">
42
+ <p className="menu-item-label">{label}</p>
43
+ </NotificationBadge>
44
+ </div>
45
+ </ConditionalWrapper>
46
+ </div>
47
+ );
@@ -0,0 +1,66 @@
1
+ // import '@oddbird/popover-polyfill';
2
+ // import polyfill from 'https://unpkg.com/@oddbird/css-anchor-positioning/fn';
3
+ import '../../styles/components/_menu-v2.scss';
4
+
5
+ import clsx from 'clsx';
6
+ import { FC, ReactNode, RefObject, useEffect, useRef } from 'react';
7
+ import { MenuItem } from './MenuItem';
8
+ import { IMenuItem, IMenuPlacement } from '../../types/IMenu';
9
+
10
+ interface Props {
11
+ id: string;
12
+ renderButton: (ref: RefObject<any>) => ReactNode;
13
+ items: IMenuItem[];
14
+ placement?: IMenuPlacement;
15
+ size?: 's' | 'm' | 'l';
16
+ className?: string;
17
+ classNameItem?: string;
18
+ }
19
+
20
+ export const MenuV2: FC<Props> = ({
21
+ id,
22
+ renderButton,
23
+ items,
24
+ placement = 'bottom-left',
25
+ size,
26
+ className,
27
+ classNameItem,
28
+ }) => {
29
+ const buttonRef = useRef<HTMLButtonElement>(null);
30
+ const popoverRef = useRef<HTMLDivElement>(null);
31
+
32
+ useEffect(() => {
33
+ // polyfill();
34
+ buttonRef.current?.setAttribute('popovertarget', id);
35
+ buttonRef.current?.style.setProperty('anchor-name', `--${id}`);
36
+ popoverRef.current?.style.setProperty('position-anchor', `--${id}`);
37
+ }, [id]);
38
+
39
+ return (
40
+ <>
41
+ {renderButton(buttonRef)}
42
+ <div
43
+ ref={popoverRef}
44
+ role="menu"
45
+ // @ts-ignore
46
+ popover="auto"
47
+ className={clsx('iui-menu-v2', size, placement)}
48
+ id={id}
49
+ >
50
+ <div className={className}>
51
+ {items.map(item => (
52
+ <MenuItem
53
+ {...item}
54
+ key={item.label}
55
+ className={classNameItem}
56
+ onClick={e => {
57
+ item.onClick?.(e);
58
+ !item.keepOpen && popoverRef.current?.hidePopover();
59
+ }}
60
+ />
61
+ ))}
62
+ </div>
63
+ </div>
64
+ </>
65
+ );
66
+ };
@@ -0,0 +1,80 @@
1
+ import { RefObject, useCallback, useEffect, useState } from 'react';
2
+ import { IMenuPlacement } from '../../../types/IMenu';
3
+
4
+ interface Offsets {
5
+ offsetTop: number;
6
+ offsetLeft: number;
7
+ }
8
+
9
+ interface Props {
10
+ isOpen: boolean;
11
+ placement: IMenuPlacement;
12
+ containerRef: RefObject<Element | null>;
13
+ menuRef: RefObject<Element | null>;
14
+ }
15
+
16
+ export const useMenuPosition = ({ isOpen, placement, containerRef, menuRef }: Props) => {
17
+ const [offsets, setOffsets] = useState<Offsets>({
18
+ offsetLeft: 0,
19
+ offsetTop: 0,
20
+ });
21
+ const [maxHeight, setMaxHeight] = useState<number>();
22
+
23
+ const recalculatePosition = useCallback(() => {
24
+ if (containerRef.current && menuRef.current) {
25
+ const containerRect = containerRef.current.getBoundingClientRect();
26
+ const menuRect = menuRef.current.getBoundingClientRect();
27
+ const [placementY, placementX] = placement.split('-');
28
+
29
+ let offsetTop = containerRect.bottom + 5;
30
+ // let offsetTop = containerRect.bottom + document.documentElement.scrollTop + 5;
31
+
32
+ const offsetLeft =
33
+ containerRect.left +
34
+ (placementX === 'right' ? containerRect.width - menuRect.width : 0);
35
+ // + document.documentElement.scrollLeft;
36
+
37
+ if (placementY === 'bottom') {
38
+ setMaxHeight(window.innerHeight - containerRect.bottom - 20);
39
+ }
40
+
41
+ if (placementY === 'top') {
42
+ setMaxHeight(
43
+ window.innerHeight - containerRect.top + 40
44
+ // - 2 * document.documentElement.scrollTop
45
+ );
46
+ }
47
+
48
+ // check for space on the bottom
49
+ if (
50
+ (placementY === 'auto' && offsetTop + menuRect.height > window.innerHeight) ||
51
+ placementY === 'top'
52
+ ) {
53
+ offsetTop = containerRect.top - menuRect.height - 5; //+ document.documentElement.scrollTop
54
+ }
55
+
56
+ setOffsets({ offsetTop, offsetLeft });
57
+ }
58
+ }, [menuRef, containerRef, placement]);
59
+
60
+ useEffect(() => {
61
+ isOpen
62
+ ? window.addEventListener('resize', recalculatePosition)
63
+ : window.removeEventListener('resize', recalculatePosition);
64
+ // Disable scroll & fix page resize on menu open
65
+ document.body.style.marginRight =
66
+ isOpen && window.innerWidth > document.body.clientWidth ? '19px' : '';
67
+ // document.body.style.overflow = isOpen ? 'hidden' : '';
68
+
69
+ recalculatePosition();
70
+ return () => {
71
+ window.removeEventListener('resize', recalculatePosition);
72
+ };
73
+ }, [isOpen, recalculatePosition]);
74
+
75
+ return {
76
+ top: offsets.offsetTop + 'px',
77
+ left: offsets.offsetLeft + 'px',
78
+ maxHeight,
79
+ };
80
+ };
@@ -0,0 +1,89 @@
1
+ import { IconDefinition } from '@fortawesome/fontawesome-svg-core';
2
+ import { FC, ReactNode, useCallback, useEffect, useRef } from 'react';
3
+ import { createPortal } from 'react-dom';
4
+ import { useTranslation } from 'react-i18next';
5
+ import { FormWrapper } from '../Wrappers/FormWrapper';
6
+ import { rootDir } from '../../utils/RootDir';
7
+ import { IButtonColor } from '../Button/Button';
8
+
9
+ interface Props {
10
+ isOpen: boolean;
11
+ onClose: () => void;
12
+ size: 's' | 'm' | 'l' | 'xl';
13
+ form?: {
14
+ isLoading: boolean;
15
+ onSubmit: (data: any) => void;
16
+ submitLabel?: string;
17
+ submitDisabled?: boolean;
18
+ };
19
+ additionalButtons?: {
20
+ label: string;
21
+ icon?: IconDefinition;
22
+ onClick: () => void;
23
+ disabled?: boolean;
24
+ hidden?: boolean;
25
+ outlined?: boolean;
26
+ color?: IButtonColor;
27
+ }[];
28
+ children: ReactNode;
29
+ }
30
+
31
+ export const Pullover: FC<Props> = ({
32
+ isOpen,
33
+ onClose,
34
+ size,
35
+ form,
36
+ additionalButtons,
37
+ children,
38
+ }) => {
39
+ const ref = useRef<HTMLDivElement>(null);
40
+ const { t } = useTranslation();
41
+
42
+ const handleClose = useCallback(() => {
43
+ ref.current?.classList.add('closing');
44
+ setTimeout(onClose, 200);
45
+ }, [ref, onClose]);
46
+
47
+ useEffect(() => {
48
+ if (isOpen) {
49
+ setTimeout(() => {
50
+ ref.current?.classList.add('open');
51
+ });
52
+ const handleClick = (e: KeyboardEvent) => {
53
+ e.code === 'Escape' && handleClose();
54
+ };
55
+ window.addEventListener('keydown', handleClick);
56
+ return () => window.removeEventListener('keydown', handleClick);
57
+ }
58
+ }, [isOpen, handleClose]);
59
+
60
+ return isOpen
61
+ ? createPortal(
62
+ <div ref={ref} className="pullover" onClick={handleClose}>
63
+ <div className={`container ${size}`} onClick={e => e.stopPropagation()}>
64
+ <div className="content">
65
+ {form ? (
66
+ <FormWrapper
67
+ isLoading={form.isLoading}
68
+ submitButton={{
69
+ onSubmit: form.onSubmit,
70
+ label: form.submitLabel,
71
+ disabled: form.submitDisabled,
72
+ }}
73
+ otherButtons={[
74
+ { label: t('Close'), onClick: handleClose },
75
+ ...(additionalButtons?.filter(e => !e.hidden) || []),
76
+ ]}
77
+ >
78
+ <div className="flex column gap-2 flex-grow">{children}</div>
79
+ </FormWrapper>
80
+ ) : (
81
+ children
82
+ )}
83
+ </div>
84
+ </div>
85
+ </div>,
86
+ rootDir
87
+ )
88
+ : null;
89
+ };
@@ -0,0 +1,51 @@
1
+ import { ComponentProps, FC, lazy, Suspense } from 'react';
2
+ import { Route, Routes } from 'react-router';
3
+ import { IRoute } from '../../types/IRouter';
4
+ import { AppLayout } from '../Wrappers/AppLayout';
5
+ import { FullScreenLoader, LazyLoader } from '../Loader/Loader';
6
+ import { Header } from '../Header/Header';
7
+ import { Sidebar } from '../Sidebar/Sidebar';
8
+
9
+ const NoAccessPage = lazy(() => import('../../pages/NoAccessPage'));
10
+ const NotFoundPage = lazy(() => import('../../pages/NotFoundPage'));
11
+
12
+ const commonFullScreenRoutes: IRoute[] = [
13
+ { path: '/*', element: <NotFoundPage /> },
14
+ { path: '/no-access', element: <NoAccessPage /> },
15
+ ];
16
+
17
+ interface Props {
18
+ fullScreenRoutes: IRoute[];
19
+ appRoutes: IRoute[];
20
+ header: ComponentProps<typeof Header>;
21
+ sidebar: ComponentProps<typeof Sidebar>;
22
+ }
23
+
24
+ export const Router: FC<Props> = ({ fullScreenRoutes, appRoutes, header, sidebar }) => (
25
+ <Routes>
26
+ {fullScreenRoutes.concat(commonFullScreenRoutes).map(route => (
27
+ <Route
28
+ key={route.path}
29
+ path={route.path}
30
+ element={
31
+ route.element && (
32
+ <Suspense fallback={<FullScreenLoader isLoading />}>{route.element}</Suspense>
33
+ )
34
+ }
35
+ />
36
+ ))}
37
+ {appRoutes.map(route => (
38
+ <Route
39
+ key={route.path}
40
+ path={route.path}
41
+ element={
42
+ route.element && (
43
+ <AppLayout header={header} sidebar={sidebar}>
44
+ <Suspense fallback={<LazyLoader />}>{route.element}</Suspense>
45
+ </AppLayout>
46
+ )
47
+ }
48
+ />
49
+ ))}
50
+ </Routes>
51
+ );
@@ -0,0 +1,22 @@
1
+ import { FC } from 'react';
2
+ import { useNavigate } from 'react-router';
3
+ import { IconButton } from '../Button/IconButton';
4
+ import { faPlus } from '../../assets/icons/solid/faPlus';
5
+
6
+ interface Props {
7
+ link: string;
8
+ }
9
+ export const AddButton: FC<Props> = ({ link }) => {
10
+ const navigate = useNavigate();
11
+ return (
12
+ <IconButton
13
+ className="add-button"
14
+ icon={faPlus}
15
+ size="s"
16
+ onClick={e => {
17
+ e.preventDefault();
18
+ navigate(link);
19
+ }}
20
+ />
21
+ );
22
+ };
@@ -0,0 +1,81 @@
1
+ import clsx from 'clsx';
2
+ import { FC, Fragment, useEffect, useRef, useState } from 'react';
3
+ import { SidebarItem } from './SidebarItem';
4
+ import { ISidebarItem } from './types/ISidebar';
5
+ import { faAngleLeft } from '../../assets/icons/solid/faAngleLeft';
6
+ import { IconButton } from '../Button/IconButton';
7
+
8
+ export interface ISidebarProps {
9
+ items: ISidebarItem[][];
10
+ logo?: string;
11
+ appVersion?: string;
12
+ }
13
+ export const Sidebar: FC<ISidebarProps> = ({ items, logo, appVersion }) => {
14
+ const [itemsList, setItemsList] = useState<ISidebarItem[][]>([]);
15
+ const [collapsed, setCollapsed] = useState(false);
16
+ const [openedMenu, setOpenedMenu] = useState('');
17
+
18
+ const sidebarRef = useRef<HTMLDivElement | null>(null);
19
+
20
+ useEffect(() => {
21
+ // Filter out hidden items & items without visible content
22
+ const newItems = items.map(list =>
23
+ list.filter(
24
+ item => !item.hidden && (item.to || item.content?.some(item => !item.hidden))
25
+ )
26
+ );
27
+ setItemsList(newItems);
28
+ }, [items, setItemsList]);
29
+
30
+ return (
31
+ <div ref={sidebarRef} className={clsx('iui-sidebar', { collapsed })}>
32
+ {/* ////// TOGGLE ////// */}
33
+ <IconButton
34
+ icon={faAngleLeft}
35
+ className={clsx('iui-collapse-btn', {
36
+ 'fa-flip-horizontal': collapsed,
37
+ collapsed,
38
+ })}
39
+ size="s"
40
+ onClick={() => setCollapsed(!collapsed)}
41
+ />
42
+
43
+ <div className="iui-sidebar-content">
44
+ {/* ////// SIDEBAR ITEMS ////// */}
45
+ <div className="iui-sidebar-items">
46
+ {itemsList.map((e, i) => (
47
+ <Fragment key={i}>
48
+ {i > 0 && !!e.length && <hr />}
49
+ {e.map(
50
+ item =>
51
+ !item.hidden && (
52
+ <SidebarItem
53
+ {...item}
54
+ key={item.label}
55
+ menu={
56
+ item.content
57
+ ? { content: item.content, openedMenu, setOpenedMenu }
58
+ : undefined
59
+ }
60
+ />
61
+ )
62
+ )}
63
+ </Fragment>
64
+ ))}
65
+ </div>
66
+ </div>
67
+ {/* ////// FOOTER ////// */}
68
+ <div className={clsx('sidebar-footer', { collapsed })}>
69
+ {logo && (
70
+ <img
71
+ className="sidebar-logo"
72
+ // src={!!organization?.reseller ? orgLogo[organization?.reseller] : logo}
73
+ src={logo}
74
+ alt="logo"
75
+ />
76
+ )}
77
+ {appVersion && <p>{appVersion}</p>}
78
+ </div>
79
+ </div>
80
+ );
81
+ };