@qoretechnologies/reqore 0.35.3 → 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 (198) 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 +27 -0
  42. package/dist/components/KeyValueTable/index.d.ts.map +1 -0
  43. package/dist/components/KeyValueTable/index.js +87 -0
  44. package/dist/components/KeyValueTable/index.js.map +1 -0
  45. package/dist/components/Layout/content.d.ts +1 -1
  46. package/dist/components/Layout/content.d.ts.map +1 -1
  47. package/dist/components/Layout/index.d.ts +1 -1
  48. package/dist/components/Layout/index.d.ts.map +1 -1
  49. package/dist/components/Menu/item.d.ts +1 -1
  50. package/dist/components/Menu/item.d.ts.map +1 -1
  51. package/dist/components/Menu/item.js +3 -3
  52. package/dist/components/Menu/item.js.map +1 -1
  53. package/dist/components/Modal/index.d.ts +1 -1
  54. package/dist/components/Modal/index.d.ts.map +1 -1
  55. package/dist/components/MultiSelect/index.d.ts +2 -2
  56. package/dist/components/MultiSelect/index.d.ts.map +1 -1
  57. package/dist/components/Notifications/notification.js +3 -3
  58. package/dist/components/Notifications/notification.js.map +1 -1
  59. package/dist/components/Paging/index.d.ts +1 -1
  60. package/dist/components/Paging/index.d.ts.map +1 -1
  61. package/dist/components/Panel/NonResponsiveActions.d.ts +1 -1
  62. package/dist/components/Panel/NonResponsiveActions.d.ts.map +1 -1
  63. package/dist/components/Panel/index.js +1 -1
  64. package/dist/components/Panel/index.js.map +1 -1
  65. package/dist/components/Panel/panel.screenshot.d.ts +1 -1
  66. package/dist/components/Panel/panel.screenshot.d.ts.map +1 -1
  67. package/dist/components/Paragraph/index.d.ts +1 -1
  68. package/dist/components/Paragraph/index.d.ts.map +1 -1
  69. package/dist/components/Popover/index.d.ts +1 -1
  70. package/dist/components/Popover/index.d.ts.map +1 -1
  71. package/dist/components/RadioGroup/index.d.ts +1 -1
  72. package/dist/components/RadioGroup/index.d.ts.map +1 -1
  73. package/dist/components/Sidebar/item.d.ts +1 -1
  74. package/dist/components/Sidebar/item.d.ts.map +1 -1
  75. package/dist/components/Spacer/index.d.ts +3 -3
  76. package/dist/components/Spacer/index.d.ts.map +1 -1
  77. package/dist/components/Spinner/index.d.ts +1 -1
  78. package/dist/components/Spinner/index.d.ts.map +1 -1
  79. package/dist/components/Table/body.d.ts +1 -1
  80. package/dist/components/Table/body.d.ts.map +1 -1
  81. package/dist/components/Table/body.js +4 -2
  82. package/dist/components/Table/body.js.map +1 -1
  83. package/dist/components/Table/cell.d.ts +1 -1
  84. package/dist/components/Table/cell.d.ts.map +1 -1
  85. package/dist/components/Table/headerCell.d.ts +1 -1
  86. package/dist/components/Table/headerCell.d.ts.map +1 -1
  87. package/dist/components/Table/helpers.d.ts +8 -6
  88. package/dist/components/Table/helpers.d.ts.map +1 -1
  89. package/dist/components/Table/helpers.js +49 -16
  90. package/dist/components/Table/helpers.js.map +1 -1
  91. package/dist/components/Table/index.d.ts +5 -4
  92. package/dist/components/Table/index.d.ts.map +1 -1
  93. package/dist/components/Table/index.js +63 -53
  94. package/dist/components/Table/index.js.map +1 -1
  95. package/dist/components/Table/row.d.ts +7 -5
  96. package/dist/components/Table/row.d.ts.map +1 -1
  97. package/dist/components/Table/row.js +12 -5
  98. package/dist/components/Table/row.js.map +1 -1
  99. package/dist/components/Table/value.d.ts +7 -0
  100. package/dist/components/Table/value.d.ts.map +1 -0
  101. package/dist/components/Table/value.js +37 -0
  102. package/dist/components/Table/value.js.map +1 -0
  103. package/dist/components/Tabs/content.d.ts +1 -1
  104. package/dist/components/Tabs/content.d.ts.map +1 -1
  105. package/dist/components/Tabs/index.d.ts +1 -1
  106. package/dist/components/Tabs/index.d.ts.map +1 -1
  107. package/dist/components/Tabs/list.d.ts +1 -1
  108. package/dist/components/Tabs/list.d.ts.map +1 -1
  109. package/dist/components/Tabs/list.js +1 -1
  110. package/dist/components/Tabs/list.js.map +1 -1
  111. package/dist/components/Tag/group.d.ts +1 -1
  112. package/dist/components/Tag/group.d.ts.map +1 -1
  113. package/dist/components/Tree/index.d.ts +2 -1
  114. package/dist/components/Tree/index.d.ts.map +1 -1
  115. package/dist/components/Tree/index.js +35 -31
  116. package/dist/components/Tree/index.js.map +1 -1
  117. package/dist/containers/Paging.d.ts +1 -1
  118. package/dist/containers/Paging.d.ts.map +1 -1
  119. package/dist/containers/ThemeProvider.d.ts +1 -1
  120. package/dist/containers/ThemeProvider.d.ts.map +1 -1
  121. package/dist/helpers/utils.d.ts +2 -1
  122. package/dist/helpers/utils.d.ts.map +1 -1
  123. package/dist/helpers/utils.js +20 -2
  124. package/dist/helpers/utils.js.map +1 -1
  125. package/dist/hooks/useAutoFocus.d.ts +1 -1
  126. package/dist/hooks/useAutoFocus.d.ts.map +1 -1
  127. package/dist/hooks/usePopover.d.ts +1 -0
  128. package/dist/hooks/usePopover.d.ts.map +1 -1
  129. package/dist/index.d.ts +2 -0
  130. package/dist/index.d.ts.map +1 -1
  131. package/dist/index.js +6 -2
  132. package/dist/index.js.map +1 -1
  133. package/dist/styles.d.ts +3 -0
  134. package/dist/styles.d.ts.map +1 -1
  135. package/dist/styles.js +49 -11
  136. package/dist/styles.js.map +1 -1
  137. package/migration-storybook.log +88 -0
  138. package/package.json +26 -20
  139. package/src/components/Breadcrumbs/index.tsx +1 -1
  140. package/src/components/Button/index.tsx +3 -54
  141. package/src/components/Collection/index.tsx +18 -15
  142. package/src/components/Collection/item.tsx +2 -1
  143. package/src/components/ExportModal/index.tsx +98 -0
  144. package/src/components/KeyValueTable/index.tsx +129 -0
  145. package/src/components/Menu/item.tsx +4 -4
  146. package/src/components/Notifications/notification.tsx +2 -2
  147. package/src/components/Panel/index.tsx +2 -2
  148. package/src/components/Table/body.tsx +6 -3
  149. package/src/components/Table/helpers.ts +52 -21
  150. package/src/components/Table/index.tsx +127 -90
  151. package/src/components/Table/row.tsx +21 -10
  152. package/src/components/Table/value.tsx +27 -0
  153. package/src/components/Tabs/list.tsx +1 -1
  154. package/src/components/Tree/index.tsx +82 -75
  155. package/src/helpers/utils.ts +10 -2
  156. package/src/hooks/useAutoFocus.ts +1 -1
  157. package/src/index.tsx +2 -0
  158. package/src/mock/tableData.ts +12 -0
  159. package/src/stories/Breadcrumbs/Breadcrumbs.stories.tsx +11 -23
  160. package/src/stories/Button/Button.stories.tsx +83 -47
  161. package/src/stories/Checkbox/Checkbox.stories.tsx +19 -9
  162. package/src/stories/Collection/Collection.stories.tsx +195 -171
  163. package/src/stories/Columns/Columns.stories.tsx +38 -24
  164. package/src/stories/Comment/Comment.stories.tsx +15 -6
  165. package/src/stories/ControlGroup/ControlGroup.stories.tsx +102 -48
  166. package/src/stories/Drawer/Drawer.stories.tsx +52 -17
  167. package/src/stories/Dropdown/Dropdown.stories.tsx +184 -152
  168. package/src/stories/ExportModal/ExportModal.stories.tsx +18 -0
  169. package/src/stories/Header/Header.stories.tsx +65 -31
  170. package/src/stories/Icon/Icon.stories.tsx +139 -133
  171. package/src/stories/Input/Input.stories.tsx +68 -31
  172. package/src/stories/KeyValueTable/KeyValueTable.stories.tsx +224 -0
  173. package/src/stories/Menu/Menu.stories.tsx +56 -20
  174. package/src/stories/Message/Message.stories.tsx +71 -37
  175. package/src/stories/Modal/Modal.stories.tsx +28 -8
  176. package/src/stories/MultiSelect/MultiSelect.stories.tsx +66 -35
  177. package/src/stories/Navbar/Navbar.stories.tsx +15 -5
  178. package/src/stories/Notifications/Interactive.stories.tsx +40 -28
  179. package/src/stories/Notifications/Notification.stories.tsx +55 -41
  180. package/src/stories/Notifications/Notifications.stories.tsx +45 -29
  181. package/src/stories/Paging/Paging.stories.tsx +206 -177
  182. package/src/stories/Panel/Panel.stories.tsx +238 -168
  183. package/src/stories/Paragraph/Paragraph.stories.tsx +66 -31
  184. package/src/stories/Popover/Popover.stories.tsx +62 -40
  185. package/src/stories/RadioGroup/RadioGroup.stories.tsx +41 -19
  186. package/src/stories/Sidebar/Sidebar.stories.tsx +29 -10
  187. package/src/stories/Spacer/Spacer.stories.tsx +13 -5
  188. package/src/stories/Spinner/Spinner.stories.tsx +26 -12
  189. package/src/stories/Table/Table.stories.tsx +200 -144
  190. package/src/stories/Table/Tests.stories.tsx +9 -0
  191. package/src/stories/Tabs/Tabs.stories.tsx +82 -46
  192. package/src/stories/Tag/Tag.stories.tsx +56 -37
  193. package/src/stories/Tag/TagGroup.stories.tsx +297 -0
  194. package/src/stories/TextArea/TextArea.stories.tsx +82 -40
  195. package/src/stories/Tree/Tree.stories.tsx +84 -22
  196. package/src/stories/utils.ts +22 -1
  197. package/src/styles.ts +55 -2
  198. package/tests.json +1 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@qoretechnologies/reqore",
