@canonical/react-components 2.14.0 → 2.15.0
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/dist/components/ScrollableContainer/ScrollableContainer.d.ts +27 -0
- package/dist/components/ScrollableContainer/ScrollableContainer.js +51 -0
- package/dist/components/ScrollableContainer/ScrollableContainer.scss +7 -0
- package/dist/components/ScrollableContainer/ScrollableContainer.stories.d.ts +6 -0
- package/dist/components/ScrollableContainer/ScrollableContainer.stories.js +36 -0
- package/dist/components/ScrollableContainer/ScrollableContainer.test.d.ts +1 -0
- package/dist/components/ScrollableContainer/index.d.ts +2 -0
- package/dist/components/ScrollableContainer/index.js +13 -0
- package/dist/components/ScrollableTable/ScrollableTable.d.ts +27 -0
- package/dist/components/ScrollableTable/ScrollableTable.js +44 -0
- package/dist/components/ScrollableTable/ScrollableTable.scss +58 -0
- package/dist/components/ScrollableTable/ScrollableTable.stories.d.ts +6 -0
- package/dist/components/ScrollableTable/ScrollableTable.stories.js +69 -0
- package/dist/components/ScrollableTable/ScrollableTable.test.d.ts +1 -0
- package/dist/components/ScrollableTable/index.d.ts +2 -0
- package/dist/components/ScrollableTable/index.js +13 -0
- package/dist/components/SidePanel/SidePanel.js +1 -1
- package/dist/components/TablePagination/TablePagination.scss +6 -6
- package/dist/components/TablePagination/TablePagination.stories.d.ts +8 -0
- package/dist/components/TablePagination/TablePagination.stories.js +53 -1
- package/dist/components/TablePagination/TablePaginationControls/TablePaginationControls.js +7 -4
- package/dist/components/TablePagination/utils.d.ts +2 -1
- package/dist/components/TablePagination/utils.js +10 -3
- package/dist/esm/components/ScrollableContainer/ScrollableContainer.d.ts +27 -0
- package/dist/esm/components/ScrollableContainer/ScrollableContainer.js +43 -0
- package/dist/esm/components/ScrollableContainer/ScrollableContainer.scss +7 -0
- package/dist/esm/components/ScrollableContainer/ScrollableContainer.stories.d.ts +6 -0
- package/dist/esm/components/ScrollableContainer/ScrollableContainer.stories.js +29 -0
- package/dist/esm/components/ScrollableContainer/ScrollableContainer.test.d.ts +1 -0
- package/dist/esm/components/ScrollableContainer/index.d.ts +2 -0
- package/dist/esm/components/ScrollableContainer/index.js +1 -0
- package/dist/esm/components/ScrollableTable/ScrollableTable.d.ts +27 -0
- package/dist/esm/components/ScrollableTable/ScrollableTable.js +37 -0
- package/dist/esm/components/ScrollableTable/ScrollableTable.scss +58 -0
- package/dist/esm/components/ScrollableTable/ScrollableTable.stories.d.ts +6 -0
- package/dist/esm/components/ScrollableTable/ScrollableTable.stories.js +62 -0
- package/dist/esm/components/ScrollableTable/ScrollableTable.test.d.ts +1 -0
- package/dist/esm/components/ScrollableTable/index.d.ts +2 -0
- package/dist/esm/components/ScrollableTable/index.js +1 -0
- package/dist/esm/components/SidePanel/SidePanel.js +1 -1
- package/dist/esm/components/TablePagination/TablePagination.scss +6 -6
- package/dist/esm/components/TablePagination/TablePagination.stories.d.ts +8 -0
- package/dist/esm/components/TablePagination/TablePagination.stories.js +52 -0
- package/dist/esm/components/TablePagination/TablePaginationControls/TablePaginationControls.js +7 -4
- package/dist/esm/components/TablePagination/utils.d.ts +2 -1
- package/dist/esm/components/TablePagination/utils.js +10 -3
- package/dist/esm/hooks/useId.d.ts +1 -1
- package/dist/esm/hooks/useId.js +1 -1
- package/dist/esm/hooks/useListener.js +8 -7
- package/dist/esm/index.d.ts +5 -1
- package/dist/esm/index.js +3 -1
- package/dist/esm/utils.d.ts +4 -0
- package/dist/esm/utils.js +32 -1
- package/dist/hooks/useId.d.ts +1 -1
- package/dist/hooks/useId.js +1 -1
- package/dist/hooks/useListener.js +8 -7
- package/dist/index.d.ts +5 -1
- package/dist/index.js +37 -0
- package/dist/utils.d.ts +4 -0
- package/dist/utils.js +37 -2
- package/package.json +2 -2
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { useEffect, useRef } from "react";
|
|
3
|
+
import classnames from "classnames";
|
|
4
|
+
import "./ScrollableContainer.scss";
|
|
5
|
+
import { getAbsoluteHeightBelowById, getParentsBottomSpacing } from "../../utils";
|
|
6
|
+
import { useListener } from "../../hooks";
|
|
7
|
+
/**
|
|
8
|
+
* This is a [React](https://reactjs.org/) component for use within the [Vanilla framework](https://docs.vanillaframework.io/).
|
|
9
|
+
*
|
|
10
|
+
* It is used to make any child element scrollable by adjusting the height based on the viewport height and the heights of elements above and below it. As a result the surrounding elements are sticky and only the wrapped element contents scroll
|
|
11
|
+
*/
|
|
12
|
+
var ScrollableContainer = _ref => {
|
|
13
|
+
var {
|
|
14
|
+
dependencies,
|
|
15
|
+
children,
|
|
16
|
+
belowIds = ["status-bar"],
|
|
17
|
+
className
|
|
18
|
+
} = _ref;
|
|
19
|
+
var ref = useRef(null);
|
|
20
|
+
var updateChildContainerHeight = () => {
|
|
21
|
+
var _ref$current;
|
|
22
|
+
var childContainer = (_ref$current = ref.current) === null || _ref$current === void 0 ? void 0 : _ref$current.children[0];
|
|
23
|
+
if (!childContainer) {
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
var above = childContainer.getBoundingClientRect().top + 1;
|
|
27
|
+
var below = belowIds.reduce((acc, belowId) => acc + getAbsoluteHeightBelowById(belowId), 0);
|
|
28
|
+
var parentsBottomSpacing = getParentsBottomSpacing(childContainer);
|
|
29
|
+
var offset = Math.ceil(above + below + parentsBottomSpacing);
|
|
30
|
+
var style = "height: calc(100dvh - ".concat(offset, "px); min-height: calc(100dvh - ").concat(offset, "px)");
|
|
31
|
+
childContainer.setAttribute("style", style);
|
|
32
|
+
};
|
|
33
|
+
useListener(window, updateChildContainerHeight, "resize", true);
|
|
34
|
+
useEffect(updateChildContainerHeight, [dependencies, belowIds, ref]);
|
|
35
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
36
|
+
ref: ref,
|
|
37
|
+
className: classnames("scrollable-container", className)
|
|
38
|
+
}, /*#__PURE__*/React.createElement("div", {
|
|
39
|
+
id: "content-details",
|
|
40
|
+
className: "content-details"
|
|
41
|
+
}, children));
|
|
42
|
+
};
|
|
43
|
+
export default ScrollableContainer;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { Meta, StoryObj } from "@storybook/react";
|
|
2
|
+
import ScrollableContainer from "./ScrollableContainer";
|
|
3
|
+
declare const meta: Meta<typeof ScrollableContainer>;
|
|
4
|
+
export default meta;
|
|
5
|
+
type Story = StoryObj<typeof ScrollableContainer>;
|
|
6
|
+
export declare const Default: Story;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import ScrollableContainer from "./ScrollableContainer";
|
|
2
|
+
import React from "react";
|
|
3
|
+
import { Description, Subtitle, Title } from "@storybook/blocks";
|
|
4
|
+
var meta = {
|
|
5
|
+
component: ScrollableContainer,
|
|
6
|
+
tags: ["autodocs"]
|
|
7
|
+
};
|
|
8
|
+
export default meta;
|
|
9
|
+
var StoryExample = args => {
|
|
10
|
+
return /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("h1", null, "Above contents"), /*#__PURE__*/React.createElement(ScrollableContainer, {
|
|
11
|
+
belowIds: args.belowIds,
|
|
12
|
+
dependencies: []
|
|
13
|
+
}, /*#__PURE__*/React.createElement("p", null, "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras varius mi eu pretium vulputate. Nunc commodo sit amet nibh quis rhoncus. Aliquam rhoncus porttitor semper. Aenean faucibus consectetur neque in sodales. Sed cursus mauris id ex sollicitudin sodales. Quisque molestie rutrum odio, ornare pharetra ligula. Pellentesque ornare tristique feugiat. In a augue neque. Aenean eget arcu quis lacus tempus posuere in sit amet dui. Suspendisse faucibus sapien nisl, nec laoreet sem convallis nec."), /*#__PURE__*/React.createElement("p", null, "Vestibulum sed placerat lorem. Nam luctus ex id nisi luctus, id vestibulum sem bibendum. Vivamus turpis sem, pellentesque fermentum malesuada eu, faucibus porta libero. Duis eget venenatis odio. Etiam sed volutpat magna, non tempus erat. Nunc id tortor ac quam consectetur dapibus ac ut tellus. Pellentesque ut tellus venenatis elit vehicula condimentum eget quis lorem. Ut non consectetur est, a fringilla ipsum. Nunc vitae ligula ipsum. Etiam suscipit, libero ut lacinia viverra, nunc urna consequat ex, vel eleifend eros mauris vitae ipsum. Pellentesque sed dictum augue. Ut sit amet ullamcorper mauris. Nunc congue orci mollis purus sodales facilisis ac ut arcu. Maecenas feugiat sapien ac massa mollis sodales. Donec vitae turpis eu nisi laoreet pulvinar quis at nisl. Integer volutpat, metus eget elementum dictum, lacus sapien viverra felis, consequat fermentum nisl mi ac dui."), /*#__PURE__*/React.createElement("p", null, "Nullam nulla turpis, dignissim vel dapibus ut, volutpat ac dui. Donec vel elementum lacus. Mauris maximus nec felis at faucibus. Nunc faucibus gravida velit, id blandit lectus tincidunt ac. Vestibulum orci diam, elementum in congue eu, placerat id risus. Sed tempor tempus tellus, vitae iaculis turpis fringilla nec. Phasellus imperdiet facilisis velit, sit amet lobortis odio dignissim ut."), /*#__PURE__*/React.createElement("p", null, "Nam placerat urna vitae ligula hendrerit, ac tincidunt lorem maximus. Mauris eu odio nisi. Nulla facilisi. Sed egestas elit sed velit rutrum, sit amet bibendum metus hendrerit. Pellentesque luctus placerat tellus, eu bibendum justo. Cras eget leo ac ex volutpat gravida. Duis vitae mollis ante. Duis a congue nunc. Aenean aliquet, sapien quis tincidunt tincidunt, odio eros consectetur lacus, vel finibus mauris tortor id velit. Donec tincidunt vitae purus eu interdum. Pellentesque scelerisque dui viverra ex ullamcorper volutpat. Vestibulum lacinia vitae arcu volutpat porta. Etiam et cursus nulla, id aliquet felis. Nam ultricies, urna id mattis pretium, velit erat viverra elit, eu maximus diam eros id nisi."), /*#__PURE__*/React.createElement("p", null, "Nullam eget nisl lectus. Pellentesque eu mauris ut tortor malesuada sagittis. Cras dictum cursus est non ultricies. Duis mollis non neque at commodo. Nunc feugiat justo et consequat aliquam. Ut consectetur libero eu erat feugiat finibus. Duis varius convallis quam eu sagittis. Maecenas ac est arcu. Suspendisse at enim eget nibh ultricies dictum. Etiam aliquet tellus vel felis malesuada laoreet.")), /*#__PURE__*/React.createElement("div", {
|
|
14
|
+
id: "footer"
|
|
15
|
+
}, /*#__PURE__*/React.createElement("h2", {
|
|
16
|
+
className: "u-no-margin"
|
|
17
|
+
}, "Below contents"), /*#__PURE__*/React.createElement("div", null, "here be dragons.")));
|
|
18
|
+
};
|
|
19
|
+
export var Default = {
|
|
20
|
+
args: {
|
|
21
|
+
belowIds: ["footer"]
|
|
22
|
+
},
|
|
23
|
+
render: StoryExample,
|
|
24
|
+
parameters: {
|
|
25
|
+
docs: {
|
|
26
|
+
page: () => /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Title, null), /*#__PURE__*/React.createElement(Subtitle, null), /*#__PURE__*/React.createElement(Description, null))
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from "./ScrollableContainer";
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { DependencyList, FC, ReactNode } from "react";
|
|
2
|
+
import "./ScrollableTable.scss";
|
|
3
|
+
export type Props = {
|
|
4
|
+
/**
|
|
5
|
+
* A MainTable that will be made scrollable.
|
|
6
|
+
*/
|
|
7
|
+
children: ReactNode;
|
|
8
|
+
/**
|
|
9
|
+
* An array of dependencies that will trigger a re-calculation of the table body height when they change.
|
|
10
|
+
*/
|
|
11
|
+
dependencies: DependencyList;
|
|
12
|
+
/**
|
|
13
|
+
* The ID of the table element that contains the `<tbody>` to be made scrollable.
|
|
14
|
+
*/
|
|
15
|
+
tableId: string;
|
|
16
|
+
/**
|
|
17
|
+
* An array of element IDs below the table that should be considered when calculating the height.
|
|
18
|
+
*/
|
|
19
|
+
belowIds?: string[];
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* This is a [React](https://reactjs.org/) component for use within the [Vanilla framework](https://docs.vanillaframework.io/).
|
|
23
|
+
*
|
|
24
|
+
* It is used to make a table scrollable by adjusting the height of the `<tbody>` element based on the viewport height and the heights of elements above and below it. As a result the header is sticky and only the body scrolls
|
|
25
|
+
*/
|
|
26
|
+
declare const ScrollableTable: FC<Props>;
|
|
27
|
+
export default ScrollableTable;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { useEffect } from "react";
|
|
3
|
+
import { getAbsoluteHeightBelowById, getParentsBottomSpacing } from "../../utils";
|
|
4
|
+
import "./ScrollableTable.scss";
|
|
5
|
+
import { useListener } from "../../hooks";
|
|
6
|
+
/**
|
|
7
|
+
* This is a [React](https://reactjs.org/) component for use within the [Vanilla framework](https://docs.vanillaframework.io/).
|
|
8
|
+
*
|
|
9
|
+
* It is used to make a table scrollable by adjusting the height of the `<tbody>` element based on the viewport height and the heights of elements above and below it. As a result the header is sticky and only the body scrolls
|
|
10
|
+
*/
|
|
11
|
+
var ScrollableTable = _ref => {
|
|
12
|
+
var {
|
|
13
|
+
dependencies,
|
|
14
|
+
children,
|
|
15
|
+
tableId,
|
|
16
|
+
belowIds = []
|
|
17
|
+
} = _ref;
|
|
18
|
+
var updateTBodyHeight = () => {
|
|
19
|
+
var table = document.getElementById(tableId);
|
|
20
|
+
if (!table || table.children.length !== 2) {
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
var tBody = table.children[1];
|
|
24
|
+
var above = tBody.getBoundingClientRect().top + 1;
|
|
25
|
+
var below = belowIds.reduce((acc, belowId) => acc + getAbsoluteHeightBelowById(belowId), 0);
|
|
26
|
+
var parentsBottomSpacing = getParentsBottomSpacing(table);
|
|
27
|
+
var offset = Math.ceil(above + below + parentsBottomSpacing);
|
|
28
|
+
var style = "height: calc(100dvh - ".concat(offset, "px); min-height: calc(100dvh - ").concat(offset, "px)");
|
|
29
|
+
tBody.setAttribute("style", style);
|
|
30
|
+
};
|
|
31
|
+
useListener(window, updateTBodyHeight, "resize", true);
|
|
32
|
+
useEffect(updateTBodyHeight, [...dependencies, belowIds, tableId]);
|
|
33
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
34
|
+
className: "scrollable-table"
|
|
35
|
+
}, children);
|
|
36
|
+
};
|
|
37
|
+
export default ScrollableTable;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
@import "vanilla-framework/scss/settings";
|
|
2
|
+
|
|
3
|
+
/* stylelint-disable selector-max-type */
|
|
4
|
+
.scrollable-table {
|
|
5
|
+
table {
|
|
6
|
+
margin-bottom: 0;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
th,
|
|
10
|
+
td {
|
|
11
|
+
display: table-cell;
|
|
12
|
+
vertical-align: top;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
th::before {
|
|
16
|
+
content: "";
|
|
17
|
+
height: 1rem;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
thead,
|
|
21
|
+
tbody {
|
|
22
|
+
display: block;
|
|
23
|
+
overflow: hidden auto;
|
|
24
|
+
scrollbar-gutter: stable;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
tbody {
|
|
28
|
+
height: calc(100dvh - 323px);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
thead tr,
|
|
32
|
+
tbody tr {
|
|
33
|
+
display: table;
|
|
34
|
+
table-layout: fixed;
|
|
35
|
+
width: 100%;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
@media screen and (max-width: $breakpoint-large) {
|
|
39
|
+
.p-table--mobile-card {
|
|
40
|
+
thead {
|
|
41
|
+
display: none;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
td {
|
|
45
|
+
display: block;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
tbody tr {
|
|
49
|
+
display: block;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
tbody tr:first-child {
|
|
53
|
+
margin-top: $spv--x-large;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
/* stylelint-enable selector-max-type */
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import ScrollableTable from "./ScrollableTable";
|
|
3
|
+
import { MainTable } from "../../index";
|
|
4
|
+
import { Description, Subtitle, Title } from "@storybook/blocks";
|
|
5
|
+
var meta = {
|
|
6
|
+
component: ScrollableTable,
|
|
7
|
+
tags: ["autodocs"]
|
|
8
|
+
};
|
|
9
|
+
export default meta;
|
|
10
|
+
var StoryExample = args => {
|
|
11
|
+
var headers = [{
|
|
12
|
+
content: "Fact"
|
|
13
|
+
}, {
|
|
14
|
+
content: "Relevancy score"
|
|
15
|
+
}, {
|
|
16
|
+
content: "Size"
|
|
17
|
+
}, {
|
|
18
|
+
content: "ID"
|
|
19
|
+
}, {
|
|
20
|
+
"aria-label": "Actions",
|
|
21
|
+
className: "actions"
|
|
22
|
+
}];
|
|
23
|
+
var facts = ["Dragons are mythical creatures", "They can fly", "They breathe fire", "They hoard treasure", "They are often depicted as large reptiles", "They appear in various cultures' folklore", "They can be friendly or hostile", "They are often associated with wisdom", "They can shapeshift in some legends", "They are sometimes guardians of sacred places", "They can be found in literature and movies", "They are often depicted with wings", "They can be of various colors", "They are sometimes associated with knights"];
|
|
24
|
+
var rows = facts.map(item => {
|
|
25
|
+
return {
|
|
26
|
+
columns: [{
|
|
27
|
+
content: item,
|
|
28
|
+
role: "rowheader"
|
|
29
|
+
}, {
|
|
30
|
+
content: 1
|
|
31
|
+
}, {
|
|
32
|
+
content: "1 GiB"
|
|
33
|
+
}, {
|
|
34
|
+
content: 2
|
|
35
|
+
}]
|
|
36
|
+
};
|
|
37
|
+
});
|
|
38
|
+
return /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("h1", null, "Above contents"), /*#__PURE__*/React.createElement(ScrollableTable, {
|
|
39
|
+
belowIds: args.belowIds,
|
|
40
|
+
dependencies: [headers, rows],
|
|
41
|
+
tableId: "facts-about-dragons"
|
|
42
|
+
}, /*#__PURE__*/React.createElement(MainTable, {
|
|
43
|
+
headers: headers,
|
|
44
|
+
rows: rows,
|
|
45
|
+
id: "facts-about-dragons"
|
|
46
|
+
})), /*#__PURE__*/React.createElement("div", {
|
|
47
|
+
id: "footer"
|
|
48
|
+
}, /*#__PURE__*/React.createElement("h2", {
|
|
49
|
+
className: "u-no-margin"
|
|
50
|
+
}, "Below contents"), /*#__PURE__*/React.createElement("div", null, "here be dragons.")));
|
|
51
|
+
};
|
|
52
|
+
export var Default = {
|
|
53
|
+
args: {
|
|
54
|
+
belowIds: ["footer"]
|
|
55
|
+
},
|
|
56
|
+
render: StoryExample,
|
|
57
|
+
parameters: {
|
|
58
|
+
docs: {
|
|
59
|
+
page: () => /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Title, null), /*#__PURE__*/React.createElement(Subtitle, null), /*#__PURE__*/React.createElement(Description, null))
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from "./ScrollableTable";
|
|
@@ -26,7 +26,7 @@ The sidepanel component should be used to show additional information relating t
|
|
|
26
26
|
|
|
27
27
|
* **SidePanel.HeaderControls:** To show controls in the header, such as buttons or icons for actions like closing the panel.
|
|
28
28
|
|
|
29
|
-
* **SidePanel.Sticky:** Can be wrapped around the header or footer to make them sticky when scrolling.
|
|
29
|
+
* **SidePanel.Sticky:** Can be wrapped around the header or footer to make them sticky when scrolling. The scrollbar will use the full area of the side panel, not just the content area. To limit the scrollbar to the content area, use the `ScrollableContainer` component instead of this one.
|
|
30
30
|
|
|
31
31
|
* **SidePanel.Content:** To show the main content of the side panel.
|
|
32
32
|
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
.next {
|
|
29
|
-
margin: 0 $spv--large;
|
|
29
|
+
margin: 0 $spv--large 0 0;
|
|
30
30
|
|
|
31
31
|
.p-icon--chevron-down {
|
|
32
32
|
rotate: 270deg;
|
|
@@ -34,11 +34,15 @@
|
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
.pagination-input {
|
|
37
|
-
margin: 0 $spv--
|
|
37
|
+
margin: 0 $spv--large;
|
|
38
38
|
min-width: 0;
|
|
39
39
|
width: 4rem;
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
+
.pagination-item-count {
|
|
43
|
+
margin: 0 $spv--large 0 0;
|
|
44
|
+
}
|
|
45
|
+
|
|
42
46
|
.pagination-select {
|
|
43
47
|
margin-bottom: 0;
|
|
44
48
|
margin-left: $spv--x-large;
|
|
@@ -48,10 +52,6 @@
|
|
|
48
52
|
|
|
49
53
|
@media screen and (max-width: $breakpoint-small) {
|
|
50
54
|
.back,
|
|
51
|
-
.pagination-input {
|
|
52
|
-
margin-left: 0;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
55
|
.next {
|
|
56
56
|
margin-left: 0;
|
|
57
57
|
margin-right: 0;
|
|
@@ -12,3 +12,11 @@ export declare const RenderBelow: Story;
|
|
|
12
12
|
* using the `TablePaginationControls` component.
|
|
13
13
|
*/
|
|
14
14
|
export declare const ControlsOnly: Story;
|
|
15
|
+
/** The `TablePaginationControls` component can be used when the total
|
|
16
|
+
* number of entries is unknown.
|
|
17
|
+
*/
|
|
18
|
+
export declare const ControlsWithUnknownEntries: Story;
|
|
19
|
+
/** The `TablePaginationControls` component can be used when it is known
|
|
20
|
+
* that there are more entries than the amount displayed on the current page.
|
|
21
|
+
*/
|
|
22
|
+
export declare const ControlsWithPartiallyKnownEntries: Story;
|
|
@@ -320,4 +320,56 @@ export var ControlsOnly = {
|
|
|
320
320
|
visibleCount: 10
|
|
321
321
|
});
|
|
322
322
|
}
|
|
323
|
+
};
|
|
324
|
+
|
|
325
|
+
/** The `TablePaginationControls` component can be used when the total
|
|
326
|
+
* number of entries is unknown.
|
|
327
|
+
*/
|
|
328
|
+
export var ControlsWithUnknownEntries = {
|
|
329
|
+
render: () => {
|
|
330
|
+
return /*#__PURE__*/React.createElement(TablePaginationControls, {
|
|
331
|
+
currentPage: 1,
|
|
332
|
+
itemName: "row",
|
|
333
|
+
nextButtonProps: {
|
|
334
|
+
disabled: false
|
|
335
|
+
},
|
|
336
|
+
onInputPageChange: console.log,
|
|
337
|
+
onNextPage: console.log,
|
|
338
|
+
onPageSizeChange: console.log,
|
|
339
|
+
onPreviousPage: console.log,
|
|
340
|
+
pageLimits: [10, 25, 50],
|
|
341
|
+
pageSize: 20,
|
|
342
|
+
previousButtonProps: {
|
|
343
|
+
disabled: false
|
|
344
|
+
},
|
|
345
|
+
showPageInput: true,
|
|
346
|
+
visibleCount: 10
|
|
347
|
+
});
|
|
348
|
+
}
|
|
349
|
+
};
|
|
350
|
+
|
|
351
|
+
/** The `TablePaginationControls` component can be used when it is known
|
|
352
|
+
* that there are more entries than the amount displayed on the current page.
|
|
353
|
+
*/
|
|
354
|
+
export var ControlsWithPartiallyKnownEntries = {
|
|
355
|
+
render: () => {
|
|
356
|
+
return /*#__PURE__*/React.createElement(TablePaginationControls, {
|
|
357
|
+
currentPage: 3,
|
|
358
|
+
itemName: "row",
|
|
359
|
+
nextButtonProps: {
|
|
360
|
+
disabled: false
|
|
361
|
+
},
|
|
362
|
+
onInputPageChange: console.log,
|
|
363
|
+
onNextPage: console.log,
|
|
364
|
+
onPageSizeChange: console.log,
|
|
365
|
+
onPreviousPage: console.log,
|
|
366
|
+
pageLimits: [10, 25, 50],
|
|
367
|
+
pageSize: 20,
|
|
368
|
+
previousButtonProps: {
|
|
369
|
+
disabled: false
|
|
370
|
+
},
|
|
371
|
+
showPageInput: true,
|
|
372
|
+
visibleCount: 10
|
|
373
|
+
});
|
|
374
|
+
}
|
|
323
375
|
};
|
package/dist/esm/components/TablePagination/TablePaginationControls/TablePaginationControls.js
CHANGED
|
@@ -23,7 +23,7 @@ var TablePaginationControls = _ref => {
|
|
|
23
23
|
description,
|
|
24
24
|
displayDescription = true,
|
|
25
25
|
onInputPageChange,
|
|
26
|
-
itemName,
|
|
26
|
+
itemName = "row",
|
|
27
27
|
nextButtonProps,
|
|
28
28
|
onNextPage,
|
|
29
29
|
onPageChange,
|
|
@@ -44,7 +44,8 @@ var TablePaginationControls = _ref => {
|
|
|
44
44
|
visibleCount,
|
|
45
45
|
isSmallScreen,
|
|
46
46
|
totalItems,
|
|
47
|
-
itemName
|
|
47
|
+
itemName,
|
|
48
|
+
currentPage
|
|
48
49
|
});
|
|
49
50
|
var handleDecrementPage = currentPage => {
|
|
50
51
|
if (currentPage > 1) {
|
|
@@ -66,7 +67,7 @@ var TablePaginationControls = _ref => {
|
|
|
66
67
|
var handlePageSizeChange = e => {
|
|
67
68
|
onPageSizeChange(parseInt(e.target.value));
|
|
68
69
|
};
|
|
69
|
-
var isInputDisabled = !totalPages || totalPages == 1;
|
|
70
|
+
var isInputDisabled = typeof totalItems === "number" && (!totalPages || totalPages == 1);
|
|
70
71
|
var maxPageValue = typeof totalPages === "number" ? totalPages : 1;
|
|
71
72
|
return /*#__PURE__*/React.createElement("div", _extends({
|
|
72
73
|
className: classnames("pagination", className)
|
|
@@ -95,7 +96,9 @@ var TablePaginationControls = _ref => {
|
|
|
95
96
|
disabled: isInputDisabled,
|
|
96
97
|
min: 1,
|
|
97
98
|
max: maxPageValue
|
|
98
|
-
}), " ", typeof totalPages === "number" ? /*#__PURE__*/React.createElement(
|
|
99
|
+
}), " ", typeof totalPages === "number" ? /*#__PURE__*/React.createElement("div", {
|
|
100
|
+
className: "pagination-item-count"
|
|
101
|
+
}, "of\xA0", totalPages) : null) : null, /*#__PURE__*/React.createElement(Button, _extends({
|
|
99
102
|
"aria-label": Label.NEXT_PAGE,
|
|
100
103
|
className: "next",
|
|
101
104
|
appearance: "base",
|
|
@@ -17,11 +17,12 @@ export declare const generatePagingOptions: (pageLimits: number[]) => {
|
|
|
17
17
|
value: number;
|
|
18
18
|
label: string;
|
|
19
19
|
}[];
|
|
20
|
-
export declare const getDescription: ({ description, isSmallScreen, totalItems, itemName, visibleCount, }: {
|
|
20
|
+
export declare const getDescription: ({ description, isSmallScreen, totalItems, itemName, visibleCount, currentPage, }: {
|
|
21
21
|
description: ReactNode;
|
|
22
22
|
isSmallScreen: boolean;
|
|
23
23
|
totalItems: number;
|
|
24
24
|
itemName: string;
|
|
25
25
|
visibleCount: number;
|
|
26
|
+
currentPage: number;
|
|
26
27
|
}) => string | number | bigint | true | import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | Iterable<ReactNode> | Promise<string | number | bigint | boolean | import("react").ReactPortal | import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | Iterable<ReactNode>>;
|
|
27
28
|
export declare const useFigureSmallScreen: () => boolean;
|
|
@@ -39,18 +39,25 @@ export var getDescription = _ref => {
|
|
|
39
39
|
isSmallScreen,
|
|
40
40
|
totalItems,
|
|
41
41
|
itemName,
|
|
42
|
-
visibleCount
|
|
42
|
+
visibleCount,
|
|
43
|
+
currentPage
|
|
43
44
|
} = _ref;
|
|
44
45
|
if (description) {
|
|
45
46
|
return description;
|
|
46
47
|
}
|
|
48
|
+
var closing = "";
|
|
49
|
+
if (typeof totalItems === "number") {
|
|
50
|
+
closing = " out of ".concat(totalItems);
|
|
51
|
+
} else if (currentPage !== 1) {
|
|
52
|
+
closing = " of more than ".concat(visibleCount);
|
|
53
|
+
}
|
|
47
54
|
if (isSmallScreen) {
|
|
48
|
-
return "".concat(visibleCount
|
|
55
|
+
return "".concat(visibleCount).concat(closing);
|
|
49
56
|
}
|
|
50
57
|
if (visibleCount === totalItems && visibleCount > 1) {
|
|
51
58
|
return "Showing all ".concat(totalItems, " ").concat(itemName, "s");
|
|
52
59
|
}
|
|
53
|
-
return "Showing ".concat(visibleCount
|
|
60
|
+
return "Showing ".concat(visibleCount).concat(closing, " ").concat(itemName).concat(totalItems !== 1 ? "s" : "");
|
|
54
61
|
};
|
|
55
62
|
export var useFigureSmallScreen = () => {
|
|
56
63
|
var [isSmallScreen, setSmallScreen] = useState(false);
|
package/dist/esm/hooks/useId.js
CHANGED
|
@@ -2,7 +2,7 @@ import { useId as useIdReact } from "react";
|
|
|
2
2
|
import { IS_DEV } from "../utils";
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
-
* @deprecated Code component is deprecated. Use
|
|
5
|
+
* @deprecated Code component is deprecated. Use useId from React directly instead.
|
|
6
6
|
*/
|
|
7
7
|
export var useId = () => {
|
|
8
8
|
var id = useIdReact();
|
|
@@ -40,12 +40,13 @@ export var useListener = function useListener(targetNode, callback, eventType) {
|
|
|
40
40
|
targetNode.addEventListener(eventType, eventListener.current, options);
|
|
41
41
|
isListening.current = true;
|
|
42
42
|
}
|
|
43
|
+
return () => {
|
|
44
|
+
// Unattach the listener if the component gets unmounted while
|
|
45
|
+
// listening.
|
|
46
|
+
if (targetNode && eventListener.current && isListening.current) {
|
|
47
|
+
targetNode.removeEventListener(eventType, eventListener.current, options);
|
|
48
|
+
isListening.current = false;
|
|
49
|
+
}
|
|
50
|
+
};
|
|
43
51
|
}, [callback, eventType, options, previousCallback, previousEventType, previousOptions, previousShouldThrottle, previousTargetNode, shouldListen, shouldThrottle, targetNode, throttle]);
|
|
44
|
-
useEffect(() => () => {
|
|
45
|
-
// Unattach the listener if the component gets unmounted while
|
|
46
|
-
// listening.
|
|
47
|
-
if (targetNode && isListening.current) {
|
|
48
|
-
targetNode.removeEventListener(eventType, eventListener.current, options);
|
|
49
|
-
}
|
|
50
|
-
}, [eventType, targetNode, options]);
|
|
51
52
|
};
|
package/dist/esm/index.d.ts
CHANGED
|
@@ -44,6 +44,8 @@ export { default as Panel } from "./components/Panel";
|
|
|
44
44
|
export { default as PasswordToggle } from "./components/PasswordToggle";
|
|
45
45
|
export { default as RadioInput } from "./components/RadioInput";
|
|
46
46
|
export { default as Row } from "./components/Row";
|
|
47
|
+
export { default as ScrollableContainer } from "./components/ScrollableContainer";
|
|
48
|
+
export { default as ScrollableTable } from "./components/ScrollableTable";
|
|
47
49
|
export { default as SearchAndFilter } from "./components/SearchAndFilter";
|
|
48
50
|
export { default as SearchBox } from "./components/SearchBox";
|
|
49
51
|
export { default as Select } from "./components/Select";
|
|
@@ -116,6 +118,8 @@ export type { PaginationProps } from "./components/Pagination";
|
|
|
116
118
|
export type { PanelProps } from "./components/Panel";
|
|
117
119
|
export type { RadioInputProps } from "./components/RadioInput";
|
|
118
120
|
export type { RowProps } from "./components/Row";
|
|
121
|
+
export type { ScrollableTableProps } from "./components/ScrollableTable";
|
|
122
|
+
export type { ScrollableContainerProps } from "./components/ScrollableContainer";
|
|
119
123
|
export type { SearchAndFilterProps } from "./components/SearchAndFilter";
|
|
120
124
|
export type { SearchBoxProps } from "./components/SearchBox";
|
|
121
125
|
export type { SelectProps } from "./components/Select";
|
|
@@ -143,7 +147,7 @@ export type { TablePaginationProps } from "./components/TablePagination";
|
|
|
143
147
|
export type { CustomSelectProps, CustomSelectDropdownProps, CustomSelectOption, } from "./components/CustomSelect";
|
|
144
148
|
export { useOnClickOutside, useClickOutside, useId, useListener, useOnEscapePressed, usePagination, usePrevious, usePrefersReducedMotion, useThrottle, useWindowFitment, } from "./hooks";
|
|
145
149
|
export type { WindowFitment } from "./hooks";
|
|
146
|
-
export { isNavigationAnchor, isNavigationButton } from "./utils";
|
|
150
|
+
export { isNavigationAnchor, isNavigationButton, getElementAbsoluteHeight, getAbsoluteHeightBelowById, getParentsBottomSpacing, } from "./utils";
|
|
147
151
|
export type { ClassName, Headings, PropsWithSpread, SortDirection, SubComponentProps, TSFixMe, ValueOf, } from "./types";
|
|
148
152
|
export { Theme } from "./enums";
|
|
149
153
|
export type { UsePortalOptions } from "./external";
|
package/dist/esm/index.js
CHANGED
|
@@ -44,6 +44,8 @@ export { default as Panel } from "./components/Panel";
|
|
|
44
44
|
export { default as PasswordToggle } from "./components/PasswordToggle";
|
|
45
45
|
export { default as RadioInput } from "./components/RadioInput";
|
|
46
46
|
export { default as Row } from "./components/Row";
|
|
47
|
+
export { default as ScrollableContainer } from "./components/ScrollableContainer";
|
|
48
|
+
export { default as ScrollableTable } from "./components/ScrollableTable";
|
|
47
49
|
export { default as SearchAndFilter } from "./components/SearchAndFilter";
|
|
48
50
|
export { default as SearchBox } from "./components/SearchBox";
|
|
49
51
|
export { default as Select } from "./components/Select";
|
|
@@ -74,6 +76,6 @@ export { default as TablePaginationControls } from "./components/TablePagination
|
|
|
74
76
|
export { default as CustomLayout } from "./components/CustomLayout";
|
|
75
77
|
export { default as CustomSelect } from "./components/CustomSelect";
|
|
76
78
|
export { useOnClickOutside, useClickOutside, useId, useListener, useOnEscapePressed, usePagination, usePrevious, usePrefersReducedMotion, useThrottle, useWindowFitment } from "./hooks";
|
|
77
|
-
export { isNavigationAnchor, isNavigationButton } from "./utils";
|
|
79
|
+
export { isNavigationAnchor, isNavigationButton, getElementAbsoluteHeight, getAbsoluteHeightBelowById, getParentsBottomSpacing } from "./utils";
|
|
78
80
|
export { Theme } from "./enums";
|
|
79
81
|
export { usePortal } from "./external";
|
package/dist/esm/utils.d.ts
CHANGED
|
@@ -25,3 +25,7 @@ export declare const isNavigationButton: (link: NavLink) => link is NavLinkButto
|
|
|
25
25
|
* A typeguard for whether an element is a ReactNode.
|
|
26
26
|
*/
|
|
27
27
|
export declare const isReactNode: (element: unknown) => element is ReactNode;
|
|
28
|
+
export declare const getElementAbsoluteHeight: (element: HTMLElement) => number;
|
|
29
|
+
export declare const getAbsoluteHeightBelowById: (belowId: string) => number;
|
|
30
|
+
export declare const getParentsBottomSpacing: (element: Element) => number;
|
|
31
|
+
export declare const toFloat: (value: string) => number;
|
package/dist/esm/utils.js
CHANGED
|
@@ -38,4 +38,35 @@ export var isNavigationButton = link => !link.url;
|
|
|
38
38
|
/**
|
|
39
39
|
* A typeguard for whether an element is a ReactNode.
|
|
40
40
|
*/
|
|
41
|
-
export var isReactNode = element => /*#__PURE__*/isValidElement(element);
|
|
41
|
+
export var isReactNode = element => /*#__PURE__*/isValidElement(element);
|
|
42
|
+
export var getElementAbsoluteHeight = element => {
|
|
43
|
+
if (!element) {
|
|
44
|
+
return 0;
|
|
45
|
+
}
|
|
46
|
+
var style = window.getComputedStyle(element);
|
|
47
|
+
var margin = toFloat(style.marginTop) + toFloat(style.marginBottom);
|
|
48
|
+
var padding = toFloat(style.paddingTop) + toFloat(style.paddingBottom);
|
|
49
|
+
return element.offsetHeight + margin + padding + 1;
|
|
50
|
+
};
|
|
51
|
+
export var getAbsoluteHeightBelowById = belowId => {
|
|
52
|
+
var element = belowId ? document.getElementById(belowId) : undefined;
|
|
53
|
+
if (!element) {
|
|
54
|
+
return 0;
|
|
55
|
+
}
|
|
56
|
+
return getElementAbsoluteHeight(element);
|
|
57
|
+
};
|
|
58
|
+
export var getParentsBottomSpacing = element => {
|
|
59
|
+
var sum = 0;
|
|
60
|
+
while (element.parentElement) {
|
|
61
|
+
element = element.parentElement;
|
|
62
|
+
var style = window.getComputedStyle(element);
|
|
63
|
+
var margin = toFloat(style.marginBottom);
|
|
64
|
+
var padding = toFloat(style.paddingBottom);
|
|
65
|
+
sum += margin + padding;
|
|
66
|
+
}
|
|
67
|
+
return sum;
|
|
68
|
+
};
|
|
69
|
+
export var toFloat = value => {
|
|
70
|
+
var result = parseFloat(value);
|
|
71
|
+
return Number.isNaN(result) ? 0 : result;
|
|
72
|
+
};
|
package/dist/hooks/useId.d.ts
CHANGED