superdesk-ui-framework 3.0.13 → 3.0.15

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 (164) hide show
  1. package/.mocharc.json +5 -0
  2. package/app-typescript/components/Dropdown.tsx +11 -7
  3. package/app-typescript/components/ResizablePanels.tsx +98 -0
  4. package/app-typescript/components/Tooltip.tsx +11 -5
  5. package/app-typescript/components/WithPagination.tsx +231 -0
  6. package/app-typescript/components/with-pagination.spec.tsx +146 -0
  7. package/app-typescript/index.ts +2 -0
  8. package/dist/examples.bundle.js +4475 -1729
  9. package/dist/react/Index.tsx +11 -0
  10. package/dist/react/ResizablePanels.tsx +49 -0
  11. package/dist/react/WithPaginationDocs.tsx +57 -0
  12. package/dist/superdesk-ui.bundle.js +3403 -1170
  13. package/dist/vendor.bundle.js +20 -20
  14. package/examples/pages/react/Index.tsx +11 -0
  15. package/examples/pages/react/ResizablePanels.tsx +49 -0
  16. package/examples/pages/react/WithPaginationDocs.tsx +57 -0
  17. package/mocha-setup.ts +5 -0
  18. package/package.json +16 -3
  19. package/react/components/Alert.js +5 -1
  20. package/react/components/Autocomplete.js +7 -2
  21. package/react/components/Avatar.js +5 -1
  22. package/react/components/Badge.js +5 -1
  23. package/react/components/Button.js +5 -1
  24. package/react/components/ButtonGroup.js +5 -1
  25. package/react/components/Carousel.js +5 -1
  26. package/react/components/CheckButtonGroup.js +5 -1
  27. package/react/components/CheckGroup.js +5 -1
  28. package/react/components/Checkbox.js +5 -1
  29. package/react/components/CheckboxButton.js +5 -1
  30. package/react/components/ContentDivider.js +5 -1
  31. package/react/components/CreateButton.js +5 -1
  32. package/react/components/DatePicker.d.ts +1 -1
  33. package/react/components/DatePicker.js +7 -2
  34. package/react/components/Divider.js +5 -1
  35. package/react/components/DonutChart.js +5 -1
  36. package/react/components/DropZone.js +5 -1
  37. package/react/components/Dropdown.js +15 -8
  38. package/react/components/DropdownFirst.js +5 -1
  39. package/react/components/DurationInput.js +5 -1
  40. package/react/components/EmptyState.js +5 -1
  41. package/react/components/Form/FormGroup.js +5 -1
  42. package/react/components/Form/FormItem.js +5 -1
  43. package/react/components/Form/FormLabel.js +5 -1
  44. package/react/components/Form/FormRow.js +5 -1
  45. package/react/components/Form/FormRowNew.js +5 -1
  46. package/react/components/Form/FormText.js +5 -1
  47. package/react/components/Form/InputBase.d.ts +1 -1
  48. package/react/components/Form/InputBase.js +7 -2
  49. package/react/components/Form/InputNew.d.ts +1 -1
  50. package/react/components/Form/InputNew.js +7 -2
  51. package/react/components/Form/InputWrapper.js +7 -2
  52. package/react/components/FormLabel.js +5 -1
  53. package/react/components/GridItem.js +5 -1
  54. package/react/components/GridList.js +5 -1
  55. package/react/components/HeadingText.js +5 -1
  56. package/react/components/HelloWorld.js +5 -1
  57. package/react/components/Icon.js +5 -1
  58. package/react/components/IconButton.js +5 -1
  59. package/react/components/IconLabel.js +5 -1
  60. package/react/components/IconPicker.js +5 -1
  61. package/react/components/Input.d.ts +1 -1
  62. package/react/components/Input.js +7 -2
  63. package/react/components/Label.js +5 -1
  64. package/react/components/Layouts/AuthorinInnerSideBar.js +5 -1
  65. package/react/components/Layouts/AuthoringContainer.js +5 -1
  66. package/react/components/Layouts/AuthoringFrame.js +5 -1
  67. package/react/components/Layouts/AuthoringFrameContainer.js +5 -1
  68. package/react/components/Layouts/AuthoringFrameLeftBar.js +5 -1
  69. package/react/components/Layouts/AuthoringFrameMain.js +5 -1
  70. package/react/components/Layouts/AuthoringFrameNavBar.js +5 -1
  71. package/react/components/Layouts/AuthoringFrameOverlay.js +5 -1
  72. package/react/components/Layouts/AuthoringFrameRightBar.js +5 -1
  73. package/react/components/Layouts/AuthoringFrameSidePanel.js +5 -1
  74. package/react/components/Layouts/AuthoringFrameSidePanelOverlay.js +5 -1
  75. package/react/components/Layouts/AuthoringInnerBody.js +5 -1
  76. package/react/components/Layouts/AuthoringInnerHeader.js +5 -1
  77. package/react/components/Layouts/AuthoringMain.js +5 -1
  78. package/react/components/Layouts/AuthoringMainContainer.js +5 -1
  79. package/react/components/Layouts/AuthoringMainContent.js +5 -1
  80. package/react/components/Layouts/AuthoringMainToolBar.js +5 -1
  81. package/react/components/Layouts/BottomBarAction.js +5 -1
  82. package/react/components/Layouts/Container.js +5 -1
  83. package/react/components/Layouts/ContentSplitter.js +5 -1
  84. package/react/components/Layouts/CoreLayout.js +5 -1
  85. package/react/components/Layouts/CoreLayoutContainer.js +5 -1
  86. package/react/components/Layouts/CoreLayoutFooter.js +5 -1
  87. package/react/components/Layouts/CoreLayoutMain.js +5 -1
  88. package/react/components/Layouts/CoreLayoutOverlay.js +5 -1
  89. package/react/components/Layouts/CoreLayoutSlideInMenu.js +5 -1
  90. package/react/components/Layouts/CoreLayoutTopMenu.js +5 -1
  91. package/react/components/Layouts/HamburgerButton.js +5 -1
  92. package/react/components/Layouts/HeaderPanel.js +5 -1
  93. package/react/components/Layouts/Layout.js +5 -1
  94. package/react/components/Layouts/LayoutContainer.js +5 -1
  95. package/react/components/Layouts/LeftPanel.js +5 -1
  96. package/react/components/Layouts/MainMenu.js +5 -1
  97. package/react/components/Layouts/MainPanel.js +5 -1
  98. package/react/components/Layouts/NotificationPanel.js +5 -1
  99. package/react/components/Layouts/OverlayPanel.js +5 -1
  100. package/react/components/Layouts/PageLayout.js +5 -1
  101. package/react/components/Layouts/Panel.js +5 -1
  102. package/react/components/Layouts/RightPanel.js +5 -1
  103. package/react/components/LeftMenu.js +5 -1
  104. package/react/components/ListItemLoader.js +5 -1
  105. package/react/components/Lists/BoxedList.js +5 -1
  106. package/react/components/Lists/ContentList.js +5 -1
  107. package/react/components/Lists/SimpleList.js +5 -1
  108. package/react/components/Lists/TableList.js +5 -1
  109. package/react/components/Loader.js +5 -1
  110. package/react/components/Menu.d.ts +2 -2
  111. package/react/components/Menu.js +5 -1
  112. package/react/components/Modal.js +5 -1
  113. package/react/components/MultiSelect.js +5 -1
  114. package/react/components/NavButton.js +5 -1
  115. package/react/components/Navigation/BottomNav.js +5 -1
  116. package/react/components/Navigation/QuickNavBar.js +5 -1
  117. package/react/components/Navigation/SideBarMenu.js +5 -1
  118. package/react/components/Navigation/SideBarTabs.js +5 -1
  119. package/react/components/Popover.js +5 -1
  120. package/react/components/PropsList.js +5 -1
  121. package/react/components/RadioButtonGroup.js +5 -1
  122. package/react/components/RadioGroup.js +5 -1
  123. package/react/components/ResizablePanels.d.ts +34 -0
  124. package/react/components/ResizablePanels.js +101 -0
  125. package/react/components/SearchBar.js +5 -1
  126. package/react/components/Select.js +7 -2
  127. package/react/components/SelectGrid.d.ts +1 -1
  128. package/react/components/SelectGrid.js +5 -1
  129. package/react/components/SelectWithTemplate.js +5 -1
  130. package/react/components/Skeleton.js +5 -1
  131. package/react/components/SlidingToolbar.js +5 -1
  132. package/react/components/Spinner.js +5 -1
  133. package/react/components/StrechBar.js +5 -1
  134. package/react/components/SubNav.js +5 -1
  135. package/react/components/Switch.js +5 -1
  136. package/react/components/SwitchGroup.js +5 -1
  137. package/react/components/TabCustom.js +5 -1
  138. package/react/components/TabList.js +5 -1
  139. package/react/components/Tag.js +5 -1
  140. package/react/components/TagInput.js +5 -1
  141. package/react/components/Text/Heading.js +5 -1
  142. package/react/components/Text/Text.js +5 -1
  143. package/react/components/Text/Time.js +5 -1
  144. package/react/components/ThemeSelector.js +5 -1
  145. package/react/components/TimePicker.js +5 -1
  146. package/react/components/Toast.js +5 -1
  147. package/react/components/ToastMessage.d.ts +3 -3
  148. package/react/components/ToastMessage.js +5 -1
  149. package/react/components/ToastText.js +5 -1
  150. package/react/components/ToastWrapper.d.ts +1 -1
  151. package/react/components/ToastWrapper.js +5 -1
  152. package/react/components/Togglebox.js +7 -2
  153. package/react/components/Tooltip.js +13 -6
  154. package/react/components/TreeSelect.d.ts +2 -2
  155. package/react/components/TreeSelect.js +5 -1
  156. package/react/components/WithPagination.d.ts +26 -0
  157. package/react/components/WithPagination.js +191 -0
  158. package/react/components/WithSizeObserver.js +5 -1
  159. package/react/components/_Positioner.d.ts +1 -1
  160. package/react/components/_Positioner.js +5 -1
  161. package/react/index.d.ts +2 -0
  162. package/react/index.js +12 -3
  163. package/tsconfig.json +1 -1
  164. package/spec/scenarios.js +0 -13
