@inceptionbg/iui 2.0.15 → 2.0.17

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 (76) hide show
  1. package/dist/NoAccessPage-BmizYfw0.js +2 -0
  2. package/dist/{NoAccessPage-DBq5IzIf.js.map → NoAccessPage-BmizYfw0.js.map} +1 -1
  3. package/dist/NotFoundPage-Cv544vAr.js +2 -0
  4. package/dist/{NotFoundPage-DM-I96ar.js.map → NotFoundPage-Cv544vAr.js.map} +1 -1
  5. package/dist/index.d.ts +160 -91
  6. package/dist/index.js +1 -1
  7. package/dist/index.js.map +1 -1
  8. package/dist/iui.css +1 -1
  9. package/package.json +4 -7
  10. package/src/assets/icons/duotone/faBell.ts +17 -0
  11. package/src/assets/icons/duotone/faPen.ts +18 -0
  12. package/src/assets/icons/duotone/faTrashCan.ts +18 -0
  13. package/src/assets/icons/light/faBell.ts +15 -0
  14. package/src/assets/icons/light/faEnvelope.ts +15 -0
  15. package/src/assets/icons/regular/faEllipsisVertical.ts +15 -0
  16. package/src/assets/icons/solid/faEnvelopeDot.ts +15 -0
  17. package/src/components/Button/SplitButton.tsx +5 -5
  18. package/src/components/Dialog/Dialog.tsx +3 -3
  19. package/src/components/Header/Components/ModuleSelect.tsx +5 -5
  20. package/src/components/Header/Components/Notifications.tsx +208 -0
  21. package/src/components/Header/Components/UserMenu.tsx +15 -14
  22. package/src/components/Header/Header.tsx +5 -4
  23. package/src/components/Inputs/NumberInput.tsx +3 -0
  24. package/src/components/Inputs/Selects/components/SelectWrapper.tsx +48 -29
  25. package/src/components/Inputs/TextInput.tsx +1 -0
  26. package/src/components/List/ListItem.tsx +1 -1
  27. package/src/components/Loader/ProgressBar.tsx +1 -1
  28. package/src/components/Menu/Menu.tsx +3 -0
  29. package/src/components/Pullover/Pullover.tsx +38 -39
  30. package/src/components/Table/Table.tsx +23 -32
  31. package/{idea/Table/Components/Columns → src/components/Table/components/columns}/ColumnsList.tsx +12 -14
  32. package/src/components/Table/components/columns/TableColumnsEdit.tsx +112 -0
  33. package/src/components/Table/components/edit/TableEditRow.tsx +26 -21
  34. package/src/components/Table/components/header/TableHeaderRow.tsx +2 -1
  35. package/src/components/Table/components/items/TableItemActions.tsx +18 -13
  36. package/src/components/Table/components/print/TablePrint.tsx +1 -5
  37. package/src/components/Table/components/templates/CreateTemplateDialog.tsx +48 -0
  38. package/src/components/Table/components/templates/TableTemplates.tsx +24 -4
  39. package/src/components/Table/contexts/TableContext.tsx +34 -33
  40. package/src/components/Table/hooks/localHooks/useLocalTableColumns.tsx +27 -28
  41. package/src/components/Table/hooks/localHooks/useLocalTableData.tsx +17 -11
  42. package/src/components/Table/hooks/localHooks/useLocalTableKeyboard.ts +8 -6
  43. package/src/components/Table/hooks/useTableColumns.ts +16 -10
  44. package/src/components/Table/hooks/useTableEdit.tsx +24 -2
  45. package/src/components/Table/hooks/useTablePrint.ts +12 -4
  46. package/src/components/Table/hooks/useTableSelect.ts +1 -1
  47. package/src/components/Tabs/Tabs.tsx +1 -0
  48. package/src/components/Tooltip/Tooltip.tsx +81 -14
  49. package/src/hooks/useIsMenuOpen.ts +3 -3
  50. package/src/hooks/usePopupControl.ts +9 -4
  51. package/src/index.ts +24 -5
  52. package/src/styles/App.scss +1 -0
  53. package/src/styles/components/_badge.scss +8 -1
  54. package/src/styles/components/_header.scss +18 -8
  55. package/src/styles/components/_list.scss +1 -1
  56. package/src/styles/components/_notifications.scss +71 -0
  57. package/src/styles/components/_page.scss +1 -0
  58. package/src/styles/components/_pullover.scss +1 -1
  59. package/src/styles/components/_sidebar.scss +1 -3
  60. package/src/styles/components/_table.scss +110 -57
  61. package/src/styles/variables/_variables.scss +9 -0
  62. package/src/types/IHeader.ts +1 -1
  63. package/src/types/IKeyboard.ts +0 -5
  64. package/src/types/IMenu.ts +2 -2
  65. package/src/types/INotifications.ts +15 -0
  66. package/src/types/IPopup.ts +2 -2
  67. package/src/types/ITable.ts +36 -32
  68. package/src/utils/i18n/i18nIUICyrilic.ts +12 -0
  69. package/src/utils/i18n/i18nIUILatin.ts +13 -0
  70. package/src/utils/i18n/i18nIUIMe.ts +12 -0
  71. package/src/utils/objectUtils.ts +19 -0
  72. package/src/utils/tableUtils.ts +1 -1
  73. package/dist/NoAccessPage-DBq5IzIf.js +0 -2
  74. package/dist/NotFoundPage-DM-I96ar.js +0 -2
  75. package/idea/Notifications.tsx +0 -245
  76. package/idea/Table/Components/Columns/SetColumnsList.tsx +0 -113