3
- "version": "0.35.3",
3
+ "version": "0.36.1",
4
4
  "description": "ReQore is a highly theme-able and modular UI library for React",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -11,9 +11,9 @@
11
11
  "build": "./node_modules/typescript/bin/tsc --project tsconfig.prod.json",
12
12
  "build:test": "./node_modules/typescript/bin/tsc --noEmit",
13
13
  "build:test:prod": "./node_modules/typescript/bin/tsc --project tsconfig.prod.json --noEmit",
14
- "storybook": "start-storybook -p 6007 --no-dll",
14
+ "storybook": "storybook dev -p 6007",
15
15
  "init-storybook": "yarn test:ci && yarn storybook",
16
- "build-storybook": "build-storybook"
16
+ "build-storybook": "storybook build"
17
17
  },
18
18
  "repository": {
19
19
  "type": "git",
@@ -26,7 +26,7 @@
26
26
  "react"
27
27
  ],
28
28
  "pre-push": [
29
- "build:test",
29
+ "build:test:prod",
30
30
  "test"
31
31
  ],
32
32
  "author": "Qore Technologies",
@@ -40,18 +40,21 @@
40
40
  "@babel/preset-env": "^7.12.11",
41
41
  "@babel/preset-react": "^7.12.10",
42
42
  "@babel/preset-typescript": "^7.12.7",
