@qoretechnologies/reqore 0.36.0 → 0.36.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 (193) hide show
  1. package/__tests__/collection.test.tsx +1 -22
  2. package/__tests__/table.test.tsx +1 -1
  3. package/__tests__/tree.test.tsx +0 -18
  4. package/dist/components/Breadcrumbs/index.js +1 -1
  5. package/dist/components/Breadcrumbs/index.js.map +1 -1
  6. package/dist/components/Button/index.d.ts +1 -4
  7. package/dist/components/Button/index.d.ts.map +1 -1
  8. package/dist/components/Button/index.js +11 -26
  9. package/dist/components/Button/index.js.map +1 -1
  10. package/dist/components/Collection/index.d.ts +2 -2
  11. package/dist/components/Collection/index.d.ts.map +1 -1
  12. package/dist/components/Collection/index.js +10 -10
  13. package/dist/components/Collection/index.js.map +1 -1
  14. package/dist/components/Collection/item.d.ts +3 -3
  15. package/dist/components/Collection/item.d.ts.map +1 -1
  16. package/dist/components/Collection/item.js.map +1 -1
  17. package/dist/components/Columns/index.d.ts +1 -1
  18. package/dist/components/Columns/index.d.ts.map +1 -1
  19. package/dist/components/Comment/index.d.ts +1 -1
  20. package/dist/components/Comment/index.d.ts.map +1 -1
  21. package/dist/components/CommentFeed/index.d.ts +1 -1
  22. package/dist/components/CommentFeed/index.d.ts.map +1 -1
  23. package/dist/components/ControlGroup/index.d.ts +1 -1
  24. package/dist/components/ControlGroup/index.d.ts.map +1 -1
  25. package/dist/components/Dropdown/index.d.ts +1 -1
  26. package/dist/components/Dropdown/index.d.ts.map +1 -1
  27. package/dist/components/Dropdown/item.d.ts +2 -2
  28. package/dist/components/Dropdown/item.d.ts.map +1 -1
  29. package/dist/components/Dropdown/list.d.ts +1 -1
  30. package/dist/components/Dropdown/list.d.ts.map +1 -1
  31. package/dist/components/Effect/index.d.ts +2 -2
  32. package/dist/components/Effect/index.d.ts.map +1 -1
  33. package/dist/components/ExportModal/index.d.ts +11 -0
  34. package/dist/components/ExportModal/index.d.ts.map +1 -0
  35. package/dist/components/ExportModal/index.js +91 -0
  36. package/dist/components/ExportModal/index.js.map +1 -0
  37. package/dist/components/Header/index.d.ts +7 -7
  38. package/dist/components/Header/index.d.ts.map +1 -1
  39. package/dist/components/InputClearButton/index.d.ts +1 -0
  40. package/dist/components/InputClearButton/index.d.ts.map +1 -1
  41. package/dist/components/KeyValueTable/index.d.ts +4 -4
  42. package/dist/components/KeyValueTable/index.d.ts.map +1 -1
  43. package/dist/components/KeyValueTable/index.js.map +1 -1
  44. package/dist/components/Layout/content.d.ts +1 -1
  45. package/dist/components/Layout/content.d.ts.map +1 -1
  46. package/dist/components/Layout/index.d.ts +1 -1
  47. package/dist/components/Layout/index.d.ts.map +1 -1
  48. package/dist/components/Menu/item.d.ts +1 -1
  49. package/dist/components/Menu/item.d.ts.map +1 -1
  50. package/dist/components/Menu/item.js +3 -3
  51. package/dist/components/Menu/item.js.map +1 -1
  52. package/dist/components/Modal/index.d.ts +1 -1
  53. package/dist/components/Modal/index.d.ts.map +1 -1
  54. package/dist/components/MultiSelect/index.d.ts +2 -2
  55. package/dist/components/MultiSelect/index.d.ts.map +1 -1
  56. package/dist/components/Notifications/notification.js +3 -3
  57. package/dist/components/Notifications/notification.js.map +1 -1
  58. package/dist/components/Paging/index.d.ts +1 -1
  59. package/dist/components/Paging/index.d.ts.map +1 -1
  60. package/dist/components/Panel/NonResponsiveActions.d.ts +1 -1
  61. package/dist/components/Panel/NonResponsiveActions.d.ts.map +1 -1
  62. package/dist/components/Panel/index.js +1 -1
  63. package/dist/components/Panel/index.js.map +1 -1
  64. package/dist/components/Panel/panel.screenshot.d.ts +1 -1
  65. package/dist/components/Panel/panel.screenshot.d.ts.map +1 -1
  66. package/dist/components/Paragraph/index.d.ts +1 -1
  67. package/dist/components/Paragraph/index.d.ts.map +1 -1
  68. package/dist/components/Popover/index.d.ts +1 -1
  69. package/dist/components/Popover/index.d.ts.map +1 -1
  70. package/dist/components/RadioGroup/index.d.ts +1 -1
  71. package/dist/components/RadioGroup/index.d.ts.map +1 -1
  72. package/dist/components/Sidebar/item.d.ts +1 -1
  73. package/dist/components/Sidebar/item.d.ts.map +1 -1
  74. package/dist/components/Spacer/index.d.ts +3 -3
  75. package/dist/components/Spacer/index.d.ts.map +1 -1
  76. package/dist/components/Spinner/index.d.ts +1 -1
  77. package/dist/components/Spinner/index.d.ts.map +1 -1
  78. package/dist/components/Table/body.d.ts +1 -1
  79. package/dist/components/Table/body.d.ts.map +1 -1
  80. package/dist/components/Table/body.js +4 -2
  81. package/dist/components/Table/body.js.map +1 -1
  82. package/dist/components/Table/cell.d.ts +1 -1
  83. package/dist/components/Table/cell.d.ts.map +1 -1
  84. package/dist/components/Table/headerCell.d.ts +1 -1
  85. package/dist/components/Table/headerCell.d.ts.map +1 -1
  86. package/dist/components/Table/helpers.d.ts +8 -6
  87. package/dist/components/Table/helpers.d.ts.map +1 -1
  88. package/dist/components/Table/helpers.js +49 -16
  89. package/dist/components/Table/helpers.js.map +1 -1
  90. package/dist/components/Table/index.d.ts +5 -4
  91. package/dist/components/Table/index.d.ts.map +1 -1
  92. package/dist/components/Table/index.js +45 -38
  93. package/dist/components/Table/index.js.map +1 -1
  94. package/dist/components/Table/row.d.ts +7 -5
  95. package/dist/components/Table/row.d.ts.map +1 -1
  96. package/dist/components/Table/row.js +3 -2
  97. package/dist/components/Table/row.js.map +1 -1
  98. package/dist/components/Table/value.d.ts +1 -1
  99. package/dist/components/Table/value.d.ts.map +1 -1
  100. package/dist/components/Tabs/content.d.ts +1 -1
  101. package/dist/components/Tabs/content.d.ts.map +1 -1
  102. package/dist/components/Tabs/index.d.ts +1 -1
  103. package/dist/components/Tabs/index.d.ts.map +1 -1
  104. package/dist/components/Tabs/list.d.ts +1 -1
  105. package/dist/components/Tabs/list.d.ts.map +1 -1
  106. package/dist/components/Tabs/list.js +1 -1
  107. package/dist/components/Tabs/list.js.map +1 -1
  108. package/dist/components/Tag/group.d.ts +1 -1
  109. package/dist/components/Tag/group.d.ts.map +1 -1
  110. package/dist/components/Tree/index.d.ts +2 -1
  111. package/dist/components/Tree/index.d.ts.map +1 -1
  112. package/dist/components/Tree/index.js +35 -31
  113. package/dist/components/Tree/index.js.map +1 -1
  114. package/dist/containers/Paging.d.ts +1 -1
  115. package/dist/containers/Paging.d.ts.map +1 -1
  116. package/dist/containers/ThemeProvider.d.ts +1 -1
  117. package/dist/containers/ThemeProvider.d.ts.map +1 -1
  118. package/dist/helpers/utils.d.ts +2 -1
  119. package/dist/helpers/utils.d.ts.map +1 -1
  120. package/dist/helpers/utils.js +20 -2
  121. package/dist/helpers/utils.js.map +1 -1
  122. package/dist/hooks/useAutoFocus.d.ts +1 -1
  123. package/dist/hooks/useAutoFocus.d.ts.map +1 -1
  124. package/dist/hooks/usePopover.d.ts +1 -0
  125. package/dist/hooks/usePopover.d.ts.map +1 -1
  126. package/dist/index.d.ts +1 -1
  127. package/dist/index.d.ts.map +1 -1
  128. package/dist/index.js.map +1 -1
  129. package/dist/styles.d.ts +3 -0
  130. package/dist/styles.d.ts.map +1 -1
  131. package/dist/styles.js +49 -11
  132. package/dist/styles.js.map +1 -1
  133. package/migration-storybook.log +88 -0
  134. package/package.json +26 -20
  135. package/src/components/Breadcrumbs/index.tsx +1 -1
  136. package/src/components/Button/index.tsx +3 -54
  137. package/src/components/Collection/index.tsx +18 -15
  138. package/src/components/Collection/item.tsx +2 -1
  139. package/src/components/ExportModal/index.tsx +98 -0
  140. package/src/components/KeyValueTable/index.tsx +17 -11
  141. package/src/components/Menu/item.tsx +4 -4
  142. package/src/components/Notifications/notification.tsx +2 -2
  143. package/src/components/Panel/index.tsx +2 -2
  144. package/src/components/Table/body.tsx +6 -3
  145. package/src/components/Table/helpers.ts +52 -21
  146. package/src/components/Table/index.tsx +108 -75
  147. package/src/components/Table/row.tsx +12 -7
  148. package/src/components/Tabs/list.tsx +1 -1
  149. package/src/components/Tree/index.tsx +82 -75
  150. package/src/helpers/utils.ts +10 -2
  151. package/src/hooks/useAutoFocus.ts +1 -1
  152. package/src/index.tsx +1 -1
  153. package/src/mock/tableData.ts +12 -0
  154. package/src/stories/Breadcrumbs/Breadcrumbs.stories.tsx +11 -23
  155. package/src/stories/Button/Button.stories.tsx +83 -47
  156. package/src/stories/Checkbox/Checkbox.stories.tsx +19 -9
  157. package/src/stories/Collection/Collection.stories.tsx +195 -171
  158. package/src/stories/Columns/Columns.stories.tsx +38 -24
  159. package/src/stories/Comment/Comment.stories.tsx +15 -6
  160. package/src/stories/ControlGroup/ControlGroup.stories.tsx +102 -48
  161. package/src/stories/Drawer/Drawer.stories.tsx +52 -17
  162. package/src/stories/Dropdown/Dropdown.stories.tsx +184 -152
  163. package/src/stories/ExportModal/ExportModal.stories.tsx +18 -0
  164. package/src/stories/Header/Header.stories.tsx +65 -31
  165. package/src/stories/Icon/Icon.stories.tsx +139 -133
  166. package/src/stories/Input/Input.stories.tsx +68 -31
  167. package/src/stories/KeyValueTable/KeyValueTable.stories.tsx +143 -118
  168. package/src/stories/Menu/Menu.stories.tsx +56 -20
  169. package/src/stories/Message/Message.stories.tsx +71 -37
  170. package/src/stories/Modal/Modal.stories.tsx +28 -8
  171. package/src/stories/MultiSelect/MultiSelect.stories.tsx +66 -35
  172. package/src/stories/Navbar/Navbar.stories.tsx +15 -5
  173. package/src/stories/Notifications/Interactive.stories.tsx +40 -28
  174. package/src/stories/Notifications/Notification.stories.tsx +55 -41
  175. package/src/stories/Notifications/Notifications.stories.tsx +45 -29
  176. package/src/stories/Paging/Paging.stories.tsx +206 -177
  177. package/src/stories/Panel/Panel.stories.tsx +238 -168
  178. package/src/stories/Paragraph/Paragraph.stories.tsx +66 -31
  179. package/src/stories/Popover/Popover.stories.tsx +62 -40
  180. package/src/stories/RadioGroup/RadioGroup.stories.tsx +41 -19
  181. package/src/stories/Sidebar/Sidebar.stories.tsx +29 -10
  182. package/src/stories/Spacer/Spacer.stories.tsx +13 -5
  183. package/src/stories/Spinner/Spinner.stories.tsx +26 -12
  184. package/src/stories/Table/Table.stories.tsx +200 -144
  185. package/src/stories/Table/Tests.stories.tsx +9 -0
  186. package/src/stories/Tabs/Tabs.stories.tsx +82 -46
  187. package/src/stories/Tag/Tag.stories.tsx +56 -37
  188. package/src/stories/Tag/TagGroup.stories.tsx +297 -0
  189. package/src/stories/TextArea/TextArea.stories.tsx +82 -40
  190. package/src/stories/Tree/Tree.stories.tsx +84 -22
  191. package/src/stories/utils.ts +22 -1
  192. package/src/styles.ts +55 -2
  193. package/tests.json +1 -1
