@qoretechnologies/reqore 0.37.9 → 0.38.0

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 (44) hide show
  1. package/dist/components/Breadcrumbs/index.d.ts.map +1 -1
  2. package/dist/components/Breadcrumbs/index.js +6 -4
  3. package/dist/components/Breadcrumbs/index.js.map +1 -1
  4. package/dist/components/Button/index.d.ts.map +1 -1
  5. package/dist/components/Button/index.js +5 -5
  6. package/dist/components/Button/index.js.map +1 -1
  7. package/dist/components/ControlGroup/index.d.ts.map +1 -1
  8. package/dist/components/ControlGroup/index.js +1 -1
  9. package/dist/components/ControlGroup/index.js.map +1 -1
  10. package/dist/components/Drawer/index.d.ts +1 -1
  11. package/dist/components/Drawer/index.d.ts.map +1 -1
  12. package/dist/components/Effect/index.d.ts +1 -0
  13. package/dist/components/Effect/index.d.ts.map +1 -1
  14. package/dist/components/Effect/index.js +39 -24
  15. package/dist/components/Effect/index.js.map +1 -1
  16. package/dist/components/InternalPopover/index.d.ts.map +1 -1
  17. package/dist/components/InternalPopover/index.js +21 -1
  18. package/dist/components/InternalPopover/index.js.map +1 -1
  19. package/dist/components/Panel/LabelEditor.d.ts +12 -0
  20. package/dist/components/Panel/LabelEditor.d.ts.map +1 -0
  21. package/dist/components/Panel/LabelEditor.js +61 -0
  22. package/dist/components/Panel/LabelEditor.js.map +1 -0
  23. package/dist/components/Panel/index.d.ts +11 -1
  24. package/dist/components/Panel/index.d.ts.map +1 -1
  25. package/dist/components/Panel/index.js +57 -20
  26. package/dist/components/Panel/index.js.map +1 -1
  27. package/dist/components/Tabs/content.d.ts +4 -2
  28. package/dist/components/Tabs/content.d.ts.map +1 -1
  29. package/dist/components/Tabs/content.js +22 -5
  30. package/dist/components/Tabs/content.js.map +1 -1
  31. package/package.json +1 -1
  32. package/src/components/Breadcrumbs/index.tsx +19 -5
  33. package/src/components/Button/index.tsx +12 -11
  34. package/src/components/ControlGroup/index.tsx +1 -0
  35. package/src/components/Drawer/index.tsx +1 -1
  36. package/src/components/Effect/index.tsx +46 -15
  37. package/src/components/InternalPopover/index.tsx +24 -1
  38. package/src/components/Panel/LabelEditor.tsx +66 -0
  39. package/src/components/Panel/index.tsx +89 -22
  40. package/src/components/Tabs/content.tsx +44 -7
  41. package/src/mock/breadcrumbs.ts +12 -1
  42. package/src/stories/Panel/Panel.stories.tsx +37 -0
  43. package/src/stories/Popover/Popover.stories.tsx +41 -0
  44. package/tests.json +1 -1
@@ -474,6 +474,7 @@ const ReqoreControlGroup = memo(
474
474
  active={isOverflownDialogOpen}
475
475
  flat
476
476
  fixed
477
+ onClick={(e) => e.stopPropagation()}
477
478
  />,
478
479
  ]
479
480
  : children,
@@ -16,7 +16,7 @@ import { ReqoreBackdrop } from './backdrop';
16
16
 
17
17
  export type TPosition = 'top' | 'bottom' | 'left' | 'right';
18
18
 