43
- "@storybook/addon-actions": "^6.5.13",
44
- "@storybook/addon-essentials": "^6.5.13",
45
- "@storybook/addon-interactions": "^6.5.13",
46
- "@storybook/addon-jest": "^6.5.13",
47
- "@storybook/addon-links": "^6.5.13",
48
- "@storybook/addon-storyshots": "^6.5.13",
49
- "@storybook/addon-storysource": "^6.5.13",
50
- "@storybook/builder-webpack5": "^6.5.13",
51
- "@storybook/jest": "^0.0.10",
52
- "@storybook/manager-webpack5": "^6.5.13",
53
- "@storybook/react": "^6.5.13",
54
- "@storybook/testing-library": "^0.0.13",
43
+ "@storybook/addon-actions": "^7.1.1",
44
+ "@storybook/addon-essentials": "^7.1.1",
45
+ "@storybook/addon-interactions": "^7.1.1",
46
+ "@storybook/addon-links": "^7.1.1",
47
+ "@storybook/builder-webpack5": "^7.1.1",
48
+ "@storybook/jest": "^0.1.0",
49
+ "@storybook/manager-api": "^7.1.1",
50
+ "@storybook/manager-webpack5": "^6.5.16",
51
+ "@storybook/react": "^7.1.1",
52
+ "@storybook/react-webpack5": "^7.1.1",
53
+ "@storybook/test-runner": "^0.9.4",
54
+ "@storybook/testing-library": "^0.2.0",
55
+ "@storybook/testing-react": "^2.0.1",
56
+ "@storybook/theming": "^7.1.1",
57
+ "@storybook/types": "^7.1.1",
55
58
  "@testing-library/jest-dom": "^5.16.5",
