@atlaskit/table 0.1.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/CHANGELOG.md +7 -0
- package/LICENSE.md +13 -0
- package/README.md +83 -0
- package/constellation/index/examples.mdx +19 -0
- package/constellation/index/props.mdx +32 -0
- package/dist/cjs/body.js +105 -0
- package/dist/cjs/head-cell.js +42 -0
- package/dist/cjs/hooks/selection-provider.js +52 -0
- package/dist/cjs/hooks/use-row-id.js +26 -0
- package/dist/cjs/hooks/use-selectable.js +183 -0
- package/dist/cjs/hooks/use-sorting.js +59 -0
- package/dist/cjs/hooks/use-table-body.js +28 -0
- package/dist/cjs/hooks/use-table.js +56 -0
- package/dist/cjs/index.js +63 -0
- package/dist/cjs/row.js +70 -0
- package/dist/cjs/selectable-cell.js +53 -0
- package/dist/cjs/sortable-column.js +129 -0
- package/dist/cjs/table.js +60 -0
- package/dist/cjs/thead.js +73 -0
- package/dist/cjs/ui/base-cell.js +72 -0
- package/dist/cjs/ui/bulk-action-overlay.js +39 -0
- package/dist/cjs/ui/index.js +69 -0
- package/dist/cjs/ui/selectable-cell.js +39 -0
- package/dist/cjs/ui/table.js +31 -0
- package/dist/cjs/ui/tbody.js +38 -0
- package/dist/cjs/ui/td.js +38 -0
- package/dist/cjs/ui/th.js +40 -0
- package/dist/cjs/ui/thead.js +40 -0
- package/dist/cjs/ui/tr.js +68 -0
- package/dist/cjs/version.json +5 -0
- package/dist/es2019/body.js +66 -0
- package/dist/es2019/head-cell.js +31 -0
- package/dist/es2019/hooks/selection-provider.js +33 -0
- package/dist/es2019/hooks/use-row-id.js +13 -0
- package/dist/es2019/hooks/use-selectable.js +158 -0
- package/dist/es2019/hooks/use-sorting.js +37 -0
- package/dist/es2019/hooks/use-table-body.js +13 -0
- package/dist/es2019/hooks/use-table.js +34 -0
- package/dist/es2019/index.js +7 -0
- package/dist/es2019/row.js +41 -0
- package/dist/es2019/selectable-cell.js +25 -0
- package/dist/es2019/sortable-column.js +109 -0
- package/dist/es2019/table.js +38 -0
- package/dist/es2019/thead.js +46 -0
- package/dist/es2019/ui/base-cell.js +54 -0
- package/dist/es2019/ui/bulk-action-overlay.js +27 -0
- package/dist/es2019/ui/index.js +11 -0
- package/dist/es2019/ui/selectable-cell.js +28 -0
- package/dist/es2019/ui/table.js +22 -0
- package/dist/es2019/ui/tbody.js +26 -0
- package/dist/es2019/ui/td.js +21 -0
- package/dist/es2019/ui/th.js +26 -0
- package/dist/es2019/ui/thead.js +31 -0
- package/dist/es2019/ui/tr.js +55 -0
- package/dist/es2019/version.json +5 -0
- package/dist/esm/body.js +84 -0
- package/dist/esm/head-cell.js +31 -0
- package/dist/esm/hooks/selection-provider.js +32 -0
- package/dist/esm/hooks/use-row-id.js +15 -0
- package/dist/esm/hooks/use-selectable.js +171 -0
- package/dist/esm/hooks/use-sorting.js +46 -0
- package/dist/esm/hooks/use-table-body.js +13 -0
- package/dist/esm/hooks/use-table.js +36 -0
- package/dist/esm/index.js +7 -0
- package/dist/esm/row.js +46 -0
- package/dist/esm/selectable-cell.js +31 -0
- package/dist/esm/sortable-column.js +114 -0
- package/dist/esm/table.js +39 -0
- package/dist/esm/thead.js +51 -0
- package/dist/esm/ui/base-cell.js +58 -0
- package/dist/esm/ui/bulk-action-overlay.js +28 -0
- package/dist/esm/ui/index.js +11 -0
- package/dist/esm/ui/selectable-cell.js +28 -0
- package/dist/esm/ui/table.js +21 -0
- package/dist/esm/ui/tbody.js +27 -0
- package/dist/esm/ui/td.js +26 -0
- package/dist/esm/ui/th.js +28 -0
- package/dist/esm/ui/thead.js +30 -0
- package/dist/esm/ui/tr.js +55 -0
- package/dist/esm/version.json +5 -0
- package/dist/types/body.d.ts +15 -0
- package/dist/types/head-cell.d.ts +10 -0
- package/dist/types/hooks/selection-provider.d.ts +25 -0
- package/dist/types/hooks/use-row-id.d.ts +10 -0
- package/dist/types/hooks/use-selectable.d.ts +14 -0
- package/dist/types/hooks/use-sorting.d.ts +6 -0
- package/dist/types/hooks/use-table-body.d.ts +7 -0
- package/dist/types/hooks/use-table.d.ts +21 -0
- package/dist/types/index.d.ts +7 -0
- package/dist/types/row.d.ts +14 -0
- package/dist/types/selectable-cell.d.ts +3 -0
- package/dist/types/sortable-column.d.ts +17 -0
- package/dist/types/table.d.ts +26 -0
- package/dist/types/thead.d.ts +7 -0
- package/dist/types/ui/base-cell.d.ts +30 -0
- package/dist/types/ui/bulk-action-overlay.d.ts +8 -0
- package/dist/types/ui/index.d.ts +11 -0
- package/dist/types/ui/selectable-cell.d.ts +10 -0
- package/dist/types/ui/table.d.ts +23 -0
- package/dist/types/ui/tbody.d.ts +8 -0
- package/dist/types/ui/td.d.ts +11 -0
- package/dist/types/ui/th.d.ts +11 -0
- package/dist/types/ui/thead.d.ts +10 -0
- package/dist/types/ui/tr.d.ts +16 -0
- package/package.json +101 -0
- package/primitives/package.json +15 -0
- package/report.api.md +139 -0
- package/tmp/api-report-tmp.d.ts +99 -0
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.SelectableCell = void 0;
|
|
7
|
+
|
|
8
|
+
var _react = require("@emotion/react");
|
|
9
|
+
|
|
10
|
+
var _baseCell = require("./base-cell");
|
|
11
|
+
|
|
12
|
+
/** @jsx jsx */
|
|
13
|
+
var spacingStyles = (0, _react.css)({
|
|
14
|
+
width: 32,
|
|
15
|
+
padding: "var(--ds-space-0, 0px)",
|
|
16
|
+
paddingLeft: "var(--ds-space-100, 8px)",
|
|
17
|
+
// eslint-disable-next-line @repo/internal/styles/no-nested-styles
|
|
18
|
+
'& + *': {
|
|
19
|
+
// eslint-disable-next-line @atlaskit/design-system/ensure-design-token-usage-spacing
|
|
20
|
+
paddingLeft: '8px !important'
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
/**
|
|
24
|
+
* __Selectable cell__
|
|
25
|
+
*
|
|
26
|
+
* A selectable cell primitive designed to be used for light weight composition.
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
var SelectableCell = function SelectableCell(_ref) {
|
|
30
|
+
var children = _ref.children,
|
|
31
|
+
_ref$as = _ref.as,
|
|
32
|
+
as = _ref$as === void 0 ? 'td' : _ref$as;
|
|
33
|
+
return (0, _react.jsx)(_baseCell.BaseCell, {
|
|
34
|
+
as: as,
|
|
35
|
+
css: spacingStyles
|
|
36
|
+
}, children);
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
exports.SelectableCell = SelectableCell;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.Table = void 0;
|
|
7
|
+
|
|
8
|
+
var _react = require("@emotion/react");
|
|
9
|
+
|
|
10
|
+
/** @jsx jsx */
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* __Table__
|
|
14
|
+
*
|
|
15
|
+
* A primitive table container. Applies the HTML native element with no other styling.
|
|
16
|
+
*
|
|
17
|
+
* - [Examples](https://atlassian.design/components/table/examples)
|
|
18
|
+
*
|
|
19
|
+
* @primitive
|
|
20
|
+
* @see https://hello.atlassian.net/wiki/spaces/DST/pages/1947062524/Dynamic+table+2.0+implementation+spec
|
|
21
|
+
*/
|
|
22
|
+
var Table = function Table(_ref) {
|
|
23
|
+
var children = _ref.children,
|
|
24
|
+
testId = _ref.testId,
|
|
25
|
+
summary = _ref.summary;
|
|
26
|
+
return (0, _react.jsx)("table", {
|
|
27
|
+
"data-testid": testId
|
|
28
|
+
}, summary && (0, _react.jsx)("caption", null, summary), children);
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
exports.Table = Table;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = exports.TBody = void 0;
|
|
7
|
+
|
|
8
|
+
var _react = require("@emotion/react");
|
|
9
|
+
|
|
10
|
+
/* eslint-disable @repo/internal/react/no-clone-element */
|
|
11
|
+
|
|
12
|
+
/** @jsx jsx */
|
|
13
|
+
var bodyStyles = (0, _react.css)({
|
|
14
|
+
position: 'relative',
|
|
15
|
+
border: 'none',
|
|
16
|
+
'&:after': {
|
|
17
|
+
position: 'absolute',
|
|
18
|
+
boxShadow: "inset 0 -2px 0 0 ".concat("var(--ds-border, #eee)"),
|
|
19
|
+
content: "''",
|
|
20
|
+
inset: 0,
|
|
21
|
+
pointerEvents: 'none'
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
/**
|
|
25
|
+
* __TBody__
|
|
26
|
+
* @primitive
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
var TBody = function TBody(_ref) {
|
|
30
|
+
var children = _ref.children;
|
|
31
|
+
return (0, _react.jsx)("tbody", {
|
|
32
|
+
css: bodyStyles
|
|
33
|
+
}, children);
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
exports.TBody = TBody;
|
|
37
|
+
var _default = TBody;
|
|
38
|
+
exports.default = _default;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
+
|
|
5
|
+
Object.defineProperty(exports, "__esModule", {
|
|
6
|
+
value: true
|
|
7
|
+
});
|
|
8
|
+
exports.TD = void 0;
|
|
9
|
+
|
|
10
|
+
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
|
|
11
|
+
|
|
12
|
+
var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties"));
|
|
13
|
+
|
|
14
|
+
var _react = require("@emotion/react");
|
|
15
|
+
|
|
16
|
+
var _baseCell = require("./base-cell");
|
|
17
|
+
|
|
18
|
+
var _excluded = ["testId"];
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* __Cell__
|
|
22
|
+
*
|
|
23
|
+
* A data cell.
|
|
24
|
+
*
|
|
25
|
+
* @primitive
|
|
26
|
+
*/
|
|
27
|
+
var TD = function TD(_ref) {
|
|
28
|
+
var testId = _ref.testId,
|
|
29
|
+
props = (0, _objectWithoutProperties2.default)(_ref, _excluded);
|
|
30
|
+
return (// eslint-disable-next-line @repo/internal/react/no-unsafe-spread-props
|
|
31
|
+
(0, _react.jsx)(_baseCell.BaseCell, (0, _extends2.default)({
|
|
32
|
+
as: "td",
|
|
33
|
+
testId: testId
|
|
34
|
+
}, props))
|
|
35
|
+
);
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
exports.TD = TD;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
+
|
|
5
|
+
Object.defineProperty(exports, "__esModule", {
|
|
6
|
+
value: true
|
|
7
|
+
});
|
|
8
|
+
exports.TH = void 0;
|
|
9
|
+
|
|
10
|
+
var _react = _interopRequireDefault(require("react"));
|
|
11
|
+
|
|
12
|
+
var _baseCell = require("./base-cell");
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* __Head cell__
|
|
16
|
+
*
|
|
17
|
+
* A head cell.
|
|
18
|
+
*
|
|
19
|
+
* @primitive
|
|
20
|
+
*/
|
|
21
|
+
var TH = function TH(_ref) {
|
|
22
|
+
var children = _ref.children,
|
|
23
|
+
testId = _ref.testId,
|
|
24
|
+
align = _ref.align,
|
|
25
|
+
scope = _ref.scope,
|
|
26
|
+
backgroundColor = _ref.backgroundColor;
|
|
27
|
+
return (
|
|
28
|
+
/*#__PURE__*/
|
|
29
|
+
// eslint-disable-next-line @repo/internal/react/no-unsafe-spread-props
|
|
30
|
+
_react.default.createElement(_baseCell.BaseCell, {
|
|
31
|
+
as: "th",
|
|
32
|
+
testId: testId,
|
|
33
|
+
align: align,
|
|
34
|
+
scope: scope,
|
|
35
|
+
backgroundColor: backgroundColor
|
|
36
|
+
}, children)
|
|
37
|
+
);
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
exports.TH = TH;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.THead = void 0;
|
|
7
|
+
|
|
8
|
+
var _react = require("@emotion/react");
|
|
9
|
+
|
|
10
|
+
/** @jsx jsx */
|
|
11
|
+
var baseStyles = (0, _react.css)({
|
|
12
|
+
position: 'sticky',
|
|
13
|
+
zIndex: 1,
|
|
14
|
+
backgroundColor: "var(--ds-surface, white)",
|
|
15
|
+
border: 'none',
|
|
16
|
+
inset: 0,
|
|
17
|
+
'&:after': {
|
|
18
|
+
position: 'absolute',
|
|
19
|
+
boxShadow: "inset 0 -2px 0 0 ".concat("var(--ds-border, #eee)"),
|
|
20
|
+
content: "''",
|
|
21
|
+
inset: 0,
|
|
22
|
+
pointerEvents: 'none'
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
/**
|
|
26
|
+
* __THead__
|
|
27
|
+
*
|
|
28
|
+
* A primitive table head container. Applies the HTML native element with minimal styling.
|
|
29
|
+
*
|
|
30
|
+
* @primitive
|
|
31
|
+
*/
|
|
32
|
+
|
|
33
|
+
var THead = function THead(_ref) {
|
|
34
|
+
var children = _ref.children;
|
|
35
|
+
return (0, _react.jsx)("thead", {
|
|
36
|
+
css: baseStyles
|
|
37
|
+
}, children);
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
exports.THead = THead;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
+
|
|
5
|
+
Object.defineProperty(exports, "__esModule", {
|
|
6
|
+
value: true
|
|
7
|
+
});
|
|
8
|
+
exports.TR = void 0;
|
|
9
|
+
|
|
10
|
+
var _react = require("@emotion/react");
|
|
11
|
+
|
|
12
|
+
var _focusRing = _interopRequireDefault(require("@atlaskit/focus-ring"));
|
|
13
|
+
|
|
14
|
+
/** @jsx jsx */
|
|
15
|
+
var baseStyles = (0, _react.css)({
|
|
16
|
+
height: 48,
|
|
17
|
+
position: 'relative',
|
|
18
|
+
border: 'none',
|
|
19
|
+
borderImageWidth: 0,
|
|
20
|
+
borderSpacing: 0
|
|
21
|
+
});
|
|
22
|
+
var selectedStyles = (0, _react.css)({
|
|
23
|
+
backgroundColor: "var(--ds-background-selected, #DEEBFF88)",
|
|
24
|
+
'&:hover': {
|
|
25
|
+
backgroundColor: "var(--ds-background-selected-hovered, #DEEBFF)" // B50
|
|
26
|
+
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
var bodyRowStyles = (0, _react.css)({
|
|
30
|
+
'&:hover': {
|
|
31
|
+
backgroundColor: "var(--ds-background-neutral-subtle-hovered, #f8f8f8)"
|
|
32
|
+
},
|
|
33
|
+
'&:focus-visible::after': {
|
|
34
|
+
boxShadow: 'none'
|
|
35
|
+
},
|
|
36
|
+
'&:after': {
|
|
37
|
+
position: 'absolute',
|
|
38
|
+
boxShadow: "inset 0 -1px 0 0 ".concat("var(--ds-border, #eee)"),
|
|
39
|
+
content: "''",
|
|
40
|
+
inset: 0,
|
|
41
|
+
pointerEvents: 'none'
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* __Row__
|
|
47
|
+
*
|
|
48
|
+
* A row primitive.
|
|
49
|
+
*
|
|
50
|
+
* - [Examples](https://atlassian.design/components/table/examples)
|
|
51
|
+
*/
|
|
52
|
+
var TR = function TR(_ref) {
|
|
53
|
+
var children = _ref.children,
|
|
54
|
+
testId = _ref.testId,
|
|
55
|
+
isSelected = _ref.isSelected,
|
|
56
|
+
_ref$isBodyRow = _ref.isBodyRow,
|
|
57
|
+
isBodyRow = _ref$isBodyRow === void 0 ? true : _ref$isBodyRow;
|
|
58
|
+
return (0, _react.jsx)(_focusRing.default, {
|
|
59
|
+
isInset: true
|
|
60
|
+
}, (0, _react.jsx)("tr", {
|
|
61
|
+
tabIndex: -1,
|
|
62
|
+
"aria-selected": isSelected,
|
|
63
|
+
"data-testid": testId,
|
|
64
|
+
css: [baseStyles, isBodyRow && bodyRowStyles, isSelected && selectedStyles]
|
|
65
|
+
}, children));
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
exports.TR = TR;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/* eslint-disable @repo/internal/react/no-clone-element */
|
|
2
|
+
|
|
3
|
+
/** @jsx jsx */
|
|
4
|
+
import { Children, useEffect } from 'react';
|
|
5
|
+
import { jsx } from '@emotion/react';
|
|
6
|
+
import { useSelection } from './hooks/selection-provider';
|
|
7
|
+
import { RowProvider } from './hooks/use-row-id';
|
|
8
|
+
import { useTable } from './hooks/use-table';
|
|
9
|
+
import { TableBodyProvider } from './hooks/use-table-body';
|
|
10
|
+
import * as Primitives from './ui';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* __Table body__
|
|
14
|
+
*/
|
|
15
|
+
function TBody({
|
|
16
|
+
rows,
|
|
17
|
+
children
|
|
18
|
+
}) {
|
|
19
|
+
const {
|
|
20
|
+
sortKey,
|
|
21
|
+
sortDirection
|
|
22
|
+
} = useTable();
|
|
23
|
+
const [_state, {
|
|
24
|
+
removeAll,
|
|
25
|
+
setMax
|
|
26
|
+
}] = useSelection(); // TODO this seems like something the user should control
|
|
27
|
+
|
|
28
|
+
useEffect(() => {
|
|
29
|
+
if (removeAll) {
|
|
30
|
+
removeAll();
|
|
31
|
+
} // eslint-disable-next-line react-hooks/exhaustive-deps
|
|
32
|
+
|
|
33
|
+
}, [rows]); // Set data length (via setMax) whenever data changes
|
|
34
|
+
|
|
35
|
+
useEffect(() => {
|
|
36
|
+
const numRows = rows !== undefined ? rows.length : Children.count(children);
|
|
37
|
+
setMax && setMax(numRows); // eslint-disable-next-line react-hooks/exhaustive-deps
|
|
38
|
+
}, [rows === null || rows === void 0 ? void 0 : rows.length, Children.count(children)]);
|
|
39
|
+
|
|
40
|
+
const sortFn = (rowA, rowB) => {
|
|
41
|
+
if (sortKey === 'unset') {
|
|
42
|
+
return 0;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const ascendingComparator = rowA[sortKey] < rowB[sortKey] ? -1 : 1;
|
|
46
|
+
return sortDirection === 'ascending' ? ascendingComparator : -ascendingComparator;
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
return jsx(TableBodyProvider, {
|
|
50
|
+
value: true
|
|
51
|
+
}, jsx(Primitives.TBody, null, typeof children === 'function' && rows ? rows.map((row, idx) => ({ ...row,
|
|
52
|
+
idx
|
|
53
|
+
})).sort(sortFn).map(({
|
|
54
|
+
idx,
|
|
55
|
+
...row
|
|
56
|
+
}) => jsx(RowProvider, {
|
|
57
|
+
key: idx,
|
|
58
|
+
value: idx
|
|
59
|
+
}, // @ts-expect-error
|
|
60
|
+
children(row))) : Children.map(children, (row, idx) => jsx(RowProvider, {
|
|
61
|
+
key: idx,
|
|
62
|
+
value: idx
|
|
63
|
+
}, row))));
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export default TBody;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/* eslint-disable no-unused-vars */
|
|
2
|
+
|
|
3
|
+
/** @jsx jsx */
|
|
4
|
+
import { jsx } from '@emotion/react';
|
|
5
|
+
import { UNSAFE_Text as Text } from '@atlaskit/ds-explorations';
|
|
6
|
+
import { TH } from './ui/th';
|
|
7
|
+
/**
|
|
8
|
+
* __HeadCell__
|
|
9
|
+
*
|
|
10
|
+
* HeadCell element
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
const Column = ({
|
|
14
|
+
children,
|
|
15
|
+
align,
|
|
16
|
+
testId,
|
|
17
|
+
backgroundColor,
|
|
18
|
+
scope = 'col'
|
|
19
|
+
}) => {
|
|
20
|
+
return jsx(TH, {
|
|
21
|
+
scope: scope,
|
|
22
|
+
align: align,
|
|
23
|
+
testId: testId,
|
|
24
|
+
backgroundColor: backgroundColor
|
|
25
|
+
}, jsx(Text, {
|
|
26
|
+
color: "color.text",
|
|
27
|
+
fontWeight: "500"
|
|
28
|
+
}, children));
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export default Column;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import React, { createContext, useContext } from 'react';
|
|
2
|
+
import useSelectionReducer from './use-selectable';
|
|
3
|
+
const SelectionContext = /*#__PURE__*/createContext([{
|
|
4
|
+
checked: [],
|
|
5
|
+
allChecked: false,
|
|
6
|
+
anyChecked: false,
|
|
7
|
+
maxChecked: 0,
|
|
8
|
+
selectionStart: -1,
|
|
9
|
+
previousSelection: []
|
|
10
|
+
}, {}]);
|
|
11
|
+
/**
|
|
12
|
+
* __Selection provider__
|
|
13
|
+
*
|
|
14
|
+
* A selection provider injects selection specific state into the table.
|
|
15
|
+
*
|
|
16
|
+
* - [Examples](https://atlassian.design/components/{packageName}/examples)
|
|
17
|
+
* - [Code](https://atlassian.design/components/{packageName}/code)
|
|
18
|
+
* - [Usage](https://atlassian.design/components/{packageName}/usage)
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
const SelectionProvider = ({
|
|
22
|
+
children
|
|
23
|
+
}) => {
|
|
24
|
+
const reducer = useSelectionReducer();
|
|
25
|
+
return /*#__PURE__*/React.createElement(SelectionContext.Provider, {
|
|
26
|
+
value: reducer
|
|
27
|
+
}, children);
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export const useSelection = () => {
|
|
31
|
+
return useContext(SelectionContext);
|
|
32
|
+
};
|
|
33
|
+
export default SelectionProvider;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { createContext, useContext } from 'react';
|
|
2
|
+
const RowContext = /*#__PURE__*/createContext(undefined);
|
|
3
|
+
/**
|
|
4
|
+
* @internal
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export const useRowId = () => useContext(RowContext);
|
|
8
|
+
/**
|
|
9
|
+
* __Row provider__
|
|
10
|
+
* @internal
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
export const RowProvider = RowContext.Provider;
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import { useCallback, useReducer } from 'react';
|
|
2
|
+
const defaultState = {
|
|
3
|
+
checked: [],
|
|
4
|
+
allChecked: false,
|
|
5
|
+
anyChecked: false,
|
|
6
|
+
maxChecked: 0,
|
|
7
|
+
selectionStart: -1,
|
|
8
|
+
previousSelection: []
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
const arrayFromRange = (from, to) => {
|
|
12
|
+
let startIdx = from;
|
|
13
|
+
let stopIdx = to;
|
|
14
|
+
let increment = 1;
|
|
15
|
+
|
|
16
|
+
if (from > to) {
|
|
17
|
+
startIdx = to;
|
|
18
|
+
stopIdx = from;
|
|
19
|
+
increment = 0;
|
|
20
|
+
} // Create an array with values between `from` and `to` - either ascending or descending
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
return Array.from({
|
|
24
|
+
length: stopIdx - startIdx
|
|
25
|
+
}, (_, i) => startIdx + i + increment);
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
function reducer({
|
|
29
|
+
checked,
|
|
30
|
+
anyChecked,
|
|
31
|
+
maxChecked,
|
|
32
|
+
selectionStart,
|
|
33
|
+
previousSelection
|
|
34
|
+
}, action) {
|
|
35
|
+
switch (action.type) {
|
|
36
|
+
case 'toggle_selection':
|
|
37
|
+
{
|
|
38
|
+
const {
|
|
39
|
+
value: {
|
|
40
|
+
id,
|
|
41
|
+
shiftHeld
|
|
42
|
+
}
|
|
43
|
+
} = action;
|
|
44
|
+
let updated = checked.slice();
|
|
45
|
+
let newSelectionStart = selectionStart;
|
|
46
|
+
let newPreviousSelection = previousSelection.slice();
|
|
47
|
+
|
|
48
|
+
if (shiftHeld) {
|
|
49
|
+
if (checked.length > 0) {
|
|
50
|
+
const newIds = arrayFromRange(selectionStart, id); // create an array of the new ids
|
|
51
|
+
// Uncheck ids from the previous selection.
|
|
52
|
+
// This is done to maintain consistency with Shift-select behaviour elsewhere (e.g. macOS)
|
|
53
|
+
// TODO: Code could be improved to only remove ids that are not included in the new range, avoiding needing to re-add them below
|
|
54
|
+
|
|
55
|
+
updated = updated.filter(id => !previousSelection.includes(id));
|
|
56
|
+
newIds.forEach(id => updated.indexOf(id) === -1 && updated.push(id) // If the new id is not already checked, check it
|
|
57
|
+
);
|
|
58
|
+
newPreviousSelection = newIds; // Maintain an array of the previous selection to allow for consistent Shift-select behaviour
|
|
59
|
+
}
|
|
60
|
+
} else {
|
|
61
|
+
const checkedIndex = checked.indexOf(id); // is index already checked
|
|
62
|
+
|
|
63
|
+
if (checkedIndex !== -1) {
|
|
64
|
+
updated.splice(checkedIndex, 1); // if index is already checked, uncheck
|
|
65
|
+
} else {
|
|
66
|
+
updated.push(id); // if index is not checked, check
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
newSelectionStart = id; // Reset selection start id to this non-shift-selected id
|
|
70
|
+
|
|
71
|
+
newPreviousSelection = []; // Reset previous selection as it is no longer relevant once a new non-shift-selected id is added
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const anyChecked = updated.length > 0;
|
|
75
|
+
return {
|
|
76
|
+
checked: updated,
|
|
77
|
+
allChecked: updated.length === maxChecked,
|
|
78
|
+
anyChecked: anyChecked || Boolean(updated[id]),
|
|
79
|
+
maxChecked,
|
|
80
|
+
selectionStart: newSelectionStart,
|
|
81
|
+
previousSelection: newPreviousSelection
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
case 'set_root':
|
|
86
|
+
return {
|
|
87
|
+
checked: action.value ? Array.from(Array(maxChecked).keys()) : [],
|
|
88
|
+
allChecked: action.value,
|
|
89
|
+
anyChecked: Boolean(action.value),
|
|
90
|
+
maxChecked,
|
|
91
|
+
selectionStart,
|
|
92
|
+
previousSelection
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
case 'set_max':
|
|
96
|
+
{
|
|
97
|
+
const {
|
|
98
|
+
value: max
|
|
99
|
+
} = action;
|
|
100
|
+
return {
|
|
101
|
+
maxChecked: max,
|
|
102
|
+
allChecked: checked.length === max,
|
|
103
|
+
anyChecked,
|
|
104
|
+
checked,
|
|
105
|
+
selectionStart,
|
|
106
|
+
previousSelection
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
default:
|
|
111
|
+
throw new Error();
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
const initialiseState = () => {
|
|
116
|
+
return { ...defaultState,
|
|
117
|
+
checked: []
|
|
118
|
+
};
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
function useSelectable() {
|
|
122
|
+
const [state, dispatch] = useReducer(reducer, initialiseState());
|
|
123
|
+
const toggleSelection = useCallback((id, shiftHeld) => {
|
|
124
|
+
dispatch({
|
|
125
|
+
type: 'toggle_selection',
|
|
126
|
+
value: {
|
|
127
|
+
id,
|
|
128
|
+
shiftHeld
|
|
129
|
+
}
|
|
130
|
+
});
|
|
131
|
+
}, []);
|
|
132
|
+
const setAll = useCallback(() => {
|
|
133
|
+
dispatch({
|
|
134
|
+
type: 'set_root',
|
|
135
|
+
value: true
|
|
136
|
+
});
|
|
137
|
+
}, []);
|
|
138
|
+
const removeAll = useCallback(() => {
|
|
139
|
+
dispatch({
|
|
140
|
+
type: 'set_root',
|
|
141
|
+
value: false
|
|
142
|
+
});
|
|
143
|
+
}, []);
|
|
144
|
+
const setMax = useCallback(max => {
|
|
145
|
+
dispatch({
|
|
146
|
+
type: 'set_max',
|
|
147
|
+
value: max
|
|
148
|
+
});
|
|
149
|
+
}, []);
|
|
150
|
+
return [state, {
|
|
151
|
+
setAll,
|
|
152
|
+
removeAll,
|
|
153
|
+
toggleSelection,
|
|
154
|
+
setMax
|
|
155
|
+
}];
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
export default useSelectable;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { useCallback, useState } from 'react';
|
|
2
|
+
export const useSorting = sortKey => {
|
|
3
|
+
const [localSortKey, setLocalSortKey] = useState(sortKey);
|
|
4
|
+
const [localSortDirection, setLocalSortDirection] = useState();
|
|
5
|
+
const toggleSortDirection = useCallback(() => {
|
|
6
|
+
setLocalSortDirection(oldLocalSortDirection => {
|
|
7
|
+
switch (oldLocalSortDirection) {
|
|
8
|
+
case undefined:
|
|
9
|
+
return 'ascending';
|
|
10
|
+
|
|
11
|
+
case 'ascending':
|
|
12
|
+
return 'descending';
|
|
13
|
+
|
|
14
|
+
case 'descending':
|
|
15
|
+
return 'ascending';
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
}, []);
|
|
19
|
+
const setSortState = useCallback(key => {
|
|
20
|
+
setLocalSortKey(localSortKey => {
|
|
21
|
+
if (key !== localSortKey) {
|
|
22
|
+
// sorting by different column
|
|
23
|
+
setLocalSortDirection('ascending');
|
|
24
|
+
return key;
|
|
25
|
+
} else {
|
|
26
|
+
toggleSortDirection();
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return localSortKey;
|
|
30
|
+
});
|
|
31
|
+
}, [toggleSortDirection]);
|
|
32
|
+
return {
|
|
33
|
+
sortKey: localSortKey,
|
|
34
|
+
sortDirection: localSortDirection,
|
|
35
|
+
setSortState
|
|
36
|
+
};
|
|
37
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { createContext, useContext } from 'react';
|
|
2
|
+
import invariant from 'tiny-invariant';
|
|
3
|
+
const TableBodyContext = /*#__PURE__*/createContext(false);
|
|
4
|
+
/**
|
|
5
|
+
* __Table body provider__
|
|
6
|
+
* Ensures correct nesting of table elements.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
export const TableBodyProvider = TableBodyContext.Provider;
|
|
10
|
+
export const useTableBody = () => {
|
|
11
|
+
const hasTableBody = useContext(TableBodyContext);
|
|
12
|
+
invariant(hasTableBody, '<Row /> must be nested inside a <TableBody>');
|
|
13
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import React, { createContext, useContext } from 'react';
|
|
2
|
+
import __noop from '@atlaskit/ds-lib/noop';
|
|
3
|
+
|
|
4
|
+
function generateContext() {
|
|
5
|
+
return /*#__PURE__*/createContext({
|
|
6
|
+
isSelectable: false,
|
|
7
|
+
sortKey: 'unset',
|
|
8
|
+
setSortState: __noop
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const TableContext = generateContext();
|
|
13
|
+
/**
|
|
14
|
+
* __Table state provider__
|
|
15
|
+
*
|
|
16
|
+
* The table context provides the data required for more complex functionality.
|
|
17
|
+
*
|
|
18
|
+
* - [Examples](https://atlassian.design/components/table/examples)
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
export function TableProvider({
|
|
22
|
+
children,
|
|
23
|
+
state
|
|
24
|
+
}) {
|
|
25
|
+
return (
|
|
26
|
+
/*#__PURE__*/
|
|
27
|
+
// @ts-expect-error
|
|
28
|
+
React.createElement(TableContext.Provider, {
|
|
29
|
+
value: state
|
|
30
|
+
}, children)
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
export const useTable = () => // @ts-expect-error
|
|
34
|
+
useContext(TableContext);
|