19
- export interface IReqoreDrawerProps extends Omit<IReqorePanelProps, 'size'> {
19
+ export interface IReqoreDrawerProps extends Omit<IReqorePanelProps, 'size' | 'resizable'> {
20
20
  children?: any;
21
21
  isOpen?: boolean;
22
22
  isHidden?: boolean;
@@ -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) });
@@ -0,0 +1,66 @@
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
+ onChange={(e: any) => setName(e.target.value)}
37
+ onKeyUp={(e) => {
38
+ if (e.key === 'Enter') {
39
+ setIsEditing(false);
40
+ }
41
+ }}
42
+ onBlur={() => setIsEditing(false)}
43
+ {...inputProps}
44
+ />
45
+ );
46
+ }
47
+
48
+ return (
49
+ <ReqoreHeading
50
+ {...rest}
51
+ className={`${rest.className || ''} reqore-label-editor`}
52
+ onClick={
53
+ onSubmit
54
+ ? (e) => {
55
+ e.stopPropagation();
56
+ setIsEditing(true);
57
+ }
58
+ : undefined
59
+ }
60
+ >
61
+ {name}
62
+ {onSubmit ? <ReqoreIcon icon='EditLine' size='small' margin='left' {...iconProps} /> : null}
63
+ </ReqoreHeading>
64
+ );
65
+ }
66
+ );
@@ -1,6 +1,7 @@
1
1
  import classNames from 'classnames';
2
- import { isArray, size } from 'lodash';
2
+ import { isArray, omit, size } from 'lodash';
3
3
  import { darken, rgba } from 'polished';
4
+ import { Resizable, ResizableProps } from 're-resizable';
4
5
  import { ReactElement, forwardRef, useCallback, useMemo, useState } from 'react';
5
6
  import { useMeasure, useUpdateEffect } from 'react-use';
6
7
  import styled, { css } from 'styled-components';
@@ -44,8 +45,9 @@ import ReqoreControlGroup from '../ControlGroup';
44
45
  import ReqoreDropdown from '../Dropdown';
45
46
  import { IReqoreDropdownItem } from '../Dropdown/list';
46
47
  import { IReqoreEffect, StyledEffect, TReqoreEffectColor } from '../Effect';
47
- import { ReqoreHeading, StyledHeader } from '../Header';
48
+ import { StyledHeader } from '../Header';
48
49
  import ReqoreIcon, { IReqoreIconProps, StyledIconWrapper } from '../Icon';
50
+ import { LabelEditor } from './LabelEditor';
49
51
  import { ReqorePanelNonResponsiveActions } from './NonResponsiveActions';
50
52
 
51
53
  export interface IReqorePanelSubAction extends Omit<IReqoreDropdownItem, 'value'> {}
@@ -92,6 +94,9 @@ export interface IReqorePanelProps
92
94
  collapseButtonProps?: IReqoreButtonProps;
93
95
  disabled?: boolean;
94
96
 
97
+ onLabelEdit?: (label: string | number) => void;
98
+ resizable?: ResizableProps;
99
+
95
100
  breadcrumbs?: IReqoreBreadcrumbsProps;
96
101
 
97
102
  onClose?: () => void;
@@ -164,7 +169,17 @@ export const StyledPanelTitleHeaderContent = styled.div`
164
169
  }
165
170
  `;
166
171
 
167
- export const StyledPanel = styled(StyledEffect)<IStyledPanel>`
172
+ export type TPanelStyle = React.FC<
173
+ Omit<IReqorePanelProps, 'onResize' | 'size'> &
174
+ ResizableProps & {
175
+ ref?: any;
176
+ theme: IReqoreTheme;
177
+ effect: IReqoreEffect;
178
+ interactive?: boolean;
179
+ }
180
+ >;
181
+
182
+ export const StyledPanel: TPanelStyle = styled(StyledEffect)<IStyledPanel>`
168
183
  background-color: ${({ theme, opacity = 1 }: IStyledPanel) =>
169
184
  rgba(changeDarkness(getMainBackgroundColor(theme), 0.03), opacity)};
170
185
  border-radius: ${({ rounded }) => (rounded ? RADIUS_FROM_SIZE.normal : 0)}px;
