@qoretechnologies/reqore 0.37.9 → 0.38.1

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 (92) hide show
  1. package/__tests__/dropdown.test.tsx +10 -8
  2. package/__tests__/table.test.tsx +0 -1
  3. package/dist/components/Breadcrumbs/index.d.ts.map +1 -1
  4. package/dist/components/Breadcrumbs/index.js +6 -4
  5. package/dist/components/Breadcrumbs/index.js.map +1 -1
  6. package/dist/components/Button/index.d.ts.map +1 -1
  7. package/dist/components/Button/index.js +5 -5
  8. package/dist/components/Button/index.js.map +1 -1
  9. package/dist/components/ControlGroup/index.d.ts.map +1 -1
  10. package/dist/components/ControlGroup/index.js +1 -1
  11. package/dist/components/ControlGroup/index.js.map +1 -1
  12. package/dist/components/Drawer/index.d.ts +1 -1
  13. package/dist/components/Drawer/index.d.ts.map +1 -1
  14. package/dist/components/Dropdown/index.d.ts +2 -2
  15. package/dist/components/Dropdown/index.d.ts.map +1 -1
  16. package/dist/components/Dropdown/index.js +5 -5
  17. package/dist/components/Dropdown/index.js.map +1 -1
  18. package/dist/components/Dropdown/item.d.ts +6 -5
  19. package/dist/components/Dropdown/item.d.ts.map +1 -1
  20. package/dist/components/Dropdown/item.js +14 -6
  21. package/dist/components/Dropdown/item.js.map +1 -1
  22. package/dist/components/Dropdown/list.d.ts +4 -2
  23. package/dist/components/Dropdown/list.d.ts.map +1 -1
  24. package/dist/components/Dropdown/list.js +33 -7
  25. package/dist/components/Dropdown/list.js.map +1 -1
  26. package/dist/components/Effect/index.d.ts +1 -0
  27. package/dist/components/Effect/index.d.ts.map +1 -1
  28. package/dist/components/Effect/index.js +39 -24
  29. package/dist/components/Effect/index.js.map +1 -1
  30. package/dist/components/InternalPopover/index.d.ts.map +1 -1
  31. package/dist/components/InternalPopover/index.js +21 -1
  32. package/dist/components/InternalPopover/index.js.map +1 -1
  33. package/dist/components/Menu/index.js +4 -4
  34. package/dist/components/Menu/index.js.map +1 -1
  35. package/dist/components/Menu/item.d.ts +1 -1
  36. package/dist/components/Menu/item.d.ts.map +1 -1
  37. package/dist/components/Menu/item.js +6 -6
  38. package/dist/components/Menu/item.js.map +1 -1
  39. package/dist/components/Message/index.d.ts.map +1 -1
  40. package/dist/components/Message/index.js +3 -4
  41. package/dist/components/Message/index.js.map +1 -1
  42. package/dist/components/MultiSelect/index.js +2 -2
  43. package/dist/components/MultiSelect/index.js.map +1 -1
  44. package/dist/components/Notifications/notification.d.ts +1 -0
  45. package/dist/components/Notifications/notification.d.ts.map +1 -1
  46. package/dist/components/Notifications/notification.js +10 -21
  47. package/dist/components/Notifications/notification.js.map +1 -1
  48. package/dist/components/Panel/LabelEditor.d.ts +12 -0
  49. package/dist/components/Panel/LabelEditor.d.ts.map +1 -0
  50. package/dist/components/Panel/LabelEditor.js +61 -0
  51. package/dist/components/Panel/LabelEditor.js.map +1 -0
  52. package/dist/components/Panel/index.d.ts +11 -1
  53. package/dist/components/Panel/index.d.ts.map +1 -1
  54. package/dist/components/Panel/index.js +65 -22
  55. package/dist/components/Panel/index.js.map +1 -1
  56. package/dist/components/Tabs/content.d.ts +4 -2
  57. package/dist/components/Tabs/content.d.ts.map +1 -1
  58. package/dist/components/Tabs/content.js +22 -5
  59. package/dist/components/Tabs/content.js.map +1 -1
  60. package/dist/components/Textarea/index.d.ts +4 -0
  61. package/dist/components/Textarea/index.d.ts.map +1 -1
  62. package/dist/components/Textarea/index.js +20 -5
  63. package/dist/components/Textarea/index.js.map +1 -1
  64. package/package.json +1 -1
  65. package/src/components/Breadcrumbs/index.tsx +19 -5
  66. package/src/components/Button/index.tsx +12 -11
  67. package/src/components/ControlGroup/index.tsx +1 -0
  68. package/src/components/Drawer/index.tsx +1 -1
  69. package/src/components/Dropdown/index.tsx +16 -14
  70. package/src/components/Dropdown/item.tsx +26 -10
  71. package/src/components/Dropdown/list.tsx +80 -30
  72. package/src/components/Effect/index.tsx +46 -15
  73. package/src/components/InternalPopover/index.tsx +24 -1
  74. package/src/components/Menu/index.tsx +2 -2
  75. package/src/components/Menu/item.tsx +93 -85
  76. package/src/components/Message/index.tsx +39 -35
  77. package/src/components/MultiSelect/index.tsx +2 -2
  78. package/src/components/Notifications/notification.tsx +34 -30
  79. package/src/components/Panel/LabelEditor.tsx +67 -0
  80. package/src/components/Panel/index.tsx +99 -25
  81. package/src/components/Tabs/content.tsx +44 -7
  82. package/src/components/Textarea/index.tsx +77 -27
  83. package/src/mock/breadcrumbs.ts +12 -1
  84. package/src/stories/Dropdown/Dropdown.stories.tsx +58 -0
  85. package/src/stories/Dropdown/DropdownTests.stories.tsx +78 -0
  86. package/src/stories/Message/Message.stories.tsx +13 -5
  87. package/src/stories/MultiSelect/MultiSelect.stories.tsx +2 -2
  88. package/src/stories/Panel/Panel.stories.tsx +123 -0
  89. package/src/stories/Popover/Popover.stories.tsx +41 -0
  90. package/src/stories/TextArea/TextArea.stories.tsx +49 -0
  91. package/src/stories/TextArea/TextAreaTests.stories.tsx +103 -0
  92. package/tests.json +1 -1