56
59
  "@testing-library/react": "^13.4.0",
57
60
  "@types/jest": "^26.0.19",
@@ -61,7 +64,7 @@
61
64
  "@types/react-dom": "^18.0.11",
62
65
  "babel-jest": "^26.6.3",
63
66
  "babel-loader": "^8.2.2",
64
- "chromatic": "^6.3.3",
67
+ "chromatic": "^6.20.0",
65
68
  "jest": "^29.4.3",
66
69
  "jest-environment-jsdom": "^29.4.3",
67
70
  "jest-github-actions-reporter": "^1.0.2",
@@ -72,8 +75,7 @@
72
75
  "react-dom": "^18.2.0",
73
76
  "react-intersection-observer": "^9.4.2",
74
77
  "react-test-renderer": "^18.2.0",
75
- "storybook-addon-outline": "^1.4.2",
76
- "storybook-dark-mode": "^1.1.2",
78
+ "storybook": "^7.1.1",
77
79
  "ts-jest": "^29.0.5",
78
80
  "ts-node": "^9.1.1",
79
81
  "typescript": "^4.7.3",
@@ -101,6 +103,10 @@
101
103
  "shortid": "^2.2.16",
102
104
  "styled-components": "^5.3.6",
103
105
  "thenby": "^1.3.4",
104
- "use-context-selector": "^1.4.1"
106
+ "use-context-selector": "^1.4.1",
107
+ "yaml": "^2.3.1"
108
+ },
109
+ "resolutions": {
110
+ "jackspeak": "2.1.1"
105
111
  }
106
112
  }
