@qoretechnologies/reqore 0.29.8 → 0.30.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 (126) hide show
  1. package/__tests__/collection.test.tsx +1 -1
  2. package/__tests__/{control_group.text.tsx → control_group.test.tsx} +4 -2
  3. package/__tests__/panel.test.tsx +22 -24
  4. package/__tests__/popover.test.tsx +24 -2
  5. package/__tests__/tabs.test.tsx +32 -0
  6. package/dist/components/Button/index.js +6 -6
  7. package/dist/components/Button/index.js.map +1 -1
  8. package/dist/components/Collection/index.d.ts +3 -2
  9. package/dist/components/Collection/index.d.ts.map +1 -1
  10. package/dist/components/Collection/index.js +19 -44
  11. package/dist/components/Collection/index.js.map +1 -1
  12. package/dist/components/Collection/item.d.ts +2 -3
  13. package/dist/components/Collection/item.d.ts.map +1 -1
  14. package/dist/components/Collection/item.js +8 -4
  15. package/dist/components/Collection/item.js.map +1 -1
  16. package/dist/components/Columns/column.d.ts.map +1 -1
  17. package/dist/components/Columns/column.js +1 -1
  18. package/dist/components/Columns/column.js.map +1 -1
  19. package/dist/components/ControlGroup/index.d.ts +7 -4
  20. package/dist/components/ControlGroup/index.d.ts.map +1 -1
  21. package/dist/components/ControlGroup/index.js +118 -22
  22. package/dist/components/ControlGroup/index.js.map +1 -1
  23. package/dist/components/Drawer/index.d.ts.map +1 -1
  24. package/dist/components/Drawer/index.js +6 -4
  25. package/dist/components/Drawer/index.js.map +1 -1
  26. package/dist/components/Effect/index.d.ts.map +1 -1
  27. package/dist/components/Effect/index.js +1 -1
  28. package/dist/components/Effect/index.js.map +1 -1
  29. package/dist/components/Icon/index.d.ts +3 -5
  30. package/dist/components/Icon/index.d.ts.map +1 -1
  31. package/dist/components/Icon/index.js +10 -6
  32. package/dist/components/Icon/index.js.map +1 -1
  33. package/dist/components/Input/index.js +2 -2
  34. package/dist/components/Input/index.js.map +1 -1
  35. package/dist/components/InternalPopover/index.d.ts.map +1 -1
  36. package/dist/components/InternalPopover/index.js +5 -3
  37. package/dist/components/InternalPopover/index.js.map +1 -1
  38. package/dist/components/MultiSelect/index.d.ts +1 -1
  39. package/dist/components/MultiSelect/index.d.ts.map +1 -1
  40. package/dist/components/MultiSelect/index.js +10 -10
  41. package/dist/components/MultiSelect/index.js.map +1 -1
  42. package/dist/components/Panel/index.d.ts +6 -3
  43. package/dist/components/Panel/index.d.ts.map +1 -1
  44. package/dist/components/Panel/index.js +64 -32
  45. package/dist/components/Panel/index.js.map +1 -1
  46. package/dist/components/Spacer/index.d.ts +2 -0
  47. package/dist/components/Spacer/index.d.ts.map +1 -1
  48. package/dist/components/Spacer/index.js +29 -7
  49. package/dist/components/Spacer/index.js.map +1 -1
  50. package/dist/components/Tabs/content.d.ts +3 -1
  51. package/dist/components/Tabs/content.d.ts.map +1 -1
  52. package/dist/components/Tabs/content.js +8 -3
  53. package/dist/components/Tabs/content.js.map +1 -1
  54. package/dist/components/Tabs/index.d.ts +4 -1
  55. package/dist/components/Tabs/index.d.ts.map +1 -1
  56. package/dist/components/Tabs/index.js +12 -4
  57. package/dist/components/Tabs/index.js.map +1 -1
  58. package/dist/components/Tabs/item.d.ts +1 -0
  59. package/dist/components/Tabs/item.d.ts.map +1 -1
  60. package/dist/components/Tabs/item.js +7 -7
  61. package/dist/components/Tabs/item.js.map +1 -1
  62. package/dist/components/Tabs/list.d.ts +1 -1
  63. package/dist/components/Tabs/list.d.ts.map +1 -1
  64. package/dist/components/Tabs/list.js +3 -2
  65. package/dist/components/Tabs/list.js.map +1 -1
  66. package/dist/components/Tag/index.d.ts +3 -2
  67. package/dist/components/Tag/index.d.ts.map +1 -1
  68. package/dist/components/Tag/index.js +10 -2
  69. package/dist/components/Tag/index.js.map +1 -1
  70. package/dist/components/Tree/index.js +1 -1
  71. package/dist/components/Tree/index.js.map +1 -1
  72. package/dist/constants/animations.js +1 -1
  73. package/dist/constants/sizes.js +7 -7
  74. package/dist/containers/PopoverProvider.js +3 -3
  75. package/dist/containers/PopoverProvider.js.map +1 -1
  76. package/dist/containers/ReqoreProvider.d.ts.map +1 -1
  77. package/dist/containers/ReqoreProvider.js +1 -0
  78. package/dist/containers/ReqoreProvider.js.map +1 -1
  79. package/dist/containers/UIProvider.d.ts +7 -0
  80. package/dist/containers/UIProvider.d.ts.map +1 -1
  81. package/dist/containers/UIProvider.js.map +1 -1
  82. package/dist/context/ReqoreContext.d.ts +1 -0
  83. package/dist/context/ReqoreContext.d.ts.map +1 -1
  84. package/dist/context/ReqoreContext.js.map +1 -1
  85. package/dist/hooks/usePopover.d.ts.map +1 -1
  86. package/dist/hooks/usePopover.js +4 -2
  87. package/dist/hooks/usePopover.js.map +1 -1
  88. package/dist/types/global.d.ts +13 -0
  89. package/dist/types/global.d.ts.map +1 -1
  90. package/package.json +1 -1
  91. package/src/components/Button/index.tsx +2 -2
  92. package/src/components/Collection/index.tsx +29 -39
  93. package/src/components/Collection/item.tsx +14 -6
  94. package/src/components/Columns/column.tsx +1 -0
  95. package/src/components/ControlGroup/index.tsx +390 -227
  96. package/src/components/Drawer/index.tsx +6 -4
  97. package/src/components/Effect/index.tsx +1 -0
  98. package/src/components/Icon/index.tsx +78 -62
  99. package/src/components/Input/index.tsx +1 -1
  100. package/src/components/InternalPopover/index.tsx +127 -123
  101. package/src/components/MultiSelect/index.tsx +180 -188
  102. package/src/components/Panel/index.tsx +171 -77
  103. package/src/components/Spacer/index.tsx +63 -14
  104. package/src/components/Tabs/content.tsx +11 -3
  105. package/src/components/Tabs/index.tsx +14 -3
  106. package/src/components/Tabs/item.tsx +24 -1
  107. package/src/components/Tabs/list.tsx +3 -0
  108. package/src/components/Tag/index.tsx +30 -23
  109. package/src/components/Tree/index.tsx +1 -1
  110. package/src/constants/animations.ts +1 -1
  111. package/src/constants/sizes.ts +7 -7
  112. package/src/containers/PopoverProvider.tsx +3 -3
  113. package/src/containers/ReqoreProvider.tsx +1 -0
  114. package/src/containers/UIProvider.tsx +7 -0
  115. package/src/context/ReqoreContext.tsx +1 -0
  116. package/src/hooks/usePopover.tsx +4 -2
  117. package/src/mock/collectionData.tsx +21 -1
  118. package/src/stories/ControlGroup/ControlGroup.stories.tsx +68 -6
  119. package/src/stories/Icon/Icon.stories.tsx +1 -0
  120. package/src/stories/Input/Input.stories.tsx +2 -1
  121. package/src/stories/Panel/Panel.stories.tsx +83 -2
  122. package/src/stories/Popover/Popover.stories.tsx +5 -5
  123. package/src/stories/Tabs/Tabs.stories.tsx +30 -14
  124. package/src/stories/Tag/Tag.stories.tsx +12 -2
  125. package/src/types/global.ts +14 -0
  126. package/tests.json +1 -1