@@ -75,6 +75,7 @@ export interface IReqoreEffect extends IReqoreEffectFilters {
75
75
  inset?: boolean;
76
76
  blur?: number;
77
77
  opacity?: number;
78
+ when?: 'always' | 'hover' | 'focus' | 'active';
78
79
  };
79
80
  interactive?: boolean;
80
81
  }
@@ -222,28 +223,58 @@ export const StyledEffect = styled.span`
222
223
  return undefined;
223
224
  }
224
225
 
226
+ let glow;
227
+
225
228
  if (!isText) {
226
- return css`
229
+ glow = css`
227
230
  box-shadow: ${effect.glow.inset ? 'inset ' : ''} 0 0 ${effect.glow.blur || 0}px
228
231
  ${effect.glow.size || 2}px ${getColorFromMaybeString(theme, effect.glow.color)};
229
232
  `;
233
+ } else {
234
+ const color = getColorFromMaybeString(
235
+ theme,
236
+ effect.glow.color === 'main' ? 'main:lighten:2' : effect.glow.color
237
+ );
238
+ const blur = effect.glow.blur || 0;
239
+ const opacity = effect.glow.opacity || 1;
240
+
241
+ glow = css`
242
+ color: ${Colors.LIGHT};
243
+ text-shadow: 0 0 ${blur}px ${rgba(color, opacity)},
244
+ 0 0 ${blur + 5}px ${rgba(color, opacity)}, 0 0 ${blur + 10}px ${rgba(color, opacity)},
245
+ 0 0 1px ${rgba(getReadableColorFrom(color), opacity)},
246
+ 0 0 2px ${rgba(getReadableColorFrom(color), opacity)},
247
+ 0 0 3px ${rgba(getReadableColorFrom(color), opacity)};
248
+ `;
230
249
  }