@@ -11,6 +11,7 @@ import { useQueryWithDelay } from '../../hooks/useQueryWithDelay';
11
11
  import { IReqoreIntent, IReqoreTooltip } from '../../types/global';
12
12
  import { IReqoreButtonProps, TReqoreBadge } from '../Button';
13
13
  import { IReqoreDropdownItem } from '../Dropdown/list';
14
+ import { ReqoreExportModal } from '../ExportModal';
14
15
  import ReqoreInput, { IReqoreInputProps } from '../Input';
15
16
  import { IReqorePanelAction, IReqorePanelProps, IReqorePanelSubAction } from '../Panel';
16
17
  import ReqoreTableBody from './body';
@@ -21,11 +22,13 @@ import {
21
22
  flipSortDirection,
22
23
  getColumnsByPinType,
23
24
  getColumnsCount,
25
+ getExportActions,
24
26
  getOnlyShownColumns,
25
27
  getZoomActions,
26
28
  hasGroupedColumns,
27
29
  hasHiddenColumns,
28
30
  prepareColumns,
31
+ removeInternalData,
29
32
  sizeToZoom,
30
33
  sortTableData,
31
34
  zoomToSize,
@@ -104,8 +107,10 @@ export interface IReqoreTableProps extends IReqorePanelProps {
104
107
 
105
108
  filterable?: boolean;
106
109
  filterProps?: (data: IReqoreTableData) => IReqoreInputProps;
107
- filter?: string;
108
- onFilterChange?: (query: string) => void;
110
+ filter?: string | number;
111
+ onFilterChange?: (query: string | number) => void;
112
+
113
+ exportable?: boolean;
109
114
 
110
115
  zoomable?: boolean;
111
116
  defaultZoom?: number;
@@ -137,7 +142,7 @@ export interface IReqoreTableStyle {
137
142
  }
138
143
 
139
144
  export interface IReqoreTableSort {
140
- by?: string;
145
+ by: string;
141
146
  thenBy?: string;
142
147
  direction?: 'asc' | 'desc';
143
148
  }
@@ -188,7 +193,7 @@ const ReqoreTable = ({
188
193
  fill,
189
194
  filterable,
190
195
  zoomable,
191
- filter,
196
+ filter = '',
192
197
  actions = [],
193
198
  onFilterChange,
194
199
  filterProps,
@@ -198,16 +203,17 @@ const ReqoreTable = ({
198
203
  bodyCellComponent,
199
204
  onSelectClick,
200
205
  paging,
206
+ exportable,
201
207
  ...rest
202
208
  }: IReqoreTableProps) => {
203
- const leftTableRef = useRef<HTMLDivElement>(undefined);
204
- const rightTableRef = useRef<HTMLDivElement>(undefined);
205
- const mainTableRef = useRef<HTMLDivElement>(undefined);
206
- const mainHeaderRef = useRef<HTMLDivElement>(undefined);
209
+ const leftTableRef = useRef<HTMLDivElement>(null);
210
+ const rightTableRef = useRef<HTMLDivElement>(null);
211
+ const mainTableRef = useRef<HTMLDivElement>(null);
212
+ const mainHeaderRef = useRef<HTMLDivElement>(null);
207
213
 
208
214
  const [isScrolled, setIsScrolled] = useState<boolean>(false);
209
215
  const [_data, setData] = useState<IReqoreTableData>(data || []);
210
- const [_sort, setSort] = useState<IReqoreTableSort>(fixSort(sort));
216
+ const [_sort, setSort] = useState<IReqoreTableSort | undefined>(fixSort(sort));
211
217
  const [_selected, setSelected] = useState<(string | number)[]>(selected || []);
212
218
  const [_selectedQuant, setSelectedQuant] = useState<'all' | 'none' | 'some'>('none');
213
219
  const [columnModifiers, setColumnModifiers] = useState<{
@@ -215,9 +221,14 @@ const ReqoreTable = ({
215
221
  }>({});
216
222
  const [_internalColumns, setColumns] = useState<IReqoreTableColumn[]>(columns);
217
223
  const [zoom, setZoom] = useState<number>(sizeToZoom[size]);
224
+ const [showExportModal, setShowExportModal] = useState<'full' | 'current' | undefined>(undefined);
218
225
 
219
226
  const [wrapperRef, sizes] = useMeasure();
220
- const { query, preQuery, setQuery, setPreQuery } = useQueryWithDelay(filter, 300, onFilterChange);
227
+ const { query, preQuery, setQuery, setPreQuery } = useQueryWithDelay(
228
+ filter.toString(),
229
+ 300,
230
+ onFilterChange
231
+ );
221
232
 
222
233
  const selectedIcon = useMemo(() => {
223
234
  switch (_selectedQuant) {
@@ -260,15 +271,15 @@ const ReqoreTable = ({
260
271
  tooltip: selectToggleTooltip,
261
272
  icon: !_selectId
262
273
  ? 'Forbid2Line'
263
- : _selected?.find((s) => s === _selectId)
274
+ : _selected?.find((s) => s.toString() === _selectId.toString())
264
275
  ? 'CheckboxCircleLine'
265
276
  : 'CheckboxBlankCircleLine',
266
277
  intent: !_selectId
267
278
  ? 'muted'
268
- : _selected?.find((s) => s === _selectId)
279
+ : _selected?.find((s) => s.toString() === _selectId.toString())
269
280
  ? selectedRowIntent
270
281
  : undefined,
271
- onClick: () => handleSelectClick(_selectId),
282
+ onClick: _selectId ? () => handleSelectClick(_selectId) : undefined,
272
283
  },
273
284
  ],
274
285
  },
@@ -345,7 +356,7 @@ const ReqoreTable = ({
345
356
  }, [data]);
346
357
 
347
358
  useUpdateEffect(() => {
348
- if (selectable) {
359
+ if (selectable && selected) {
349
360
  setSelected(selected);
350
361
  }
351
362
  }, [selected]);
@@ -370,7 +381,7 @@ const ReqoreTable = ({
370
381
  }
371
382
  }, [_selected]);
372
383
 
373
- const handleSortChange = (by?: string) => {
384
+ const handleSortChange = (by: string) => {
374
385
  setSort((currentSort: IReqoreTableSort) => {
375
386
  const newSort: IReqoreTableSort = { ...currentSort };
376
387
 
@@ -444,7 +455,7 @@ const ReqoreTable = ({
444
455
 
445
456
  const addColumn = (column: IReqoreTableColumn) => {
446
457
  _columnsList.push({
447
- label: typeof column.header.label === 'string' ? column.header.label : column.dataId,
458
+ label: typeof column.header?.label === 'string' ? column.header.label : column.dataId,
448
459
  selected: column.show !== false,
449
460
  onClick: () =>
450
461
  handleColumnsUpdate(column.dataId, 'show', column.show !== false ? false : true),
@@ -498,7 +509,6 @@ const ReqoreTable = ({
498
509
 
499
510
  if (count(columnsList)) {
500
511
  finalActions.push({
501
- label: 'Columns',
502
512
  icon: 'LayoutColumnLine',
503
513
  className: 'reqore-table-columns-options',
504
514
  badge: getColumnsCount(getOnlyShownColumns(finalColumns)),
@@ -529,13 +539,6 @@ const ReqoreTable = ({
529
539
  });
530
540
  }
531
541
 
532
- if (zoomable) {
533
- finalActions.push({
534
- fluid: false,
535
- group: getZoomActions('reqore-table', zoom, setZoom),
536
- });
537
- }
538
-
539
542
  if (isScrolled) {
540
543
  finalActions.push({
541
544
  icon: 'ArrowUpSFill',
@@ -546,11 +549,28 @@ const ReqoreTable = ({
546
549
  });
547
550
  }
548
551
 
549
- if (count(columnModifiers) || zoomable || filterable) {
552
+ if (count(columnModifiers) || zoomable || filterable || exportable) {
553
+ let moreActions: IReqorePanelSubAction[] = [];
554
+
555
+ if (exportable) {
556
+ moreActions = [
557
+ ...getExportActions((type) => setShowExportModal(type)),
558
+ { divider: true, line: true },
559
+ ];
560
+ }
561
+
562
+ if (zoomable) {
563
+ moreActions = [
564
+ ...getZoomActions('reqore-table', zoom, setZoom, true),
565
+ { divider: true, line: true },
566
+ ];
567
+ }
568
+
550
569
  finalActions.push({
551
570
  icon: 'MoreLine',
552
571
  className: 'reqore-table-more',
553
572
  actions: [
573
+ ...moreActions,
554
574
  {
555
575
  label: 'Reset table',
556
576
  icon: 'RestartLine',
@@ -581,7 +601,7 @@ const ReqoreTable = ({
581
601
  ]);
582
602
 
583
603
  const badge = useMemo(() => {
584
- const badgeList: TReqoreBadge[] = rest.label ? [count(transformedData)] : undefined;
604
+ const badgeList: TReqoreBadge[] = rest.label ? [count(transformedData)] : [];
585
605
 
586
606
  if (rest.badge) {
587
607
  if (isArray(rest.badge)) {
@@ -661,58 +681,71 @@ const ReqoreTable = ({
661
681
  );
662
682
  };
663
683
 
664
- const pagingOptions = useMemo(() => getPagingObjectFromType(paging), [paging]);
684
+ const pagingOptions = useMemo(
685
+ () => (paging ? getPagingObjectFromType(paging) : undefined),
686
+ [paging]
687
+ );
665
688
 
666
689
  return (
667
- <ReqorePanel
668
- transparent
669
- flat
670
- padded={false}
671
- contentStyle={{ display: 'flex', flexFlow: 'column', overflow: 'hidden' }}
672
- responsiveActions={false}
673
- {...rest}
674
- size={wrapperSize}
675
- actions={tableActions}
676
- fill={fill}
677
- className={`${className || ''} reqore-table`}
678
- style={{ width, ...(rest.style || {}) }}
679
- getContentRef={wrapperRef}
680
- badge={badge}
681
- >
682
- <ReqorePaginationContainer<IReqoreTableRowData>
683
- items={transformedData}
684
- type={
685
- paging
686
- ? {
687
- ...pagingOptions,
688
- onPageChange: () => {
689
- if (!pagingOptions.infinite) {
690
- handleScrollToTop();
691
- }
692
- },
693
- }
694
- : undefined
695
- }
690
+ <>
691
+ <ReqorePanel
692
+ transparent
693
+ flat
694
+ padded={false}
695
+ contentStyle={{ display: 'flex', flexFlow: 'column', overflow: 'hidden' }}
696
+ responsiveActions={false}
697
+ {...rest}
698
+ size={wrapperSize}
699
+ actions={tableActions}
700
+ fill={fill}
701
+ className={`${className || ''} reqore-table`}
702
+ style={{ width, ...(rest.style || {}) }}
703
+ getContentRef={wrapperRef}
704
+ badge={badge}
696
705
  >
697
- {(pagedData) => (
698
- <>
699
- <StyledTablesWrapper className='reqore-table-wrapper'>
700
- {renderTable('left', pagedData)}
701
- {renderTable('main', pagedData)}
702
- {renderTable('right', pagedData)}
703
- </StyledTablesWrapper>
704
- {count(pagedData) === 0 ? (
705
- <>
706
- <ReqoreVerticalSpacer height={10} />
707
- <ReqoreMessage flat size={size} icon='Search2Line'>
708
- {emptyMessage}
709
- </ReqoreMessage>
710
- </>
711
- ) : null}
712
- </>
713
- )}
714
- </ReqorePaginationContainer>
715
- </ReqorePanel>
706
+ <ReqorePaginationContainer<IReqoreTableRowData>
707
+ items={transformedData}
708
+ type={
709
+ pagingOptions
710
+ ? {
711
+ ...pagingOptions,
712
+ onPageChange: () => {
713
+ if (!pagingOptions.infinite) {
714
+ handleScrollToTop();
715
+ }
716
+ },
717
+ }
718
+ : undefined
719
+ }
720
+ >
721
+ {(pagedData) => (
722
+ <>
723
+ {showExportModal && (
724
+ <ReqoreExportModal
725
+ data={removeInternalData(
726
+ showExportModal === 'current' ? pagedData : transformedData
727
+ )}
728
+ onClose={() => setShowExportModal(undefined)}
729
+ />
730
+ )}
731
+ <StyledTablesWrapper className='reqore-table-wrapper'>
732
+ {renderTable('left', pagedData)}
733
+ {renderTable('main', pagedData)}
734
+ {renderTable('right', pagedData)}
735
+ </StyledTablesWrapper>
736
+ {count(pagedData) === 0 ? (
737
+ <>
738
+ <ReqoreVerticalSpacer height={10} />
739
+ <ReqoreMessage flat size={size} icon='Search2Line'>
740
+ {emptyMessage}
741
+ </ReqoreMessage>
742
+ </>
743
+ ) : null}
744
+ </>
745
+ )}
746
+ </ReqorePaginationContainer>
747
+ </ReqorePanel>
748
+ </>
716
749
  );
717
750
  };
718
751
 
@@ -17,10 +17,10 @@ import { getOnlyShownColumns } from './helpers';
17
17
 
18
18
  export interface IReqoreTableRowOptions {
19
19
  columns: IReqoreTableColumn[];
20
- data?: IReqoreTableData;
20
+ data: IReqoreTableData;
21
21
  selectable?: boolean;
22
- onSelectClick?: (selectId: string | number) => void;
23
- selected?: (string | number)[];
22
+ onSelectClick: (selectId: string | number) => void;
23
+ selected: (string | number)[];
24
24
  onRowClick?: IReqoreTableRowClick;
25
25
  striped?: boolean;
26
26
  selectedRowIntent?: TReqoreIntent;
@@ -29,7 +29,10 @@ export interface IReqoreTableRowOptions {
29
29
  cellComponent?: IReqoreCustomTableBodyCell;
30
30
  rowComponent?: IReqoreCustomTableRow;
31
31
  }
32
- export interface IReqoreCustomTableRowProps extends IReqoreTableRowOptions {}
32
+ export interface IReqoreCustomTableRowProps extends IReqoreTableRowOptions {
33
+ style?: React.CSSProperties;
34
+ children?: ReactElement;
35
+ }
33
36
  export interface IReqoreCustomTableRow extends React.FC<IReqoreCustomTableRowProps> {}
34
37
  export interface IReqoreTableRowProps extends React.HTMLAttributes<HTMLDivElement> {
35
38
  data: IReqoreTableRowOptions;
@@ -92,7 +95,9 @@ const ReqoreTableRow = ({
92
95
  index,
93
96
  }: IReqoreTableRowProps) => {
94
97
  const [isHovered, setIsHovered] = useState<boolean>(false);
95
- const isSelected = selected.find((selectId) => selectId === data[index]._selectId);
98
+ const isSelected =
99
+ data[index]._selectId &&
100
+ selected.find((selectId) => selectId.toString() === data[index]._selectId.toString());
96
101
 
97
102
  const CellComponent = cellComponent || ReqoreTableBodyCell;
98
103
  const RowComponent = rowComponent || StyledTableRow;
@@ -181,7 +186,7 @@ const ReqoreTableRow = ({
181
186
  const renderCells = (columns: IReqoreTableColumn[], data: IReqoreTableData) =>
182
187
  getOnlyShownColumns(columns).map(
183
188
  ({ width, minWidth, maxWidth, resizedWidth, grow, dataId, cell, header, align, intent }) => {
184
- if (header.columns) {
189
+ if (header?.columns) {
185
190
  return renderCells(header.columns, data);
186
191
  }
187
192
 
@@ -227,7 +232,7 @@ const ReqoreTableRow = ({
227
232
  onRowClick(data[index]);
228
233
  } else if (selectable && data[index]._selectId) {
229
234
  // Otherwise select the row if selectable
230
- onSelectClick(data[index]._selectId);
235
+ onSelectClick(data[index]._selectId!);
231
236
  }
232
237
  },
233
238
  className: 'reqore-table-cell',
@@ -252,7 +252,7 @@ const ReqoreTabsList = ({
252
252
  }
253
253
  : undefined,
254
254
  selected: activeTab === id,
255
- onClick: (_id, event: React.MouseEvent<any>) => {
255
+ onClick: (event: React.MouseEvent<any>) => {
256
256
  if (!disabled) {
257
257
  onTabChange?.(id);
258
258
 
@@ -1,14 +1,15 @@
1
1
  import { cloneDeep, size as lodashSize } from 'lodash';
2
- import { useState } from 'react';
2
+ import { useMemo, useState } from 'react';
3
3
  import styled from 'styled-components';
4
- import { ReqoreMessage, ReqorePanel, ReqoreTextarea, useReqoreProperty } from '../..';
4
+ import { ReqoreMessage, ReqorePanel, useReqoreProperty } from '../..';
5
5
  import { IReqoreTheme } from '../../constants/theme';
6
6
  import { getTypeFromValue } from '../../helpers/utils';
7
7
  import { IWithReqoreSize } from '../../types/global';
8
8
  import ReqoreButton from '../Button';
9
9
  import ReqoreControlGroup from '../ControlGroup';
10
- import { IReqorePanelProps } from '../Panel';
11
- import { getZoomActions, sizeToZoom, zoomToSize } from '../Table/helpers';
10
+ import { ReqoreExportModal } from '../ExportModal';
11
+ import { IReqorePanelAction, IReqorePanelProps } from '../Panel';
12
+ import { getExportActions, getZoomActions, sizeToZoom, zoomToSize } from '../Table/helpers';
12
13
  import ReqoreTag from '../Tag';
13
14
 
14
15
  export interface IReqoreTreeProps extends IReqorePanelProps, IWithReqoreSize {
@@ -20,6 +21,7 @@ export interface IReqoreTreeProps extends IReqorePanelProps, IWithReqoreSize {
20
21
  withLabelCopy?: boolean;
21
22
  showControls?: boolean;
22
23
  zoomable?: boolean;
24
+ exportable?: boolean;
23
25
  defaultZoom?: 0 | 0.5 | 1 | 1.5 | 2;
24
26
  }
25
27
 
@@ -41,29 +43,23 @@ export const ReqoreTree = ({
41
43
  onItemClick,
42
44
  withLabelCopy,
43
45
  showControls = true,
46
+
47
+ exportable,
44
48
  zoomable,
45
49
  defaultZoom,
46
50
  ...rest
47
51
  }: IReqoreTreeProps) => {
48
- const [_mode, setMode] = useState<'tree' | 'copy'>(mode);
49
52
  const [items, setItems] = useState({});
50
53
  const [allExpanded, setAllExpanded] = useState(expanded || !showControls);
51
54
  const [_showTypes, setShowTypes] = useState(showTypes);
52
55
  const addNotification = useReqoreProperty('addNotification');
53
56
  const [zoom, setZoom] = useState(defaultZoom || sizeToZoom[size]);
54
-
55
- const handleCopyClick = () => {
56
- setMode('copy');
57
- };
57
+ const [showExportModal, setShowExportModal] = useState<'full' | 'current' | undefined>(undefined);
58
58
 
59
59
  const handleTypesClick = () => {
60
60
  setShowTypes(!_showTypes);
61
61
  };
62
62
 
63
- const handleTreeClick = () => {
64
- setMode('tree');
65
- };
66
-
67
63
  const handleExpandClick = () => {
68
64
  setItems({});
69
65
  setAllExpanded(true);
@@ -173,73 +169,84 @@ export const ReqoreTree = ({
173
169
  return text;
174
170
  };
175
171
 
172
+ const actions = useMemo(() => {
173
+ let _actions: IReqorePanelAction[] = [];
174
+
175
+ if (showControls) {
176
+ _actions = [
177
+ {
178
+ className: 'reqore-tree-expand-all',
179
+ icon: 'ArrowDownFill',
180
+ onClick: handleExpandClick,
181
+ show: !!(isDeep() && !allExpanded),
182
+ label: 'Expand all',
183
+ },
184
+ {
185
+ show: !!(isDeep() && (allExpanded || lodashSize(items) > 0)),
186
+ className: 'reqore-tree-collapse-all',
187
+ icon: 'ArrowUpFill',
188
+ onClick: handleCollapseClick,
189
+
190
+ label: 'Collapse all',
191
+ },
192
+ {
193
+ className: 'reqore-tree-show-types',
194
+ icon: 'CodeBoxFill',
195
+ active: _showTypes,
196
+ onClick: handleTypesClick,
197
+ label: 'Show types',
198
+ },
199
+ ];
200
+ }
201
+
202
+ if (zoomable || exportable) {
203
+ const moreActions: IReqorePanelAction = {
204
+ className: 'reqore-tree-more',
205
+ icon: 'MoreLine',
206
+ actions: [],
207
+ };
208
+
209
+ if (zoomable) {
210
+ moreActions.actions = [
211
+ ...moreActions.actions,
212
+ ...getZoomActions('reqore-tree', zoom, setZoom, true),
213
+ ];
214
+ }
215
+
216
+ if (exportable) {
217
+ moreActions.actions = [
218
+ ...moreActions.actions,
219
+ { divider: true, line: true },
220
+ ...getExportActions((type) => setShowExportModal(type)),
221
+ ];
222
+ }
223
+
224
+ _actions = [..._actions, moreActions];
225
+ }
226
+
227
+ return _actions;
228
+ }, [allExpanded, items, showControls, _showTypes, isDeep(), zoom]);
229
+
176
230
  if (!data || !Object.keys(data).length) {
177
231
  return <p>No data</p>;
178
232
  }
179
233
 
180
- const textData: string = renderText(data);
181
-
182
234
  return (
183
- <ReqorePanel
184
- className='reqore-tree'
185
- minimal
186
- flat
187
- transparent
188
- size={size}
189
- {...rest}
190
- actions={
191
- showControls
192
- ? [
193
- {
194
- fluid: false,
195
- group: getZoomActions('reqore-tree', zoom, setZoom),
196
- show: !!zoomable,
197
- },
198
- {
199
- className: 'reqore-tree-expand-all',
200
- icon: 'ArrowDownFill',
201
- onClick: handleExpandClick,
202
- show: !!(isDeep() && !allExpanded),
203
- label: 'Expand all',
204
- },
205
- {
206
- show: !!(isDeep() && (allExpanded || lodashSize(items) > 0)),
207
- className: 'reqore-tree-collapse-all',
208
- icon: 'ArrowUpFill',
209
- onClick: handleCollapseClick,
210
-
211
- label: 'Collapse all',
212
- },
213
- {
214
- className: 'reqore-tree-show-types',
215
- icon: 'CodeBoxFill',
216
- active: _showTypes,
217
- onClick: handleTypesClick,
218
- label: 'Show types',
219
- },
220
- {
221
- className: _mode === 'tree' ? 'reqore-tree-as-text' : 'reqore-tree-as-tree',
222
- onClick: _mode === 'tree' ? handleCopyClick : handleTreeClick,
223
- icon: _mode === 'tree' ? 'Menu2Fill' : 'ClipboardFill',
224
- label: _mode === 'tree' ? 'Text View' : 'Tree View',
225
- },
226
- ]
227
- : undefined
228
- }
229
- >
230
- {_mode === 'tree' && renderTree(data, true)}
231
-
232
- {_mode === 'copy' && (
233
- <ReqoreTextarea
234
- className='reqore-tree-textarea'
235
- id='tree-content'
236
- value={textData}
237
- scaleWithContent
238
- size={size}
239
- fluid
240
- readOnly
241
- />
235
+ <>
236
+ {showExportModal && (
237
+ <ReqoreExportModal data={data} onClose={() => setShowExportModal(undefined)} />
242
238
  )}
243
- </ReqorePanel>
239
+ <ReqorePanel
240
+ className='reqore-tree'
241
+ minimal
242
+ flat
243
+ transparent
244
+ size={size}
245
+ {...rest}
246
+ actions={actions}
247
+ >
248
+ {renderTree(data, true)}
249
+ </ReqorePanel>
250
+ </>
244
251
  );
245
252
  };
@@ -45,14 +45,22 @@ export const getTypeFromValue: Function = (item: any): string => {
45
45
  return 'null';
46
46
  };
47
47
 
48
- export const getLineCount = (value: string): number => {
48
+ export const getLineCount = (value: string | null): number => {
49
49
  try {
50
- return value.match(/[^\n]*\n[^\n]*/gi).length;
50
+ return value?.match(/[^\n]*\n[^\n]*/gi)?.length ?? 0;
51
51
  } catch (e) {
52
52
  return 0;
53
53
  }
54
54
  };
55
55
 
56
+ // A function that takes list of objects and transforms it
57
+ // to a CSV string
58
+ export const convertToCSV = (objArray: any[]): string => {
59
+ const header = Object.keys(objArray[0]).join(',');
60
+ const rows = objArray.map((obj) => Object.values(obj).join(','));
61
+ return [header, ...rows].join('\n');
62
+ };
63
+
56
64
  export const calculateStringSizeInPixels = (value: string = '', fontSize: number): number => {
57
65
  const widths = [
58
66
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@@ -15,7 +15,7 @@ export interface IReqoreAutoFocusRules {
15
15
  export const useAutoFocus = (
16
16
  element: HTMLInputElement | HTMLTextAreaElement,
17
17
  rules?: IReqoreAutoFocusRules,
18
- onChange?: (e: unknown) => void
18
+ onChange?: (event: any) => void
19
19
  ) => {
20
20
  const isInViewport = useRef<boolean>(false);
21
21
  const observer = useRef<IntersectionObserver>(null);
package/src/index.tsx CHANGED
@@ -24,7 +24,7 @@ export {
24
24
  } from './components/Header';
25
25
  export { default as ReqoreIcon } from './components/Icon';
26
26
  export { default as ReqoreInput } from './components/Input';
27
- export { IReqoreKeyValueTableProps, ReqoreKeyValueTable } from './components/KeyValueTable';
27
+ export { ReqoreKeyValueTable } from './components/KeyValueTable';
28
28
  export { default as ReqoreLayoutContent } from './components/Layout/content';
29
29
  export { default as ReqoreMenu } from './components/Menu';
30
30
  export { default as ReqoreMenuDivider } from './components/Menu/divider';
@@ -1,6 +1,18 @@
1
1
  import { IReqoreTableProps } from '../components/Table';
2
2
  import data from './data.json';
3
3
 
4
+ export type TestTableItem = {
5
+ id: number;
6
+ firstName: string;
7
+ lastName: string;
8
+ address: string;
9
+ age: number;
10
+ occupation: string;
11
+ group: string;
12
+ _selectId: number;
13
+ _disabled: boolean;
14
+ };
15
+
4
16
  export const tableData = data;
5
17
  export const testColumns: IReqoreTableProps['columns'] = [
6
18
  {