@@ -4,6 +4,7 @@ import { ReactElement, forwardRef, useCallback, useMemo, useState } from 'react'
4
4
  import { useUpdateEffect } from 'react-use';
5
5
  import styled, { css } from 'styled-components';
6
6
  import {
7
+ GAP_FROM_SIZE,
7
8
  ICON_FROM_HEADER_SIZE,
8
9
  PADDING_FROM_SIZE,
9
10
  RADIUS_FROM_SIZE,
@@ -25,6 +26,7 @@ import {
25
26
  IReqoreIntent,
26
27
  IWithReqoreCustomTheme,
27
28
  IWithReqoreFlat,
29
+ IWithReqoreFluid,
28
30
  IWithReqoreSize,
29
31
  IWithReqoreTooltip,
30
32
  } from '../../types/global';
@@ -37,7 +39,7 @@ import { IReqoreDropdownItem } from '../Dropdown/list';
37
39
  import { IReqoreEffect, StyledEffect, TReqoreEffectColor } from '../Effect';
38
40
  import { ReqoreHeading } from '../Header';
39
41
  import ReqoreIcon, { StyledIconWrapper } from '../Icon';
40
- import { ReqoreSpacer } from '../Spacer';
42
+ import { ReqoreHorizontalSpacer, ReqoreSpacer } from '../Spacer';
41
43
 
42
44
  export interface IReqorePanelAction extends IReqoreButtonProps, IWithReqoreTooltip, IReqoreIntent {
43
45
  label?: string | number;
@@ -45,9 +47,11 @@ export interface IReqorePanelAction extends IReqoreButtonProps, IWithReqoreToolt
45
47
  actions?: Omit<IReqoreDropdownItem[], 'value'>;
46
48
  // Custom react element
47
49
  as?: React.ElementType;
48
- props?: any;
50
+ props?: { [key: string | number]: any } | undefined;
49
51
  // Hide the action if the condition is false
50
52
  show?: boolean;
53
+ // Hide the action if the group is too small
54
+ responsive?: boolean;
51
55
  }
52
56
 
53
57
  export interface IReqorePanelBottomAction extends IReqorePanelAction {
@@ -62,6 +66,7 @@ export interface IReqorePanelProps
62
66
  IWithReqoreFlat,
63
67
  IReqoreIntent,
64
68
  IWithReqoreTooltip,
69
+ IWithReqoreFluid,
65
70
  React.HTMLAttributes<HTMLDivElement> {
66
71
  as?: any;
67
72
  children?: any;
@@ -99,12 +104,12 @@ export const StyledPanel = styled(StyledEffect)<IStyledPanel>`
99
104
  background-color: ${({ theme, opacity = 1 }: IStyledPanel) =>
100
105
  rgba(changeDarkness(getMainBackgroundColor(theme), 0.03), opacity)};
101
106
  border-radius: ${({ rounded }) => (rounded ? RADIUS_FROM_SIZE.normal : 0)}px;
102
- border: ${({ theme, flat, opacity = 1, intent }) =>
107
+ border: ${({ theme, flat, intent }) =>
103
108
  flat && !intent
104
109
  ? undefined
105
- : `1px solid ${rgba(
106
- changeLightness(intent ? theme.intents[intent] : getMainBackgroundColor(theme), 0.2),
107
- opacity
110
+ : `1px solid ${changeLightness(
111
+ intent ? theme.intents[intent] : getMainBackgroundColor(theme),
112
+ 0.2
108
113
  )}`};
109
114
  color: ${({ theme }) => getReadableColor(theme, undefined, undefined, true)};
110
115
  overflow: hidden;
@@ -113,7 +118,9 @@ export const StyledPanel = styled(StyledEffect)<IStyledPanel>`
113
118
  position: relative;
114
119
  backdrop-filter: ${({ blur, opacity }) => (blur && opacity < 1 ? `blur(${blur}px)` : undefined)};
115
120
  transition: 0.2s ease-in-out;
116
- flex: auto;
121
+ width: ${({ fluid }) => (fluid ? '100%' : undefined)};
122
+ max-width: 100%;
123
+ flex: ${({ fluid }) => (fluid ? '1 auto' : '0 0 auto')};
117
124
 
118
125
  ${({ interactive, theme, opacity = 1, flat, intent }) =>
119
126
  interactive
@@ -125,35 +132,37 @@ export const StyledPanel = styled(StyledEffect)<IStyledPanel>`
125
132
  transform: scale(${ACTIVE_ICON_SCALE});
126
133
  }
127
134
 
128
- background-color: ${rgba(
129
- darken(0.025, rgba(changeDarkness(getMainBackgroundColor(theme), 0.03), opacity)),
130
- opacity === 0 ? 0.2 : opacity
131
- )};
135
+ background-color: ${opacity === 0 && flat
136
+ ? undefined
137
+ : rgba(
138
+ darken(0.025, rgba(changeDarkness(getMainBackgroundColor(theme), 0.03), opacity)),
139
+ opacity
140
+ )};
132
141
 
133
142
  border-color: ${flat && !intent
134
143
  ? undefined
135
- : `${rgba(
136
- changeLightness(
137
- intent ? theme.intents[intent] : getMainBackgroundColor(theme),
138
- 0.25
139
- ),
140
- opacity
144
+ : `${changeLightness(
145
+ intent ? theme.intents[intent] : getMainBackgroundColor(theme),
146
+ 0.25
141
147
  )}`};
142
148
 
143
- ${StyledCollectionItemContent}:after {
144
- background: linear-gradient(
145
- to top,
146
- ${rgba(
147
- darken(
148
- 0.025,
149
- rgba(changeDarkness(getMainBackgroundColor(theme), 0.03), opacity)
150
- ),
151
- opacity === 0 ? 0.2 : opacity
152
- )}
153
- 0%,
154
- transparent 100%
155
- );
156
- }
149
+ ${opacity !== 0 &&
150
+ css`
151
+ ${StyledCollectionItemContent}:after {
152
+ background: linear-gradient(
153
+ to top,
154
+ ${rgba(
155
+ darken(
156
+ 0.025,
157
+ rgba(changeDarkness(getMainBackgroundColor(theme), 0.03), opacity)
158
+ ),
159
+ opacity
160
+ )}
161
+ 0%,
162
+ transparent 100%
163
+ );
164
+ }
165
+ `}
157
166
  }
158
167
  `
159
168
  : undefined}
@@ -215,7 +224,7 @@ export const StyledPanelBottomActions = styled(StyledPanelTitle)`
215
224
  `;
216
225
 
217
226
  export const StyledPanelContent = styled.div<IStyledPanel>`
218
- display: ${({ isCollapsed }) => (isCollapsed ? 'none' : undefined)};
227
+ display: ${({ isCollapsed }) => (isCollapsed ? 'none !important' : undefined)};
219
228
  padding: ${({ padded, contentSize, noHorizontalPadding }) =>
220
229
  !padded
221
230
  ? undefined
@@ -224,9 +233,10 @@ export const StyledPanelContent = styled.div<IStyledPanel>`
224
233
  : `${TEXT_FROM_SIZE[contentSize]}px`};
225
234
  // The padding is not needed when the panel is minimal and has title, since
226
235
  // the title already has padding and is transparent
227
- padding-top: ${({ minimal, hasLabel, padded }) =>
228
- minimal && hasLabel && padded ? '0px' : undefined};
229
- padding-bottom: ${({ minimal, padded }) => (minimal && padded ? '10px' : undefined)};
236
+ padding-top: ${({ minimal, hasLabel, padded, contentSize }) =>
237
+ minimal && hasLabel && padded ? `${TEXT_FROM_SIZE[contentSize] / 2}px` : undefined};
238
+ padding-bottom: ${({ minimal, padded, contentSize }) =>
239
+ minimal && padded ? `${TEXT_FROM_SIZE[contentSize]}px` : undefined};
230
240
  flex: 1;
231
241
  overflow: auto;
232
242
  font-size: ${({ contentSize }) => TEXT_FROM_SIZE[contentSize]}px;
@@ -234,10 +244,13 @@ export const StyledPanelContent = styled.div<IStyledPanel>`
234
244
 
235
245
  export const StyledPanelTitleHeader = styled.div`
236
246
  display: flex;
237
- justify-content: center;
247
+ justify-content: flex-start;
238
248
  align-items: center;
239
- overflow: hidden;
240
249
  padding-right: 5px;
250
+ flex: 1 1 auto;
251
+ width: 100%;
252
+ overflow: hidden;
253
+ min-width: 100px;
241
254
  `;
242
255
 
243
256
  export const ReqorePanel = forwardRef<HTMLDivElement, IReqorePanelProps>(
@@ -268,6 +281,7 @@ export const ReqorePanel = forwardRef<HTMLDivElement, IReqorePanelProps>(
268
281
  tooltip,
269
282
  badge,
270
283
  iconColor,
284
+ fluid,
271
285
  ...rest
272
286
  }: IReqorePanelProps,
273
287
  ref
@@ -321,17 +335,56 @@ export const ReqorePanel = forwardRef<HTMLDivElement, IReqorePanelProps>(
321
335
  [leftBottomActions, rightBottomActions]
322
336
  );
323
337
 
324
- const renderActions = useCallback(
338
+ const renderResponsiveActions = useCallback(
325
339
  (actionOrActions: IReqorePanelAction | IReqorePanelAction[], index: number) => {
326
- if (Array.isArray(actionOrActions)) {
327
- return (
328
- <ReqoreControlGroup key={index} stack>
329
- {actionOrActions.map(renderActions)}
330
- </ReqoreControlGroup>
331
- );
332
- }
340
+ return renderActions(actionOrActions, index, true);
341
+ },
342
+ [actions]
343
+ );
344
+
345
+ const hasNonResponsiveActions = useCallback(
346
+ (data: (IReqorePanelAction[] | IReqorePanelAction)[]) =>
347
+ data.some((action) => !Array.isArray(action) && action.responsive === false),
348
+ [actions, bottomActions]
349
+ );
350
+
351
+ const hasResponsiveActions = useCallback(
352
+ (data: (IReqorePanelAction[] | IReqorePanelAction)[]) =>
353
+ data.some((action) => Array.isArray(action) || action.responsive !== false),
354
+ [actions, bottomActions]
355
+ );
333
356
 
334
- if (actionOrActions.show === false) {
357
+ const renderNonResponsiveActions = useCallback(
358
+ (actionOrActions: IReqorePanelAction | IReqorePanelAction[], index: number) => {
359
+ return renderActions(actionOrActions, index, false);
360
+ },
361
+ [actions]
362
+ );
363
+
364
+ const renderActions = useCallback(
365
+ (
366
+ actionOrActions: IReqorePanelAction | IReqorePanelAction[],
367
+ index: number,
368
+ includeResponsive
369
+ ) => {
370
+ const action: IReqorePanelAction = Array.isArray(actionOrActions)
371
+ ? {
372
+ show: true,
373
+ responsive: true,
374
+ as: ReqoreControlGroup,
375
+ props: {
376
+ stack: true,
377
+ fluid: true,
378
+ children: actionOrActions.map(renderActions),
379
+ },
380
+ }
381
+ : actionOrActions;
382
+
383
+ if (
384
+ action.show === false ||
385
+ (includeResponsive && action.responsive === false) ||
386
+ (!includeResponsive && (action.responsive === true || !('responsive' in action)))
387
+ ) {
335
388
  return null;
336
389
  }
337
390
 
@@ -342,20 +395,21 @@ export const ReqorePanel = forwardRef<HTMLDivElement, IReqorePanelProps>(
342
395
  intent,
343
396
  className,
344
397
  as: CustomElement,
345
- props,
398
+ props = {},
346
399
  ...rest
347
- }: IReqorePanelAction = actionOrActions;
400
+ }: IReqorePanelAction = action;
348
401
 
349
402
  if (size(actions)) {
350
403
  return (
351
404
  <ReqoreDropdown<IReqoreButtonProps>
352
405
  {...rest}
353
406
  key={index}
407
+ fixed
354
408
  label={label}
355
409
  items={actions}
356
410
  intent={intent}
357
411
  className={className}
358
- customTheme={theme}
412
+ customTheme={rest.customTheme || theme}
359
413
  onClick={(e: React.MouseEvent<HTMLButtonElement>) => e.stopPropagation()}
360
414
  id={id}
361
415
  />
@@ -365,9 +419,10 @@ export const ReqorePanel = forwardRef<HTMLDivElement, IReqorePanelProps>(
365
419
  if (CustomElement) {
366
420
  return (
367
421
  <CustomElement
422
+ fixed
368
423
  {...props}
369
424
  key={index}
370
- customTheme={theme}
425
+ customTheme={props.customTheme || theme}
371
426
  onClick={(e: React.MouseEvent<any>) => {
372
427
  e.stopPropagation();
373
428
  props?.onClick?.(e);
@@ -380,9 +435,10 @@ export const ReqorePanel = forwardRef<HTMLDivElement, IReqorePanelProps>(
380
435
  <ReqoreButton
381
436
  {...rest}
382
437
  id={id}
438
+ fixed
383
439
  key={index}
384
440
  className={className}
385
- customTheme={theme}
441
+ customTheme={rest.customTheme || theme}
386
442
  intent={intent}
387
443
  onClick={
388
444
  rest.onClick
@@ -423,6 +479,7 @@ export const ReqorePanel = forwardRef<HTMLDivElement, IReqorePanelProps>(
423
479
  }, [intent, theme, contentEffect, interactive]);
424
480
 
425
481
  const opacity = rest.transparent ? 0 : rest.opacity;
482
+ const noHorizontalPadding = opacity === 0 && flat && !intent;
426
483
 
427
484
  return (
428
485
  <StyledPanel
@@ -438,6 +495,7 @@ export const ReqorePanel = forwardRef<HTMLDivElement, IReqorePanelProps>(
438
495
  theme={theme}
439
496
  effect={transformedContentEffect}
440
497
  opacity={opacity}
498
+ fluid={fluid}
441
499
  >
442
500
  {hasTitleBar && (
443
501
  <StyledPanelTitle
@@ -449,7 +507,7 @@ export const ReqorePanel = forwardRef<HTMLDivElement, IReqorePanelProps>(
449
507
  theme={theme}
450
508
  contentSize={contentSize}
451
509
  opacity={opacity ?? (minimal ? 0 : 1)}
452
- noHorizontalPadding={opacity === 0}
510
+ noHorizontalPadding={noHorizontalPadding}
453
511
  >
454
512
  <StyledPanelTitleHeader>
455
513
  {icon && (
@@ -485,27 +543,39 @@ export const ReqorePanel = forwardRef<HTMLDivElement, IReqorePanelProps>(
485
543
  </>
486
544
  ) : null}
487
545
  </StyledPanelTitleHeader>
488
- <ReqoreControlGroup>
489
- {actions.map(renderActions)}
490
- {collapsible && (
491
- <ReqoreButton
492
- customTheme={theme}
493
- icon={_isCollapsed ? 'ArrowDownSLine' : 'ArrowUpSLine'}
494
- onClick={handleCollapseClick}
495
- tooltip={_isCollapsed ? 'Expand' : 'Collapse'}
496
- />
497
- )}
498
- {onClose && (
499
- <ReqoreButton
500
- customTheme={theme}
501
- icon='CloseLine'
502
- onClick={(e: React.MouseEvent<HTMLButtonElement>) => {
503
- e.stopPropagation();
504
- onClose?.();
505
- }}
506
- />
507
- )}
508
- </ReqoreControlGroup>
546
+ {hasResponsiveActions(actions) && (
547
+ <ReqoreControlGroup responsive fluid horizontalAlign='flex-end' customTheme={theme}>
548
+ {actions.map(renderResponsiveActions)}
549
+ </ReqoreControlGroup>
550
+ )}
551
+ {collapsible || onClose || hasNonResponsiveActions(actions) ? (
552
+ <>
553
+ <ReqoreHorizontalSpacer width={GAP_FROM_SIZE.normal} />
554
+ <ReqoreControlGroup fixed horizontalAlign='flex-end'>
555
+ {actions.map(renderNonResponsiveActions)}
556
+ {collapsible && (
557
+ <ReqoreButton
558
+ customTheme={theme}
559
+ icon={_isCollapsed ? 'ArrowDownSLine' : 'ArrowUpSLine'}
560
+ onClick={handleCollapseClick}
561
+ tooltip={_isCollapsed ? 'Expand' : 'Collapse'}
562
+ fixed
563
+ />
564
+ )}
565
+ {onClose && (
566
+ <ReqoreButton
567
+ fixed
568
+ customTheme={theme}
569
+ icon='CloseLine'
570
+ onClick={(e: React.MouseEvent<HTMLButtonElement>) => {
571
+ e.stopPropagation();
572
+ onClose?.();
573
+ }}
574
+ />
575
+ )}
576
+ </ReqoreControlGroup>
577
+ </>
578
+ ) : null}
509
579
  </StyledPanelTitle>
510
580
  )}
511
581
  {!_isCollapsed || (_isCollapsed && !unMountContentOnCollapse) ? (
@@ -518,7 +588,7 @@ export const ReqorePanel = forwardRef<HTMLDivElement, IReqorePanelProps>(
518
588
  padded={padded}
519
589
  minimal={minimal}
520
590
  contentSize={contentSize}
521
- noHorizontalPadding={opacity === 0}
591
+ noHorizontalPadding={noHorizontalPadding}
522
592
  >
523
593
  {children}
524
594
  </StyledPanelContent>
@@ -529,10 +599,34 @@ export const ReqorePanel = forwardRef<HTMLDivElement, IReqorePanelProps>(
529
599
  className='reqore-panel-bottom-actions'
530
600
  theme={theme}
531
601
  opacity={opacity ?? (minimal ? 0 : 1)}
532
- noHorizontalPadding={opacity === 0}
602
+ noHorizontalPadding={noHorizontalPadding}
533
603
  >
534
- <ReqoreControlGroup>{leftBottomActions.map(renderActions)}</ReqoreControlGroup>
535
- <ReqoreControlGroup>{rightBottomActions.map(renderActions)}</ReqoreControlGroup>
604
+ {hasNonResponsiveActions(leftBottomActions) ? (
605
+ <>
606
+ <ReqoreControlGroup>
607
+ {leftBottomActions.map(renderNonResponsiveActions)}
608
+ </ReqoreControlGroup>
609
+ <ReqoreHorizontalSpacer width={GAP_FROM_SIZE.normal} />
610
+ </>
611
+ ) : null}
612
+ {hasResponsiveActions(leftBottomActions) && (
613
+ <ReqoreControlGroup fluid responsive customTheme={theme}>
614
+ {leftBottomActions.map(renderResponsiveActions)}
615
+ </ReqoreControlGroup>
616
+ )}
617
+ {hasResponsiveActions(rightBottomActions) && (
618
+ <ReqoreControlGroup fluid horizontalAlign='flex-end' responsive customTheme={theme}>
619
+ {rightBottomActions.map(renderResponsiveActions)}
620
+ </ReqoreControlGroup>
621
+ )}
622
+ {hasNonResponsiveActions(rightBottomActions) ? (
623
+ <>
624
+ <ReqoreHorizontalSpacer width={GAP_FROM_SIZE.normal} />
625
+ <ReqoreControlGroup horizontalAlign='flex-end'>
626
+ {rightBottomActions.map(renderNonResponsiveActions)}
627
+ </ReqoreControlGroup>
628
+ </>
629
+ ) : null}
536
630
  </StyledPanelBottomActions>
537
631
  ) : null}
538
632
  </StyledPanel>
@@ -1,4 +1,4 @@
1
- import { memo } from 'react';
1
+ import { memo, useMemo } from 'react';
2
2
  import styled, { css } from 'styled-components';
3
3
  import { SIZE_TO_NUMBER, TEXT_FROM_SIZE, TSizes } from '../../constants/sizes';
4
4
  import { changeLightness } from '../../helpers/colors';
@@ -6,32 +6,68 @@ import { useReqoreTheme } from '../../hooks/useTheme';
6
6
  import { IReqoreIntent, IWithReqoreCustomTheme, IWithReqoreEffect } from '../../types/global';
7
7
  import { StyledEffect } from '../Effect';
8
8
 
9
- export const StyledSpacer = styled(StyledEffect)`
9
+ export const StyledSpacer = styled.div`
10
+ display: ${({ horizontal }) => (horizontal ? 'inline-flex' : 'flex')};
11
+ vertical-align: middle;
12
+
13
+ ${({ horizontal, vertical }) => {
14
+ if (horizontal) {
15
+ return css`
16
+ flex-flow: row;
17
+ `;
18
+ }
19
+
20
+ if (vertical) {
21
+ return css`
22
+ flex-flow: column;
23
+ `;
24
+ }
25
+ }}
26
+
27
+ flex-shrink: 0;
28
+ `;
29
+
30
+ export const StyledSpace = styled.div`
31
+ display: inline-block;
32
+ flex: 0 0 auto;
33
+
10
34
  ${({ horizontal, vertical, width, height, lineSize }) => {
11
35
  if (horizontal) {
12
36
  return css`
13
- margin-left: ${width / 2}px;
14
- margin-right: ${width / 2}px;
15
- width: ${lineSize === 'none' ? 1 : SIZE_TO_NUMBER[lineSize]}px;
37
+ width: ${width / 2 - lineSize / 2}px;
16
38
  height: ${height ? `${height}px` : `${TEXT_FROM_SIZE.normal}px`};
17
- vertical-align: middle;
18
- display: inline-block;
19
39
  `;
20
40
  }
21
41
 
22
42
  if (vertical) {
23
43
  return css`
24
- margin-top: ${height / 2}px;
25
- margin-bottom: ${height / 2}px;
26
- height: ${lineSize === 'none' ? 1 : SIZE_TO_NUMBER[lineSize]}px;
27
44
  width: ${width ? `${width}px` : '100%'};
45
+ height: ${height / 2 - lineSize / 2}px;
28
46
  `;
29
47
  }
30
48
  }}
49
+ `;
31
50
 
51
+ export const StyledLine = styled(StyledEffect)`
52
+ flex-shrink: 0;
32
53
  background-color: ${({ theme, lineSize }) =>
33
54
  lineSize === 'none' ? 'transparent' : changeLightness(theme.main, 0.2)};
34
- flex-shrink: 0;
55
+
56
+ ${({ horizontal, vertical, width, height, lineSize }) => {
57
+ if (horizontal) {
58
+ return css`
59
+ width: ${lineSize}px;
60
+ height: ${height ? `${height}px` : `${TEXT_FROM_SIZE.normal}px`};
61
+ `;
62
+ }
63
+
64
+ if (vertical) {
65
+ return css`
66
+ width: ${width ? `${width}px` : '100%'};
67
+ height: ${lineSize}px;
68
+ `;
69
+ }
70
+ }}
35
71
  `;
36
72
 
37
73
  export interface IReqoreSpacerProps
@@ -66,16 +102,29 @@ export const ReqoreSpacer = memo(
66
102
  }
67
103
  }
68
104
 
105
+ const _lineSize = useMemo(
106
+ () => (lineSize === 'none' ? 0 : SIZE_TO_NUMBER[lineSize]),
107
+ [lineSize]
108
+ );
109
+
69
110
  return (
70
111
  <StyledSpacer
71
112
  as='div'
72
113
  {...rest}
73
- theme={theme}
74
- lineSize={lineSize}
75
114
  horizontal={horizontal}
76
115
  vertical={vertical}
77
116
  className='reqore-spacer'
78
- />
117
+ >
118
+ <StyledSpace {...rest} horizontal={horizontal} vertical={vertical} lineSize={_lineSize} />
119
+ <StyledLine
120
+ {...rest}
121
+ horizontal={horizontal}
122
+ vertical={vertical}
123
+ theme={theme}
124
+ lineSize={_lineSize}
125
+ />
126
+ <StyledSpace {...rest} horizontal={horizontal} vertical={vertical} lineSize={_lineSize} />
127
+ </StyledSpacer>
79
128
  );
80
129
  }