231
250
 
232
- const color = getColorFromMaybeString(
233
- theme,
234
- effect.glow.color === 'main' ? 'main:lighten:2' : effect.glow.color
235
- );
236
- const blur = effect.glow.blur || 0;
237
- const opacity = effect.glow.opacity || 1;
251
+ if (effect.glow.when === 'always' || !effect.glow.when) {
252
+ return glow;
253
+ }
238
254
 
239
- return css`
240
- color: ${Colors.LIGHT};
241
- text-shadow: 0 0 ${blur}px ${rgba(color, opacity)}, 0 0 ${blur + 5}px ${rgba(color, opacity)},
242
- 0 0 ${blur + 10}px ${rgba(color, opacity)},
243
- 0 0 1px ${rgba(getReadableColorFrom(color), opacity)},
244
- 0 0 2px ${rgba(getReadableColorFrom(color), opacity)},
245
- 0 0 3px ${rgba(getReadableColorFrom(color), opacity)};
246
- `;
255
+ if (effect.glow.when === 'hover') {
256
+ return css`
257
+ &:hover {
258
+ ${glow}
259
+ }
260
+ `;
261
+ }
262
+
263
+ if (effect.glow.when === 'focus') {
264
+ return css`
265
+ &:focus {
266
+ ${glow}
267
+ }
268
+ `;
269
+ }
270
+
271
+ if (effect.glow.when === 'active') {
272
+ return css`
273
+ &:active {
274
+ ${glow}
275
+ }
276
+ `;
277
+ }
247
278
  }}
248
279
 