package/.mocharc.json ADDED
@@ -0,0 +1,5 @@
1
+ {
2
+ "extension": ["ts", ".tsx"],
3
+ "spec": "app-typescript/components/*.spec.*",
4
+ "require": ["ts-node/register", "./mocha-setup.ts"]
5
+ }
@@ -257,13 +257,17 @@ export const Dropdown = ({
257
257
  {typeof children === 'object' ?
258
258
  (React.isValidElement(children) ?
259
259
  <div ref={buttonRef} style={{ display: 'content' }}>
260
- {React.cloneElement(children, {
261
- className: children.props.className ? (children.props.className + ' dropdown__toggle dropdown-toggle') : 'dropdown__toggle dropdown-toggle',
262
- 'aria-haspopup': "menu",
263
- 'aria-expanded': open,
264
- onClick: toggleDisplay,
265
- ref: buttonRef,
266
- })}
260
+ {(() => {
261
+ const attrs = {
262
+ className: children.props.className ? (children.props.className + ' dropdown__toggle dropdown-toggle') : 'dropdown__toggle dropdown-toggle',
263
+ 'aria-haspopup': "menu",
264
+ 'aria-expanded': open,
265
+ onClick: toggleDisplay,
266
+ ref: buttonRef,
267
+ };
268
+
269
+ return React.cloneElement(children, attrs);
270
+ })()}
267
271
  </div> : null)
268
272
  :
269
273
  <button ref={buttonRef}
@@ -0,0 +1,98 @@
1
+ import * as React from 'react';
2
+ import {ImperativePanelHandle, Panel, PanelGroup, PanelResizeHandle} from '@superdesk/react-resizable-panels';
3
+
4
+ interface IPanelSize {
5
+ min?: number; // percent
6
+ max?: number; // percent
7
+ default?: number; // percent
8
+ }
9
+
10
+ interface IProps {
11
+ /**
12
+ * component will set primary dimension(width when horizontal, height when vertical) to 100%
13
+ * parent component has to support this
14
+ */
15
+ direction: 'horizontal' | 'vertical';
16
+
17
+ primarySize?: IPanelSize;
18
+ secondarySize?: IPanelSize;
19
+
20
+ /**
21
+ * Only 2 items are supported to keep API surface minimal so it's easy to switch to another library if needed.
22
+ */
23
+ children: [React.ReactNode, React.ReactNode];
24
+ }
25
+
26
+
27
+ /**
28
+ Features:
29
+ * No absolute positioning is used
30
+ * Component height is fully dynamic and adjusts according to children inside panes
31
+ * Library supports an arbitrary number of panes. We are not using it to keep API minimal.
32
+ * Drawback: only works with percent units. Can be made to work with pixels
33
+ * by creating a wrapper that measures available space and converts to percent.
34
+ */
35
+ export class ResizablePanels extends React.PureComponent<IProps> {
36
+ private primaryPanelRef: ImperativePanelHandle | null;
37
+ private secondaryPanelRef: ImperativePanelHandle | null;
38
+
39
+ constructor(props: IProps) {
40
+ super(props);
41
+
42
+ this.primaryPanelRef = null;
43
+ this.secondaryPanelRef = null;
44
+ }
45
+
46
+ render(): React.ReactNode {
47
+ const {direction, primarySize, secondarySize, children} = this.props;
48
+ const separatorDimensions: React.CSSProperties = direction === 'horizontal'
49
+ ? {width: 3, height: '100%'}
50
+ : {height: 3, width: '100%'};
51
+
52
+ // Sometimes second panel is conditional. Checking here is more convenient.
53
+ if (children.some((child) => child === false || child == null)) {
54
+ return children;
55
+ }
56
+
57
+ return (
58
+ <PanelGroup direction={direction}>
59
+ <Panel
60
+ id="primary"
61
+ minSize={primarySize?.min}
62
+ maxSize={primarySize?.max}
63
+ defaultSize={primarySize?.default}
64
+ ref={(panelRef) => {
65
+ this.primaryPanelRef = panelRef;
66
+ }}
67
+ >
68
+ {children[0]}
69
+ </Panel>
70
+
71
+ <PanelResizeHandle>
72
+ <div
73
+ style={{background: 'var(--color-text-lighter)', ...separatorDimensions}}
74
+ onDoubleClick={() => {
75
+ if (primarySize?.default != null) {
76
+ this.primaryPanelRef?.resize(primarySize.default);
77
+ } else if (secondarySize?.default != null) {
78
+ this.secondaryPanelRef?.resize(secondarySize.default);
79
+ }
80
+ }}
81
+ />
82
+ </PanelResizeHandle>
83
+
84
+ <Panel
85
+ id="secondary"
86
+ minSize={secondarySize?.min}
87
+ maxSize={secondarySize?.max}
88
+ defaultSize={secondarySize?.default}
89
+ ref={(panelRef) => {
90
+ this.secondaryPanelRef = panelRef;
91
+ }}
92
+ >
93
+ {children[1]}
94
+ </Panel>
95
+ </PanelGroup>
96
+ );
97
+ }
98
+ }
@@ -26,8 +26,10 @@ class TooltipBasic extends React.PureComponent<IProps> {
26
26
  }
27
27
  render() {
28
28
  if (React.isValidElement(this.props.children)) {
29
+ const attrs = {id: 't' + this.htmlId};
30
+
29
31
  return (
30
- React.cloneElement(this.props.children, { id: 't' + this.htmlId })
32
+ React.cloneElement(this.props.children, attrs)
31
33
  );
32
34
  } else {
33
35
  return (
@@ -45,10 +47,14 @@ const TooltipAppended: React.FC<IProps> = ({children, flow, text}) => {
45
47
  return (
46
48
  <React.Fragment>
47
49
  <PRTooltip target={"#" + triggerId} content={text} position={position ?? 'top'}/>
48
- {React.isValidElement(children) ?
49
- React.cloneElement(children, { id: triggerId})
50
- :
51
- <React.Fragment />}
50
+ { React.isValidElement(children)
51
+ ? (() => {
52
+ const attrs = {id: triggerId};
53
+
54
+ return React.cloneElement(children, attrs);
55
+ })()
56
+ : <React.Fragment />
57
+ }
52
58
  </React.Fragment>
53
59
  );
54
60
  };
@@ -0,0 +1,231 @@
1
+ import * as React from 'react';
2
+ import {Icon} from '../components/Icon';
3
+
4
+ interface IProps<T> {
5
+ getItems(pageNo: number, signal: AbortSignal): Promise<{items: Array<T>, itemCount: number}>;
6
+ children: (items: Array<T>) => JSX.Element;
7
+ pageSize?: number;
8
+ }
9
+
10
+ interface IState<T> {
11
+ currentPage: number;
12
+ items: Array<T> | null;
13
+ }
14
+
15
+ export function getPagination(currentPage: number, totalPages: number): Array<number | 'dots'> {
16
+ if (currentPage <= 0 || totalPages <= 0 || currentPage > totalPages) {
17
+ return [];
18
+ }
19
+
20
+ let basePages: ReturnType<typeof getPagination> = [
21
+ currentPage - 2,
22
+ currentPage - 1,
23
+ currentPage,
24
+ currentPage + 1,
25
+ currentPage + 2,
26
+ ].filter((page) => page >= 1 && page <= totalPages);
27
+
28
+ if (!basePages.includes(1)) { // include first and maybe dots
29
+ const firstInCurrentList = basePages[0];
30
+
31
+ if (firstInCurrentList !== 1) {
32
+ basePages = [
33
+ 'dots',
34
+ ...basePages,
35
+ ];
36
+ }
37
+
38
+ basePages = [
39
+ 1,
40
+ ...basePages,
41
+ ];
42
+ }
43
+
44
+ if (!basePages.includes(totalPages)) { // include last and maybe dots
45
+ const lastInCurrentList = basePages[basePages.length - 1];
46
+
47
+ if (lastInCurrentList !== totalPages - 1) { // add dots if we're skipping some numbers
48
+ basePages = basePages.concat('dots');
49
+ }
50
+
51
+ basePages = [
52
+ ...basePages,
53
+ totalPages,
54
+ ];
55
+ }
56
+
57
+ return basePages;
58
+ }
59
+
60
+ function getScrollParent(element: HTMLElement | null): HTMLElement | null {
61
+ if (element == null) {
62
+ return null;
63
+ }
64
+
65
+ let parentElement: HTMLElement | null = element;
66
+
67
+ const overflowY = window.getComputedStyle(parentElement).overflowY;
68
+ const hasScrollbar = overflowY === 'auto' || overflowY === 'scroll';
69
+
70
+ while (parentElement !== null && !hasScrollbar) {
71
+ parentElement = parentElement.parentElement ?? null;
72
+ }
73
+
74
+ return parentElement;
75
+ }
76
+
77
+ export class WithPagination<T> extends React.PureComponent<IProps<T>, IState<T>> {
78
+ private pageCount: number;
79
+ private abortController: AbortController;
80
+ private ref: HTMLDivElement | null;
81
+ private inProgress: boolean;
82
+
83
+ constructor(props: IProps<T>) {
84
+ super(props);
85
+
86
+ this.state = {
87
+ currentPage: 1,
88
+ items: null,
89
+ };
90
+
91
+ this.switchPage = this.switchPage.bind(this);
92
+ this.getPageSize = this.getPageSize.bind(this);
93
+
94
+ this.pageCount = 0;
95
+ this.abortController = new window.AbortController(); // window. needed for unit tests
96
+ this.ref = null;
97
+ this.inProgress = false;
98
+ }
99
+
100
+ getPageSize() {
101
+ return this.props.pageSize ?? 20;
102
+ }
103
+
104
+ switchPage(page: number) {
105
+ if (this.inProgress) {
106
+ this.abortController.abort();
107
+ }
108
+
109
+ this.inProgress = true;
110
+ this.props.getItems(page, this.abortController.signal).then((res) => {
111
+ this.inProgress = false;
112
+ this.setState({items: res.items, currentPage: page}, () => {
113
+ const scrollableEl = getScrollParent(this.ref);
114
+ const diff = scrollableEl != null && this.ref?.scrollHeight != null
115
+ ? scrollableEl.offsetHeight - this.ref.scrollHeight
116
+ : null;
117
+
118
+ if (scrollableEl != null) {
119
+ scrollableEl.scrollTop = diff != null ? diff : 0;
120
+ }
121
+ });
122
+ });
123
+ }
124
+
125
+ componentDidMount(): void {
126
+ this.props.getItems(1, this.abortController.signal).then((res) => {
127
+ this.pageCount = Math.ceil(res.itemCount / this.getPageSize());
128
+ this.setState({items: res.items});
129
+ });
130
+ }
131
+
132
+ render() {
133
+ if (this.state.items == null) {
134
+ return null;
135
+ }
136
+
137
+ const pageElements = getPagination(this.state.currentPage, this.pageCount).map((el, i) => {
138
+ if (el === 'dots') {
139
+ return (
140
+ <span data-test-id="more-pages" className='sd-pagination__item sd-pagination__item--more'>...</span>
141
+ );
142
+ } else {
143
+ return (
144
+ <button
145
+ data-test-id={`page-button-${i}`}
146
+ className={
147
+ this.state.currentPage === el
148
+ ? 'sd-pagination__item sd-pagination__item--active'
149
+ : 'sd-pagination__item'
150
+ }
151
+ onClick={() => this.switchPage(el)}
152
+ >
153
+ {el}
154
+ </button>
155
+ );
156
+ }
157
+ });
158
+
159
+ pageElements.unshift(
160
+ <>
161
+ <button
162
+ data-test-id="btn-1"
163
+ className='sd-pagination__item sd-pagination__item--start'
164
+ disabled={this.state.currentPage === 1}
165
+ onClick={() => this.switchPage(1)}
166
+ >
167
+ <Icon name='backward-thin' />
168
+ </button>
169
+ <button
170
+ data-test-id="btn-2"
171
+ className='sd-pagination__item sd-pagination__item--start'
172
+ disabled={this.state.currentPage <= 1}
173
+ onClick={() => this.switchPage(this.state.currentPage - 1)}
174
+ >
175
+ <Icon name='chevron-left-thin' />
176
+ </button>
177
+ </>,
178
+ );
179
+
180
+ pageElements.push(
181
+ <>
182
+ <button
183
+ data-test-id="btn-3"
184
+ className='sd-pagination__item sd-pagination__item--forward'
185
+ onClick={() => this.switchPage(this.state.currentPage + 1)}
186
+ disabled={this.state.currentPage === this.pageCount}
187
+ >
188
+ <Icon name='chevron-right-thin' />
189
+ </button>
190
+ <button
191
+ data-test-id="btn-4"
192
+ className='sd-pagination__item sd-pagination__item--end'
193
+ onClick={() => this.switchPage(this.pageCount)}
194
+ disabled={this.state.currentPage === this.pageCount}
195
+ >
196
+ <Icon name='forward-thin' />
197
+ </button>
198
+ </>,
199
+ );
200
+
201
+ const StyledPagination: React.ComponentType = () => (
202
+ <div
203
+ style={{
204
+ display: 'flex',
205
+ flexDirection: 'row',
206
+ justifyContent: 'center',
207
+ }}
208
+ >
209
+ {pageElements}
210
+ </div>
211
+ );
212
+
213
+ return (
214
+ <div
215
+ style={{
216
+ height: '100%',
217
+ width: '100%',
218
+ display: 'flex',
219
+ flexDirection: 'column',
220
+ }}
221
+ ref={(element) => {
222
+ this.ref = element;
223
+ }}
224
+ >
225
+ <StyledPagination />
226
+ {this.props.children(this.state.items)}
227
+ <StyledPagination />
228
+ </div>
229
+ );
230
+ }
231
+ }
@@ -0,0 +1,146 @@
1
+ import {describe, it} from 'mocha';
2
+ import * as assert from 'assert';
3
+ import {mount} from 'enzyme';
4
+ import * as React from 'react';
5
+ import {getPagination, WithPagination} from './WithPagination';
6
+ import {range} from 'lodash';
7
+
8
+ interface IPost {
9
+ title: string;
10
+ }
11
+
12
+ // Simulate fetching delay
13
+ const TIMEOUT = 1000;
14
+
15
+ export class Paginated extends React.PureComponent {
16
+ getItems(): Promise<{items: Array<IPost>, itemCount: number}> {
17
+ return new Promise((resolve) => {
18
+ setTimeout(() => {
19
+ return resolve({items: range(1, 500).map((x) => ({title: `title ${x}`})), itemCount: 500});
20
+ }, TIMEOUT);
21
+ });
22
+ }
23
+
24
+ render() {
25
+ return (
26
+ <WithPagination
27
+ getItems={() => this.getItems()}
28
+ >
29
+ {
30
+ (items) => <div>{JSON.stringify(items)}</div>
31
+ }
32
+ </WithPagination>
33
+ );
34
+ }
35
+ }
36
+
37
+ describe('getPagination', () => {
38
+ it('returns empty array when we have 0 pages', () => {
39
+ assert.strictEqual(getPagination(1, 0).length, 0);
40
+ });
41
+
42
+ it('returns empty array when we try to access page <= 0', () => {
43
+ assert.strictEqual(getPagination(-10, 100).length, 0);
44
+ });
45
+
46
+ it('returns dots when on page 1 having 5 total pages', () => {
47
+ assert.notStrictEqual(getPagination(1, 5), [1, 2, 3, 'dots', 5]);
48
+ });
49
+
50
+ it('returns dots when on the last page having 5 total pages', () => {
51
+ assert.notStrictEqual(getPagination(5, 5), [1, 'dots', 3, 4, 5]);
52
+ });
53
+
54
+ it('returns dots twice when on the middle page', () => {
55
+ assert.notStrictEqual(getPagination(5, 10), [1, 'dots', 3, 4, 5, 6, 7, 'dots', 10]);
56
+ });
57
+
58
+ it('returns page 1 and last page when on the middle page', () => {
59
+ assert.notStrictEqual(getPagination(5, 10), [1, 'dots', 3, 4, 5, 6, 7, 'dots', 10]);
60
+ });
61
+
62
+ it('contains no pages out of reach', () => {
63
+ const res = getPagination(101, 100);
64
+ assert.strictEqual(res.length, 0);
65
+ });
66
+ });
67
+
68
+ describe('with-pagination', () => {
69
+ it('contains page-button-1 button when first rendered', (done) => {
70
+ const wrapper = mount(<Paginated />);
71
+
72
+ setTimeout(() => {
73
+ assert.strictEqual(
74
+ wrapper.update().find('[data-test-id="page-button-1"]').length,
75
+ 2,
76
+ );
77
+ done();
78
+ }, TIMEOUT + 100);
79
+ });
80
+
81
+ it('contains page-button-4 after clicking forward', (done) => {
82
+ const wrapper = mount(<Paginated />);
83
+
84
+ setTimeout(() => {
85
+ wrapper.update();
86
+ wrapper.find('[data-test-id="btn-3"]').at(0).simulate('click');
87
+
88
+ assert.strictEqual(
89
+ wrapper.find('[data-test-id="page-button-4"]').length,
90
+ 2,
91
+ );
92
+ done();
93
+ }, TIMEOUT + 100);
94
+ });
95
+
96
+ it('previous-next buttons works', (done) => {
97
+ const wrapper = mount(<Paginated />);
98
+
99
+ setTimeout(() => {
100
+ wrapper.update();
101
+ wrapper.find('[data-test-id="btn-4"]').at(0).simulate('click');
102
+ wrapper.find('[data-test-id="btn-2"]').at(0).simulate('click');
103
+
104
+ assert.strictEqual(
105
+ wrapper.find('[data-test-id="button4"]').length,
106
+ 2,
107
+ );
108
+ done();
109
+ }, TIMEOUT + 100);
110
+ });
111
+
112
+ it('returns span when at last page', (done) => {
113
+ const wrapper = mount(<Paginated />);
114
+
115
+ setTimeout(() => {
116
+ wrapper.update();
117
+ wrapper.find('[data-test-id="btn-4"]').at(0).simulate('click');
118
+
119
+ assert.strictEqual(
120
+ wrapper.find('[data-test-id="more-pages"]').length,
121
+ 2,
122
+ );
123
+ done();
124
+ }, TIMEOUT + 100);
125
+ });
126
+
127
+ it.only('scrolls to the top of the pagination container', (done) => {
128
+ const wrapper = mount(
129
+ <div style={{height: 1200, overflowY: 'auto'}}>
130
+ <div style={{height: 400}} />
131
+ <Paginated />
132
+ </div>,
133
+ );
134
+
135
+ setTimeout(() => {
136
+ wrapper.update();
137
+ wrapper.find('[data-test-id="btn-4"]').at(1).simulate('click');
138
+
139
+ assert.strictEqual(
140
+ wrapper.getDOMNode().scrollTop,
141
+ 0,
142
+ );
143
+ done();
144
+ }, TIMEOUT + 100);
145
+ });
146
+ });
@@ -6,6 +6,7 @@ export { Button } from './components/Button';
6
6
  export { Input } from './components/Input';
7
7
  export { Select, Option } from './components/Select';
8
8
  export { SelectWithTemplate } from './components/SelectWithTemplate';
9
+ export { WithPagination } from './components/WithPagination';
9
10
  export { Popover } from './components/Popover';
10
11
  export { Label } from './components/Label';
11
12
  export { Badge } from './components/Badge';
@@ -90,6 +91,7 @@ export { TreeSelect } from './components/TreeSelect';
90
91
  export { TableList, TableListItem } from './components/Lists/TableList';
91
92
  export { ContentListItem } from './components/Lists/ContentList';
92
93
  export { MultiSelect } from './components/MultiSelect';
94
+ export { ResizablePanels } from './components/ResizablePanels';
93
95
 
94
96
  // declare non-typescript exports to prevent errors
95
97
  export declare const ToggleBoxNext: any;