@@ -0,0 +1,208 @@
1
+ import {
2
+ Dispatch,
3
+ SetStateAction,
4
+ useCallback,
5
+ useEffect,
6
+ useState,
7
+ type FC,
8
+ } from 'react';
9
+ import { INotification } from '../../../types/INotifications';
10
+ import { Menu } from '../../Menu/Menu';
11
+ import { useIsMenuOpen } from '../../../hooks/useIsMenuOpen';
12
+ import { IconButton } from '../../Button/IconButton';
13
+ import { NotificationBadge } from '../../Badge/NotificationBadge';
14
+ import { faBell } from '../../../assets/icons/duotone/faBell';
15
+ import { faBell as faBellLight } from '../../../assets/icons/light/faBell';
16
+ import { Trans, useTranslation } from 'react-i18next';
17
+ import { Link } from 'react-router';
18
+ import clsx from 'clsx';
19
+ import { formatDateAndTime } from '../../../utils/dateUtils';
20
+ import { faEnvelope } from '../../../assets/icons/light/faEnvelope';
21
+ import { faEnvelopeDot } from '../../../assets/icons/solid/faEnvelopeDot';
22
+ import { SearchInput } from '../../Inputs/SearchInput';
23
+ import { Loader } from '../../Loader/Loader';
24
+ import { ISelectData } from '../../../types/ISelect';
25
+ import { faEllipsisVertical } from '../../../assets/icons';
26
+ import { getNotificationValues } from '../../../utils/objectUtils';
27
+
28
+ export interface INotificationsProps {
29
+ notificationCount: number;
30
+ notifications: INotification[];
31
+ isLoading: boolean;
32
+ menuControl: { isOpen: boolean; onClose: () => void; onOpen: () => void };
33
+ seen: boolean | null;
34
+ setSeen: Dispatch<SetStateAction<boolean | null>>;
35
+ markAsSeen: (uuid: string) => void;
36
+ markAllAsSeen: () => void;
37
+ }
38
+
39
+ export const Notifications: FC<INotificationsProps> = ({
40
+ notificationCount,
41
+ notifications = [],
42
+ isLoading,
43
+ menuControl,
44
+ seen,
45
+ setSeen,
46
+ markAsSeen,
47
+ markAllAsSeen,
48
+ }) => {
49
+ const { t } = useTranslation();
50
+ const { isOpen, onClose, onOpen } = menuControl;
51
+ const {
52
+ isOpen: isOpenOptions,
53
+ onClose: onCloseOptions,
54
+ onOpen: onOpenOptions,
55
+ } = useIsMenuOpen();
56
+
57
+ const seenOptions: ISelectData[] = [
58
+ { label: t('NotificationsAll'), value: null },
59
+ { label: t('NotificationsUnread'), value: false },
60
+ { label: t('NotificationsRead'), value: true },
61
+ ];
62
+
63
+ const [filteredNotifications, setFilteredNotifications] = useState<INotification[]>([]);
64
+
65
+ useEffect(() => {
66
+ setFilteredNotifications(notifications);
67
+ }, [notifications]);
68
+
69
+ const onSearch = useCallback(
70
+ (e: string) =>
71
+ setFilteredNotifications(
72
+ !e
73
+ ? notifications
74
+ : notifications.filter(notification => {
75
+ const title = t(`NTitle${notification.event}`);
76
+ const description = t(`NContent${notification.event}`, {
77
+ ...getNotificationValues(t, notification.values),
78
+ });
79
+
80
+ const searchContent = `${title} ${description}`.toLowerCase();
81
+ const searchWords = e.toLowerCase().trim().split(/\s+/);
82
+
83
+ return searchWords.every(word => searchContent.includes(word));
84
+ })
85
+ ),
86
+ [notifications, t]
87
+ );
88
+
89
+ return (
90
+ <Menu
91
+ isOpen={isOpen}
92
+ onClose={onClose}
93
+ placement="bottom-right"
94
+ size="m"
95
+ className="header-user-menu"
96
+ renderButton={ref => (
97
+ <NotificationBadge
98
+ number={notificationCount}
99
+ className="header-btn-badge"
100
+ size="s"
101
+ >
102
+ <IconButton
103
+ ref={ref}
104
+ icon={!!notificationCount ? faBell : faBellLight}
105
+ onClick={onOpen}
106
+ className="header-button notification-button"
107
+ active={isOpen}
108
+ variant="solid"
109
+ />
110
+ </NotificationBadge>
111
+ )}
112
+ >
113
+ <div className="notifications">
114
+ <div className="notifications-content-header">
115
+ <h3>{t('Notifications')}</h3>
116
+ <SearchInput onSearch={onSearch} />
117
+ </div>
118
+ <div className="notifications-options">
119
+ <div className="flex gap-2">
120
+ {seenOptions.map(({ label, value }) => (
121
+ <div
122
+ key={label}
123
+ className={clsx('link fs-13', {
124
+ inactive: seen !== value,
125
+ })}
126
+ onClick={() => setSeen(value)}
127
+ >
128
+ {label}
129
+ </div>
130
+ ))}
131
+ </div>
132
+ <Menu
133
+ isOpen={isOpenOptions}
134
+ onClose={onCloseOptions}
135
+ placement="bottom-right"
136
+ size="m"
137
+ renderButton={ref => (
138
+ <IconButton
139
+ ref={ref}
140
+ icon={faEllipsisVertical}
141
+ onClick={onOpenOptions}
142
+ className="header-button notification-button"
143
+ active={isOpenOptions}
144
+ size="s"
145
+ />
146
+ )}
147
+ items={[{ label: t('MarkAllAsRead'), onClick: markAllAsSeen }]}
148
+ />
149
+ </div>
150
+ <Loader isLoading={isLoading}>
151
+ <div className="notifications-container">
152
+ {!!filteredNotifications.length ? (
153
+ filteredNotifications.map(notification => (
154
+ <div
155
+ key={notification.uuid}
156
+ className={clsx('notification', { seen: notification.seen })}
157
+ >
158
+ <div className="notification-header">
159
+ <div>
160
+ <p className="title">{t(`NTitle${notification.event}`)}</p>
161
+ <p className="date">{formatDateAndTime(notification.createdAt)}</p>
162
+ </div>
163
+ <IconButton
164
+ // tooltip={t('MarkAsRead')}
165
+ icon={notification.seen ? faEnvelope : faEnvelopeDot}
166
+ disabled={notification.seen}
167
+ onClick={() => markAsSeen(notification.uuid)}
168
+ size="s"
169
+ />
170
+ </div>
171
+ <p className="desc">
172
+ <Trans
173
+ i18nKey={`NContent${notification.event}`}
174
+ values={getNotificationValues(t, notification.values)}
175
+ t={t}
176
+ components={notification.values?.reduce(
177
+ (obj, e) =>
178
+ e.url
179
+ ? {
180
+ ...obj,
181
+ [e.key]: (
182
+ <Link
183
+ to={e.url}
184
+ className="link"
185
+ onClick={() =>
186
+ !notification.seen && markAsSeen(notification.uuid)
187
+ }
188
+ />
189
+ ),
190
+ }
191
+ : obj,
192
+ {
193
+ bold: <span className="bold" />,
194
+ }
195
+ )}
196
+ />
197
+ </p>
198
+ </div>
199
+ ))
200
+ ) : (
201
+ <p className="text-center fs-13 pt-2">{t('NoNewNotifications')}</p>
202
+ )}
203
+ </div>
204
+ </Loader>
205
+ </div>
206
+ </Menu>
207
+ );
208
+ };
@@ -4,6 +4,7 @@ import { faCircleUser } from '../../../assets/icons/duotone/faCircleUser';
4
4
  import { Tooltip } from '../../Tooltip/Tooltip';