@@ -181,7 +196,6 @@ export const StyledPanel = styled(StyledEffect)<IStyledPanel>`
181
196
  flex-flow: column;
182
197
  position: relative;
183
198
  backdrop-filter: ${({ blur, opacity }) => (blur && opacity < 1 ? `blur(${blur}px)` : undefined)};
184
- transition: 0.2s ease-in-out;
185
199
  width: ${({ fluid }) => (fluid ? '100%' : undefined)};
186
200
  max-width: 100%;
187
201
  flex: ${({ fluid }) => (fluid ? '1 auto' : '0 0 auto')};
@@ -255,10 +269,16 @@ export const StyledPanelTitle = styled.div<IStyledPanel>`
255
269
  rgba(changeLightness(getMainBackgroundColor(theme), 0.03), opacity)};
256
270
  justify-content: space-between;
257
271
  // 2 is border that has to be added to the size + the button size + padding
258
- min-height: ${({ size }) => 2 + (SIZE_TO_PX[size] + PADDING_FROM_SIZE[size] * 2)}px;
272
+ min-height: ${({ size, transparent, flat, minimal }) =>
273
+ 2 +
274
+ (SIZE_TO_PX[size] + ((transparent && flat) || minimal ? 0 : PADDING_FROM_SIZE[size]) * 2)}px;
259
275
  align-items: center;
260
- padding: ${({ noHorizontalPadding, size }: IStyledPanel) =>
261
- `${PADDING_FROM_SIZE[size]}px ${noHorizontalPadding ? 0 : `${PADDING_FROM_SIZE[size]}px`}`};
276
+ padding: ${({ noHorizontalPadding, size, transparent, flat, minimal, intent }: IStyledPanel) =>
277
+ `${transparent && flat && !intent ? 0 : PADDING_FROM_SIZE[size]}px ${
278
+ noHorizontalPadding
279
+ ? 0
280
+ : `${minimal ? PADDING_FROM_SIZE[size] / 2 : PADDING_FROM_SIZE[size]}px`
281
+ }`};
262
282
  border-bottom: ${({ theme, isCollapsed, flat, opacity = 1 }) =>
263
283
  !isCollapsed && !flat
264
284
  ? `1px solid ${rgba(changeLightness(getMainBackgroundColor(theme), 0.2), opacity)}`
@@ -287,9 +307,18 @@ export const StyledPanelTitle = styled.div<IStyledPanel>`
287
307
  `}
288
308
  `;
289
309
 
310
+ export const StyledPanelTopBar = styled(StyledPanelTitle)`
311
+ padding-bottom: ${({ minimal, padded, size }: IStyledPanel) =>
312
+ !padded ? `${PADDING_FROM_SIZE[size] / (minimal ? 2 : 1)}px` : minimal ? 0 : undefined};
313
+ padding-top: ${({ minimal, size }: IStyledPanel) =>
314
+ minimal ? `${PADDING_FROM_SIZE[size] / 2}px` : undefined};
315
+ `;
316
+
290
317
  export const StyledPanelBottomActions = styled(StyledPanelTitle)`
291
- padding: ${({ noHorizontalPadding, size }: IStyledPanel) =>
292
- `${PADDING_FROM_SIZE[size]}px ${noHorizontalPadding ? 0 : `${PADDING_FROM_SIZE[size]}px`}`};
318
+ padding-top: ${({ minimal, padded, size }: IStyledPanel) =>
319
+ !padded ? `${PADDING_FROM_SIZE[size] / (minimal ? 2 : 1)}px` : minimal ? 0 : undefined};
320
+ padding-bottom: ${({ minimal, size }: IStyledPanel) =>
321
+ minimal ? `${PADDING_FROM_SIZE[size] / 2}px` : undefined};
293
322
  border-bottom: 0;
