@inceptionbg/iui 2.0.8 → 2.0.11

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 (143) hide show
  1. package/dist/icons/index.d.ts +2 -2
  2. package/dist/icons/index.js +1 -1
  3. package/dist/index.d.ts +305 -265
  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/GridTable/GridTable.tsx +119 -0
  8. package/idea/GridTable/gridTable.scss +42 -0
  9. package/{src/components → idea}/Table/Components/Print/CustomTablePrint.tsx +2 -2
  10. package/{src/components → idea}/Table/Components/Print/TablePrint.tsx +2 -2
  11. package/{src/components → idea}/Table/Components/SetTableFilter.tsx +1 -1
  12. package/{src/components → idea}/Table/Components/TableOptions.tsx +4 -4
  13. package/idea/{Table2 → Table}/Table.tsx +151 -281
  14. package/idea/Table/hooks/useDefaultTemplate.ts +20 -0
  15. package/{src/components → idea}/Table/hooks/useTableKeyboard.ts +1 -2
  16. package/idea/Table/hooks/useTableSelect.ts +11 -0
  17. package/package.json +1 -1
  18. package/src/assets/icons/index.ts +1 -1
  19. package/src/assets/icons/light/faClipboardCheck.ts +15 -0
  20. package/src/assets/icons/light/faHouse.ts +15 -15
  21. package/src/assets/icons/light/faIdBadge.ts +15 -15
  22. package/src/assets/icons/light/faPen.ts +15 -0
  23. package/src/components/Button/IconButton.tsx +3 -1
  24. package/src/components/Dialog/Dialog.tsx +57 -123
  25. package/src/components/Dialog/components/DialogFooter.tsx +92 -0
  26. package/src/components/Dialog/hooks/useDialogKeyboard.ts +6 -5
  27. package/src/components/Header/Components/UserMenu.tsx +2 -4
  28. package/src/components/Header/Header.tsx +1 -1
  29. package/src/components/Inputs/DateInput/DateInput.tsx +107 -102
  30. package/src/components/Inputs/DateInput/components/DatePartInput.tsx +7 -3
  31. package/src/components/Inputs/InputWrapper.tsx +6 -1
  32. package/src/components/Inputs/PasswordInput.tsx +2 -1
  33. package/src/components/Inputs/SearchInput.tsx +9 -4
  34. package/src/components/Inputs/Select2/Select.tsx +64 -30
  35. package/src/components/Inputs/Select2/select.scss +13 -14
  36. package/src/components/Inputs/Selects/components/SelectWrapper.tsx +4 -2
  37. package/src/components/Inputs/Selects/utils/selectStyles.ts +9 -12
  38. package/src/components/Menu/Menu.tsx +10 -2
  39. package/src/components/Menu/MenuItem.tsx +11 -10
  40. package/src/components/Menu/hooks/useMenuPosition.tsx +49 -14
  41. package/src/components/Pullover/Pullover.tsx +138 -59
  42. package/src/components/Table/Table.tsx +78 -342
  43. package/src/components/Table/components/edit/TableEditRow.tsx +69 -0
  44. package/src/components/Table/components/filters/FilterItem.tsx +15 -0
  45. package/src/components/Table/components/filters/TableFilters.tsx +125 -0
  46. package/src/components/Table/components/footer/TableFooter.tsx +128 -0
  47. package/src/components/Table/components/header/TableHeader.tsx +42 -0
  48. package/src/components/Table/components/header/TableHeaderRow.tsx +47 -0
  49. package/src/components/Table/components/items/TableItemActions.tsx +66 -0
  50. package/src/components/Table/components/select/TableSelect.tsx +49 -0
  51. package/src/components/Table/components/sort/TableSort.tsx +52 -0
  52. package/src/components/Table/contexts/TableContext.tsx +123 -0
  53. package/src/components/Table/hooks/localHooks/useLocalTableColumns.tsx +73 -0
  54. package/src/components/Table/hooks/localHooks/useLocalTableData.tsx +78 -0
  55. package/src/components/Table/hooks/localHooks/useLocalTableKeyboard.ts +173 -0
  56. package/src/components/Table/hooks/localHooks/useLocalTablePagination.ts +12 -0
  57. package/src/components/Table/hooks/useTableEdit.tsx +111 -0
  58. package/src/components/Table/hooks/useTableFilterFields.tsx +150 -0
  59. package/src/components/Table/hooks/useTablePagination.ts +16 -0
  60. package/src/components/Table/hooks/useTableSearch.ts +29 -0
  61. package/src/components/Table/hooks/useTableSort.ts +8 -0
  62. package/src/components/Tooltip/Tooltip.tsx +1 -1
  63. package/src/components/Wrappers/PageLayout.tsx +9 -12
  64. package/src/hooks/useGetFocusableElements.ts +42 -0
  65. package/src/hooks/useLocalPopoverControl.ts +32 -0
  66. package/src/hooks/usePopupControl.ts +17 -0
  67. package/src/index.ts +56 -39
  68. package/src/styles/common/_typography.scss +1 -1
  69. package/src/styles/components/_accordions.scss +1 -1
  70. package/src/styles/components/_badge.scss +4 -3
  71. package/src/styles/components/_card.scss +1 -1
  72. package/src/styles/components/_dialog.scss +8 -8
  73. package/src/styles/components/_input.scss +1 -1
  74. package/src/styles/components/_inputCheckbox.scss +1 -1
  75. package/src/styles/components/_inputDateTime.scss +2 -2
  76. package/src/styles/components/_inputRadio.scss +1 -1
  77. package/src/styles/components/_inputSelect.scss +6 -4
  78. package/src/styles/components/_menu-v2.scss +1 -1
  79. package/src/styles/components/_menu.scss +23 -15
  80. package/src/styles/components/_pullover.scss +74 -18
  81. package/src/styles/components/_table.scss +151 -142
  82. package/src/styles/components/_widget.scss +1 -1
  83. package/src/styles/variables/_bp.scss +1 -0
  84. package/src/styles/variables/_variables.scss +4 -2
  85. package/src/types/IHeader.ts +13 -7
  86. package/src/types/IKeyboard.ts +2 -1
  87. package/src/types/IMenu.ts +1 -0
  88. package/src/types/IPopup.ts +17 -0
  89. package/src/types/ISelect.ts +1 -0
  90. package/src/types/ITable.ts +87 -80
  91. package/src/utils/fileUtils.ts +3 -3
  92. package/src/utils/i18n/i18nIUICyrilic.ts +4 -0
  93. package/src/utils/i18n/i18nIUILatin.ts +3 -1
  94. package/src/utils/i18n/i18nIUIMe.ts +4 -0
  95. package/src/utils/{ObjectUtils.ts → objectUtils.ts} +8 -8
  96. package/src/utils/popupUtils.ts +82 -0
  97. package/src/utils/{TableUtils.ts → tableUtils.ts} +5 -5
  98. package/src/utils/{Toasts.ts → toasts.ts} +6 -6
  99. package/src/utils/{UrlUtils.ts → urlUtils.ts} +4 -4
  100. package/idea/Table2/Components/Columns/ColumnsList.tsx +0 -56
  101. package/idea/Table2/Components/Columns/SetColumnsList.tsx +0 -107
  102. package/idea/Table2/Components/Edit/ItemActionsMenu.tsx +0 -87
  103. package/idea/Table2/Components/Edit/ItemEditOptionsButtons.tsx +0 -32
  104. package/idea/Table2/Components/Edit/TableEditRow.tsx +0 -56
  105. package/idea/Table2/Components/FilterItem.tsx +0 -20
  106. package/idea/Table2/Components/Header/TableHeader.tsx +0 -35
  107. package/idea/Table2/Components/Header/TableHeaderRow.tsx +0 -37
  108. package/idea/Table2/Components/Print/CustomTablePrint.tsx +0 -119
  109. package/idea/Table2/Components/Print/TablePrint.tsx +0 -208
  110. package/idea/Table2/Components/SetSortList.tsx +0 -33
  111. package/idea/Table2/Components/SetTableFilter.tsx +0 -90
  112. package/idea/Table2/Components/TableFooter.tsx +0 -107
  113. package/idea/Table2/Components/TableOptions.tsx +0 -211
  114. package/idea/Table2/Components/Templates/TemplateCreate.tsx +0 -75
  115. package/idea/Table2/Components/Templates/TemplateCreateDefault.tsx +0 -45
  116. package/idea/Table2/Components/Templates/TemplateList.tsx +0 -167
  117. package/idea/Table2/Components/Templates/repo/TemplateRepo.ts +0 -51
  118. package/idea/Table2/_table.scss +0 -300
  119. package/idea/Table2/hooks/useDefaultTemplate.ts +0 -22
  120. package/idea/Table2/hooks/useTableKeyboard.ts +0 -115
  121. package/src/assets/icons/light/faPenField.ts +0 -15
  122. package/src/assets/icons/solid/faMagnifyingGlass.ts +0 -15
  123. package/src/components/Dialog/DeleteItemDialog.tsx +0 -52
  124. package/src/components/Dialog/hooks/useDialogObserver.ts +0 -21
  125. /package/{src/components → idea}/Table/Components/Columns/ColumnsList.tsx +0 -0
  126. /package/{src/components → idea}/Table/Components/Columns/SetColumnsList.tsx +0 -0
  127. /package/{src/components → idea}/Table/Components/Edit/ItemActionsMenu.tsx +0 -0
  128. /package/{src/components → idea}/Table/Components/Edit/ItemEditOptionsButtons.tsx +0 -0
  129. /package/{src/components → idea}/Table/Components/Edit/TableEditRow.tsx +0 -0
  130. /package/{src/components → idea}/Table/Components/FilterItem.tsx +0 -0
  131. /package/{src/components → idea}/Table/Components/Header/TableHeader.tsx +0 -0
  132. /package/{src/components → idea}/Table/Components/Header/TableHeaderRow.tsx +0 -0
  133. /package/{src/components → idea}/Table/Components/SetSortList.tsx +0 -0
  134. /package/{src/components → idea}/Table/Components/TableFooter.tsx +0 -0
  135. /package/{src/components → idea}/Table/Components/Templates/TemplateCreate.tsx +0 -0
  136. /package/{src/components → idea}/Table/Components/Templates/TemplateCreateDefault.tsx +0 -0
  137. /package/{src/components → idea}/Table/Components/Templates/TemplateList.tsx +0 -0
  138. /package/{src/components → idea}/Table/Components/Templates/repo/TemplateRepo.ts +0 -0
  139. /package/src/utils/{DateUtils.ts → dateUtils.ts} +0 -0
  140. /package/src/utils/{LocalStorageHelper.ts → localStorageHelper.ts} +0 -0
  141. /package/src/utils/{NumberUtils.ts → numberUtils.ts} +0 -0
  142. /package/src/utils/{RootDir.ts → rootDir.ts} +0 -0
  143. /package/src/utils/{StringUtils.ts → stringUtils.ts} +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inceptionbg/iui",
