@spaced-out/ui-design-system 0.3.42 → 0.3.43
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/.cspell/custom-words.txt +1 -0
- package/.github/workflows/pages.yml +1 -1
- package/.github/workflows/publish_to_npm.yml +2 -12
- package/.github/workflows/pull_request_checks.yml +1 -11
- package/.storybook/SenseTheme.js +1 -1
- package/.storybook/main.js +16 -40
- package/.storybook/manager.js +2 -3
- package/.storybook/preview.js +22 -1
- package/.vscode/settings.json +2 -1
- package/CHANGELOG.md +19 -0
- package/CONTRIBUTING.md +19 -0
- package/dts-generator/package.json +1 -1
- package/lib/components/EmptyState/EmptyImages/ChartEmptyImage.d.ts +2 -2
- package/lib/components/EmptyState/EmptyImages/ChartEmptyImage.js +2 -2
- package/lib/components/EmptyState/EmptyImages/ChartEmptyImage.js.flow +2 -2
- package/lib/components/FilterButtonOverlay/FilterButtonOverlay.d.ts +130 -0
- package/lib/components/FilterButtonOverlay/FilterButtonOverlay.js +90 -0
- package/lib/components/FilterButtonOverlay/FilterButtonOverlay.js.flow +135 -0
- package/lib/components/FilterButtonOverlay/FilterButtonOverlay.module.css +35 -0
- package/lib/components/FilterButtonOverlay/index.d.ts +1 -0
- package/lib/components/FilterButtonOverlay/index.js +16 -0
- package/lib/components/FilterButtonOverlay/index.js.flow +3 -0
- package/lib/components/Icon/ClickableIcon.d.ts +2 -1
- package/lib/components/Icon/ClickableIcon.js +3 -2
- package/lib/components/Icon/ClickableIcon.js.flow +2 -1
- package/lib/components/Icon/ClickableIcon.module.css +2 -2
- package/lib/components/Icon/Icon.docs.d.ts +15 -1
- package/lib/components/Icon/Icon.docs.js +15 -1
- package/lib/components/Icon/Icon.docs.js.flow +11 -1
- package/lib/components/InfinitePagination/InfinitePagination.d.ts +112 -0
- package/lib/components/InfinitePagination/InfinitePagination.js +84 -0
- package/lib/components/InfinitePagination/InfinitePagination.js.flow +122 -0
- package/lib/components/InfinitePagination/InfinitePagination.module.css +18 -0
- package/lib/components/InfinitePagination/index.d.ts +1 -0
- package/lib/components/InfinitePagination/index.js +16 -0
- package/lib/components/InfinitePagination/index.js.flow +3 -0
- package/lib/components/Table/Table.docs.d.ts +1 -1
- package/lib/components/Table/Table.docs.js +1 -1
- package/lib/components/Table/Table.docs.js.flow +1 -1
- package/lib/components/index.d.ts +2 -0
- package/lib/components/index.js +22 -0
- package/lib/components/index.js.flow +2 -0
- package/lib/hooks/index.d.ts +2 -0
- package/lib/hooks/index.js +22 -0
- package/lib/hooks/index.js.flow +2 -0
- package/lib/hooks/useInfiniteScroll/index.d.ts +1 -0
- package/lib/hooks/useInfiniteScroll/index.js +16 -0
- package/lib/hooks/useInfiniteScroll/index.js.flow +3 -0
- package/lib/hooks/useInfiniteScroll/useInfiniteScroll.d.ts +77 -0
- package/lib/hooks/useInfiniteScroll/useInfiniteScroll.js +58 -0
- package/lib/hooks/useInfiniteScroll/useInfiniteScroll.js.flow +82 -0
- package/lib/hooks/useResizeObserver/index.d.ts +1 -0
- package/lib/hooks/useResizeObserver/index.js +16 -0
- package/lib/hooks/useResizeObserver/index.js.flow +3 -0
- package/lib/hooks/useResizeObserver/useResizeObserver.d.ts +22 -0
- package/lib/hooks/useResizeObserver/useResizeObserver.js +30 -0
- package/lib/hooks/useResizeObserver/useResizeObserver.js.flow +28 -0
- package/package.json +9 -16
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
@value (colorBackgroundTertiary) from '../../styles/variables/_color.css';
|
|
2
|
+
@value (size160, sizeFluid, size300, size240) from '../../styles/variables/_size.css';
|
|
3
|
+
@value (borderRadiusMedium) from '../../styles/variables/_border.css';
|
|
4
|
+
@value (elevationMenu) from '../../styles/variables/_elevation.css';
|
|
5
|
+
|
|
6
|
+
.overlayWrapper {
|
|
7
|
+
position: relative;
|
|
8
|
+
composes: boxShadow2 from '../../styles/shadow.module.css';
|
|
9
|
+
composes: borderPrimary from '../../styles/border.module.css';
|
|
10
|
+
background-color: colorBackgroundTertiary;
|
|
11
|
+
display: flex;
|
|
12
|
+
flex-flow: column;
|
|
13
|
+
min-width: size160;
|
|
14
|
+
border-radius: borderRadiusMedium;
|
|
15
|
+
z-index: elevationMenu;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
.fluid {
|
|
19
|
+
width: sizeFluid;
|
|
20
|
+
min-width: size160;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.medium {
|
|
24
|
+
width: size300;
|
|
25
|
+
min-width: size300;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
.small {
|
|
29
|
+
width: size240;
|
|
30
|
+
min-width: size240;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.isFluid {
|
|
34
|
+
width: sizeFluid;
|
|
35
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './FilterButtonOverlay';
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
var _FilterButtonOverlay = require("./FilterButtonOverlay");
|
|
7
|
+
Object.keys(_FilterButtonOverlay).forEach(function (key) {
|
|
8
|
+
if (key === "default" || key === "__esModule") return;
|
|
9
|
+
if (key in exports && exports[key] === _FilterButtonOverlay[key]) return;
|
|
10
|
+
Object.defineProperty(exports, key, {
|
|
11
|
+
enumerable: true,
|
|
12
|
+
get: function () {
|
|
13
|
+
return _FilterButtonOverlay[key];
|
|
14
|
+
}
|
|
15
|
+
});
|
|
16
|
+
});
|
|
@@ -58,9 +58,10 @@ export const ClickableIcon: React$AbstractComponent<
|
|
|
58
58
|
ref={ref}
|
|
59
59
|
>
|
|
60
60
|
<Icon
|
|
61
|
+
{...props}
|
|
61
62
|
size={size}
|
|
63
|
+
color={disabled ? TEXT_COLORS.disabled : props.color}
|
|
62
64
|
className={classNames?.icon || className}
|
|
63
|
-
{...props}
|
|
64
65
|
/>
|
|
65
66
|
</UnstyledButton>
|
|
66
67
|
);
|
|
@@ -42,10 +42,11 @@ const ClickableIcon = /*#__PURE__*/React.forwardRef((_ref, ref) => {
|
|
|
42
42
|
[_ClickableIconModule.default.large]: size === 'large'
|
|
43
43
|
}, classNames?.button),
|
|
44
44
|
ref: ref
|
|
45
|
-
}), /*#__PURE__*/React.createElement(_.Icon, _extends({
|
|
45
|
+
}), /*#__PURE__*/React.createElement(_.Icon, _extends({}, props, {
|
|
46
46
|
size: size,
|
|
47
|
+
color: disabled ? _Text.TEXT_COLORS.disabled : props.color,
|
|
47
48
|
className: classNames?.icon || className
|
|
48
|
-
}
|
|
49
|
+
})));
|
|
49
50
|
});
|
|
50
51
|
exports.ClickableIcon = ClickableIcon;
|
|
51
52
|
const CloseIcon = /*#__PURE__*/React.forwardRef((_ref2, ref) => {
|
|
@@ -65,9 +65,10 @@ export const ClickableIcon: React$AbstractComponent<
|
|
|
65
65
|
ref={ref}
|
|
66
66
|
>
|
|
67
67
|
<Icon
|
|
68
|
+
{...props}
|
|
68
69
|
size={size}
|
|
70
|
+
color={disabled ? TEXT_COLORS.disabled : props.color}
|
|
69
71
|
className={classNames?.icon || className}
|
|
70
|
-
{...props}
|
|
71
72
|
/>
|
|
72
73
|
</UnstyledButton>
|
|
73
74
|
);
|
|
@@ -54,12 +54,12 @@ button {
|
|
|
54
54
|
border-radius: borderRadiusXSmall;
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
-
.button:focus {
|
|
57
|
+
.button:focus-visible:not(:disabled) {
|
|
58
58
|
box-shadow: borderWidthNone borderWidthNone borderWidthNone
|
|
59
59
|
borderWidthTertiary colorFocusPrimary;
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
-
.button:hover {
|
|
62
|
+
.button:hover:not(:disabled) {
|
|
63
63
|
background-color: colorButtonFillGhostPressed;
|
|
64
64
|
color: colorTextPrimary;
|
|
65
65
|
}
|
|
@@ -100,6 +100,20 @@ export const ICON_DOCS = {
|
|
|
100
100
|
},
|
|
101
101
|
},
|
|
102
102
|
},
|
|
103
|
+
disabled: {
|
|
104
|
+
description: 'If **true**, the clickable icon is disabled',
|
|
105
|
+
control: {
|
|
106
|
+
type: 'boolean',
|
|
107
|
+
},
|
|
108
|
+
table: {
|
|
109
|
+
type: {
|
|
110
|
+
summary: 'boolean',
|
|
111
|
+
},
|
|
112
|
+
defaultValue: {
|
|
113
|
+
summary: 'false',
|
|
114
|
+
},
|
|
115
|
+
},
|
|
116
|
+
},
|
|
103
117
|
ariaLabel: {
|
|
104
118
|
control: {
|
|
105
119
|
type: 'text',
|
|
@@ -114,8 +128,8 @@ export const ICON_DOCS = {
|
|
|
114
128
|
},
|
|
115
129
|
},
|
|
116
130
|
parameters: {
|
|
117
|
-
componentSubtitle: 'Generates a Icon component',
|
|
118
131
|
docs: {
|
|
132
|
+
subtitle: 'Generates a Icon component',
|
|
119
133
|
description: {
|
|
120
134
|
component: `
|
|
121
135
|
\`\`\`js
|
|
@@ -104,6 +104,20 @@ const ICON_DOCS = {
|
|
|
104
104
|
}
|
|
105
105
|
}
|
|
106
106
|
},
|
|
107
|
+
disabled: {
|
|
108
|
+
description: 'If **true**, the clickable icon is disabled',
|
|
109
|
+
control: {
|
|
110
|
+
type: 'boolean'
|
|
111
|
+
},
|
|
112
|
+
table: {
|
|
113
|
+
type: {
|
|
114
|
+
summary: 'boolean'
|
|
115
|
+
},
|
|
116
|
+
defaultValue: {
|
|
117
|
+
summary: 'false'
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
},
|
|
107
121
|
ariaLabel: {
|
|
108
122
|
control: {
|
|
109
123
|
type: 'text'
|
|
@@ -117,8 +131,8 @@ const ICON_DOCS = {
|
|
|
117
131
|
}
|
|
118
132
|
},
|
|
119
133
|
parameters: {
|
|
120
|
-
componentSubtitle: 'Generates a Icon component',
|
|
121
134
|
docs: {
|
|
135
|
+
subtitle: 'Generates a Icon component',
|
|
122
136
|
description: {
|
|
123
137
|
component: `
|
|
124
138
|
\`\`\`js
|
|
@@ -74,6 +74,16 @@ export const ICON_DOCS = {
|
|
|
74
74
|
type: {summary: '(SyntheticEvent<HTMLElement>) => mixed'},
|
|
75
75
|
},
|
|
76
76
|
},
|
|
77
|
+
disabled: {
|
|
78
|
+
description: 'If **true**, the clickable icon is disabled',
|
|
79
|
+
control: {
|
|
80
|
+
type: 'boolean',
|
|
81
|
+
},
|
|
82
|
+
table: {
|
|
83
|
+
type: {summary: 'boolean'},
|
|
84
|
+
defaultValue: {summary: 'false'},
|
|
85
|
+
},
|
|
86
|
+
},
|
|
77
87
|
ariaLabel: {
|
|
78
88
|
control: {
|
|
79
89
|
type: 'text',
|
|
@@ -86,8 +96,8 @@ export const ICON_DOCS = {
|
|
|
86
96
|
},
|
|
87
97
|
},
|
|
88
98
|
parameters: {
|
|
89
|
-
componentSubtitle: 'Generates a Icon component',
|
|
90
99
|
docs: {
|
|
100
|
+
subtitle: 'Generates a Icon component',
|
|
91
101
|
description: {
|
|
92
102
|
component: `
|
|
93
103
|
\`\`\`js
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import {$ReadOnly} from 'utility-types';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
// @ts-expect-error[nonstrict-import]
|
|
4
|
+
import {FixedSizeList, VariableSizeList} from 'react-window';
|
|
5
|
+
import {useInfiniteScroll, useResizeObserver} from '../../hooks';
|
|
6
|
+
import {spaceFluid} from '../../styles/variables/_space';
|
|
7
|
+
import classify from '../../utils/classify';
|
|
8
|
+
import {CircularLoader} from '../CircularLoader';
|
|
9
|
+
import type {GenericObject} from '../Table';
|
|
10
|
+
import css from './InfinitePagination.module.css';
|
|
11
|
+
type ClassNames = $ReadOnly<{
|
|
12
|
+
wrapper?: string;
|
|
13
|
+
}>;
|
|
14
|
+
const DEFAULT_THRESHOLD = 200;
|
|
15
|
+
export type InfinitePaginationProps = (
|
|
16
|
+
| {
|
|
17
|
+
itemSize: (index: number) => number;
|
|
18
|
+
isVariableSizeList: true;
|
|
19
|
+
}
|
|
20
|
+
| {
|
|
21
|
+
itemSize: number;
|
|
22
|
+
isVariableSizeList?: false;
|
|
23
|
+
}
|
|
24
|
+
) & {
|
|
25
|
+
items: Array<GenericObject>;
|
|
26
|
+
width: string;
|
|
27
|
+
threshold?: number;
|
|
28
|
+
classNames?: ClassNames;
|
|
29
|
+
renderItem: (item: GenericObject, index: number) => React.ReactNode;
|
|
30
|
+
getItemKey?: (item: GenericObject, index: number) => string | number;
|
|
31
|
+
hasNextPage: boolean;
|
|
32
|
+
loadMoreItems: () => Promise<void>;
|
|
33
|
+
};
|
|
34
|
+
export const InfinitePagination: React$AbstractComponent<
|
|
35
|
+
InfinitePaginationProps,
|
|
36
|
+
HTMLDivElement
|
|
37
|
+
> = React.forwardRef<InfinitePaginationProps, HTMLDivElement>(
|
|
38
|
+
(props: InfinitePaginationProps, ref) => {
|
|
39
|
+
const {
|
|
40
|
+
items,
|
|
41
|
+
width = spaceFluid,
|
|
42
|
+
itemSize,
|
|
43
|
+
renderItem,
|
|
44
|
+
threshold = DEFAULT_THRESHOLD,
|
|
45
|
+
getItemKey,
|
|
46
|
+
classNames,
|
|
47
|
+
hasNextPage,
|
|
48
|
+
loadMoreItems,
|
|
49
|
+
isVariableSizeList,
|
|
50
|
+
} = props;
|
|
51
|
+
const listRef = React.useRef(null);
|
|
52
|
+
const itemsLength = items.length;
|
|
53
|
+
const totalItemsCount = itemsLength + (hasNextPage ? 1 : 0);
|
|
54
|
+
const [containerRef, containerHeight] = useResizeObserver();
|
|
55
|
+
React.useImperativeHandle(ref, () => listRef.current);
|
|
56
|
+
React.useEffect(() => {
|
|
57
|
+
if (listRef.current) {
|
|
58
|
+
listRef.current.scrollToItem(0);
|
|
59
|
+
}
|
|
60
|
+
}, [itemsLength === 0]);
|
|
61
|
+
const handleScroll = useInfiniteScroll({
|
|
62
|
+
itemSize,
|
|
63
|
+
threshold,
|
|
64
|
+
itemsLength,
|
|
65
|
+
hasNextPage,
|
|
66
|
+
loadMoreItems,
|
|
67
|
+
containerHeight,
|
|
68
|
+
isVariableSizeList,
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
const Row = ({index, style}) =>
|
|
72
|
+
index === itemsLength ? (
|
|
73
|
+
<div style={style} className={css.loader}>
|
|
74
|
+
<CircularLoader size="large" />
|
|
75
|
+
</div>
|
|
76
|
+
) : (
|
|
77
|
+
<div style={style} className={css.listRow}>
|
|
78
|
+
{renderItem(items[index], index)}
|
|
79
|
+
</div>
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
const itemKey = React.useCallback(
|
|
83
|
+
(index) =>
|
|
84
|
+
index === itemsLength
|
|
85
|
+
? 'loading-indicator'
|
|
86
|
+
: getItemKey
|
|
87
|
+
? getItemKey(items[index], index)
|
|
88
|
+
: index,
|
|
89
|
+
[items, getItemKey],
|
|
90
|
+
);
|
|
91
|
+
const ListComponent = isVariableSizeList ? VariableSizeList : FixedSizeList;
|
|
92
|
+
return (
|
|
93
|
+
<div
|
|
94
|
+
ref={containerRef}
|
|
95
|
+
data-testid="InfinitePagination"
|
|
96
|
+
className={classify(css.wrapper, classNames?.wrapper)}
|
|
97
|
+
>
|
|
98
|
+
<ListComponent
|
|
99
|
+
ref={listRef}
|
|
100
|
+
width={width}
|
|
101
|
+
height={containerHeight}
|
|
102
|
+
itemKey={itemKey}
|
|
103
|
+
itemSize={itemSize}
|
|
104
|
+
onScroll={handleScroll}
|
|
105
|
+
itemCount={totalItemsCount}
|
|
106
|
+
>
|
|
107
|
+
{Row}
|
|
108
|
+
</ListComponent>
|
|
109
|
+
</div>
|
|
110
|
+
);
|
|
111
|
+
},
|
|
112
|
+
);
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.InfinitePagination = void 0;
|
|
7
|
+
var React = _interopRequireWildcard(require("react"));
|
|
8
|
+
var _reactWindow = require("react-window");
|
|
9
|
+
var _hooks = require("../../hooks");
|
|
10
|
+
var _space = require("../../styles/variables/_space");
|
|
11
|
+
var _classify = _interopRequireDefault(require("../../utils/classify"));
|
|
12
|
+
var _CircularLoader = require("../CircularLoader");
|
|
13
|
+
var _InfinitePaginationModule = _interopRequireDefault(require("./InfinitePagination.module.css"));
|
|
14
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
15
|
+
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
|
|
16
|
+
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
|
17
|
+
|
|
18
|
+
// $FlowFixMe[nonstrict-import]
|
|
19
|
+
|
|
20
|
+
const DEFAULT_THRESHOLD = 200;
|
|
21
|
+
const InfinitePagination = /*#__PURE__*/React.forwardRef((props, ref) => {
|
|
22
|
+
const {
|
|
23
|
+
items,
|
|
24
|
+
width = _space.spaceFluid,
|
|
25
|
+
itemSize,
|
|
26
|
+
renderItem,
|
|
27
|
+
threshold = DEFAULT_THRESHOLD,
|
|
28
|
+
getItemKey,
|
|
29
|
+
classNames,
|
|
30
|
+
hasNextPage,
|
|
31
|
+
loadMoreItems,
|
|
32
|
+
isVariableSizeList
|
|
33
|
+
} = props;
|
|
34
|
+
const listRef = React.useRef(null);
|
|
35
|
+
const itemsLength = items.length;
|
|
36
|
+
const totalItemsCount = itemsLength + (hasNextPage ? 1 : 0);
|
|
37
|
+
const [containerRef, containerHeight] = (0, _hooks.useResizeObserver)();
|
|
38
|
+
React.useImperativeHandle(ref, () => listRef.current);
|
|
39
|
+
React.useEffect(() => {
|
|
40
|
+
if (listRef.current) {
|
|
41
|
+
listRef.current.scrollToItem(0);
|
|
42
|
+
}
|
|
43
|
+
}, [itemsLength === 0]);
|
|
44
|
+
const handleScroll = (0, _hooks.useInfiniteScroll)({
|
|
45
|
+
itemSize,
|
|
46
|
+
threshold,
|
|
47
|
+
itemsLength,
|
|
48
|
+
hasNextPage,
|
|
49
|
+
loadMoreItems,
|
|
50
|
+
containerHeight,
|
|
51
|
+
isVariableSizeList
|
|
52
|
+
});
|
|
53
|
+
const Row = _ref => {
|
|
54
|
+
let {
|
|
55
|
+
index,
|
|
56
|
+
style
|
|
57
|
+
} = _ref;
|
|
58
|
+
return index === itemsLength ? /*#__PURE__*/React.createElement("div", {
|
|
59
|
+
style: style,
|
|
60
|
+
className: _InfinitePaginationModule.default.loader
|
|
61
|
+
}, /*#__PURE__*/React.createElement(_CircularLoader.CircularLoader, {
|
|
62
|
+
size: "large"
|
|
63
|
+
})) : /*#__PURE__*/React.createElement("div", {
|
|
64
|
+
style: style,
|
|
65
|
+
className: _InfinitePaginationModule.default.listRow
|
|
66
|
+
}, renderItem(items[index], index));
|
|
67
|
+
};
|
|
68
|
+
const itemKey = React.useCallback(index => index === itemsLength ? 'loading-indicator' : getItemKey ? getItemKey(items[index], index) : index, [items, getItemKey]);
|
|
69
|
+
const ListComponent = isVariableSizeList ? _reactWindow.VariableSizeList : _reactWindow.FixedSizeList;
|
|
70
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
71
|
+
ref: containerRef,
|
|
72
|
+
"data-testid": "InfinitePagination",
|
|
73
|
+
className: (0, _classify.default)(_InfinitePaginationModule.default.wrapper, classNames?.wrapper)
|
|
74
|
+
}, /*#__PURE__*/React.createElement(ListComponent, {
|
|
75
|
+
ref: listRef,
|
|
76
|
+
width: width,
|
|
77
|
+
height: containerHeight,
|
|
78
|
+
itemKey: itemKey,
|
|
79
|
+
itemSize: itemSize,
|
|
80
|
+
onScroll: handleScroll,
|
|
81
|
+
itemCount: totalItemsCount
|
|
82
|
+
}, Row));
|
|
83
|
+
});
|
|
84
|
+
exports.InfinitePagination = InfinitePagination;
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
// @flow strict
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
// $FlowFixMe[nonstrict-import]
|
|
4
|
+
import {FixedSizeList, VariableSizeList} from 'react-window';
|
|
5
|
+
|
|
6
|
+
import {useInfiniteScroll, useResizeObserver} from '../../hooks';
|
|
7
|
+
import {spaceFluid} from '../../styles/variables/_space';
|
|
8
|
+
import classify from '../../utils/classify';
|
|
9
|
+
import {CircularLoader} from '../CircularLoader';
|
|
10
|
+
import type {GenericObject} from '../Table';
|
|
11
|
+
|
|
12
|
+
import css from './InfinitePagination.module.css';
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
type ClassNames = $ReadOnly<{wrapper?: string}>;
|
|
16
|
+
|
|
17
|
+
const DEFAULT_THRESHOLD = 200;
|
|
18
|
+
|
|
19
|
+
export type InfinitePaginationProps = {
|
|
20
|
+
items: Array<GenericObject>,
|
|
21
|
+
width: string,
|
|
22
|
+
threshold?: number,
|
|
23
|
+
classNames?: ClassNames,
|
|
24
|
+
renderItem: (item: GenericObject, index: number) => React.Node,
|
|
25
|
+
getItemKey?: (item: GenericObject, index: number) => string | number,
|
|
26
|
+
hasNextPage: boolean,
|
|
27
|
+
loadMoreItems: () => Promise<void>,
|
|
28
|
+
// to make Flow happy with the disjoint union isVariableSizeList is a mandatory prop
|
|
29
|
+
...
|
|
30
|
+
| {
|
|
31
|
+
itemSize: (index: number) => number,
|
|
32
|
+
isVariableSizeList: true,
|
|
33
|
+
}
|
|
34
|
+
| {
|
|
35
|
+
itemSize: number,
|
|
36
|
+
isVariableSizeList?: false,
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export const InfinitePagination: React$AbstractComponent<
|
|
41
|
+
InfinitePaginationProps,
|
|
42
|
+
HTMLDivElement,
|
|
43
|
+
> = React.forwardRef<InfinitePaginationProps, HTMLDivElement>(
|
|
44
|
+
(props: InfinitePaginationProps, ref) => {
|
|
45
|
+
const {
|
|
46
|
+
items,
|
|
47
|
+
width = spaceFluid,
|
|
48
|
+
itemSize,
|
|
49
|
+
renderItem,
|
|
50
|
+
threshold = DEFAULT_THRESHOLD,
|
|
51
|
+
getItemKey,
|
|
52
|
+
classNames,
|
|
53
|
+
hasNextPage,
|
|
54
|
+
loadMoreItems,
|
|
55
|
+
isVariableSizeList,
|
|
56
|
+
} = props;
|
|
57
|
+
const listRef = React.useRef(null);
|
|
58
|
+
const itemsLength = items.length;
|
|
59
|
+
const totalItemsCount = itemsLength + (hasNextPage ? 1 : 0);
|
|
60
|
+
const [containerRef, containerHeight] = useResizeObserver();
|
|
61
|
+
|
|
62
|
+
React.useImperativeHandle(ref, () => listRef.current);
|
|
63
|
+
React.useEffect(() => {
|
|
64
|
+
if (listRef.current) {
|
|
65
|
+
listRef.current.scrollToItem(0);
|
|
66
|
+
}
|
|
67
|
+
}, [itemsLength === 0]);
|
|
68
|
+
|
|
69
|
+
const handleScroll = useInfiniteScroll({
|
|
70
|
+
itemSize,
|
|
71
|
+
threshold,
|
|
72
|
+
itemsLength,
|
|
73
|
+
hasNextPage,
|
|
74
|
+
loadMoreItems,
|
|
75
|
+
containerHeight,
|
|
76
|
+
isVariableSizeList,
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
const Row = ({index, style}) =>
|
|
80
|
+
index === itemsLength ? (
|
|
81
|
+
<div style={style} className={css.loader}>
|
|
82
|
+
<CircularLoader size="large" />
|
|
83
|
+
</div>
|
|
84
|
+
) : (
|
|
85
|
+
<div style={style} className={css.listRow}>
|
|
86
|
+
{renderItem(items[index], index)}
|
|
87
|
+
</div>
|
|
88
|
+
);
|
|
89
|
+
|
|
90
|
+
const itemKey = React.useCallback(
|
|
91
|
+
(index) =>
|
|
92
|
+
index === itemsLength
|
|
93
|
+
? 'loading-indicator'
|
|
94
|
+
: getItemKey
|
|
95
|
+
? getItemKey(items[index], index)
|
|
96
|
+
: index,
|
|
97
|
+
[items, getItemKey],
|
|
98
|
+
);
|
|
99
|
+
|
|
100
|
+
const ListComponent = isVariableSizeList ? VariableSizeList : FixedSizeList;
|
|
101
|
+
|
|
102
|
+
return (
|
|
103
|
+
<div
|
|
104
|
+
ref={containerRef}
|
|
105
|
+
data-testid="InfinitePagination"
|
|
106
|
+
className={classify(css.wrapper, classNames?.wrapper)}
|
|
107
|
+
>
|
|
108
|
+
<ListComponent
|
|
109
|
+
ref={listRef}
|
|
110
|
+
width={width}
|
|
111
|
+
height={containerHeight}
|
|
112
|
+
itemKey={itemKey}
|
|
113
|
+
itemSize={itemSize}
|
|
114
|
+
onScroll={handleScroll}
|
|
115
|
+
itemCount={totalItemsCount}
|
|
116
|
+
>
|
|
117
|
+
{Row}
|
|
118
|
+
</ListComponent>
|
|
119
|
+
</div>
|
|
120
|
+
);
|
|
121
|
+
},
|
|
122
|
+
);
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
@value (
|
|
2
|
+
spaceFluid
|
|
3
|
+
) from '../../styles/variables/_space.css';
|
|
4
|
+
|
|
5
|
+
.wrapper {
|
|
6
|
+
display: flex;
|
|
7
|
+
height: spaceFluid;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
.loader {
|
|
11
|
+
display: flex;
|
|
12
|
+
align-items: center;
|
|
13
|
+
justify-content: center;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
.listRow {
|
|
17
|
+
box-sizing: border-box;
|
|
18
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './InfinitePagination';
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
var _InfinitePagination = require("./InfinitePagination");
|
|
7
|
+
Object.keys(_InfinitePagination).forEach(function (key) {
|
|
8
|
+
if (key === "default" || key === "__esModule") return;
|
|
9
|
+
if (key in exports && exports[key] === _InfinitePagination[key]) return;
|
|
10
|
+
Object.defineProperty(exports, key, {
|
|
11
|
+
enumerable: true,
|
|
12
|
+
get: function () {
|
|
13
|
+
return _InfinitePagination[key];
|
|
14
|
+
}
|
|
15
|
+
});
|
|
16
|
+
});
|
|
@@ -22,12 +22,14 @@ export * from './Dropdown';
|
|
|
22
22
|
export * from './EmptyState';
|
|
23
23
|
export * from './ErrorMessage';
|
|
24
24
|
export * from './FileUpload';
|
|
25
|
+
export * from './FilterButtonOverlay';
|
|
25
26
|
export * from './FocusManager';
|
|
26
27
|
export * from './FocusManagerWithArrowKeyNavigation';
|
|
27
28
|
export * from './FormTitleWrapper';
|
|
28
29
|
export * from './Grid';
|
|
29
30
|
export * from './Icon';
|
|
30
31
|
export * from './InContextAlert';
|
|
32
|
+
export * from './InfinitePagination';
|
|
31
33
|
export * from './InlineDropdown';
|
|
32
34
|
export * from './Input';
|
|
33
35
|
export * from './KPIBox';
|
package/lib/components/index.js
CHANGED
|
@@ -267,6 +267,17 @@ Object.keys(_FileUpload).forEach(function (key) {
|
|
|
267
267
|
}
|
|
268
268
|
});
|
|
269
269
|
});
|
|
270
|
+
var _FilterButtonOverlay = require("./FilterButtonOverlay");
|
|
271
|
+
Object.keys(_FilterButtonOverlay).forEach(function (key) {
|
|
272
|
+
if (key === "default" || key === "__esModule") return;
|
|
273
|
+
if (key in exports && exports[key] === _FilterButtonOverlay[key]) return;
|
|
274
|
+
Object.defineProperty(exports, key, {
|
|
275
|
+
enumerable: true,
|
|
276
|
+
get: function () {
|
|
277
|
+
return _FilterButtonOverlay[key];
|
|
278
|
+
}
|
|
279
|
+
});
|
|
280
|
+
});
|
|
270
281
|
var _FocusManager = require("./FocusManager");
|
|
271
282
|
Object.keys(_FocusManager).forEach(function (key) {
|
|
272
283
|
if (key === "default" || key === "__esModule") return;
|
|
@@ -333,6 +344,17 @@ Object.keys(_InContextAlert).forEach(function (key) {
|
|
|
333
344
|
}
|
|
334
345
|
});
|
|
335
346
|
});
|
|
347
|
+
var _InfinitePagination = require("./InfinitePagination");
|
|
348
|
+
Object.keys(_InfinitePagination).forEach(function (key) {
|
|
349
|
+
if (key === "default" || key === "__esModule") return;
|
|
350
|
+
if (key in exports && exports[key] === _InfinitePagination[key]) return;
|
|
351
|
+
Object.defineProperty(exports, key, {
|
|
352
|
+
enumerable: true,
|
|
353
|
+
get: function () {
|
|
354
|
+
return _InfinitePagination[key];
|
|
355
|
+
}
|
|
356
|
+
});
|
|
357
|
+
});
|
|
336
358
|
var _InlineDropdown = require("./InlineDropdown");
|
|
337
359
|
Object.keys(_InlineDropdown).forEach(function (key) {
|
|
338
360
|
if (key === "default" || key === "__esModule") return;
|
|
@@ -24,12 +24,14 @@ export * from './Dropdown';
|
|
|
24
24
|
export * from './EmptyState';
|
|
25
25
|
export * from './ErrorMessage';
|
|
26
26
|
export * from './FileUpload';
|
|
27
|
+
export * from './FilterButtonOverlay';
|
|
27
28
|
export * from './FocusManager';
|
|
28
29
|
export * from './FocusManagerWithArrowKeyNavigation';
|
|
29
30
|
export * from './FormTitleWrapper';
|
|
30
31
|
export * from './Grid';
|
|
31
32
|
export * from './Icon';
|
|
32
33
|
export * from './InContextAlert';
|
|
34
|
+
export * from './InfinitePagination';
|
|
33
35
|
export * from './InlineDropdown';
|
|
34
36
|
export * from './Input';
|
|
35
37
|
export * from './KPIBox';
|