@@ -199,7 +199,7 @@ const ReqoreBreadcrumbs: React.FC<IReqoreBreadcrumbsProps> = ({
199
199
  {...props}
200
200
  icon={icon}
201
201
  as={as}
202
- onClick={(_itemId, event) => {
202
+ onClick={(event) => {
203
203
  props?.onClick?.(event);
204
204
  }}
205
205
  tooltip={tooltip}
@@ -23,6 +23,9 @@ import {
23
23
  InactiveIconScale,
24
24
  ReadOnlyElement,
25
25
  ScaleIconOnHover,
26
+ StyledActiveContent,
27
+ StyledInActiveContent,
28
+ StyledInvisibleContent,
26
29
  } from '../../styles';
27
30
  import {
28
31
  IReqoreDisabled,
@@ -37,7 +40,6 @@ import {
37
40
  IReqoreEffect,
38
41
  ReqoreTextEffect,
39
42
  StyledEffect,
40
- StyledTextEffect,
41
43
  TReqoreEffectColor,
42
44
  TReqoreHexColor,
43
45
  } from '../Effect';
@@ -105,59 +107,6 @@ export const StyledAnimatedTextWrapper = styled.span`
105
107
  align-items: ${({ textAlign }) => alignToFlexAlign(textAlign)};
106
108
  `;
107
109
 
108
- export const StyledActiveContent = styled(StyledTextEffect)`
109
- position: absolute;
110
- transform: translateY(-150%);
111
- opacity: 0;
112
- transition: all 0.2s ease-out;
113
- filter: blur(10px);
114
-
115
- ${({ wrap }) =>
116
- !wrap
117
- ? css`
118
- overflow: hidden;
119
- text-overflow: ellipsis;
120
- white-space: nowrap;
121
- width: 100%;
122
- `
123
- : css`
124
- word-break: break-word;
125
- `}
126
- `;
127
-
128
- export const StyledInActiveContent = styled(StyledTextEffect)`
129
- position: absolute;
130
- transform: translateY(0);
131
- transition: all 0.2s ease-out;
132
-
133
- ${({ wrap }) =>
134
- !wrap
135
- ? css`
136
- overflow: hidden;
137
- text-overflow: ellipsis;
138
- white-space: nowrap;
139
- width: 100%;
140
- `
141
- : css`
142
- word-break: break-word;
143
- `}
144
- `;
145
-
146
- export const StyledInvisibleContent = styled(StyledTextEffect)`
147
- visibility: hidden;
148
- position: relative;
149
- overflow: hidden;
150
-
151
- ${({ wrap }) =>
152
- !wrap
153
- ? css`
154
- white-space: nowrap;
155
- `
156
- : css`
157
- word-break: break-word;
158
- `}
159
- `;
160
-
161
110
  export const StyledButton = styled(StyledEffect)<IReqoreButtonStyle>`
162
111
  display: flex;
163
112
  flex-flow: column;
@@ -48,7 +48,7 @@ export interface IReqoreCollectionProps extends IReqorePanelProps, IReqoreColumn
48
48
  searchInput?: React.ReactNode
49
49
  ) => React.ReactNode;
50
50
 
51
- onQueryChange?: (query: string) => void;
51
+ onQueryChange?: (query: string | number) => void;
52
52
 
53
53
  emptyMessage?: string;
54
54
  sortButtonTooltip?: (sort?: 'asc' | 'desc') => string;
@@ -88,8 +88,10 @@ export const ReqoreCollection = ({
88
88
  maxItemHeight,
89
89
  filterable,
90
90
  inputInTitle = true,
91
+
91
92
  sortable,
92
93
  zoomable,
94
+
93
95
  defaultZoom,
94
96
  showSelectedFirst,
95
97
  inputProps,
@@ -132,6 +134,7 @@ export const ReqoreCollection = ({
132
134
  const [contentRef, setContentRef] = useState<HTMLDivElement>(undefined);
133
135
  const isMobile = useReqoreProperty('isMobile');
134
136
  const [zoom, setZoom] = useState<number>(defaultZoom || sizeToZoom.normal);
137
+
135
138
  const { query, setQuery, preQuery, setPreQuery } = useQueryWithDelay(
136
139
  defaultQuery,
137
140
  searchDelay,
@@ -199,39 +202,39 @@ export const ReqoreCollection = ({
199
202
 
200
203
  const toolbarGroup: IReqorePanelAction = {
201
204
  responsive: false,
202
- fluid: isMobile,
203
- group: [
205
+ icon: 'MoreLine',
206
+ className: 'reqore-collection-more',
207
+ actions: [
204
208
  {
205
209
  icon: _showAs === 'grid' ? 'ListUnordered' : 'GridLine',
206
210
  onClick: () => setShowAs(_showAs === 'grid' ? 'list' : 'grid'),
207
211
  tooltip: displayButtonTooltip(_showAs),
212
+ label: displayButtonTooltip(_showAs),
208
213
  disabled: !size(filteredItems),
209
- textAlign: 'center',
210
- fixed: !isMobile,
211
214
  ...displayButtonProps,
212
215
  },
213
216
  ],
214
217
  };
215
218
 
216
- if (zoomable) {
217
- actions.push({
218
- fluid: false,
219
- group: getZoomActions('reqore-collection', zoom, setZoom),
220
- });
221
- }
222
-
223
219
  if (sortable) {
224
- toolbarGroup.group.push({
220
+ toolbarGroup.actions.push({
225
221
  icon: sort === 'desc' ? 'SortDesc' : 'SortAsc',
226
222
  onClick: () => setSort(sort === 'desc' ? 'asc' : 'desc'),
227
223
  tooltip: sortButtonTooltip(sort),
224
+ label: sortButtonTooltip(sort),
228
225
  disabled: !size(filteredItems),
229
- textAlign: 'center',
230
- fixed: !isMobile,
231
226
  ...sortButtonProps,
232
227
  });
233
228
  }
234
229
 
230
+ if (zoomable) {
231
+ toolbarGroup.actions = [
232
+ ...toolbarGroup.actions,
233
+ { divider: true, line: true },
234
+ ...getZoomActions('reqore-collection', zoom, setZoom, true),
235
+ ];
236
+ }
237
+
235
238
  if (filterable && inputInTitle) {
236
239
  actions = [
237
240
  ...actions,
@@ -28,9 +28,10 @@ export interface IReqoreCollectionItemProps
28
28
  | 'isCollapsed'
29
29
  | 'unMountContentOnCollapse'
30
30
  | 'bottomActions'
31
+ | 'content'
31
32
  > {
32
33
  selected?: boolean;
33
- content?: string | React.ReactNode;
34
+ content?: string | number | React.ReactNode;
34
35
  expandable?: boolean;
35
36
  expandedContent?: string | React.ReactNode;
36
37
  expandedActions?: IReqorePanelBottomAction[];
@@ -0,0 +1,98 @@
1
+ import { useCallback, useMemo, useState } from 'react';
2
+ import { stringify } from 'yaml';
3
+ import { ReqoreTextarea, useReqoreProperty } from '../..';
4
+ import { convertToCSV } from '../../helpers/utils';
5
+ import { IReqoreModalProps, ReqoreModal } from '../Modal';
6
+ import ReqoreTabs, { IReqoreTabsProps } from '../Tabs';
7
+ import ReqoreTabsContent from '../Tabs/content';
8
+
9
+ export interface IReqoreExportModalProps extends IReqoreModalProps {
10
+ data: { [key: string]: any } | any[];
11
+ sendNotificationOnCopy?: boolean;
12
+ tabsOptions?: Omit<IReqoreTabsProps, 'tabs'>;
13
+ }
14
+
15
+ export const ReqoreExportModal = ({
16
+ data,
17
+ sendNotificationOnCopy = true,
18
+ tabsOptions = {},
19
+ ...rest
20
+ }: IReqoreExportModalProps) => {
21
+ const addNotification = useReqoreProperty('addNotification');
22
+ const isArray = Array.isArray(data);
23
+ const [tab, setTab] = useState<string>(isArray ? 'csv' : 'json');
24
+ const tabs: IReqoreTabsProps['tabs'] = [
25
+ { label: 'CSV', id: 'csv', disabled: !isArray },
26
+ { label: 'JSON', id: 'json' },
27
+ { label: 'YAML', id: 'yaml' },
28
+ ];
29
+
30
+ const dataToExport = useMemo(() => {
31
+ switch (tab) {
32
+ case 'csv':
33
+ return convertToCSV(data as any[]);
34
+ case 'json':
35
+ return JSON.stringify(data, null, 2);
36
+ case 'yaml':
37
+ return stringify(data, null, 2);
38
+ default:
39
+ return '';
40
+ }
41
+ }, [data, tab, isArray]);
42
+
43
+ const handleCopyClick = useCallback(() => {
44
+ navigator.clipboard.writeText(dataToExport);
45
+
46
+ if (sendNotificationOnCopy) {
47
+ addNotification({
48
+ content: 'Data copied to clipboard',
49
+ intent: 'success',
50
+ duration: 3000,
51
+ });
52
+ }
53
+ }, [sendNotificationOnCopy, dataToExport]);
54
+
55
+ return (
56
+ <ReqoreModal
57
+ label='Export data'
58
+ icon='DownloadLine'
59
+ {...rest}
60
+ isOpen
61
+ bottomActions={[
62
+ {
63
+ position: 'right',
64
+ label: 'Copy',
65
+ icon: 'ClipboardLine',
66
+ onClick: () => {
67
+ handleCopyClick();
68
+ },
69
+ },
70
+ {
71
+ position: 'right',
72
+ label: 'Copy and close',
73
+ icon: 'ClipboardFill',
74
+ onClick: () => {
75
+ handleCopyClick();
76
+ rest.onClose?.();
77
+ },
78
+ },
79
+ ]}
80
+ >
81
+ <ReqoreTabs
82
+ fillParent
83
+ activeTabIntent='info'
84
+ activeTab={isArray ? 'csv' : 'json'}
85
+ padded={false}
86
+ {...tabsOptions}
87
+ onTabChange={(tabId) => setTab(tabId.toString())}
88
+ tabs={tabs}
89
+ >
90
+ {tabs.map((tab) => (
91
+ <ReqoreTabsContent tabId={tab.id} key={tab.id} padded='none'>
92
+ <ReqoreTextarea readOnly value={dataToExport} scaleWithContent minimal />
93
+ </ReqoreTabsContent>
94
+ ))}
95
+ </ReqoreTabs>
96
+ </ReqoreModal>
97
+ );
98
+ };
@@ -0,0 +1,129 @@
1
+ import { keys } from 'lodash';
2
+ import { useMemo } from 'react';
3
+ import { TReqoreIntent } from '../../constants/theme';
4
+ import { IReqoreIconName } from '../../types/icons';
5
+ import { IReqorePanelProps } from '../Panel';
6
+ import ReqoreTable, { IReqoreTableColumn, IReqoreTableProps, IReqoreTableRowData } from '../Table';
7
+ import { IReqoreTableValueProps, ReqoreTableValue } from '../Table/value';
8
+
9
+ export type TReqoreKeyValueTablePrimitiveValue = string | number | boolean | null | undefined;
10
+ export type TReqoreKeyValueTableValue =
11
+ | TReqoreKeyValueTablePrimitiveValue
12
+ | TReqoreKeyValueTablePrimitiveValue[]
13
+ | { [key: string]: TReqoreKeyValueTableValue };
14
+
15
+ export interface IReqoreKeyValueTableProps
16
+ extends IReqorePanelProps,
17
+ Pick<
18
+ IReqoreTableProps,
19
+ | 'striped'
20
+ | 'width'
21
+ | 'height'
22
+ | 'fill'
23
+ | 'filterable'
24
+ | 'filter'
25
+ | 'onFilterChange'
26
+ | 'filterProps'
27
+ | 'zoomable'
28
+ | 'wrapperSize'
29
+ | 'paging'
30
+ > {
31
+ data: { [key: string | number]: TReqoreKeyValueTableValue };
32
+
33
+ keyLabel?: string;
34
+ keyIcon?: IReqoreIconName;
35
+ keyColumnIntent?: TReqoreIntent;
36
+ keyAlign?: IReqoreTableColumn['align'];
37
+ maxKeyWidth?: number;
38
+
39
+ valueLabel?: string;
40
+ valueIcon?: IReqoreIconName;
41
+ valueAlign?: IReqoreTableColumn['align'];
42
+ minValueWidth?: number;
43
+ defaultValueFilter?: string | number;
44
+
45
+ valueRenderer?: (
46
+ data: IReqoreTableRowData,
47
+ defaultComponent?: ({ value }: IReqoreTableValueProps) => any
48
+ ) => any;
49
+ }
50
+
51
+ export const ReqoreKeyValueTable = ({
52
+ data,
53
+ keyLabel,
54
+ keyIcon,
55
+ valueLabel,
56
+ valueIcon,
57
+ valueRenderer,
58
+ keyColumnIntent = 'muted',
59
+ minValueWidth = 100,
60
+ maxKeyWidth = 200,
61
+ keyAlign = 'left',
62
+ valueAlign = 'left',
63
+ defaultValueFilter,
64
+ ...rest
65
+ }: IReqoreKeyValueTableProps) => {
66
+ const { columns, items } = useMemo(() => {
67
+ let columns: IReqoreTableColumn[] = [
68
+ {
69
+ dataId: 'tableKey',
70
+ grow: 1,
71
+ width: maxKeyWidth < 150 ? maxKeyWidth : 150,
72
+ pin: 'left',
73
+ hideable: false,
74
+ intent: keyColumnIntent,
75
+ maxWidth: maxKeyWidth,
76
+ align: keyAlign,
77
+
78
+ header: {
79
+ icon: keyIcon,
80
+ label: keyLabel,
81
+ },
82
+
83
+ cell: {
84
+ content: 'title',
85
+ },
86
+ },
87
+ {
88
+ dataId: 'value',
89
+ grow: 3,
90
+ hideable: false,
91
+ filterable: true,
92
+ pinnable: false,
93
+ minWidth: minValueWidth,
94
+ filter: defaultValueFilter,
95
+ align: valueAlign,
96
+
97
+ header: {
98
+ icon: valueIcon,
99
+ label: valueLabel,
100
+ },
101
+
102
+ cell: {
103
+ content: (data) =>
104
+ valueRenderer?.(data, ReqoreTableValue) || <ReqoreTableValue value={data.value} />,
105
+ },
106
+ },
107
+ ];
108
+
109
+ let items: IReqoreTableRowData[] = [];
110
+
111
+ keys(data).map((key) => {
112
+ items.push({
113
+ tableKey: key,
114
+ value: data[key],
115
+ });
116
+ });
117
+
118
+ return { columns, items };
119
+ }, [data]);
120
+
121
+ return (
122
+ <ReqoreTable
123
+ columns={columns}
124
+ data={items}
125
+ {...rest}
126
+ className={`${rest.className || ''} reqore-key-value-table`}
127
+ />
128
+ );
129
+ };
@@ -17,7 +17,7 @@ export interface IReqoreMenuItemProps
17
17
  selected?: boolean;
18
18
  itemId?: string;
19
19
  onRightIconClick?: (itemId?: string, event?: React.MouseEvent<HTMLElement>) => void;
20
- onClick?: (itemId?: string, event?: React.MouseEvent<HTMLElement>) => void;
20
+ onClick?: (event: React.MouseEvent<HTMLElement>, itemId?: string) => void;
21
21
  scrollIntoView?: boolean;
22
22
  }
23
23
 
@@ -59,12 +59,12 @@ const ReqoreMenuItem = forwardRef<HTMLButtonElement, IReqoreMenuItemProps>(
59
59
  ) => {
60
60
  const { removePopover } = useContext(PopoverContext);
61
61
  const { targetRef } = useCombinedRefs<HTMLButtonElement>(ref);
62
- const [itemRef, setItemRef] = useState<HTMLButtonElement>(undefined);
62
+ const [itemRef, setItemRef] = useState<HTMLButtonElement | null>(null);
63
63
 
64
64
  const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
65
65
  event.persist();
66
66
 
67
- onClick?.(itemId, event);
67
+ onClick?.(event, itemId);
68
68
 
69
69
  if (_insidePopover && _popoverId) {
70
70
  removePopover!(_popoverId);
@@ -102,7 +102,7 @@ const ReqoreMenuItem = forwardRef<HTMLButtonElement, IReqoreMenuItemProps>(
102
102
  onClick={handleClick}
103
103
  active={selected}
104
104
  ref={(ref) => {
105
- targetRef.current = ref;
105
+ targetRef.current = ref || undefined;
106
106
  setItemRef(ref);
107
107
  }}
108
108
  disabled={disabled}
@@ -236,7 +236,7 @@ const ReqoreNotification = forwardRef<HTMLDivElement, IReqoreNotificationProps>(
236
236
  onFinish,
237
237
  flat,
238
238
  minimal,
239
- opaque,
239
+ opaque = true,
240
240
  size = 'normal',
241
241
  customTheme,
242
242
  },
@@ -287,7 +287,7 @@ const ReqoreNotification = forwardRef<HTMLDivElement, IReqoreNotificationProps>(
287
287
  hasShadow
288
288
  timeout={duration}
289
289
  clickable={!!onClick}
290
- onClick={onClick}
290
+ onClick={() => onClick?.()}
291
291
  flat={flat}
292
292
  minimal={minimal}
293
293
  className='reqore-notification'
@@ -1,5 +1,5 @@
1
1
  import classNames from 'classnames';
2
- import { size } from 'lodash';
2
+ import { isArray, size } from 'lodash';
3
3
  import { darken, rgba } from 'polished';
4
4
  import { ReactElement, forwardRef, useCallback, useMemo, useState } from 'react';
5
5
  import { useMeasure, useUpdateEffect } from 'react-use';
@@ -379,7 +379,7 @@ export const ReqorePanel = forwardRef<HTMLDivElement, IReqorePanelProps>(
379
379
  collapsible ||
380
380
  !!onClose ||
381
381
  !!size(actions.filter(isActionShown)) ||
382
- !!badge ||
382
+ !!(isArray(badge) ? size(badge) : badge) ||
383
383
  !!icon,
384
384
  [label, collapsible, onClose, actions, badge, icon]
385
385
  );
@@ -1,3 +1,4 @@
1
+ import count from 'lodash/size';
1
2
  import { forwardRef, useMemo } from 'react';
2
3
  import { useMount } from 'react-use';
3
4
  import { FixedSizeList as List } from 'react-window';
@@ -14,7 +15,7 @@ export interface IReqoreTableSectionBodyProps extends IReqoreTableRowOptions {
14
15
  main: React.RefObject<HTMLDivElement>;
15
16
  header: React.RefObject<HTMLDivElement>;
16
17
  };
17
- type?: 'left' | 'right' | 'main';
18
+ type: 'left' | 'right' | 'main';
18
19
  onScrollChange?: (isScrolled: boolean) => void;
19
20
  }
20
21
 
@@ -73,13 +74,15 @@ const ReqoreTableBody = forwardRef<HTMLDivElement, IReqoreTableSectionBodyProps>
73
74
  [size, rest.flat]
74
75
  );
75
76
 
77
+ const itemCount = useMemo(() => count(data), [data]);
78
+
76
79
  return (
77
80
  <StyledList
78
81
  outerRef={targetRef}
79
- itemCount={data.length}
82
+ itemCount={itemCount}
80
83
  // If the defined height is less than the count of items' height
81
84
  // use that height instead
82
- height={height > data.length * rowHeight ? data.length * rowHeight : height}
85
+ height={height > itemCount * rowHeight ? itemCount * rowHeight : height}
83
86
  className='reqore-table-body'
84
87
  itemSize={rest.flat ? TABLE_SIZE_TO_PX[size] : TABLE_SIZE_TO_PX[size] + 1}
85
88
  itemData={{