294
323
  border-top: ${({ theme, flat, opacity = 1 }) =>
295
324
  !flat
@@ -299,18 +328,18 @@ export const StyledPanelBottomActions = styled(StyledPanelTitle)`
299
328
 
300
329
  export const StyledPanelContent = styled.div<IStyledPanel>`
301
330
  display: ${({ isCollapsed }) => (isCollapsed ? 'none !important' : undefined)};
302
- padding: ${({ padded, size, noHorizontalPadding }) =>
331
+ padding: ${({ padded, size, noHorizontalPadding, minimal }) =>
303
332
  !padded
304
333
  ? undefined
305
334
  : noHorizontalPadding
306
335
  ? `${PADDING_FROM_SIZE[size]}px 0`
307
- : `${PADDING_FROM_SIZE[size]}px`};
336
+ : `${minimal ? PADDING_FROM_SIZE[size] / 2 : PADDING_FROM_SIZE[size]}px`};
308
337
  // The padding is not needed when the panel is minimal and has title, since
309
338
  // the title already has padding and is transparent
310
339
  padding-top: ${({ minimal, hasLabel, padded, size }) =>
311
340
  minimal && hasLabel && padded ? `${PADDING_FROM_SIZE[size] / 2}px` : undefined};
312
341
  padding-bottom: ${({ minimal, padded, size }) =>
313
- minimal && padded ? `${PADDING_FROM_SIZE[size]}px` : undefined};
342
+ minimal && padded ? `${PADDING_FROM_SIZE[size] / 2}px` : undefined};
314
343
  flex: 1;
315
344
  overflow: auto;
316
345
  overflow-wrap: anywhere;
@@ -359,6 +388,8 @@ export const ReqorePanel = forwardRef<HTMLDivElement, IReqorePanelProps>(
359
388
  breadcrumbs,
360
389
  showActionsWhenCollapsed = true,
361
390
  showHeaderTooltip,
391
+ resizable,
392
+ onLabelEdit,
362
393
  ...rest
363
394
  }: IReqorePanelProps,
364
395
  ref
@@ -382,6 +413,27 @@ export const ReqorePanel = forwardRef<HTMLDivElement, IReqorePanelProps>(
382
413
  setIsCollapsed(!!isCollapsed);
383
414
  }, [isCollapsed]);
384
415
 
416
+ const _resizable: ResizableProps = useMemo(() => {
417
+ const disabledProps: ResizableProps = {
418
+ enable: {
419
+ top: false,
420
+ right: false,
421
+ bottom: false,
422
+ left: false,
423
+ topRight: false,
424
+ bottomRight: false,
425
+ bottomLeft: false,
426
+ topLeft: false,
427
+ },
428
+ };
429
+
430
+ if (isCollapsed || disabled) {
431
+ return disabledProps;
432
+ }
433
+
434
+ return resizable || disabledProps;
435
+ }, [resizable, isCollapsed, disabled]);
436
+
385
437
  // Return true if the card has a title bar, otherwise return false.