249
280
  ${({ effect }: IReqoreTextEffectProps) =>
@@ -3,6 +3,7 @@ import { rgba } from 'polished';
3
3
  import React, { MutableRefObject, memo, useEffect, useRef, useState } from 'react';
4
4
  import { createPortal } from 'react-dom';
5
5
  import { usePopper } from 'react-popper';
6
+ import { useUnmount, useUpdateEffect } from 'react-use';
6
7
  import styled, { css } from 'styled-components';
7
8
  import { useContext } from 'use-context-selector';
8
9
  import { RADIUS_FROM_SIZE } from '../../constants/sizes';
@@ -164,7 +165,8 @@ const InternalPopover: React.FC<IReqoreInternalPopoverProps> = memo(
164
165
  const [popperElement, setPopperElement] = useState(null);
165
166
  const [arrowElement, setArrowElement] = useState(null);
166
167
  const popperRef: MutableRefObject<any> = useRef(null);
167
- const { styles, attributes } = usePopper(targetElement, popperElement, {
168
+ const mutationObserber: MutableRefObject<any> = useRef(null);
169
+ const { styles, attributes, forceUpdate, state } = usePopper(targetElement, popperElement, {
168
170
  placement,
169
171
  modifiers: [
170
172
  {
@@ -186,6 +188,27 @@ const InternalPopover: React.FC<IReqoreInternalPopoverProps> = memo(
186
188
  ],
187
189
  });
188
190
 
191
+ useUpdateEffect(() => {
192
+ if (!mutationObserber.current && targetElement && state) {
193
+ // Watch for changes in the target element
194
+ const observer = new MutationObserver(() => {
195
+ forceUpdate();
196
+ });
197
+
198
+ observer.observe(document, {
199
+ attributes: true,
200
+ childList: true,
201
+ subtree: true,
202
+ });
203
+
204
+ mutationObserber.current = observer;
205
+ }
206
+ }, [styles, attributes, state]);
207
+
208
+ useUnmount(() => {
209
+ mutationObserber.current?.disconnect();
210
+ });
211
+
189
212
  useEffect(() => {
190
213
  if (popperRef.current) {
191
214
  updatePopover?.(id, { popperRef: cloneDeep(popperRef) });
@@ -85,8 +85,8 @@ const ReqoreMenu = forwardRef<HTMLDivElement, IReqoreMenuProps>(
85
85
  {React.Children.map(children, (child) => {
86
86
  return child
87
87
  ? React.cloneElement(child, {
88
- _insidePopover,
89
- _popoverId,
88
+ _insidePopover: child.props?._insidePopover ?? _insidePopover,
89
+ _popoverId: child.props?._popoverId ?? _popoverId,
90
90
  customTheme: child.props?.customTheme || theme,
91
91
  wrap: 'wrap' in (child.props || {}) ? child.props.wrap : wrapText,
92
92
  flat: 'flat' in (child.props || {}) ? child.props.flat : flat,
@@ -1,4 +1,4 @@
1
- import React, { forwardRef, useEffect, useState } from 'react';
1
+ import React, { forwardRef, memo, useCallback, useEffect, useState } from 'react';
2
2
  import { useContext } from 'use-context-selector';
3
3
  import { ReqoreButton, ReqoreControlGroup } from '../..';
4
4
  import { IReqoreTheme, TReqoreIntent } from '../../constants/theme';
@@ -29,101 +29,109 @@ export interface IReqoreMenuItemRightIconStyle {
29
29
  intent?: TReqoreIntent;
30
30
  }
31
31
 
32
- const ReqoreMenuItem = forwardRef<HTMLButtonElement, IReqoreMenuItemProps>(
33
- (
34
- {
35
- children,
36
- label,
37
- icon,
38
- rightIcon,
39
- as,
40
- selected,
41
- onClick,
42
- onRightIconClick,
43
- disabled,
44
- itemId,
45
- _insidePopover,
46
- _popoverId,
47
- tooltip,
48
- intent,
49
- flat = true,
50
- scrollIntoView,
51
- ...rest
52
- }: IReqoreMenuItemProps,
53
- ref
54
- ) => {
55
- const { removePopover } = useContext(PopoverContext);
56
- const { targetRef } = useCombinedRefs<HTMLButtonElement>(ref);
57
- const [itemRef, setItemRef] = useState<HTMLButtonElement | null>(null);
32
+ const ReqoreMenuItem = memo(
33
+ forwardRef<HTMLButtonElement, IReqoreMenuItemProps>(
34
+ (
35
+ {
36
+ children,
37
+ label,
38
+ icon,
39
+ rightIcon,
40
+ as,
41
+ selected,
42
+ onClick,
43
+ onRightIconClick,
44
+ disabled,
45
+ itemId,
46
+ _insidePopover,
47
+ _popoverId,
48
+ tooltip,
49
+ intent,
50
+ flat = true,
51
+ scrollIntoView,
52
+ ...rest
53
+ }: IReqoreMenuItemProps,
54
+ ref
55
+ ) => {
56
+ const { removePopover } = useContext(PopoverContext);
57
+ const { targetRef } = useCombinedRefs<HTMLButtonElement>(ref);
58
+ const [itemRef, setItemRef] = useState<HTMLButtonElement | null>(null);
58
59
 
59
- const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
60
- event.persist();
60
+ const handleClick = useCallback(
61
+ (event: React.MouseEvent<HTMLButtonElement>) => {
62
+ event.persist();
61
63
 
62
- onClick?.(event, itemId);
64
+ onClick?.(event, itemId);
63
65
 
64
- if (_insidePopover && _popoverId) {
65
- removePopover!(_popoverId);
66
- }
67
- };
66
+ if (_insidePopover && _popoverId) {
67
+ removePopover!(_popoverId);
68
+ }
69
+ },
70
+ [itemId, _insidePopover, _popoverId, onClick]
71
+ );
68
72
 
69
- const handleRightIconClick = (event: React.MouseEvent<HTMLSpanElement>) => {
70
- event.persist();
71
- event.stopPropagation();
73
+ const handleRightIconClick = useCallback(
74
+ (event: React.MouseEvent<HTMLSpanElement>) => {
75
+ event.persist();
76
+ event.stopPropagation();
72
77
 
73
- if (onRightIconClick) {
74
- onRightIconClick(itemId, event);
78
+ if (onRightIconClick) {
79
+ onRightIconClick(itemId, event);
75
80
 
76
- if (_insidePopover && _popoverId) {
77
- removePopover!(_popoverId);
78
- }
79
- }
80
- };
81
+ if (_insidePopover && _popoverId) {
82
+ removePopover!(_popoverId);
83
+ }
84
+ }
85
+ },
86
+ [itemId, _insidePopover, _popoverId, onRightIconClick]
87
+ );
81
88
 
82
- useEffect(() => {
83
- if (scrollIntoView && itemRef) {
84
- itemRef.scrollIntoView?.({ behavior: 'smooth', block: 'center', inline: 'center' });
85
- }
86
- }, [itemRef, scrollIntoView]);
89
+ useEffect(() => {
90
+ if (scrollIntoView && itemRef) {
91
+ itemRef.scrollIntoView?.({ behavior: 'smooth', block: 'center', inline: 'center' });
92
+ }
93
+ }, [itemRef, scrollIntoView]);
87
94
 
88
- return (
89
- <ReqoreControlGroup stack={!!onRightIconClick} fluid fill>
90
- <ReqoreButton
91
- as={as}
92
- {...rest}
93
- flat={flat}
94
- className={`${rest.className || ''} reqore-menu-item`}
95
- fluid
96
- onClick={handleClick}
97
- active={selected}
98
- ref={(ref) => {
99
- targetRef.current = ref || undefined;
100
- setItemRef(ref);
101
- }}
102
- disabled={disabled}
103
- intent={intent}
104
- icon={icon}
105
- rightIcon={onRightIconClick ? undefined : rightIcon}
106
- tooltip={tooltip}
107
- >
108
- {label || children}
109
- </ReqoreButton>
110
- {rightIcon && onRightIconClick ? (
95
+ return (
96
+ <ReqoreControlGroup stack={!!onRightIconClick} fluid fill>
111
97
  <ReqoreButton
112
- icon={rightIcon}
98
+ as={as}
99
+ {...rest}
113
100
  flat={flat}
114
- fixed
115
- minimal={!onRightIconClick}
116
- customTheme={rest.customTheme}
117
- className='reqore-menu-item-right-icon'
118
- onClick={handleRightIconClick}
119
- readOnly={!onRightIconClick}
101
+ className={`${rest.className || ''} reqore-menu-item`}
102
+ fluid
103
+ onClick={handleClick}
104
+ active={selected}
105
+ ref={(ref) => {
106
+ targetRef.current = ref || undefined;
107
+ setItemRef(ref);
108
+ }}
109
+ disabled={disabled}
120
110
  intent={intent}
121
- active={selected && !!onRightIconClick}
122
- />
123
- ) : null}
124
- </ReqoreControlGroup>
125
- );
126
- }
111
+ icon={icon}
112
+ rightIcon={onRightIconClick ? undefined : rightIcon}
113
+ tooltip={tooltip}
114
+ >
115
+ {label || children}
116
+ </ReqoreButton>
117
+ {rightIcon && onRightIconClick ? (
118
+ <ReqoreButton
119
+ icon={rightIcon}
120
+ flat={flat}
121
+ fixed
122
+ minimal={!onRightIconClick}
123
+ customTheme={rest.customTheme}
124
+ className='reqore-menu-item-right-icon'
125
+ onClick={handleRightIconClick}
126
+ readOnly={!onRightIconClick}
127
+ intent={intent}
128
+ active={selected && !!onRightIconClick}
129
+ />
130
+ ) : null}
131
+ </ReqoreControlGroup>
132
+ );
133
+ }
134
+ )
127
135
  );
128
136
 
129
137
  export default ReqoreMenuItem;
@@ -26,6 +26,7 @@ import {
26
26
  StyledIconWrapper,
27
27
  StyledNotificationContent,
28
28
  StyledNotificationContentWrapper,
29
+ StyledNotificationInnerContent,
29
30
  StyledReqoreNotification,
30
31
  typeToIcon,
31
32
  } from '../Notifications/notification';
@@ -153,43 +154,46 @@ const ReqoreMessage = memo(
153
154
  size={size}
154
155
  theme={theme}
155
156
  >
156
- {leftIcon ? (
157
- <StyledIconWrapper intent={intent} size={size} theme={theme}>
158
- {intent === 'pending' ? (
159
- <ReqoreSpinner
160
- size={size}
161
- iconColor={iconColor}
162
- type={5}
163
- iconMargin={flat && minimal ? 'right' : 'both'}
164
- iconProps={iconProps}
165
- />
166
- ) : (
167
- <ReqoreIcon
168
- icon={leftIcon}
169
- margin={flat && minimal ? 'right' : 'both'}
157
+ <StyledNotificationContentWrapper size={size} theme={theme}>
158
+ {leftIcon ? (
159
+ <>
160
+ {intent === 'pending' ? (
161
+ <ReqoreSpinner
162
+ size={size}
163
+ iconColor={iconColor}
164
+ type={5}
165
+ iconMargin={'right'}
166
+ iconProps={iconProps}
167
+ />
168
+ ) : (
169
+ <ReqoreIcon
170
+ icon={leftIcon}
171
+ margin={'right'}
172
+ size={size}
173
+ color={iconColor}
174
+ {...iconProps}
175
+ />
176
+ )}
177
+ </>
178
+ ) : null}
179
+ <StyledNotificationInnerContent>
180
+ {title && (
181
+ <ReqoreHeading
170
182
  size={size}
171
- color={iconColor}
172
- {...iconProps}
173
- />
183
+ customTheme={
184
+ rest.effect?.color
185
+ ? { text: { color: getColorFromMaybeString(theme, rest.effect.color) } }
186
+ : undefined
187
+ }
188
+ >
189
+ {title}
190
+ </ReqoreHeading>
174
191
  )}
175
- </StyledIconWrapper>
176
- ) : null}
177
- <StyledNotificationContentWrapper size={size} theme={theme}>
178
- {title && (
179
- <ReqoreHeading
180
- size={size}
181
- customTheme={
182
- rest.effect?.color
183
- ? { text: { color: getColorFromMaybeString(theme, rest.effect.color) } }
184
- : undefined
185
- }
186
- >
187
- {title}
188
- </ReqoreHeading>
189
- )}
190
- <StyledNotificationContent theme={theme} hasTitle={!!title} size={size}>
191
- {children}
192
- </StyledNotificationContent>
192
+
193
+ <StyledNotificationContent theme={theme} hasTitle={!!title} size={size}>
194
+ {children}
195
+ </StyledNotificationContent>
196
+ </StyledNotificationInnerContent>
193
197
  </StyledNotificationContentWrapper>
194
198
  {onClose && (
195
199
  <StyledIconWrapper
@@ -124,7 +124,7 @@ export const ReqoreMultiSelect = ({
124
124
  onItemAdded?.(item.value);
125
125
  }
126
126
  },
127
- [value]
127
+ [value, onValueChange, onItemAdded, onItemRemoved]
128
128
  );
129
129
 
130
130
  const handleItemSelect = useCallback(
@@ -142,7 +142,7 @@ export const ReqoreMultiSelect = ({
142
142
 
143
143
  setQuery('');
144
144
  },
145
- [createdItems, value]
145
+ [createdItems, value, items, addRemoveItem]
146
146
  );
147
147
 
148
148
  /*
@@ -4,13 +4,7 @@ import React, { forwardRef, useEffect, useState } from 'react';
4
4
  import { useMount, useUnmount } from 'react-use';
5
5
  import styled, { css, keyframes } from 'styled-components';
6
6
  import { SPRING_CONFIG } from '../../constants/animations';
7
- import {
8
- ICON_WRAPPER_FROM_HEADER_SIZE,
9
- PADDING_FROM_SIZE,
10
- TABS_SIZE_TO_PX,
11
- TEXT_FROM_SIZE,
12
- TSizes,
13
- } from '../../constants/sizes';
7
+ import { PADDING_FROM_SIZE, TEXT_FROM_SIZE, TSizes } from '../../constants/sizes';
14
8
  import { IReqoreTheme, TReqoreIntent } from '../../constants/theme';
15
9
  import ReqoreThemeProvider from '../../containers/ThemeProvider';
16
10
  import { fadeIn } from '../../helpers/animations';
@@ -82,7 +76,6 @@ export const StyledReqoreNotification = styled(StyledEffect)<IReqoreNotification
82
76
  min-width: ${({ fluid }) => (!fluid ? '30px' : undefined)};
83
77
  max-width: ${({ maxWidth, fluid, fixed }) => maxWidth || (fluid && !fixed ? '100%' : undefined)};
84
78
  border-radius: 5px;
85
- min-height: ${({ size = 'normal' }: IReqoreNotificationStyle) => TABS_SIZE_TO_PX[size]}px;
86
79
  display: flex;
87
80
  flex: ${({ fluid, fixed }) => (fixed ? '0 0 auto' : fluid ? '1 auto' : '0 0 auto')};
88
81
  align-self: ${({ fixed, fluid }) => (fixed ? 'flex-start' : fluid ? 'stretch' : undefined)};
@@ -172,15 +165,12 @@ export const StyledReqoreNotification = styled(StyledEffect)<IReqoreNotification
172
165
  `;
173
166
 
174
167
  export const StyledIconWrapper = styled.div<IReqoreNotificationStyle>`
175
- height: ${({ size = 'normal' }: IReqoreNotificationStyle) =>
176
- ICON_WRAPPER_FROM_HEADER_SIZE[size]}px;
177
168
  flex: 0 1 auto;
178
169
  flex-shrink: 0;
179
170
  display: flex;
180
171
  justify-content: center;
181
172
  align-items: center;
182
173
  transition: all 0.2s ease-out;
183
- margin-top: ${({ size = 'normal' }: IReqoreNotificationStyle) => `${PADDING_FROM_SIZE[size]}px`};
184
174
 
185
175
  ${({ clickable, theme, intent, type }) =>
186
176
  clickable &&
@@ -202,12 +192,21 @@ export const StyledIconWrapper = styled.div<IReqoreNotificationStyle>`
202
192
  `}
203
193
  `;
204
194
 
205
- export const StyledNotificationContentWrapper = styled.div<IReqoreNotificationStyle>`
195
+ export const StyledNotificationInnerContent = styled.div<IReqoreNotificationStyle>`
206
196
  flex: 1;
207
- min-height: ${({ size = 'normal' }: IReqoreNotificationStyle) => TABS_SIZE_TO_PX[size]}px;
208
197
  display: flex;
209
198
  flex-flow: column;
210
199
  justify-content: center;
200
+
201
+ .reqore-heading {
202
+ line-height: 1;
203
+ }
204
+ `;
205
+
206
+ export const StyledNotificationContentWrapper = styled.div<IReqoreNotificationStyle>`
207
+ flex: 1;
208
+ display: flex;
209
+ justify-content: center;
211
210
  padding: ${({ size = 'normal' }: IReqoreNotificationStyle) => `${PADDING_FROM_SIZE[size]}px`};
212
211
  `;
213
212
 
@@ -224,6 +223,9 @@ export const StyledNotificationContent = styled.div`
224
223
  flex: 1;
225
224
  font-size: ${({ size = 'normal' }) => TEXT_FROM_SIZE[size]}px;
226
225
  overflow-wrap: anywhere;
226
+ display: flex;
227
+ flex-flow: column;
228
+ justify-content: center;
227
229
 
228
230
  ${({ hasTitle, size = 'normal' }) =>
229
231
  hasTitle &&
@@ -317,24 +319,26 @@ const ReqoreNotification = forwardRef<HTMLDivElement, IReqoreNotificationProps>(
317
319
  theme={theme}
318
320
  maxWidth='450px'
319
321
  >
320
- {type || intent || icon ? (
321
- <StyledIconWrapper type={type || intent} size={size}>
322
- {intent === 'pending' || type === 'pending' ? (
323
- <ReqoreSpinner size={size} type={5} iconMargin={'both'} />
324
- ) : (
325
- <ReqoreIcon
326
- icon={icon || typeToIcon[type || intent]}
327
- margin={'both'}
328
- size={size}
329
- />
330
- )}
331
- </StyledIconWrapper>
332
- ) : null}
333
322
  <StyledNotificationContentWrapper size={size} theme={theme}>
334
- {title && <ReqoreHeading size={size}>{title}</ReqoreHeading>}
335
- <StyledNotificationContent theme={theme} hasTitle={!!title} size={size}>
336
- {content}
337
- </StyledNotificationContent>
323
+ {type || intent || icon ? (
324
+ <>
325
+ {intent === 'pending' || type === 'pending' ? (
326
+ <ReqoreSpinner size={size} type={5} iconMargin={'right'} />
327
+ ) : (
328
+ <ReqoreIcon
329
+ icon={icon || typeToIcon[type || intent]}
330
+ margin={'right'}
331
+ size={size}
332
+ />
333
+ )}
334
+ </>
335
+ ) : null}
336
+ <StyledNotificationInnerContent>
337
+ {title && <ReqoreHeading size={size}>{title}</ReqoreHeading>}
338
+ <StyledNotificationContent theme={theme} hasTitle={!!title} size={size}>
339
+ {content}
340
+ </StyledNotificationContent>
341
+ </StyledNotificationInnerContent>
338
342
  </StyledNotificationContentWrapper>
339
343
  <StyledIconWrapper
340
344
  type={type || intent}
@@ -0,0 +1,67 @@
1
+ import { memo, useEffect, useState } from 'react';
2
+ import { useUpdateEffect } from 'react-use';
3
+ import { IReqoreHeadingProps, ReqoreHeading } from '../Header';
4
+ import ReqoreIcon, { IReqoreIconProps } from '../Icon';
5
+ import ReqoreInput, { IReqoreInputProps } from '../Input';
6
+
7
+ export interface IReqoreLabelEditorProps extends Omit<IReqoreHeadingProps, 'onSubmit'> {
8
+ label: string | number;
9
+ onSubmit?: (label: string | number) => void;
10
+ iconProps?: IReqoreIconProps;
11
+ inputProps?: IReqoreInputProps;
12
+ }
13
+
14
+ export const LabelEditor = memo(
15
+ ({ label, onSubmit, inputProps, iconProps, ...rest }: IReqoreLabelEditorProps) => {
16
+ const [name, setName] = useState<string | number>(label);
17
+ const [isEditing, setIsEditing] = useState(false);
18
+
19
+ useEffect(() => {
20
+ setName(label);
21
+ }, [label]);
22
+
23
+ useUpdateEffect(() => {
24
+ if (!isEditing) {
25
+ onSubmit?.(name);
26
+ }
27
+ }, [isEditing]);
28
+
29
+ if (isEditing) {
30
+ return (
31
+ <ReqoreInput
32
+ focusRules={{ type: 'auto' }}
33
+ onClick={(e) => e.stopPropagation()}
34
+ value={name}
35
+ minimal
36
+ fluid
37
+ onChange={(e: any) => setName(e.target.value)}
38
+ onKeyUp={(e) => {
39
+ if (e.key === 'Enter') {
40
+ setIsEditing(false);
41
+ }
42
+ }}
43
+ onBlur={() => setIsEditing(false)}
44
+ {...inputProps}
45
+ />
46
+ );
47
+ }
48
+
49
+ return (
50
+ <ReqoreHeading
51
+ {...rest}
52
+ className={`${rest.className || ''} reqore-label-editor`}
53
+ onClick={
54
+ onSubmit
55
+ ? (e) => {
56
+ e.stopPropagation();
57
+ setIsEditing(true);
58
+ }
59
+ : undefined
60
+ }
61
+ >
62
+ {name}
63
+ {onSubmit ? <ReqoreIcon icon='EditLine' size='small' margin='left' {...iconProps} /> : null}
64
+ </ReqoreHeading>
65
+ );
66
+ }
67
+ );