81
130
  );
@@ -1,9 +1,12 @@
1
1
  import React from 'react';
2
2
  import styled from 'styled-components';
3
3
 
4
+ export type TReqoreTabsContentPadding = 'horizontal' | 'vertical' | 'none' | 'both' | true | false;
5
+
4
6
  export interface IReqoreTabsContent extends React.HTMLAttributes<HTMLDivElement> {
5
7
  children?: any;
6
8
  tabId: string | number;
9
+ padded?: TReqoreTabsContentPadding;
7
10
  }
8
11
 
9
12
  const StyledTabsContent = styled.div`
@@ -11,11 +14,16 @@ const StyledTabsContent = styled.div`
11
14
  flex-flow: column;
12
15
  overflow: hidden;
13
16
  flex: 1;
14
- padding: 10px;
17
+ padding: ${({ padded }: IReqoreTabsContent) =>
18
+ padded === 'none' || padded === false
19
+ ? undefined
20
+ : `${padded === 'both' || padded === true || padded === 'vertical' ? 10 : 0}px ${
21
+ padded === 'both' || padded === true || padded === 'horizontal' ? 10 : 0
22
+ }px}`};
15
23
  `;
16
24
 
17
- const ReqoreTabsContent = ({ children, className, ...rest }: IReqoreTabsContent) => (
18
- <StyledTabsContent {...rest} className={`${className || ''} reqore-tabs-content`}>
25
+ const ReqoreTabsContent = ({ children, className, padded = true, ...rest }: IReqoreTabsContent) => (
26
+ <StyledTabsContent {...rest} padded={padded} className={`${className || ''} reqore-tabs-content`}>
19
27
  {children}
20
28
  </StyledTabsContent>
21
29
  );
@@ -1,9 +1,11 @@
1
- import React, { ReactElement, useEffect, useState } from 'react';
1
+ import React, { ReactElement, useState } from 'react';
2
+ import { useUpdateEffect } from 'react-use';
2
3
  import styled, { css } from 'styled-components';
3
4
  import { TSizes } from '../../constants/sizes';
4
5
  import { IReqoreCustomTheme, TReqoreIntent } from '../../constants/theme';
5
6
  import { IReqoreIconName } from '../../types/icons';
6
7
  import { IReqoreButtonProps } from '../Button';
8
+ import { TReqoreTabsContentPadding } from './content';
7
9
  import ReqoreTabsList from './list';
8
10
 
9
11
  export interface IReqoreTabsListItem extends Omit<IReqoreButtonProps, 'id'> {
@@ -26,6 +28,8 @@ export interface IReqoreTabsProps extends React.HTMLAttributes<HTMLDivElement> {
26
28
  fillParent?: boolean;
27
29
  vertical?: boolean;
28
30
  activeTabIntent?: TReqoreIntent;
31
+ padded?: boolean;
32
+ tabsPadding?: TReqoreTabsContentPadding;
29
33
  wrapTabNames?: boolean;
30
34
  flat?: boolean;
31
35
  size?: TSizes;
@@ -61,11 +65,13 @@ const ReqoreTabs = ({
61
65
  wrapTabNames,
62
66
  customTheme,
63
67
  intent,
68
+ padded,
69
+ tabsPadding,
64
70
  ...rest
65
71
  }: IReqoreTabsProps) => {
66
72
  const [_activeTab, setActiveTab] = useState<string | number>(activeTab || tabs[0].id);
67
73
 
68
- useEffect(() => {
74
+ useUpdateEffect(() => {
69
75
  if (activeTab || activeTab === 0) {
70
76
  setActiveTab(activeTab);
71
77
 
@@ -84,6 +90,7 @@ const ReqoreTabs = ({
84
90
  >
85
91
  <ReqoreTabsList
86
92
  tabs={tabs}
93
+ padded={padded}
87
94
  flat={flat}
88
95
  fill={fill}
89
96
  size={size}
@@ -104,7 +111,11 @@ const ReqoreTabs = ({
104
111
  }}
105
112
  />
106
113
  {React.Children.map(children, (child) =>
107
- child && child.props?.tabId === _activeTab ? child : null
114
+ child && child.props?.tabId === _activeTab
115
+ ? React.cloneElement(child, {
116
+ padded: child.props?.padded || tabsPadding,
117
+ })
118
+ : null
108
119
  )}
109
120
  </StyledTabs>
110
121
  );