386
438
  const hasTitleBar: boolean = useMemo(
387
439
  () =>
@@ -626,11 +678,18 @@ export const ReqorePanel = forwardRef<HTMLDivElement, IReqorePanelProps>(
626
678
 
627
679
  return (
628
680
  <StyledPanel
629
- {...rest}
630
- as={rest.as || 'div'}
681
+ {...omit(rest, ['onResize'])}
682
+ {..._resizable}
683
+ as={rest.as || !!resizable ? Resizable : 'div'}
631
684
  ref={(ref) => {
632
- targetRef.current = ref;
633
- setItemRef(ref);
685
+ let _ref = ref;
686
+
687
+ if (ref?.resizable) {
688
+ _ref = ref.resizable;
689
+ }
690
+
691
+ targetRef.current = _ref;
692
+ setItemRef(_ref);
634
693
  }}
635
694
  isCollapsed={_isCollapsed}
636
695
  rounded={rounded}
@@ -645,19 +704,23 @@ export const ReqorePanel = forwardRef<HTMLDivElement, IReqorePanelProps>(
645
704
  disabled={disabled}
646
705
  >
647
706
  {hasTitleBar && (
648
- <StyledPanelTitle
707
+ <StyledPanelTopBar
649
708
  flat={flat}
650
709
  isCollapsed={_isCollapsed}
651
710
  collapsible={collapsible}
652
711
  className='reqore-panel-title'
653
712
  onClick={handleCollapseClick}
654
713
  theme={theme}
714
+ minimal={minimal}
655
715
  size={contentSize || panelSize}
656
716
  opacity={opacity ?? (minimal ? 0 : 1)}
657
717
  noHorizontalPadding={noHorizontalPadding}
658
718
  responsive={responsiveTitle}
659
719
  isMobile={isMobile || isSmall}
660
720
  ref={measureRef}
721
+ padded={padded}
722
+ transparent={rest.transparent}
723
+ intent={intent}
661
724
  >
662
725
  {hasTitleHeader && (
663
726
  <StyledPanelTitleHeader>
@@ -693,17 +756,17 @@ export const ReqorePanel = forwardRef<HTMLDivElement, IReqorePanelProps>(
693
756
  />
694
757
  ) : null}
695
758
  {typeof label === 'string' ? (
696
- <ReqoreHeading
759
+ <LabelEditor
697
760
  size={headerSize || panelSize}
698
761
  customTheme={theme}
699
762
  effect={{
700
763
  noWrap: true,
701
764
  ...headerEffect,
702
765
  }}
766
+ label={label}
767
+ onSubmit={onLabelEdit}
703
768
  tooltip={showHeaderTooltip ? label : undefined}
704
- >
705
- {label}
706
- </ReqoreHeading>
769
+ />
707
770
  ) : (
708
771
  label
709
772
  )}
@@ -761,7 +824,7 @@ export const ReqorePanel = forwardRef<HTMLDivElement, IReqorePanelProps>(
761
824
  >
762
825
  {actions.map(renderNonResponsiveActions())}
763
826
  </ReqorePanelNonResponsiveActions>
764
- </StyledPanelTitle>
827
+ </StyledPanelTopBar>
765
828
  )}
766
829
  {!_isCollapsed || (_isCollapsed && !unMountContentOnCollapse) ? (
767
830
  <StyledPanelContent
@@ -784,6 +847,10 @@ export const ReqorePanel = forwardRef<HTMLDivElement, IReqorePanelProps>(
784
847
  flat={flat}
785
848
  className='reqore-panel-bottom-actions'
786
849
  theme={theme}
850
+ padded={padded}
851
+ intent={intent}
852
+ minimal={minimal}
853
+ transparent={rest.transparent}
787
854
  opacity={opacity ?? (minimal ? 0 : 1)}
788
855
  size={contentSize || panelSize}
789
856
  noHorizontalPadding={noHorizontalPadding}
@@ -1,12 +1,24 @@
1
1
  import React from 'react';
2
2
  import styled from 'styled-components';
3
+ import { PADDING_FROM_SIZE, TSizes } from '../../constants/sizes';
3
4
 
4
- export type TReqoreTabsContentPadding = 'horizontal' | 'vertical' | 'none' | 'both' | true | false;
5
+ export type TReqoreTabsContentPadding =
6
+ | 'horizontal'
7
+ | 'vertical'
8
+ | 'none'
9
+ | 'both'
10
+ | 'top'
11
+ | 'bottom'
12
+ | 'left'
13
+ | 'right'
14
+ | true
15
+ | false;
5
16
 
6
17
  export interface IReqoreTabsContent extends React.HTMLAttributes<HTMLDivElement> {
7
18
  children?: any;
8
19
  tabId: string | number;
9
20
  padded?: TReqoreTabsContentPadding;
21
+ size?: TSizes;
10
22
  }
11
23
 
12
24
  const StyledTabsContent = styled.div`
@@ -14,16 +26,41 @@ const StyledTabsContent = styled.div`
14
26
  flex-flow: column;
15
27
  overflow: hidden;
16
28
  flex: 1;
17
- padding: ${({ padded }: IReqoreTabsContent) =>
29
+ padding: ${({ padded, size }: IReqoreTabsContent) =>
18
30
  padded === 'none' || padded === false
19
31
  ? undefined
20
- : `${padded === 'both' || padded === true || padded === 'vertical' ? 10 : 0}px ${
21
- padded === 'both' || padded === true || padded === 'horizontal' ? 10 : 0
22
- }px}`};
32
+ : `${
33
+ padded === 'both' || padded === true || padded === 'vertical'
34
+ ? `${PADDING_FROM_SIZE[size]}px`
35
+ : 0
36
+ } ${
37
+ padded === 'both' || padded === true || padded === 'horizontal'
38
+ ? `${PADDING_FROM_SIZE[size]}px`
39
+ : 0
40
+ }`};
41
+ padding-top: ${({ padded, size }: IReqoreTabsContent) =>
42
+ padded === 'top' ? `${PADDING_FROM_SIZE[size]}px` : undefined};
43
+ padding-bottom: ${({ padded, size }: IReqoreTabsContent) =>
44
+ padded === 'bottom' ? `${PADDING_FROM_SIZE[size]}px` : undefined};
45
+ padding-left: ${({ padded, size }: IReqoreTabsContent) =>
46
+ padded === 'left' ? `${PADDING_FROM_SIZE[size]}px` : undefined};
47
+ padding-right: ${({ padded, size }: IReqoreTabsContent) =>
48
+ padded === 'right' ? `${PADDING_FROM_SIZE[size]}px` : undefined};
23
49
  `;
24
50
 
25
- const ReqoreTabsContent = ({ children, className, padded = true, ...rest }: IReqoreTabsContent) => (
26
- <StyledTabsContent {...rest} padded={padded} className={`${className || ''} reqore-tabs-content`}>
51
+ const ReqoreTabsContent = ({
52
+ children,
53
+ className,
54
+ padded = true,
55
+ size = 'normal',
56
+ ...rest
57
+ }: IReqoreTabsContent) => (
58
+ <StyledTabsContent
59
+ {...rest}
60
+ size={size}
61
+ padded={padded}
62
+ className={`${className || ''} reqore-tabs-content`}
63
+ >
27
64
  {children}
28
65
  </StyledTabsContent>
29
66
  );
@@ -17,9 +17,20 @@ export default [
17
17
  props: {
18
18
  href: 'https://google.com',
19
19
  },
20
- icon: Icons.Workflows,
20
+ leftIconProps: {
21
+ image:
22
+ 'https://avatars.githubusercontent.com/u/44835090?s=400&u=371120ce0755102d2e432f11ad9aa0378c871b45&v=4',
23
+ },
21
24
  flat: false,
22
25
  intent: 'info',
26
+ effect: {
27
+ glow: {
28
+ color: 'info',
29
+ size: 1,
30
+ blur: 10,
31
+ when: 'hover',
32
+ },
33
+ },
23
34
  },
24
35
  {
25
36
  icon: Icons.Services,
@@ -1,4 +1,5 @@
1
1
  import { StoryFn, StoryObj } from '@storybook/react';
2
+ import { fireEvent } from '@storybook/testing-library';
2
3
  import { noop } from 'lodash';
3
4
  import ReqoreControlGroup from '../../components/ControlGroup';
4
5
  import ReqoreInput, { IReqoreInputProps } from '../../components/Input';
@@ -358,6 +359,17 @@ export const Minimal: Story = {
358
359
  },
359
360
  };
360
361
 
362
+ export const MinimalWithIntent: Story = {
363
+ render: Template,
364
+
365
+ args: {
366
+ minimal: true,
367
+ flat: true,
368
+ intent: 'info',
369
+ transparent: true,
370
+ },
371
+ };
372
+
361
373
  export const Disabled: Story = {
362
374
  render: Template,
363
375
 
@@ -615,3 +627,28 @@ export const WithEffect: Story = {
615
627
  headerSize: 2,
616
628
  },
617
629
  };
630
+
631
+ export const Resizable: Story = {
632
+ render: Template,
633
+
634
+ args: {
635
+ resizable: {
636
+ minWidth: 400,
637
+ maxWidth: 600,
638
+ defaultSize: { width: 400, height: '100%' },
639
+ enable: { right: true },
640
+ },
641
+ },
642
+ };
643
+
644
+ export const EditableLabel: Story = {
645
+ render: Template,
646
+
647
+ args: {
648
+ onLabelEdit: (label) => console.log(label),
649
+ badge: undefined,
650
+ },
651
+ play: async ({ canvasElement }) => {
652
+ await fireEvent.click(canvasElement.querySelector('.reqore-label-editor'));
653
+ },
654
+ };
@@ -1,15 +1,20 @@
1
1
  import { StoryFn, StoryObj } from '@storybook/react';
2
+ import { fireEvent } from '@storybook/testing-library';
2
3
  import { useState } from 'react';
3
4
  import { IReqorePopoverProps } from '../../components/Popover';
5
+ import { sleep } from '../../helpers/utils';
4
6
  import usePopover from '../../hooks/usePopover';
5
7
  import {
6
8
  ReqoreButton,
7
9
  ReqoreControlGroup,
10
+ ReqoreMenu,
11
+ ReqoreMenuItem,
8
12
  ReqoreMessage,
9
13
  ReqoreModal,
10
14
  ReqorePanel,
11
15
  ReqorePopover,
12
16
  ReqoreSpacer,
17
+ ReqoreTextarea,
13
18
  } from '../../index';
14
19
  import { StoryMeta } from '../utils';
15
20
  import { FlatArg, argManager } from '../utils/args';
@@ -393,3 +398,39 @@ export const BlurredInsideModal: Story = {
393
398
  animatedDialogs: false,
394
399
  },
395
400
  };
401
+
402
+ export const ChangingElement: Story = {
403
+ render: (args) => {
404
+ return <ReqoreTextarea scaleWithContent tooltip={args} />;
405
+ },
406
+
407
+ args: {
408
+ content: (
409
+ <ReqoreMenu>
410
+ <ReqoreMenuItem label='Item 1' />
411
+ <ReqoreMenuItem label='Item 2' />
412
+ <ReqoreMenuItem label='Item 3' />
413
+ <ReqoreMenuItem label='Item 4' />
414
+ <ReqoreMenuItem label='Item 5' />
415
+ <ReqoreMenuItem label='Item 6' />
416
+ </ReqoreMenu>
417
+ ),
418
+ handler: 'focus',
419
+ noArrow: true,
420
+ noWrapper: true,
421
+ useTargetWidth: true,
422
+ },
423
+
424
+ play: async ({ canvasElement }) => {
425
+ const textarea = canvasElement.querySelector('textarea');
426
+ await sleep(1000);
427
+ fireEvent.focusIn(textarea);
428
+ await sleep(1000);
429
+ fireEvent.change(textarea, {
430
+ target: {
431
+ value:
432
+ 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed euismod, nisl eget aliquam tincidunt, nunc nisl aliquet nunc, quis aliquam nisl nisl. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed euismod, nisl eget aliquam tincidunt, nunc nisl aliquet nunc, quis aliquam nisl nisl. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed euismod, nisl eget aliquam tincidunt, nunc nisl aliquet nunc, quis aliquam nisl nisl. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed euismod, nisl eget aliquam tincidunt, nunc nisl aliquet nunc, quis aliquam nisl nisl. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed euismod, nisl eget aliquam tincidunt, nunc nisl aliquet nunc, quis aliquam nisl nisl. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed euismod, nisl eget aliquam tincidunt, nunc nisl aliquet nunc, quis aliquam nisl nisl.',
433
+ },
434
+ });
435
+ },
436
+ };