3
- "version": "2.0.8",
3
+ "version": "2.0.11",
4
4
  "description": "UI components, elements & utils for Inception ecosystem",
5
5
  "type": "module",
6
6
  "exports": {
@@ -11,7 +11,7 @@ export * from './light/faHouse';
11
11
  export * from './light/faIdBadge';
12
12
  export * from './light/faLink';
13
13
  export * from './light/faMagnifyingGlass';
14
- export * from './light/faPenField';
14
+ export * from './light/faPen';
15
15
  export * from './light/faPrint';
16
16
  export * from './light/faQuestion';
17
17
  export * from './light/faRotateRight';
@@ -0,0 +1,15 @@
1
+ import { IconDefinition } from "@fortawesome/fontawesome-svg-core";
2
+
3
+ const prefix = "fal";
4
+ const iconName = "clipboard-check";
5
+ const width = 384;
6
+ const height = 512;
7
+ const unicode = "f46c";
8
+ const svgPathData =
9
+ "M320 64c-8.844 0-16 7.156-16 16S311.2 96 320 96c17.64 0 32 14.34 32 32v320c0 17.66-14.36 32-32 32H64c-17.64 0-32-14.34-32-32V128c0-17.66 14.36-32 32-32c8.844 0 16-7.156 16-16S72.84 64 64 64C28.7 64 0 92.72 0 128v320c0 35.28 28.7 64 64 64h256c35.3 0 64-28.72 64-64V128C384 92.72 355.3 64 320 64zM112 128h160C280.8 128 288 120.8 288 112S280.8 96 272 96h-24.88C252.6 86.55 256 75.72 256 64c0-35.35-28.65-64-64-64S128 28.65 128 64c0 11.72 3.379 22.55 8.877 32H112C103.2 96 96 103.2 96 112S103.2 128 112 128zM192 32c17.64 0 32 14.36 32 32s-14.36 32-32 32S160 81.64 160 64S174.4 32 192 32zM84.69 299.3l64 64C151.8 366.4 155.9 368 160 368s8.188-1.562 11.31-4.688l128-128c6.25-6.25 6.25-16.38 0-22.62s-16.38-6.25-22.62 0L160 329.4L107.3 276.7c-6.25-6.25-16.38-6.25-22.62 0S78.44 293.1 84.69 299.3z";
10
+
11
+ export const faClipboardCheck: IconDefinition = {
12
+ prefix,
13
+ iconName,
14
+ icon: [width, height, [], unicode, svgPathData],
15
+ };
@@ -1,15 +1,15 @@
1
- import { IconDefinition } from "@fortawesome/fontawesome-svg-core";
2
-
3
- const prefix = "fal";
4
- const iconName = "house";
5
- const width = 576;
6
- const height = 512;
7
- const unicode = "f015";
8
- const svgPathData =
9
- "M570.6 244C577.2 249.8 577.8 259.1 571.1 266.6C566.2 273.2 556 273.8 549.4 267.1L512 234.1V432C512 476.2 476.2 512 432 512H144C99.82 512 64 476.2 64 432V234.1L26.59 267.1C19.96 273.8 9.849 273.2 4.003 266.6C-1.844 259.1-1.212 249.8 5.414 244L277.4 4.002C283.5-1.334 292.5-1.334 298.6 4.002L570.6 244zM144 480H208V320C208 302.3 222.3 288 240 288H336C353.7 288 368 302.3 368 320V480H432C458.5 480 480 458.5 480 432V206.7L288 37.34L96 206.7V432C96 458.5 117.5 480 144 480zM240 480H336V320H240V480z";
10
-
11
- export const faHouse: IconDefinition = {
12
- prefix,
13
- iconName,
14
- icon: [width, height, [], unicode, svgPathData],
15
- };
1
+ import { IconDefinition } from "@fortawesome/fontawesome-svg-core";
2
+
3
+ const prefix = "fal";
4
+ const iconName = "house";
5
+ const width = 576;
6
+ const height = 512;
7
+ const unicode = "f015";
8
+ const svgPathData =
9
+ "M570.6 244C577.2 249.8 577.8 259.1 571.1 266.6C566.2 273.2 556 273.8 549.4 267.1L512 234.1V432C512 476.2 476.2 512 432 512H144C99.82 512 64 476.2 64 432V234.1L26.59 267.1C19.96 273.8 9.849 273.2 4.003 266.6C-1.844 259.1-1.212 249.8 5.414 244L277.4 4.002C283.5-1.334 292.5-1.334 298.6 4.002L570.6 244zM144 480H208V320C208 302.3 222.3 288 240 288H336C353.7 288 368 302.3 368 320V480H432C458.5 480 480 458.5 480 432V206.7L288 37.34L96 206.7V432C96 458.5 117.5 480 144 480zM240 480H336V320H240V480z";
10
+
11
+ export const faHouse: IconDefinition = {
12
+ prefix,
13
+ iconName,
14
+ icon: [width, height, [], unicode, svgPathData],
15
+ };
@@ -1,15 +1,15 @@
1
- import { IconDefinition } from "@fortawesome/fontawesome-svg-core";
2
-
3
- const prefix = "fal";
4
- const iconName = "id-badge";
5
- const width = 384;
6
- const height = 512;
7
- const unicode = "f2c1";
8
- const svgPathData =
9
- "M320 0H64C28.65 0 0 28.65 0 64v384c0 35.35 28.65 64 64 64h256c35.35 0 64-28.65 64-64V64C384 28.65 355.3 0 320 0zM352 448c0 17.64-14.36 32-32 32H64c-17.64 0-32-14.36-32-32V64c0-17.64 14.36-32 32-32h256c17.64 0 32 14.36 32 32V448zM192 288c35.35 0 64-28.65 64-64s-28.65-64-64-64S128 188.7 128 224S156.7 288 192 288zM192 192c17.64 0 32 14.36 32 32s-14.36 32-32 32S160 241.6 160 224S174.4 192 192 192zM224 320H160c-44.18 0-80 35.82-80 80C80 408.8 87.16 416 96 416c8.838 0 16-7.164 16-16C112 373.5 133.5 352 160 352h64c26.51 0 48 21.49 48 48c0 8.836 7.164 16 16 16c8.838 0 16-7.164 16-16C304 355.8 268.2 320 224 320zM144 96h96C248.8 96 256 88.84 256 80S248.8 64 240 64h-96C135.2 64 128 71.16 128 80S135.2 96 144 96z";
10
-
11
- export const faIdBadge: IconDefinition = {
12
- prefix,
13
- iconName,
14
- icon: [width, height, [], unicode, svgPathData],
15
- };
1
+ import { IconDefinition } from "@fortawesome/fontawesome-svg-core";
2
+
3
+ const prefix = "fal";
4
+ const iconName = "id-badge";
5
+ const width = 384;
6
+ const height = 512;
7
+ const unicode = "f2c1";
8
+ const svgPathData =
9
+ "M320 0H64C28.65 0 0 28.65 0 64v384c0 35.35 28.65 64 64 64h256c35.35 0 64-28.65 64-64V64C384 28.65 355.3 0 320 0zM352 448c0 17.64-14.36 32-32 32H64c-17.64 0-32-14.36-32-32V64c0-17.64 14.36-32 32-32h256c17.64 0 32 14.36 32 32V448zM192 288c35.35 0 64-28.65 64-64s-28.65-64-64-64S128 188.7 128 224S156.7 288 192 288zM192 192c17.64 0 32 14.36 32 32s-14.36 32-32 32S160 241.6 160 224S174.4 192 192 192zM224 320H160c-44.18 0-80 35.82-80 80C80 408.8 87.16 416 96 416c8.838 0 16-7.164 16-16C112 373.5 133.5 352 160 352h64c26.51 0 48 21.49 48 48c0 8.836 7.164 16 16 16c8.838 0 16-7.164 16-16C304 355.8 268.2 320 224 320zM144 96h96C248.8 96 256 88.84 256 80S248.8 64 240 64h-96C135.2 64 128 71.16 128 80S135.2 96 144 96z";
10
+
11
+ export const faIdBadge: IconDefinition = {
12
+ prefix,
13
+ iconName,
14
+ icon: [width, height, [], unicode, svgPathData],
15
+ };
@@ -0,0 +1,15 @@
1
+ import { IconDefinition } from "@fortawesome/fontawesome-svg-core";
2
+
3
+ const prefix = "fal";
4
+ const iconName = "pen";
5
+ const width = 512;
6
+ const height = 512;
7
+ const unicode = "f304";
8
+ const svgPathData =
9
+ "M493.2 56.26l-37.51-37.51C443.2 6.252 426.8 0 410.5 0c-16.38 0-32.76 6.25-45.26 18.75L45.11 338.9c-8.568 8.566-14.53 19.39-17.18 31.21l-27.61 122.8C-1.7 502.1 6.158 512 15.95 512c1.047 0 2.116-.1034 3.198-.3202c0 0 84.61-17.95 122.8-26.93c11.54-2.717 21.87-8.523 30.25-16.9l321.2-321.2C518.3 121.7 518.2 81.26 493.2 56.26zM149.5 445.2c-4.219 4.219-9.252 7.039-14.96 8.383c-24.68 5.811-69.64 15.55-97.46 21.52l22.04-98.01c1.332-5.918 4.303-11.31 8.594-15.6l247.6-247.6l82.76 82.76L149.5 445.2zM470.7 124l-50.03 50.02l-82.76-82.76l49.93-49.93C393.9 35.33 401.9 32 410.5 32s16.58 3.33 22.63 9.375l37.51 37.51C483.1 91.37 483.1 111.6 470.7 124z";
10
+
11
+ export const faPen: IconDefinition = {
12
+ prefix,
13
+ iconName,
14
+ icon: [width, height, [], unicode, svgPathData],
15
+ };
@@ -14,6 +14,7 @@ export interface IIconButtonProps {
14
14
  disabled?: boolean;
15
15
  active?: boolean;
16
16
  tooltip?: string;
17
+ type?: ButtonHTMLAttributes<HTMLButtonElement>['type'];
17
18
  className?: string;
18
19
  buttonProps?: ButtonHTMLAttributes<HTMLButtonElement>;
19
20
  ref?: Ref<HTMLButtonElement>;
@@ -28,6 +29,7 @@ export const IconButton: FC<IIconButtonProps> = ({
28
29
  disabled,
29
30
  active,
30
31
  tooltip,
32
+ type = 'button',
31
33
  className,
32
34
  buttonProps,
33
35
  ref,
@@ -40,7 +42,7 @@ export const IconButton: FC<IIconButtonProps> = ({
40
42
  active,
41
43
  })}
42
44
  onClick={onClick}
43
- type={buttonProps?.type || onClick ? 'button' : 'submit'}
45
+ type={type}
44
46
  {...buttonProps}
45
47
  >
46
48
  <FontAwesomeIcon icon={icon} />
@@ -1,52 +1,31 @@
1
- import { IconDefinition } from '@fortawesome/fontawesome-svg-core';
2
1
  import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
3
2
  import clsx from 'clsx';
4
- import { FC, ReactNode, useCallback, useRef } from 'react';
3
+ import { FC, KeyboardEventHandler, ReactNode, useRef } from 'react';
5
4
  import { createPortal } from 'react-dom';
6
- import { useTranslation } from 'react-i18next';
7
- import { rootDir } from '../../utils/RootDir';
8
- import { Button, IButtonColor, IButtonVariant } from '../Button/Button';
5
+ import { rootDir } from '../../utils/rootDir';
9
6
  import { Loader } from '../Loader/Loader';
10
7
  import { ConditionalWrapper } from '../Wrappers/ConditionalWrapper';
11
- import { useDialogKeyboard } from './hooks/useDialogKeyboard';
12
8
  import { faXmark } from '../../assets/icons';
13
9
  import { IconButton } from '../Button/IconButton';
14
10
  import { infoIcons } from '../../utils/icons';
15
11
  import { IInfoType } from '../../types/IInfo';
12
+ import { ILocalPopupControl } from '../../types/IPopup';
16
13
  import { useBackgroundClose } from '../../hooks/useBackgroundClose';
14
+ import { DialogFooter, IDialogFooterActions } from './components/DialogFooter';
15
+ import { useLocalPopoverControl } from '../../hooks/useLocalPopoverControl';
16
+ import { useGetFocusableElements } from '../../hooks/useGetFocusableElements';
17
+ import { onPopupKeyDown } from '../../utils/popupUtils';
17
18
 
18
19
  interface Props {
20
+ control: ILocalPopupControl;
19
21
  title?: string;
20
22
  titleEl?: ReactNode;
21
23
  desc?: string;
22
24
  descEl?: ReactNode;
23
- isOpen: boolean;
24
- onClose: () => void;
25
+ onFormSubmit?: () => void;
26
+ onCloseCallback?: () => void;
25
27
  isLoading?: boolean;
26
- confirmButton?: {
27
- label?: string;
28
- icon?: IconDefinition;
29
- onClick?: () => void;
30
- onFormSubmit?: () => void;
31
- disabled?: boolean;
32
- keepOpen?: boolean;
33
- isKeyboardDisabled?: boolean;
34
- };
35
- cancelButton?: {
36
- label?: string;
37
- icon?: IconDefinition;
38
- onClick?: () => void;
39
- };
40
- additionalButton?: {
41
- label: string;
42
- icon?: IconDefinition;
43
- onClick?: () => void;
44
- disabled?: boolean;
45
- keepOpen?: boolean;
46
- color?: IButtonColor;
47
- variant?: IButtonVariant;
48
- };
49
- hideActionButtons?: boolean;
28
+ footer?: IDialogFooterActions;
50
29
  isKeyboardDisabled?: boolean;
51
30
  noBackgroundClick?: boolean;
52
31
  noOverflow?: boolean;
@@ -57,18 +36,16 @@ interface Props {
57
36
  }
58
37
 
59
38
  export const Dialog: FC<Props> = ({
39
+ control,
60
40
  title,
61
41
  titleEl,
62
42
  desc,
63
43
  descEl,
64
- isOpen,
65
- onClose,
44
+ onFormSubmit,
45
+ onCloseCallback,
66
46
  isLoading,
67
- confirmButton,
68
- cancelButton,
69
- additionalButton,
47
+ footer,
70
48
  isKeyboardDisabled,
71
- hideActionButtons,
72
49
  noBackgroundClick,
73
50
  noOverflow,
74
51
  type,
@@ -76,58 +53,60 @@ export const Dialog: FC<Props> = ({
76
53
  className,
77
54
  children,
78
55
  }) => {
79
- const { t } = useTranslation();
80
-
81
- const portalRef = useRef<HTMLDivElement>(null);
82
56
  const formRef = useRef<HTMLFormElement>(null);
83
57
 
84
- const handleClose = useCallback(() => {
85
- portalRef.current?.classList.add('closing');
86
- setTimeout(onClose, 200);
87
- }, [portalRef, onClose]);
58
+ const { elementRef, isOpen, onClose } = useLocalPopoverControl({
59
+ control,
60
+ onCloseCallback,
61
+ });
88
62
 
89
- useDialogKeyboard({
63
+ const focusableElements = useGetFocusableElements({
64
+ elementRef,
90
65
  isOpen,
91
- isDisabled: isKeyboardDisabled,
92
- onClose: handleClose,
93
- submit: {
94
- onEnter: () => {
95
- if (confirmButton) {
96
- if (confirmButton.onFormSubmit) {
97
- formRef.current?.requestSubmit();
98
- } else {
99
- confirmButton.onClick?.();
100
- !confirmButton.keepOpen && handleClose();
101
- }
102
- } else {
103
- cancelButton?.onClick ? cancelButton.onClick() : handleClose();
104
- }
105
- },
106
- isDisabled: !confirmButton?.disabled && !confirmButton?.isKeyboardDisabled,
107
- },
108
66
  });
109
67
 
110
68
  useBackgroundClose({
111
- portalRef,
69
+ portalRef: elementRef,
112
70
  disabled: noBackgroundClick || !isOpen,
113
- handleClose,
71
+ handleClose: onClose,
114
72
  });
115
73
 
74
+ const onKeyDown: KeyboardEventHandler<HTMLDivElement> = event => {
75
+ !isKeyboardDisabled &&
76
+ onPopupKeyDown(event, {
77
+ onClose,
78
+ enter: {
79
+ onAction: () => {
80
+ footer?.confirmButton.onClick?.();
81
+ !footer?.confirmButton.keepOpen && onClose();
82
+ },
83
+ disabled: !footer?.confirmButton.onClick,
84
+ },
85
+ focusableElements,
86
+ });
87
+ };
88
+
116
89
  return isOpen
117
90
  ? createPortal(
118
- <div ref={portalRef} className="iui-dialog">
91
+ <div
92
+ ref={elementRef}
93
+ className="iui-dialog"
94
+ aria-label="popup"
95
+ onKeyDown={onKeyDown}
96
+ tabIndex={-1}
97
+ >
119
98
  <Loader isLoading={!!isLoading}>
120
99
  <div className={clsx('iui-dialog-container', size, type, className)}>
121
100
  <ConditionalWrapper
122
- condition={!!confirmButton?.onFormSubmit}
101
+ condition={!!onFormSubmit}
123
102
  wrapper={children => (
124
103
  <form
125
104
  ref={formRef}
126
105
  onSubmit={e => {
127
106
  e.preventDefault();
128
107
  e.stopPropagation();
129
- confirmButton?.onFormSubmit?.();
130
- !confirmButton?.keepOpen && handleClose();
108
+ onFormSubmit?.();
109
+ !footer?.confirmButton?.keepOpen && onClose();
131
110
  }}
132
111
  >
133
112
  {children}
@@ -151,10 +130,11 @@ export const Dialog: FC<Props> = ({
151
130
  {title ? <h4>{title}</h4> : titleEl}
152
131
  <IconButton
153
132
  icon={faXmark}
154
- onClick={handleClose}
133
+ onClick={onClose}
155
134
  color="neutral"
156
135
  size="l"
157
136
  className="close-icon"
137
+ buttonProps={{ tabIndex: -1 }}
158
138
  />
159
139
  </div>
160
140
  {desc ? <p className="iui-dialog-desc">{desc}</p> : descEl}
@@ -162,59 +142,13 @@ export const Dialog: FC<Props> = ({
162
142
  </div>
163
143
  {children}
164
144
  </div>
165
- {!hideActionButtons && (
166
- <div className="iui-dialog-actions">
167
- <Button
168
- label={
169
- cancelButton?.label || (confirmButton ? t('Cancel') : t('Close'))
170
- }
171
- icon={cancelButton?.icon}
172
- variant={confirmButton ? 'outlined' : 'solid'}
173
- onClick={e => {
174
- e.stopPropagation();
175
- cancelButton?.onClick ? cancelButton.onClick() : handleClose();
176
- }}
177
- type="button"
178
- />
179
- {additionalButton && (
180
- <Button
181
- label={additionalButton.label}
182
- icon={additionalButton.icon}
183
- onClick={
184
- !!additionalButton.onClick
185
- ? e => {
186
- e.stopPropagation();
187
- additionalButton.onClick!();
188
- !additionalButton.keepOpen && handleClose();
189
- }
190
- : undefined
191
- }
192
- type="button"
193
- variant={additionalButton.variant ?? 'outlined'}
194
- color={additionalButton.color}
195
- disabled={additionalButton.disabled}
196
- />
197
- )}
198
- {confirmButton && (
199
- <Button
200
- label={confirmButton.label || 'Potvrdi'}
201
- icon={confirmButton.icon}
202
- variant="solid"
203
- type={confirmButton.onFormSubmit ? 'submit' : 'button'}
204
- onClick={
205
- !!confirmButton.onClick
206
- ? e => {
207
- e.stopPropagation();
208
- confirmButton.onClick!();
209
- !confirmButton.keepOpen && handleClose();
210
- }
211
- : undefined
212
- }
213
- color={type === 'danger' ? 'danger' : undefined}
214
- disabled={confirmButton.disabled}
215
- />
216
- )}
217
- </div>
145
+ {footer && (
146
+ <DialogFooter
147
+ {...footer}
148
+ onClose={onClose}
149
+ isForm={!!onFormSubmit}
150
+ type={type}
151
+ />
218
152
  )}
219
153
  </ConditionalWrapper>
220
154
  </div>
@@ -0,0 +1,92 @@
1
+ import { IconDefinition } from '@fortawesome/fontawesome-svg-core';
2
+ import type { ButtonHTMLAttributes, FC } from 'react';
3
+ import { Button, IButtonColor } from '../../Button/Button';
4
+ import { useTranslation } from 'react-i18next';
5
+ import { IInfoType } from '../../../types/IInfo';
6
+
7
+ export interface IDialogFooterActions {
8
+ confirmButton: {
9
+ label?: string;
10
+ icon?: IconDefinition;
11
+ onClick?: () => void;
12
+ disabled?: boolean;
13
+ keepOpen?: boolean;
14
+ color?: IButtonColor;
15
+ isKeyboardDisabled?: boolean;
16
+ type?: ButtonHTMLAttributes<HTMLButtonElement>['type'];
17
+ };
18
+ cancelButton?: {
19
+ label?: string;
20
+ icon?: IconDefinition;
21
+ onClick?: () => void;
22
+ hidden?: boolean;
23
+ };
24
+ additionalButton?: {
25
+ label: string;
26
+ icon?: IconDefinition;
27
+ onClick: () => void;
28
+ disabled?: boolean;
29
+ keepOpen?: boolean;
30
+ color?: IButtonColor;
31
+ };
32
+ }
33
+
34
+ interface Props extends IDialogFooterActions {
35
+ onClose: () => void;
36
+ isForm?: boolean;
37
+ type?: IInfoType;
38
+ }
39
+
40
+ export const DialogFooter: FC<Props> = ({
41
+ confirmButton,
42
+ cancelButton,
43
+ additionalButton,
44
+ onClose,
45
+ isForm,
46
+ type,
47
+ }) => {
48
+ const { t } = useTranslation();
49
+
50
+ return (
51
+ <div className="iui-dialog-actions">
52
+ {additionalButton && (
53
+ <Button
54
+ {...additionalButton}
55
+ onClick={e => {
56
+ e.stopPropagation();
57
+ additionalButton.onClick!();
58
+ !additionalButton.keepOpen && onClose();
59
+ }}
60
+ variant="simple"
61
+ className="mr-auto"
62
+ />
63
+ )}
64
+ {!cancelButton?.hidden && (
65
+ <Button
66
+ label={cancelButton?.label ?? t('Cancel')}
67
+ icon={cancelButton?.icon}
68
+ variant="outlined"
69
+ onClick={e => {
70
+ e.stopPropagation();
71
+ cancelButton?.onClick?.();
72
+ onClose();
73
+ }}
74
+ type="button"
75
+ />
76
+ )}
77
+ <Button
78
+ label={confirmButton.label || t('Confirm')}
79
+ icon={confirmButton.icon}
80
+ variant="solid"
81
+ type={confirmButton.type ?? (isForm ? 'submit' : 'button')}
82
+ onClick={e => {
83
+ e.stopPropagation();
84
+ confirmButton.onClick?.();
85
+ !confirmButton.keepOpen && !isForm && onClose();
86
+ }}
87
+ color={(confirmButton.color ?? type === 'danger') ? 'danger' : undefined}
88
+ disabled={confirmButton.disabled}
89
+ />
90
+ </div>
91
+ );
92
+ };
@@ -18,13 +18,14 @@ export const useDialogKeyboard = ({
18
18
  useEffect(() => {
19
19
  if (isOpen && !isDisabled) {
20
20
  const handleKeyDown = (event: KeyboardEvent) => {
21
+ event.stopPropagation();
21
22
  const actions: IKeyboardAction[] = [
22
- { key: 'Enter', onAction: submit.onEnter!, disabled: submit.isDisabled },
23
- { key: 'Escape', onAction: onClose },
23
+ { code: 'Enter', onAction: submit.onEnter!, disabled: submit.isDisabled },
24
+ { code: 'Escape', onAction: onClose },
24
25
  ];
25
26
 
26
27
  actions.forEach(item => {
27
- if (!item.disabled && item.key === event.key) {
28
+ if (!item.disabled && item.code === event.key) {
28
29
  event.preventDefault();
29
30
  event.stopPropagation();
30
31
  item.onAction();
@@ -32,9 +33,9 @@ export const useDialogKeyboard = ({
32
33
  });
33
34
  };
34
35
 
35
- window.addEventListener('keydown', handleKeyDown);
36
+ document.addEventListener('keydown', handleKeyDown);
36
37
  return () => {
37
- window.removeEventListener('keydown', handleKeyDown);
38
+ document.removeEventListener('keydown', handleKeyDown);
38
39
  };
39
40
  }
40
41
  }, [isOpen, submit, onClose, isDisabled]);
@@ -14,8 +14,7 @@ export const UserMenu: FC<IHeaderUserMenuProps> = ({
14
14
  showBadge,
15
15
 
16
16
  HeaderUserMenuDialogs,
17
- openedDialog,
18
- setOpenedDialog,
17
+ controls,
19
18
  refetchOrganizationInvites,
20
19
  }) => (
21
20
  <>
@@ -44,8 +43,7 @@ export const UserMenu: FC<IHeaderUserMenuProps> = ({
44
43
  )}
45
44
  />
46
45
  <HeaderUserMenuDialogs
47
- openedDialog={openedDialog}
48
- setOpenedDialog={setOpenedDialog}
46
+ controls={controls}
49
47
  refetchOrganizationInvites={refetchOrganizationInvites}
50
48
  />
51
49
  </>
@@ -21,7 +21,7 @@ export const Header: FC<Props> = ({
21
21
  }) => (
22
22
  <div className="iui-header">
23
23
  {modulesProps && <ModuleSelect {...modulesProps} />}
24
- {customTitle && <h3 className="p-3">{customTitle}</h3>}
24
+ {customTitle && <h3 className="ml-3">{customTitle}</h3>}
25
25
  <div className="flex gap-2 align-center">
26
26
  {children}
27
27
  {/* {!hideNotifications && <Notifications />} */}