5
5
  import { Menu } from '../../Menu/Menu';
6
6
  import { IHeaderUserMenuProps } from '../../../types/IHeader';
7
+ import { NotificationBadge } from '../../Badge/NotificationBadge';
7
8
 
8
9
  export const UserMenu: FC<IHeaderUserMenuProps> = ({
9
10
  isOpen,
@@ -11,8 +12,7 @@ export const UserMenu: FC<IHeaderUserMenuProps> = ({
11
12
  userName,
12
13
  organizationName,
13
14
  menuItems,
14
- showBadge,
15
-
15
+ inviteCount,
16
16
  HeaderUserMenuDialogs,
17
17
  controls,
18
18
  refetchOrganizationInvites,
@@ -27,19 +27,20 @@ export const UserMenu: FC<IHeaderUserMenuProps> = ({
27
27
  items={menuItems}
28
28
  renderButton={ref => (
29
29
  <button ref={ref} className="user-box" onClick={() => setIsOpen(true)}>
30
- {showBadge && <div className="user-badge" />}
31
30
  <FontAwesomeIcon icon={faCircleUser} className="user-icon" />
32
- <div className="user-info">
33
- {userName && <p className="user-name">{userName}</p>}
34
- {organizationName && (
35
- <Tooltip
36
- label={(organizationName?.length || 0) > 20 ? organizationName : ''}
37
- position="bottom"
38
- >
39
- <p className="org-name">{organizationName}</p>
40
- </Tooltip>
41
- )}
42
- </div>
31
+ <NotificationBadge number={inviteCount} className="user-notif-badge" size="s">
32
+ <div className="user-info">
33
+ {userName && <p className="user-name">{userName}</p>}
34
+ {organizationName && (
35
+ <Tooltip
36
+ label={(organizationName?.length || 0) > 20 ? organizationName : ''}
37
+ position="bottom"
38
+ >
39
+ <p className="org-name">{organizationName}</p>
40
+ </Tooltip>
41
+ )}
42
+ </div>
43
+ </NotificationBadge>
43
44
  </button>
44
45
  )}
45
46
  />
@@ -2,14 +2,14 @@ import { ComponentProps, FC, ReactNode } from 'react';
2
2
  import { UserMenu } from './Components/UserMenu';
3
3
  import { ModuleSelect } from './Components/ModuleSelect';
4
4
  import { IHeaderUserMenuProps } from '../../types/IHeader';
5
+ import { INotificationsProps, Notifications } from './Components/Notifications';
5
6
 
6
7
  interface Props {
7
8
  customTitle?: string;
8
9
  modulesProps?: ComponentProps<typeof ModuleSelect>;
9
- // actions: {
10
- // icon: IconDefinition;
11
- // };
10
+ // actions: { icon: IconDefinition };
12
11
  userMenuProps: IHeaderUserMenuProps;
12
+ notificationsProps?: INotificationsProps;
13
13
  children?: ReactNode;
14
14
  }
15
15
 
@@ -17,6 +17,7 @@ export const Header: FC<Props> = ({
17
17
  customTitle,
18
18
  modulesProps,
19
19
  userMenuProps,
20
+ notificationsProps,
20
21
  children,
21
22
  }) => (
22
23
  <div className="iui-header">
@@ -24,7 +25,7 @@ export const Header: FC<Props> = ({
24
25
  {customTitle && <h3 className="ml-3">{customTitle}</h3>}
25
26
  <div className="flex gap-2 align-center">
26
27
  {children}
27
- {/* {!hideNotifications && <Notifications />} */}
28
+ {notificationsProps && <Notifications {...notificationsProps} />}
28
29
  <UserMenu {...userMenuProps} />
29
30
  </div>
30
31
  </div>
@@ -11,6 +11,7 @@ export interface INumberInputProps {
11
11
  placeholder?: string;
12
12
  endText?: string;
13
13
  isClearable?: boolean;
14
+ onClear?: () => void;
14
15
  helperText?: string;
15
16
  errorText?: string;
16
17
  error?: boolean;
@@ -32,6 +33,7 @@ export const NumberInput: FC<INumberInputProps> = ({
32
33
  placeholder,
33
34
  endText,
34
35
  isClearable,
36
+ onClear,
35
37
  helperText,
36
38
  errorText,
37
39
  error,
@@ -64,6 +66,7 @@ export const NumberInput: FC<INumberInputProps> = ({
64
66
  disabled={disabled}
65
67
  endText={endText}
66
68
  isClearable={isClearable}
69
+ onClear={onClear}
67
70
  placeholder={
68
71
  placeholder ? placeholder : decimalPlaces ? `0.${'0'.repeat(decimalPlaces)}` : '0'
69
72
  }
@@ -68,34 +68,34 @@ export const SelectWrapper = forwardRef<any, ISelectProps>((props, forwardedRef)
68
68
  formatOptionLabel,
69
69
  };
70
70
 
71
- const renderSelect = () => {
72
- switch (variant) {
73
- case 'basic':
74
- return <ReactSelect {...commonProps} options={props.options} />;
75
- case 'async':
76
- return (
77
- <AsyncPaginate
78
- {...commonProps}
79
- loadOptions={props.loadOptions}
80
- defaultOptions={props.defaultData ?? true}
81
- />
82
- );
83
- case 'async-creatable':
84
- return (
85
- <AsyncCreatableSelect
86
- {...commonProps}
87
- loadOptions={props.loadOptions}
88
- defaultOptions={props.defaultData ?? true}
89
- onCreateOption={props.onCreate}
90
- formatCreateLabel={(inputValue: string) => (
91
- <p>{`${t('FreeText')} "${inputValue}"`}</p>
92
- )}
93
- />
94
- );
95
- default:
96
- return null;
97
- }
98
- };
71
+ // const renderSelect = () => {
72
+ // switch (variant) {
73
+ // case 'basic':
74
+ // return <ReactSelect {...commonProps} options={props.options} />;
75
+ // case 'async':
76
+ // return (
77
+ // <AsyncPaginate
78
+ // {...commonProps}
79
+ // loadOptions={props.loadOptions}
80
+ // defaultOptions={props.defaultData ?? true}
81
+ // />
82
+ // );
83
+ // case 'async-creatable':
84
+ // return (
85
+ // <AsyncCreatableSelect
86
+ // {...commonProps}
87
+ // loadOptions={props.loadOptions}
88
+ // defaultOptions={props.defaultData ?? true}
89
+ // onCreateOption={props.onCreate}
90
+ // formatCreateLabel={(inputValue: string) => (
91
+ // <p>{`${t('FreeText')} "${inputValue}"`}</p>
92
+ // )}
93
+ // />
94
+ // );
95
+ // default:
96
+ // return null;
97
+ // }
98
+ // };
99
99
 
100
100
  return (
101
101
  <InputWrapper
@@ -109,7 +109,26 @@ export const SelectWrapper = forwardRef<any, ISelectProps>((props, forwardedRef)
109
109
  minWidth={minWidth}
110
110
  heightAuto
111
111
  >
112
- {renderSelect()}
112
+ {/* {renderSelect()} */}
113
+ {variant === 'async' ? (
114
+ <AsyncPaginate
115
+ {...commonProps}
116
+ loadOptions={props.loadOptions}
117
+ defaultOptions={props.defaultData ?? true}
118
+ />
119
+ ) : variant === 'async-creatable' ? (
120
+ <AsyncCreatableSelect
121
+ {...commonProps}
122
+ loadOptions={props.loadOptions}
123
+ defaultOptions={props.defaultData ?? true}
124
+ onCreateOption={props.onCreate}
125
+ formatCreateLabel={(inputValue: string) => (
126
+ <p>{`${t('FreeText')} "${inputValue}"`}</p>
127
+ )}
128
+ />
129
+ ) : (
130
+ <ReactSelect {...commonProps} options={props.options} />
131
+ )}
113
132
  {required && !disabled && (
114
133
  <input
115
134
  className="fake-input"
@@ -91,6 +91,7 @@ export const TextInput: FC<ITextInputProps> = ({
91
91
  disabled={disabled}
92
92
  onAnimationStart={() => setIsAutoFill(true)}
93
93
  pattern={pattern}
94
+ spellCheck={inputProps?.spellCheck ?? false}
94
95
  {...inputProps}
95
96
  />
96
97
  </InputWrapper>
@@ -37,7 +37,7 @@ export const ListItem: FC<IListItem> = ({
37
37
 
38
38
  return (
39
39
  <div
40
- className={clsx('iui-list-item', { active, disabled })}
40
+ className={clsx('iui-list-item', { active, disabled, clickable: !!onClick })}
41
41
  onClick={e => {
42
42
  e.stopPropagation();
43
43
  onClick?.();
@@ -27,7 +27,7 @@ export const ProgressBar: FC<Props> = ({ progress, label }) => {
27
27
  {
28
28
  '--progress-clip': `${now}%`,
29
29
  '--progress-text': `'${now}%'`,
30
- } as CSSProperties
30
+ } as CSSProperties & { [key: string]: string }
31
31
  }
32
32
  >
33
33
  <div
@@ -8,6 +8,7 @@ import { MenuItem } from './MenuItem';
8
8
  import { IMenuItem, IMenuPlacement } from '../../types/IMenu';
9
9
 
10
10
  interface Props {
11
+ id?: string;
11
12
  isOpen: boolean;
12
13
  onClose: () => void;
13
14
  renderButton: (ref: RefObject<any>) => ReactNode;
@@ -19,6 +20,7 @@ interface Props {
19
20
  }
20
21
 
21
22
  export const Menu: FC<Props> = ({
23
+ id,
22
24
  isOpen,
23
25
  onClose,
24
26
  renderButton,
@@ -47,6 +49,7 @@ export const Menu: FC<Props> = ({
47
49
  {isOpen
48
50
  ? createPortal(
49
51
  <div
52
+ id={id}
50
53
  ref={portalRef}
51
54
  className="portal-background"
52
55
  onClick={e => e.stopPropagation()}
@@ -13,6 +13,8 @@ import { onPopupKeyDown } from '../../utils/popupUtils';
13
13
  import { ILocalPopupControl } from '../../types/IPopup';
14
14
  import { Loader } from '../Loader/Loader';
15
15
  import { SplitButton } from '../Button/SplitButton';
16
+ import { IconButton } from '../Button/IconButton';
17
+ import { faXmark } from '../../assets/icons';
16
18
 
17
19
  interface Props {
18
20
  id?: string;
@@ -108,13 +110,16 @@ export const Pullover: FC<Props> = ({
108
110
  {header && (
109
111
  <div className="pullover-header no-print">
110
112
  <h3>{header.title}</h3>
111
- {header.onSearch && (
112
- <SearchInput
113
- ref={searchRef}
114
- onSearch={header.onSearch}
115
- className="search-input"
116
- />
117
- )}
113
+ <div className="flex gap-2">
114
+ {header.onSearch && (
115
+ <SearchInput
116
+ ref={searchRef}
117
+ onSearch={header.onSearch}
118
+ className="search-input"
119
+ />
120
+ )}
121
+ <IconButton icon={faXmark} onClick={onClose} color="neutral" />
122
+ </div>
118
123
  </div>
119
124
  )}
120
125
  <ConditionalWrapper
@@ -147,40 +152,34 @@ export const Pullover: FC<Props> = ({
147
152
  )}
148
153
 
149
154
  {/* FOOTER */}
150
- {footer && (
151
- <div className={clsx('pullover-footer no-print', className)}>
152
- {footer.additionalButton && (
153
- <Button
154
- {...footer.additionalButton}
155
- disabled={
156
- footer.additionalButton.disabled || isFetching || isLoading
157
- }
158
- variant="simple"
159
- className="mr-auto"
160
- />
161
- )}
155
+ <div className={clsx('pullover-footer no-print', className)}>
156
+ {footer?.additionalButton && (
162
157
  <Button
163
- label={t('Cancel')}
164
- variant="outlined"
165
- onClick={onClose}
166
- disabled={isFetching || isLoading}
158
+ {...footer.additionalButton}
159
+ disabled={
160
+ footer.additionalButton.disabled || isFetching || isLoading
161
+ }
162
+ variant="simple"
163
+ className="mr-auto"
167
164
  />
168
- {footer.confirmButton && (
169
- <ConfirmButton
170
- {...footer.confirmButton}
171
- label={footer.confirmButton.label ?? t('Confirm')}
172
- disabled={
173
- footer.confirmButton.disabled || isFetching || isLoading
174
- }
175
- type={
176
- (footer.confirmButton.type ?? onFormSubmit)
177
- ? 'submit'
178
- : 'button'
179
- }
180
- />
181
- )}
182
- </div>
183
- )}
165
+ )}
166
+ <Button
167
+ label={t(footer ? 'Cancel' : 'Close')}
168
+ variant="outlined"
169
+ onClick={onClose}
170
+ disabled={isFetching || isLoading}
171
+ />
172
+ {footer?.confirmButton && (
173
+ <ConfirmButton
174
+ {...footer.confirmButton}
175
+ label={footer.confirmButton.label ?? t('Confirm')}
176
+ disabled={footer.confirmButton.disabled || isFetching || isLoading}
177
+ type={
178
+ (footer.confirmButton.type ?? onFormSubmit) ? 'submit' : 'button'
179
+ }
180
+ />
181
+ )}
182
+ </div>
184
183
  </ConditionalWrapper>
185
184
  </div>
186
185
  </div>