@spaced-out/ui-design-system 0.1.67 → 0.1.68
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.
- package/CHANGELOG.md +12 -0
- package/design-tokens/color/app-color.json +14 -0
- package/design-tokens/size/base-size.json +3 -0
- package/lib/components/CircularLoader/CircularLoader.module.css +18 -14
- package/lib/components/Icon/SemanticIcon.js +1 -0
- package/lib/components/Icon/SemanticIcon.js.flow +6 -1
- package/lib/components/Table/Table.docs.js +514 -0
- package/lib/components/Table/Table.docs.js.flow +476 -0
- package/lib/components/Table/TableActionBar.js +37 -3
- package/lib/components/Table/TableActionBar.js.flow +27 -0
- package/lib/components/Table/TableBar.module.css +22 -2
- package/lib/styles/index.css +10 -0
- package/lib/styles/index.js +13 -3
- package/lib/styles/index.js.flow +10 -0
- package/lib/styles/variables/_color.css +8 -0
- package/lib/styles/variables/_color.js +9 -1
- package/lib/styles/variables/_color.js.flow +8 -0
- package/lib/styles/variables/_size.css +2 -0
- package/lib/styles/variables/_size.js +3 -1
- package/lib/styles/variables/_size.js.flow +2 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
|
4
4
|
|
|
5
|
+
### [0.1.68](https://github.com/spaced-out/ui-design-system/compare/v0.1.67...v0.1.68) (2023-12-04)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
### Features
|
|
9
|
+
|
|
10
|
+
* bulk action buttons and table inline edit ([#155](https://github.com/spaced-out/ui-design-system/issues/155)) ([7ae82fc](https://github.com/spaced-out/ui-design-system/commit/7ae82fc6f3fba77f53d7a2269d7a4df675c6d69f))
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
### Bug Fixes
|
|
14
|
+
|
|
15
|
+
* circular loader extra space ([#154](https://github.com/spaced-out/ui-design-system/issues/154)) ([a6ce232](https://github.com/spaced-out/ui-design-system/commit/a6ce2326edc4ce7779471f171d70ba2f33203cfc))
|
|
16
|
+
|
|
5
17
|
### [0.1.67](https://github.com/spaced-out/ui-design-system/compare/v0.1.66...v0.1.67) (2023-11-10)
|
|
6
18
|
|
|
7
19
|
|
|
@@ -105,6 +105,20 @@
|
|
|
105
105
|
"value": "{baseColor.indigo.940.70.value}"
|
|
106
106
|
},
|
|
107
107
|
"button-fill": {
|
|
108
|
+
"tableAction": {
|
|
109
|
+
"enabled": {
|
|
110
|
+
"value": "{baseColor.purple.600.value}"
|
|
111
|
+
},
|
|
112
|
+
"hovered": {
|
|
113
|
+
"value": "{baseColor.purple.700.value}"
|
|
114
|
+
},
|
|
115
|
+
"pressed": {
|
|
116
|
+
"value": "{baseColor.purple.700.value}"
|
|
117
|
+
},
|
|
118
|
+
"border": {
|
|
119
|
+
"value": "{baseColor.purple.400.value}"
|
|
120
|
+
}
|
|
121
|
+
},
|
|
108
122
|
"primary": {
|
|
109
123
|
"enabled": {
|
|
110
124
|
"value": "{baseColor.purple.500.value}"
|
|
@@ -15,27 +15,29 @@
|
|
|
15
15
|
@value spinnerSize: size60;
|
|
16
16
|
@value spinnerThickness: size5;
|
|
17
17
|
|
|
18
|
-
@value
|
|
19
|
-
|
|
20
|
-
@value innerMaskGradient: radial-gradient(farthest-side, colorFillNone calc(99% - spinnerThickness), colorFillPrimary calc(100% - spinnerThickness));
|
|
18
|
+
@value innerMaskGradient: radial-gradient(farthest-side, colorFillNone calc(99% - var(--spinner-thickness)), colorFillPrimary calc(100% - var(--spinner-thickness)));
|
|
21
19
|
|
|
22
20
|
.container {
|
|
23
21
|
display: flex;
|
|
24
22
|
justify-content: flex-start;
|
|
25
23
|
align-items: flex-start;
|
|
24
|
+
--spinner-size: spinnerSize;
|
|
25
|
+
--spinner-thickness: spinnerThickness;
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
.mediumContainer {
|
|
29
|
-
|
|
29
|
+
--spinner-size: calc(0.5 * spinnerSize);
|
|
30
|
+
--spinner-thickness: calc(0.5 * spinnerThickness);
|
|
30
31
|
}
|
|
31
32
|
|
|
32
33
|
.smallContainer {
|
|
33
|
-
|
|
34
|
+
--spinner-size: calc(0.36 * spinnerSize);
|
|
35
|
+
--spinner-thickness: calc(0.36 * spinnerThickness);
|
|
34
36
|
}
|
|
35
37
|
|
|
36
38
|
.spinLoader {
|
|
37
|
-
height:
|
|
38
|
-
width:
|
|
39
|
+
height: var(--spinner-size);
|
|
40
|
+
width: var(--spinner-size);
|
|
39
41
|
display: block;
|
|
40
42
|
position: relative;
|
|
41
43
|
animation: spin motionDurationSlowest linear 0s infinite normal;
|
|
@@ -46,9 +48,9 @@
|
|
|
46
48
|
--color: colorFillPrimary;
|
|
47
49
|
display: block;
|
|
48
50
|
position: absolute;
|
|
49
|
-
border-radius: calc(
|
|
50
|
-
height:
|
|
51
|
-
width:
|
|
51
|
+
border-radius: calc(var(--spinner-size) / 2);
|
|
52
|
+
height: var(--spinner-size);
|
|
53
|
+
width: var(--spinner-size);
|
|
52
54
|
top: spaceNone;
|
|
53
55
|
right: spaceNone;
|
|
54
56
|
background: conic-gradient(
|
|
@@ -63,18 +65,20 @@
|
|
|
63
65
|
.ellipse {
|
|
64
66
|
--color: colorFillPrimary;
|
|
65
67
|
position: absolute;
|
|
66
|
-
left: calc(spinnerSize - spinnerThickness);
|
|
67
68
|
right: spaceNone;
|
|
68
69
|
top: spaceNone;
|
|
69
70
|
bottom: spaceNone;
|
|
70
|
-
border-radius: calc(
|
|
71
|
-
height:
|
|
72
|
-
width:
|
|
71
|
+
border-radius: calc(var(--spinner-thickness) / 2);
|
|
72
|
+
height: var(--spinner-thickness);
|
|
73
|
+
width: var(--spinner-thickness);
|
|
73
74
|
margin: auto;
|
|
74
75
|
background: var(--color);
|
|
75
76
|
}
|
|
76
77
|
|
|
77
78
|
@keyframes spin {
|
|
79
|
+
from {
|
|
80
|
+
transform: rotate(0deg);
|
|
81
|
+
}
|
|
78
82
|
to {
|
|
79
83
|
transform: rotate(360deg);
|
|
80
84
|
}
|
|
@@ -23,6 +23,7 @@ const SemanticIcon = _ref => {
|
|
|
23
23
|
return /*#__PURE__*/React.createElement(React.Fragment, null, !!iconProps.name && /*#__PURE__*/React.createElement("div", {
|
|
24
24
|
className: (0, _classify.default)(_SemanticIconModule.default.iconContainer, _SemanticIconModule.default[semantic], classNames?.wrapper)
|
|
25
25
|
}, /*#__PURE__*/React.createElement(_Icon.Icon, _extends({}, iconProps, {
|
|
26
|
+
className: (0, _classify.default)(iconProps.className, classNames?.icon),
|
|
26
27
|
color: _typography.TEXT_COLORS[semantic],
|
|
27
28
|
type: type
|
|
28
29
|
}))));
|
|
@@ -35,7 +35,12 @@ export const SemanticIcon = ({
|
|
|
35
35
|
classNames?.wrapper,
|
|
36
36
|
)}
|
|
37
37
|
>
|
|
38
|
-
<Icon
|
|
38
|
+
<Icon
|
|
39
|
+
{...iconProps}
|
|
40
|
+
className={classify(iconProps.className, classNames?.icon)}
|
|
41
|
+
color={TEXT_COLORS[semantic]}
|
|
42
|
+
type={type}
|
|
43
|
+
/>
|
|
39
44
|
</div>
|
|
40
45
|
)}
|
|
41
46
|
</>
|
|
@@ -0,0 +1,514 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.TABLE_DOCS = void 0;
|
|
7
|
+
const TABLE_DOCS = {
|
|
8
|
+
argTypes: {
|
|
9
|
+
headers: {
|
|
10
|
+
type: {
|
|
11
|
+
required: true
|
|
12
|
+
},
|
|
13
|
+
description: 'Provide an array of objects to render the header, each object should consist of label(*), key(*), sortable, sticky and render function',
|
|
14
|
+
control: {
|
|
15
|
+
type: 'object'
|
|
16
|
+
},
|
|
17
|
+
table: {
|
|
18
|
+
type: {
|
|
19
|
+
summary: '{label: React.Node, key: $Keys<T>, className?: string, filterIcon?: React.Node, filtered?: boolean, subtext?: string, sortable?: boolean, headerIconClassName?: string, sticky?: boolean, render?: React.ComponentType<{data: T, extras?: U, className?: string, selected?: boolean,}>, }'
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
entries: {
|
|
24
|
+
type: {
|
|
25
|
+
required: true
|
|
26
|
+
},
|
|
27
|
+
description: 'Provide an array of object. Each object belong on one row in the table. Each object should have id and all the keys with values that is being passed in headers array',
|
|
28
|
+
control: {
|
|
29
|
+
type: 'object'
|
|
30
|
+
},
|
|
31
|
+
table: {
|
|
32
|
+
type: {
|
|
33
|
+
summary: 'Array<T>'
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
classNames: {
|
|
38
|
+
description: 'Provide optional classNames to be applied to the wrapper, table, tableHeader, tableBody, tableRow, or checkbox',
|
|
39
|
+
control: {
|
|
40
|
+
type: 'object'
|
|
41
|
+
},
|
|
42
|
+
table: {
|
|
43
|
+
type: {
|
|
44
|
+
summary: '{wrapper?: string, table?: string, tableHeader?: string, tableBody?: string, tableRow?: string, checkbox?: string}'
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
Row: {
|
|
49
|
+
description: 'Custom Row component to be passed to table',
|
|
50
|
+
table: {
|
|
51
|
+
type: {
|
|
52
|
+
summary: 'TableRow<T, U>'
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
sortable: {
|
|
57
|
+
description: 'Sort Icon will appear in right side of column\'s header with column level true sortable value',
|
|
58
|
+
name: 'sortable',
|
|
59
|
+
options: [false, true],
|
|
60
|
+
control: 'boolean',
|
|
61
|
+
table: {
|
|
62
|
+
type: {
|
|
63
|
+
summary: 'boolean'
|
|
64
|
+
},
|
|
65
|
+
defaultValue: {
|
|
66
|
+
summary: true
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
showHeader: {
|
|
71
|
+
description: 'Show or hide header',
|
|
72
|
+
options: [false, true],
|
|
73
|
+
control: 'boolean',
|
|
74
|
+
table: {
|
|
75
|
+
type: {
|
|
76
|
+
summary: 'boolean'
|
|
77
|
+
},
|
|
78
|
+
defaultValue: {
|
|
79
|
+
summary: true
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
defaultSortKey: {
|
|
84
|
+
description: 'key name for which table should be sorted by default. headers array should have sortable true for that key object',
|
|
85
|
+
control: {
|
|
86
|
+
type: 'text'
|
|
87
|
+
},
|
|
88
|
+
table: {
|
|
89
|
+
type: {
|
|
90
|
+
summary: 'string'
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
},
|
|
94
|
+
// defaultSortDirection?: 'asc' | 'desc' | 'original',
|
|
95
|
+
defaultSortDirection: {
|
|
96
|
+
description: 'default sorting direction for the defaultSortKey column',
|
|
97
|
+
control: {
|
|
98
|
+
type: 'text'
|
|
99
|
+
},
|
|
100
|
+
table: {
|
|
101
|
+
type: {
|
|
102
|
+
summary: '\'asc\' | \'desc\' | \'original\''
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
},
|
|
106
|
+
selectedKeys: {
|
|
107
|
+
description: 'array of keys which are selected. This prop is also used to decide weather to show checkboxes or not. So, pass an empty array incase no row is selected.',
|
|
108
|
+
control: {
|
|
109
|
+
type: 'object'
|
|
110
|
+
},
|
|
111
|
+
table: {
|
|
112
|
+
type: {
|
|
113
|
+
summary: 'string[]'
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
},
|
|
117
|
+
//onSelect?: (keys: string[]) => mixed
|
|
118
|
+
onSelect: {
|
|
119
|
+
description: 'callback function when any row is selected',
|
|
120
|
+
action: 'selected',
|
|
121
|
+
type: {
|
|
122
|
+
summary: '(keys: string[]) => mixed'
|
|
123
|
+
}
|
|
124
|
+
},
|
|
125
|
+
idName: {
|
|
126
|
+
description: 'name of key in row objects that has to be used as id'
|
|
127
|
+
},
|
|
128
|
+
//onSort?: (key: $Keys<T>
|
|
129
|
+
onSort: {
|
|
130
|
+
description: 'callback function when any table is sorted',
|
|
131
|
+
action: 'sorted',
|
|
132
|
+
type: {
|
|
133
|
+
summary: '(key: $Keys<T>, direction: SortDirection) => void'
|
|
134
|
+
}
|
|
135
|
+
},
|
|
136
|
+
isLoading: {
|
|
137
|
+
description: 'to wait for data to populate in table and show loading state when entries array is empty.',
|
|
138
|
+
options: [false, true],
|
|
139
|
+
control: 'boolean',
|
|
140
|
+
table: {
|
|
141
|
+
type: {
|
|
142
|
+
summary: 'boolean'
|
|
143
|
+
},
|
|
144
|
+
defaultValue: {
|
|
145
|
+
summary: false
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
},
|
|
149
|
+
emptyText: {
|
|
150
|
+
description: 'Provide component to be shown in case of empty data',
|
|
151
|
+
table: {
|
|
152
|
+
type: {
|
|
153
|
+
summary: 'React.Component'
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
},
|
|
157
|
+
customLoader: {
|
|
158
|
+
description: 'Provide optional component to be shown in case of loading state. It will override the default loader.',
|
|
159
|
+
table: {
|
|
160
|
+
type: {
|
|
161
|
+
summary: 'React.Component'
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
},
|
|
165
|
+
disabled: {
|
|
166
|
+
description: 'disable all the checkboxes of each row in the table',
|
|
167
|
+
options: [false, true],
|
|
168
|
+
control: 'boolean',
|
|
169
|
+
table: {
|
|
170
|
+
type: {
|
|
171
|
+
summary: 'boolean'
|
|
172
|
+
},
|
|
173
|
+
defaultValue: {
|
|
174
|
+
summary: false
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
},
|
|
178
|
+
borderRadius: {
|
|
179
|
+
description: 'Border Radius of all four corners of the table. Default value is borderRadiusMedium i.e., 12px.',
|
|
180
|
+
control: 'text',
|
|
181
|
+
table: {
|
|
182
|
+
type: {
|
|
183
|
+
summary: 'string'
|
|
184
|
+
},
|
|
185
|
+
defaultValue: {
|
|
186
|
+
summary: '12px'
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
},
|
|
190
|
+
stickyHeader: {
|
|
191
|
+
description: 'Sticky header will stick the header to the top of the table when scrolling. This would only work if the table wrapper is scrollable.',
|
|
192
|
+
control: 'boolean',
|
|
193
|
+
table: {
|
|
194
|
+
type: {
|
|
195
|
+
summary: 'boolean'
|
|
196
|
+
},
|
|
197
|
+
defaultValue: {
|
|
198
|
+
summary: false
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
},
|
|
203
|
+
parameters: {
|
|
204
|
+
componentSubtitle: 'Generates a Table component.',
|
|
205
|
+
docs: {
|
|
206
|
+
description: {
|
|
207
|
+
component: `
|
|
208
|
+
\`\`\`js
|
|
209
|
+
import {
|
|
210
|
+
Table,
|
|
211
|
+
StaticTable,
|
|
212
|
+
DefaultRow,
|
|
213
|
+
BasicSingleCell,
|
|
214
|
+
DateCell,
|
|
215
|
+
DoubleCell,
|
|
216
|
+
SingleCell,
|
|
217
|
+
MonogramCell,
|
|
218
|
+
TableActionBar,
|
|
219
|
+
ButtonCta,
|
|
220
|
+
DropdownCta,
|
|
221
|
+
TableTopBar,
|
|
222
|
+
TableBottomBar
|
|
223
|
+
} from "@spaced-out/ui-design-system/lib/components/Table";
|
|
224
|
+
\`\`\`
|
|
225
|
+
Table component internally uses HTML Table, Thead, Tbody, Tr, Th and Td tags. It accepts entries and headers for showing table.
|
|
226
|
+
The Table component takes care of lots of things for you but it's not a magical component, it wraps a lot of behavior, so you can have,
|
|
227
|
+
for instance, a static table with no sorting options.
|
|
228
|
+
|
|
229
|
+
StaticTables work just like regular tables, except they don't have interactive headers, so you lose sorting.
|
|
230
|
+
But remember, a regular interactive table uses a static table under the hood,
|
|
231
|
+
so how does it work? You can think of the StaticTable as a kind of controlled table component.
|
|
232
|
+
except that traditionally we'd update the entries prop and rerender from that.
|
|
233
|
+
That would work just fine, but instead we can just pass in the keys we care about. By using StaticTable,
|
|
234
|
+
we can simplify filtering and sorting outside of the table while the table keeps a stable value reference to all the entities.
|
|
235
|
+
|
|
236
|
+
To make any of rows selectable, we can do that by also passing in another property, selectedKeys.
|
|
237
|
+
|
|
238
|
+
Let's say we want to also make any of the rows selectable, we can do that by also passing in another property, selectedKeys.
|
|
239
|
+
|
|
240
|
+
### Custom Cells
|
|
241
|
+
|
|
242
|
+
It's possible you need to render out a custom cell, not just the default cell.
|
|
243
|
+
There are two ways to do that. If you only need to modify a single cell,
|
|
244
|
+
you can simply add a render: \`React.ComponentType<{data: T, extras?: U}>\`
|
|
245
|
+
key to any given header item.
|
|
246
|
+
|
|
247
|
+
This cell renderer receives the _whole row_ of data, not just the individual cell, it's up to you what to do with it.
|
|
248
|
+
|
|
249
|
+
### With Table Top, Bottom Bar and Actions
|
|
250
|
+
|
|
251
|
+
You can attach a top, bottom and action bar to the table by adding \`TableTopBar\`, \`TableBottomBar\` and \`TableActionBar\` components.
|
|
252
|
+
There are just semantic components which just provide padding and border standardization. You can add any component inside these components.
|
|
253
|
+
These also accept **className** prop.
|
|
254
|
+
|
|
255
|
+
### Best Practices
|
|
256
|
+
* A Data Table should always have a \`TableTopBar\`
|
|
257
|
+
* Use \`stickyHeader\` prop to make the header sticky
|
|
258
|
+
* Always assign a height to the table wrapper to make it scrollable
|
|
259
|
+
* Manage the Table's Wrapper height effectively when using \`TableActionBar\` component
|
|
260
|
+
* Always use local \`ButtonCta\` and \`DropdownCta\` for actions in Action bar. These components are
|
|
261
|
+
just CSS Wrappers for Button and SimpleButtonDropdown components
|
|
262
|
+
* Use ButtonCta component to add a button CTA in the \`TableActionBar\`
|
|
263
|
+
* Use DropdownCta component to add a dropdown CTA button in the \`TableActionBar\` for screen width less than size1280(1280px)
|
|
264
|
+
|
|
265
|
+
\`\`\`jsx
|
|
266
|
+
<Table
|
|
267
|
+
headers={TABLE_HEADERS}
|
|
268
|
+
entries={TABLE_DATA}
|
|
269
|
+
stickyHeader={true}
|
|
270
|
+
classNames={{
|
|
271
|
+
wrapper: classify(css.tableWrapper, {
|
|
272
|
+
[css.withActionBar]: getNumberOfEntriesSelected() > 0,
|
|
273
|
+
})
|
|
274
|
+
}}
|
|
275
|
+
/>
|
|
276
|
+
\`\`\`
|
|
277
|
+
|
|
278
|
+
\`\`\`css
|
|
279
|
+
.tableWrapper {
|
|
280
|
+
height: calc(sizeFullViewportHeight - size160);
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
.tableWrapper.withActionBar {
|
|
284
|
+
height: calc((sizeFullViewportHeight - size160) - actionBarHeight);
|
|
285
|
+
}
|
|
286
|
+
\`\`\`
|
|
287
|
+
|
|
288
|
+
### Usage
|
|
289
|
+
|
|
290
|
+
\`\`\`jsx
|
|
291
|
+
const TABLE_HEADERS = [
|
|
292
|
+
{ label: "Name", key: "name", sortable: true, className: css.mediumColumn },
|
|
293
|
+
{ label: "Tel", key: "phone", sortable: true, className: css.mediumColumn },
|
|
294
|
+
];
|
|
295
|
+
|
|
296
|
+
const TABLE_DATA = [
|
|
297
|
+
{
|
|
298
|
+
id: "1",
|
|
299
|
+
name: "Alice",
|
|
300
|
+
phone: "123-456-7890",
|
|
301
|
+
},
|
|
302
|
+
{
|
|
303
|
+
id: "2",
|
|
304
|
+
name: "Bob",
|
|
305
|
+
phone: "987-654-3210",
|
|
306
|
+
},
|
|
307
|
+
];
|
|
308
|
+
|
|
309
|
+
export const _TableExample = (): React.Node => {
|
|
310
|
+
return (
|
|
311
|
+
<div className={css.container}>
|
|
312
|
+
{/* Top Bar with Filters */}
|
|
313
|
+
<TableTopBar>
|
|
314
|
+
<div className={css.left}>
|
|
315
|
+
<SubTitleMedium className={css.title}>Basic Data Table</SubTitleMedium>
|
|
316
|
+
<SearchInput />
|
|
317
|
+
</div>
|
|
318
|
+
</TableTopBar>
|
|
319
|
+
|
|
320
|
+
{/* Table */}
|
|
321
|
+
<Table
|
|
322
|
+
headers={TABLE_HEADERS}
|
|
323
|
+
entries={TABLE_DATA}
|
|
324
|
+
isLoading={isLoading}
|
|
325
|
+
stickyHeader={true}
|
|
326
|
+
borderRadius={'0'}
|
|
327
|
+
selectedKeys={staticTableKeysAcrossPages[currPage] || []}
|
|
328
|
+
onSelect={(keys) => {
|
|
329
|
+
setSelectAllEntries(false);
|
|
330
|
+
setStaticTableKeysAcrossPages({
|
|
331
|
+
...staticTableKeysAcrossPages,
|
|
332
|
+
[currPage]: keys,
|
|
333
|
+
});
|
|
334
|
+
}}
|
|
335
|
+
classNames={{
|
|
336
|
+
wrapper: classify(css.tableWrapper, {
|
|
337
|
+
[css.withActionBar]: getNumberOfEntriesSelected() > 0,
|
|
338
|
+
})
|
|
339
|
+
}}
|
|
340
|
+
/>
|
|
341
|
+
|
|
342
|
+
{/* Table Actions */}
|
|
343
|
+
{getNumberOfEntriesSelected() > 0 && (
|
|
344
|
+
<TableActionBar className={css.actionBar}>
|
|
345
|
+
<div className={css.leftActionSlot}>
|
|
346
|
+
<ButtonCta
|
|
347
|
+
onClick={() => {
|
|
348
|
+
setSelectAllEntries(true);
|
|
349
|
+
setStaticTableKeysAcrossPages({
|
|
350
|
+
...staticTableKeysAcrossPages,
|
|
351
|
+
[currPage]: tableEntries.map((entry) => entry.id),
|
|
352
|
+
});
|
|
353
|
+
}}
|
|
354
|
+
>
|
|
355
|
+
Select all items
|
|
356
|
+
</ButtonCta>
|
|
357
|
+
{getNumberOfEntriesSelected() > 0 && (
|
|
358
|
+
<BodySmall color="inversePrimary">
|
|
359
|
+
{getNumberOfEntriesSelected() entries selected}
|
|
360
|
+
</BodySmall>
|
|
361
|
+
)}
|
|
362
|
+
</div>
|
|
363
|
+
<div className={classify(css.middleActionSlot, css.fullTable)}>
|
|
364
|
+
<ButtonCta size="small" iconLeftName="folder-plus">
|
|
365
|
+
Add to group
|
|
366
|
+
</ButtonCta>
|
|
367
|
+
</div>
|
|
368
|
+
<div className={classify(css.middleActionSlot, css.smallTable)}>
|
|
369
|
+
<ButtonCta size="small" iconLeftName="folder-plus">
|
|
370
|
+
Add to group
|
|
371
|
+
</ButtonCta>
|
|
372
|
+
<DropdownCta
|
|
373
|
+
ariaLabel="Icon Button Dropdown"
|
|
374
|
+
iconLeftName="ellipsis"
|
|
375
|
+
options={[
|
|
376
|
+
{
|
|
377
|
+
iconLeft: 'layer-plus',
|
|
378
|
+
key: '1',
|
|
379
|
+
label: 'Create group',
|
|
380
|
+
},
|
|
381
|
+
]}
|
|
382
|
+
selectedKeys={selectedKeys}
|
|
383
|
+
onOptionSelect={() => setSelectedKeys([])}
|
|
384
|
+
size="small"
|
|
385
|
+
/>
|
|
386
|
+
</div>
|
|
387
|
+
<div className={css.rightActionSlot}>
|
|
388
|
+
<ButtonCta
|
|
389
|
+
iconLeftName="close"
|
|
390
|
+
onClick={() => {
|
|
391
|
+
setSelectAllEntries(false);
|
|
392
|
+
setStaticTableKeysAcrossPages({});
|
|
393
|
+
}}
|
|
394
|
+
>
|
|
395
|
+
Close
|
|
396
|
+
</ButtonCta>
|
|
397
|
+
</div>
|
|
398
|
+
</TableActionBar>
|
|
399
|
+
)}
|
|
400
|
+
|
|
401
|
+
{/* Bottom Bar with Pagination */}
|
|
402
|
+
<TableBottomBar>
|
|
403
|
+
<Pagination
|
|
404
|
+
currentPage={currPage}
|
|
405
|
+
totalPages={totalPages}
|
|
406
|
+
onChange={(page) => {
|
|
407
|
+
onMove(page || 1);
|
|
408
|
+
}}
|
|
409
|
+
>
|
|
410
|
+
<SubTitleExtraSmall color="secondary">
|
|
411
|
+
Showing page {currPage} of {totalPages}
|
|
412
|
+
</SubTitleExtraSmall>
|
|
413
|
+
</Pagination>
|
|
414
|
+
</TableBottomBar>
|
|
415
|
+
</div>
|
|
416
|
+
);
|
|
417
|
+
};
|
|
418
|
+
\`\`\`
|
|
419
|
+
|
|
420
|
+
\`\`\`css
|
|
421
|
+
@value actionBarHeight: size50;
|
|
422
|
+
|
|
423
|
+
.container {
|
|
424
|
+
width: sizeFluid;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
.left {
|
|
428
|
+
display: flex;
|
|
429
|
+
align-items: center;
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
.title {
|
|
433
|
+
margin-right: spaceMedium;
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
.mediumColumn {
|
|
437
|
+
width: calc(sizeFluid / 5);
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
.tableWrapper {
|
|
441
|
+
height: calc(sizeFullViewportHeight - size160);
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
.actionBar {
|
|
445
|
+
display: flex;
|
|
446
|
+
align-items: center;
|
|
447
|
+
gap: spaceXSmall;
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
.tableWrapper.withActionBar {
|
|
451
|
+
height: calc((sizeFullViewportHeight - size160) - actionBarHeight);
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
.leftActionSlot,
|
|
455
|
+
.rightActionSlot,
|
|
456
|
+
.middleActionSlot {
|
|
457
|
+
display: flex;
|
|
458
|
+
gap: spaceSmall;
|
|
459
|
+
align-items: center;
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
.leftActionSlot,
|
|
463
|
+
.rightActionSlot {
|
|
464
|
+
width: calc(sizeFluid / 4);
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
.leftActionSlot {
|
|
468
|
+
justify-content: flex-start;
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
.middleActionSlot {
|
|
472
|
+
width: calc(sizeFluid / 2);
|
|
473
|
+
justify-content: center;
|
|
474
|
+
gap: spaceXXSmall;
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
.rightActionSlot {
|
|
478
|
+
justify-content: flex-end;
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
.smallTable {
|
|
482
|
+
display: none;
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
@media only screen and (max-width: size1280) {
|
|
486
|
+
.fullTable {
|
|
487
|
+
display: none;
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
.smallTable {
|
|
491
|
+
display: flex;
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
.dangerText {
|
|
496
|
+
color: colorTextDanger;
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
.dangerText:hover,
|
|
500
|
+
.dangerText:active,
|
|
501
|
+
.dangerText:focus {
|
|
502
|
+
color: colorTextDanger;
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
\`\`\`
|
|
506
|
+
`
|
|
507
|
+
}
|
|
508
|
+
},
|
|
509
|
+
storySource: {
|
|
510
|
+
componentPath: '/src/components/Table/Table.js'
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
};
|
|
514
|
+
exports.TABLE_DOCS = TABLE_DOCS;
|