@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,7 @@
|
|
|
1
|
+
export { default } from './table';
|
|
2
|
+
export { default as TBody } from './body';
|
|
3
|
+
export { default as Row } from './row';
|
|
4
|
+
export { TD as Cell } from './ui';
|
|
5
|
+
export { default as HeadCell } from './head-cell';
|
|
6
|
+
export { default as SortableColumn } from './sortable-column';
|
|
7
|
+
export { default as THead } from './thead';
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/** @jsx jsx */
|
|
2
|
+
import { memo } from 'react';
|
|
3
|
+
import { jsx } from '@emotion/react';
|
|
4
|
+
import { useSelection } from './hooks/selection-provider';
|
|
5
|
+
import { useRowId } from './hooks/use-row-id';
|
|
6
|
+
import { useTable } from './hooks/use-table';
|
|
7
|
+
import { useTableBody } from './hooks/use-table-body';
|
|
8
|
+
import SelectableCell from './selectable-cell';
|
|
9
|
+
import * as Primitives from './ui';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* __Row__
|
|
13
|
+
*
|
|
14
|
+
* A table row.
|
|
15
|
+
*
|
|
16
|
+
* - [Examples](https://atlassian.design/components/table/examples)
|
|
17
|
+
*/
|
|
18
|
+
const Row = /*#__PURE__*/memo(({
|
|
19
|
+
children,
|
|
20
|
+
testId
|
|
21
|
+
}) => {
|
|
22
|
+
// To ensure valid nesting
|
|
23
|
+
useTableBody(); // to access table state
|
|
24
|
+
|
|
25
|
+
const table = useTable();
|
|
26
|
+
const [selectionState] = useSelection();
|
|
27
|
+
const rowId = useRowId();
|
|
28
|
+
|
|
29
|
+
if (!table.isSelectable) {
|
|
30
|
+
return jsx(Primitives.TR, {
|
|
31
|
+
testId: testId
|
|
32
|
+
}, children);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const isChecked = selectionState.allChecked || selectionState.checked.includes(rowId);
|
|
36
|
+
return jsx(Primitives.TR, {
|
|
37
|
+
isSelected: !!isChecked,
|
|
38
|
+
testId: testId
|
|
39
|
+
}, jsx(SelectableCell, null), children);
|
|
40
|
+
});
|
|
41
|
+
export default Row;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/** @jsx jsx */
|
|
2
|
+
import { memo, useCallback } from 'react';
|
|
3
|
+
import { jsx } from '@emotion/react';
|
|
4
|
+
import Checkbox from '@atlaskit/checkbox';
|
|
5
|
+
import { useSelection } from './hooks/selection-provider';
|
|
6
|
+
import { useRowId } from './hooks/use-row-id';
|
|
7
|
+
import * as Primitives from './ui';
|
|
8
|
+
|
|
9
|
+
const SelectableCell = () => {
|
|
10
|
+
const [state, {
|
|
11
|
+
toggleSelection
|
|
12
|
+
}] = useSelection();
|
|
13
|
+
const idx = useRowId();
|
|
14
|
+
const isChecked = state.allChecked || state.checked.includes(idx);
|
|
15
|
+
const onChange = useCallback(e => toggleSelection(idx, e.nativeEvent.shiftKey), // eslint-disable-next-line react-hooks/exhaustive-deps
|
|
16
|
+
[idx]);
|
|
17
|
+
return jsx(Primitives.SelectableCell, {
|
|
18
|
+
as: "td"
|
|
19
|
+
}, jsx(Checkbox, {
|
|
20
|
+
isChecked: isChecked,
|
|
21
|
+
onChange: onChange
|
|
22
|
+
}));
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export default /*#__PURE__*/memo(SelectableCell);
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import _extends from "@babel/runtime/helpers/extends";
|
|
2
|
+
|
|
3
|
+
/* eslint-disable no-unused-vars */
|
|
4
|
+
|
|
5
|
+
/** @jsx jsx */
|
|
6
|
+
import { css, jsx } from '@emotion/react';
|
|
7
|
+
import Button from '@atlaskit/button';
|
|
8
|
+
import ArrowDownIcon from '@atlaskit/icon/glyph/arrow-down';
|
|
9
|
+
import ArrowUpIcon from '@atlaskit/icon/glyph/arrow-up';
|
|
10
|
+
import Tooltip from '@atlaskit/tooltip';
|
|
11
|
+
import { useTable } from './hooks/use-table';
|
|
12
|
+
import { TH } from './ui';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* TODO these need to be i18n supported
|
|
16
|
+
*/
|
|
17
|
+
const sortingMessages = {
|
|
18
|
+
unsorted: {
|
|
19
|
+
string: 'Sort from A to Z',
|
|
20
|
+
number: 'Sort from 0 to 9'
|
|
21
|
+
},
|
|
22
|
+
ascending: {
|
|
23
|
+
string: 'Sort from A to Z',
|
|
24
|
+
number: 'Sort from 0 to 9'
|
|
25
|
+
},
|
|
26
|
+
descending: {
|
|
27
|
+
string: 'Sort from Z to A',
|
|
28
|
+
number: 'Sort from 9 to 0'
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
const overrideStyles = css({
|
|
32
|
+
// eslint-disable-next-line @atlaskit/design-system/ensure-design-token-usage-spacing
|
|
33
|
+
margin: '0 -2px !important',
|
|
34
|
+
gap: "var(--ds-space-050, 4px)",
|
|
35
|
+
// eslint-disable-next-line @atlaskit/design-system/ensure-design-token-usage-spacing
|
|
36
|
+
paddingInline: `2px !important`
|
|
37
|
+
});
|
|
38
|
+
/**
|
|
39
|
+
* __SortableColumn__
|
|
40
|
+
*
|
|
41
|
+
* SortableColumn is used in place of the default Column when sorting is desired.
|
|
42
|
+
*/
|
|
43
|
+
|
|
44
|
+
const SortableColumn = ({
|
|
45
|
+
name,
|
|
46
|
+
testId,
|
|
47
|
+
onClick,
|
|
48
|
+
children,
|
|
49
|
+
...other
|
|
50
|
+
}) => {
|
|
51
|
+
const {
|
|
52
|
+
sortKey,
|
|
53
|
+
sortDirection,
|
|
54
|
+
setSortState
|
|
55
|
+
} = useTable();
|
|
56
|
+
|
|
57
|
+
const getSortMessage = () => {
|
|
58
|
+
if (sortKey === name) {
|
|
59
|
+
// TODO: Change message depending on data type (string/number)
|
|
60
|
+
return sortingMessages[sortDirection || 'unsorted'].string;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return sortingMessages.unsorted.string;
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
const getSortIcon = () => {
|
|
67
|
+
if (sortKey === name) {
|
|
68
|
+
switch (sortDirection) {
|
|
69
|
+
case undefined:
|
|
70
|
+
return undefined;
|
|
71
|
+
|
|
72
|
+
case 'ascending':
|
|
73
|
+
return jsx(ArrowUpIcon, {
|
|
74
|
+
size: "small",
|
|
75
|
+
label: "",
|
|
76
|
+
primaryColor: "inherit"
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
case 'descending':
|
|
80
|
+
return jsx(ArrowDownIcon, {
|
|
81
|
+
size: "small",
|
|
82
|
+
label: "",
|
|
83
|
+
primaryColor: "inherit"
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return undefined;
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
return (// eslint-disable-next-line @repo/internal/react/no-unsafe-spread-props
|
|
92
|
+
jsx(TH, _extends({
|
|
93
|
+
testId: testId
|
|
94
|
+
}, other), jsx(Tooltip, {
|
|
95
|
+
content: getSortMessage(),
|
|
96
|
+
position: "top"
|
|
97
|
+
}, tooltipProps => jsx(Button, _extends({
|
|
98
|
+
spacing: "compact",
|
|
99
|
+
appearance: "subtle",
|
|
100
|
+
iconAfter: getSortIcon()
|
|
101
|
+
}, tooltipProps, {
|
|
102
|
+
// @ts-expect-error
|
|
103
|
+
onClick: () => setSortState(name),
|
|
104
|
+
css: overrideStyles
|
|
105
|
+
}), children)))
|
|
106
|
+
);
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
export default SortableColumn;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/** @jsx jsx */
|
|
2
|
+
import { jsx } from '@emotion/react';
|
|
3
|
+
import SelectionProvider from './hooks/selection-provider';
|
|
4
|
+
import { useSorting } from './hooks/use-sorting';
|
|
5
|
+
import { TableProvider } from './hooks/use-table';
|
|
6
|
+
import * as Primitives from './ui';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* __Table__
|
|
10
|
+
*
|
|
11
|
+
* A data table is used to display dynamic data.
|
|
12
|
+
*
|
|
13
|
+
* - [Examples](https://atlassian.design/components/table/examples)
|
|
14
|
+
*/
|
|
15
|
+
function Table({
|
|
16
|
+
children,
|
|
17
|
+
isSelectable,
|
|
18
|
+
sortKey = 'unset',
|
|
19
|
+
testId
|
|
20
|
+
}) {
|
|
21
|
+
const {
|
|
22
|
+
sortKey: localSortKey,
|
|
23
|
+
sortDirection,
|
|
24
|
+
setSortState
|
|
25
|
+
} = useSorting(sortKey);
|
|
26
|
+
return jsx(TableProvider, {
|
|
27
|
+
state: {
|
|
28
|
+
isSelectable,
|
|
29
|
+
sortKey: localSortKey,
|
|
30
|
+
sortDirection: sortDirection,
|
|
31
|
+
setSortState
|
|
32
|
+
}
|
|
33
|
+
}, jsx(Primitives.Table, {
|
|
34
|
+
testId: testId
|
|
35
|
+
}, isSelectable ? jsx(SelectionProvider, null, children) : children));
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export default Table;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/** @jsx jsx */
|
|
2
|
+
import { jsx } from '@emotion/react';
|
|
3
|
+
import Checkbox from '@atlaskit/checkbox';
|
|
4
|
+
import { UNSAFE_Inline as Inline, UNSAFE_Text as Text } from '@atlaskit/ds-explorations';
|
|
5
|
+
import VisuallyHidden from '@atlaskit/visually-hidden';
|
|
6
|
+
import { useSelection } from './hooks/selection-provider';
|
|
7
|
+
import { useTable } from './hooks/use-table';
|
|
8
|
+
import * as Primitives from './ui';
|
|
9
|
+
|
|
10
|
+
const THead = ({
|
|
11
|
+
actions,
|
|
12
|
+
children
|
|
13
|
+
}) => {
|
|
14
|
+
const table = useTable();
|
|
15
|
+
const [state, {
|
|
16
|
+
setAll,
|
|
17
|
+
removeAll
|
|
18
|
+
}] = useSelection();
|
|
19
|
+
const isChecked = state.allChecked || state.anyChecked;
|
|
20
|
+
|
|
21
|
+
if (!table.isSelectable) {
|
|
22
|
+
return jsx(Primitives.THead, null, jsx(Primitives.TR, {
|
|
23
|
+
isBodyRow: false
|
|
24
|
+
}, children));
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return jsx(Primitives.THead, null, jsx(Primitives.TR, {
|
|
28
|
+
isBodyRow: false
|
|
29
|
+
}, jsx(Primitives.SelectableCell, {
|
|
30
|
+
as: "th"
|
|
31
|
+
}, jsx(Checkbox, {
|
|
32
|
+
"aria-labelledby": "select-all",
|
|
33
|
+
onChange: isChecked ? removeAll : setAll,
|
|
34
|
+
isChecked: isChecked,
|
|
35
|
+
isIndeterminate: state.anyChecked && !state.allChecked
|
|
36
|
+
}), jsx(VisuallyHidden, {
|
|
37
|
+
id: "select-all"
|
|
38
|
+
}, "Select all rows")), children, isChecked && jsx(Primitives.BulkActionOverlay, null, jsx(Text, {
|
|
39
|
+
color: "color.text",
|
|
40
|
+
fontWeight: "500"
|
|
41
|
+
}, state.checked.length, " selected"), actions && jsx(Inline, {
|
|
42
|
+
gap: "scale.100"
|
|
43
|
+
}, actions(state.checked)))));
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
export default THead;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/* eslint-disable @atlassian/tangerine/import/entry-points */
|
|
2
|
+
|
|
3
|
+
/** @jsx jsx */
|
|
4
|
+
import { forwardRef } from 'react';
|
|
5
|
+
import { css, jsx } from '@emotion/react';
|
|
6
|
+
import Box from '@atlaskit/ds-explorations/box';
|
|
7
|
+
import Inline from '@atlaskit/ds-explorations/inline';
|
|
8
|
+
const alignMap = {
|
|
9
|
+
text: 'flexStart',
|
|
10
|
+
number: 'flexEnd',
|
|
11
|
+
icon: 'center'
|
|
12
|
+
};
|
|
13
|
+
const baseResetStyles = css({
|
|
14
|
+
display: 'table-cell',
|
|
15
|
+
verticalAlign: 'middle',
|
|
16
|
+
'&:first-of-type': {
|
|
17
|
+
paddingLeft: "var(--ds-space-100, 8px)"
|
|
18
|
+
},
|
|
19
|
+
'&:last-of-type': {
|
|
20
|
+
paddingRight: "var(--ds-space-100, 8px)"
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
/**
|
|
24
|
+
* __BaseCell__
|
|
25
|
+
*
|
|
26
|
+
* @internal
|
|
27
|
+
*
|
|
28
|
+
* Basic cell element.
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
export const BaseCell = /*#__PURE__*/forwardRef(({
|
|
32
|
+
testId,
|
|
33
|
+
as,
|
|
34
|
+
children,
|
|
35
|
+
align = 'text',
|
|
36
|
+
paddingBlock = 'scale.100',
|
|
37
|
+
paddingInline = 'scale.200',
|
|
38
|
+
backgroundColor,
|
|
39
|
+
scope,
|
|
40
|
+
className
|
|
41
|
+
}, ref) => jsx(Box, {
|
|
42
|
+
css: baseResetStyles,
|
|
43
|
+
ref: ref,
|
|
44
|
+
scope: scope,
|
|
45
|
+
backgroundColor: backgroundColor,
|
|
46
|
+
paddingBlock: paddingBlock,
|
|
47
|
+
paddingInline: paddingInline,
|
|
48
|
+
as: as,
|
|
49
|
+
testId: testId,
|
|
50
|
+
className: className
|
|
51
|
+
}, jsx(Inline, {
|
|
52
|
+
justifyContent: alignMap[align],
|
|
53
|
+
gap: "scale.0"
|
|
54
|
+
}, children)));
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/** @jsx jsx */
|
|
2
|
+
import { css, jsx } from '@emotion/react';
|
|
3
|
+
import { UNSAFE_Box as Box, UNSAFE_Inline as Inline } from '@atlaskit/ds-explorations';
|
|
4
|
+
const overlayStyles = css({
|
|
5
|
+
top: 0,
|
|
6
|
+
right: 0,
|
|
7
|
+
bottom: 0,
|
|
8
|
+
left: 32
|
|
9
|
+
});
|
|
10
|
+
/**
|
|
11
|
+
* __Bulk action overlay__
|
|
12
|
+
*
|
|
13
|
+
* A bulk action overlay is used to conditionally render when a user makes a row selection
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
export const BulkActionOverlay = ({
|
|
17
|
+
children
|
|
18
|
+
}) => jsx(Box, {
|
|
19
|
+
as: "th",
|
|
20
|
+
position: "absolute",
|
|
21
|
+
paddingInline: "scale.100",
|
|
22
|
+
backgroundColor: "elevation.surface",
|
|
23
|
+
css: overlayStyles
|
|
24
|
+
}, jsx(Inline, {
|
|
25
|
+
gap: "scale.300",
|
|
26
|
+
alignItems: "center"
|
|
27
|
+
}, children));
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* File exposes the HTML table primitives for use
|
|
3
|
+
*/
|
|
4
|
+
export { Table } from './table';
|
|
5
|
+
export { TBody } from './tbody';
|
|
6
|
+
export { TR } from './tr';
|
|
7
|
+
export { TD } from './td';
|
|
8
|
+
export { TH } from './th';
|
|
9
|
+
export { SelectableCell } from './selectable-cell';
|
|
10
|
+
export { THead } from './thead';
|
|
11
|
+
export { BulkActionOverlay } from './bulk-action-overlay';
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/** @jsx jsx */
|
|
2
|
+
import { css, jsx } from '@emotion/react';
|
|
3
|
+
import { BaseCell } from './base-cell';
|
|
4
|
+
const spacingStyles = css({
|
|
5
|
+
width: 32,
|
|
6
|
+
padding: "var(--ds-space-0, 0px)",
|
|
7
|
+
paddingLeft: "var(--ds-space-100, 8px)",
|
|
8
|
+
// eslint-disable-next-line @repo/internal/styles/no-nested-styles
|
|
9
|
+
'& + *': {
|
|
10
|
+
// eslint-disable-next-line @atlaskit/design-system/ensure-design-token-usage-spacing
|
|
11
|
+
paddingLeft: '8px !important'
|
|
12
|
+
}
|
|
13
|
+
});
|
|
14
|
+
/**
|
|
15
|
+
* __Selectable cell__
|
|
16
|
+
*
|
|
17
|
+
* A selectable cell primitive designed to be used for light weight composition.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
export const SelectableCell = ({
|
|
21
|
+
children,
|
|
22
|
+
as = 'td'
|
|
23
|
+
}) => {
|
|
24
|
+
return jsx(BaseCell, {
|
|
25
|
+
as: as,
|
|
26
|
+
css: spacingStyles
|
|
27
|
+
}, children);
|
|
28
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/** @jsx jsx */
|
|
2
|
+
import { jsx } from '@emotion/react';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* __Table__
|
|
6
|
+
*
|
|
7
|
+
* A primitive table container. Applies the HTML native element with no other styling.
|
|
8
|
+
*
|
|
9
|
+
* - [Examples](https://atlassian.design/components/table/examples)
|
|
10
|
+
*
|
|
11
|
+
* @primitive
|
|
12
|
+
* @see https://hello.atlassian.net/wiki/spaces/DST/pages/1947062524/Dynamic+table+2.0+implementation+spec
|
|
13
|
+
*/
|
|
14
|
+
export const Table = ({
|
|
15
|
+
children,
|
|
16
|
+
testId,
|
|
17
|
+
summary
|
|
18
|
+
}) => {
|
|
19
|
+
return jsx("table", {
|
|
20
|
+
"data-testid": testId
|
|
21
|
+
}, summary && jsx("caption", null, summary), children);
|
|
22
|
+
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/* eslint-disable @repo/internal/react/no-clone-element */
|
|
2
|
+
|
|
3
|
+
/** @jsx jsx */
|
|
4
|
+
import { css, jsx } from '@emotion/react';
|
|
5
|
+
const bodyStyles = css({
|
|
6
|
+
position: 'relative',
|
|
7
|
+
border: 'none',
|
|
8
|
+
'&:after': {
|
|
9
|
+
position: 'absolute',
|
|
10
|
+
boxShadow: `inset 0 -2px 0 0 ${"var(--ds-border, #eee)"}`,
|
|
11
|
+
content: "''",
|
|
12
|
+
inset: 0,
|
|
13
|
+
pointerEvents: 'none'
|
|
14
|
+
}
|
|
15
|
+
});
|
|
16
|
+
/**
|
|
17
|
+
* __TBody__
|
|
18
|
+
* @primitive
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
export const TBody = ({
|
|
22
|
+
children
|
|
23
|
+
}) => jsx("tbody", {
|
|
24
|
+
css: bodyStyles
|
|
25
|
+
}, children);
|
|
26
|
+
export default TBody;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import _extends from "@babel/runtime/helpers/extends";
|
|
2
|
+
|
|
3
|
+
/** @jsx jsx */
|
|
4
|
+
import { jsx } from '@emotion/react';
|
|
5
|
+
import { BaseCell } from './base-cell';
|
|
6
|
+
/**
|
|
7
|
+
* __Cell__
|
|
8
|
+
*
|
|
9
|
+
* A data cell.
|
|
10
|
+
*
|
|
11
|
+
* @primitive
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
export const TD = ({
|
|
15
|
+
testId,
|
|
16
|
+
...props
|
|
17
|
+
}) => // eslint-disable-next-line @repo/internal/react/no-unsafe-spread-props
|
|
18
|
+
jsx(BaseCell, _extends({
|
|
19
|
+
as: "td",
|
|
20
|
+
testId: testId
|
|
21
|
+
}, props));
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { BaseCell } from './base-cell';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* __Head cell__
|
|
6
|
+
*
|
|
7
|
+
* A head cell.
|
|
8
|
+
*
|
|
9
|
+
* @primitive
|
|
10
|
+
*/
|
|
11
|
+
export const TH = ({
|
|
12
|
+
children,
|
|
13
|
+
testId,
|
|
14
|
+
align,
|
|
15
|
+
scope,
|
|
16
|
+
backgroundColor
|
|
17
|
+
}) =>
|
|
18
|
+
/*#__PURE__*/
|
|
19
|
+
// eslint-disable-next-line @repo/internal/react/no-unsafe-spread-props
|
|
20
|
+
React.createElement(BaseCell, {
|
|
21
|
+
as: "th",
|
|
22
|
+
testId: testId,
|
|
23
|
+
align: align,
|
|
24
|
+
scope: scope,
|
|
25
|
+
backgroundColor: backgroundColor
|
|
26
|
+
}, children);
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/** @jsx jsx */
|
|
2
|
+
import { css, jsx } from '@emotion/react';
|
|
3
|
+
const baseStyles = css({
|
|
4
|
+
position: 'sticky',
|
|
5
|
+
zIndex: 1,
|
|
6
|
+
backgroundColor: "var(--ds-surface, white)",
|
|
7
|
+
border: 'none',
|
|
8
|
+
inset: 0,
|
|
9
|
+
'&:after': {
|
|
10
|
+
position: 'absolute',
|
|
11
|
+
boxShadow: `inset 0 -2px 0 0 ${"var(--ds-border, #eee)"}`,
|
|
12
|
+
content: "''",
|
|
13
|
+
inset: 0,
|
|
14
|
+
pointerEvents: 'none'
|
|
15
|
+
}
|
|
16
|
+
});
|
|
17
|
+
/**
|
|
18
|
+
* __THead__
|
|
19
|
+
*
|
|
20
|
+
* A primitive table head container. Applies the HTML native element with minimal styling.
|
|
21
|
+
*
|
|
22
|
+
* @primitive
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
export const THead = ({
|
|
26
|
+
children
|
|
27
|
+
}) => {
|
|
28
|
+
return jsx("thead", {
|
|
29
|
+
css: baseStyles
|
|
30
|
+
}, children);
|
|
31
|
+
};
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/** @jsx jsx */
|
|
2
|
+
import { css, jsx } from '@emotion/react';
|
|
3
|
+
import FocusRing from '@atlaskit/focus-ring';
|
|
4
|
+
const baseStyles = css({
|
|
5
|
+
height: 48,
|
|
6
|
+
position: 'relative',
|
|
7
|
+
border: 'none',
|
|
8
|
+
borderImageWidth: 0,
|
|
9
|
+
borderSpacing: 0
|
|
10
|
+
});
|
|
11
|
+
const selectedStyles = css({
|
|
12
|
+
backgroundColor: "var(--ds-background-selected, #DEEBFF88)",
|
|
13
|
+
'&:hover': {
|
|
14
|
+
backgroundColor: "var(--ds-background-selected-hovered, #DEEBFF)" // B50
|
|
15
|
+
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
const bodyRowStyles = css({
|
|
19
|
+
'&:hover': {
|
|
20
|
+
backgroundColor: "var(--ds-background-neutral-subtle-hovered, #f8f8f8)"
|
|
21
|
+
},
|
|
22
|
+
'&:focus-visible::after': {
|
|
23
|
+
boxShadow: 'none'
|
|
24
|
+
},
|
|
25
|
+
'&:after': {
|
|
26
|
+
position: 'absolute',
|
|
27
|
+
boxShadow: `inset 0 -1px 0 0 ${"var(--ds-border, #eee)"}`,
|
|
28
|
+
content: "''",
|
|
29
|
+
inset: 0,
|
|
30
|
+
pointerEvents: 'none'
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* __Row__
|
|
36
|
+
*
|
|
37
|
+
* A row primitive.
|
|
38
|
+
*
|
|
39
|
+
* - [Examples](https://atlassian.design/components/table/examples)
|
|
40
|
+
*/
|
|
41
|
+
export const TR = ({
|
|
42
|
+
children,
|
|
43
|
+
testId,
|
|
44
|
+
isSelected,
|
|
45
|
+
isBodyRow = true
|
|
46
|
+
}) => {
|
|
47
|
+
return jsx(FocusRing, {
|
|
48
|
+
isInset: true
|
|
49
|
+
}, jsx("tr", {
|
|
50
|
+
tabIndex: -1,
|
|
51
|
+
"aria-selected": isSelected,
|
|
52
|
+
"data-testid": testId,
|
|
53
|
+
css: [baseStyles, isBodyRow && bodyRowStyles, isSelected && selectedStyles]
|
|
54
|
+
}, children));
|
|
55
|
+
};
|
package/dist/esm/body.js
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProperties";
|
|
2
|
+
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
3
|
+
import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
|
|
4
|
+
var _excluded = ["idx"];
|
|
5
|
+
|
|
6
|
+
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
|
|
7
|
+
|
|
8
|
+
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
|
|
9
|
+
|
|
10
|
+
/* eslint-disable @repo/internal/react/no-clone-element */
|
|
11
|
+
|
|
12
|
+
/** @jsx jsx */
|
|
13
|
+
import { Children, useEffect } from 'react';
|
|
14
|
+
import { jsx } from '@emotion/react';
|
|
15
|
+
import { useSelection } from './hooks/selection-provider';
|
|
16
|
+
import { RowProvider } from './hooks/use-row-id';
|
|
17
|
+
import { useTable } from './hooks/use-table';
|
|
18
|
+
import { TableBodyProvider } from './hooks/use-table-body';
|
|
19
|
+
import * as Primitives from './ui';
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* __Table body__
|
|
23
|
+
*/
|
|
24
|
+
function TBody(_ref) {
|
|
25
|
+
var rows = _ref.rows,
|
|
26
|
+
children = _ref.children;
|
|
27
|
+
|
|
28
|
+
var _useTable = useTable(),
|
|
29
|
+
sortKey = _useTable.sortKey,
|
|
30
|
+
sortDirection = _useTable.sortDirection;
|
|
31
|
+
|
|
32
|
+
var _useSelection = useSelection(),
|
|
33
|
+
_useSelection2 = _slicedToArray(_useSelection, 2),
|
|
34
|
+
_state = _useSelection2[0],
|
|
35
|
+
_useSelection2$ = _useSelection2[1],
|
|
36
|
+
removeAll = _useSelection2$.removeAll,
|
|
37
|
+
setMax = _useSelection2$.setMax; // TODO this seems like something the user should control
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
useEffect(function () {
|
|
41
|
+
if (removeAll) {
|
|
42
|
+
removeAll();
|
|
43
|
+
} // eslint-disable-next-line react-hooks/exhaustive-deps
|
|
44
|
+
|
|
45
|
+
}, [rows]); // Set data length (via setMax) whenever data changes
|
|
46
|
+
|
|
47
|
+
useEffect(function () {
|
|
48
|
+
var numRows = rows !== undefined ? rows.length : Children.count(children);
|
|
49
|
+
setMax && setMax(numRows); // eslint-disable-next-line react-hooks/exhaustive-deps
|
|
50
|
+
}, [rows === null || rows === void 0 ? void 0 : rows.length, Children.count(children)]);
|
|
51
|
+
|
|
52
|
+
var sortFn = function sortFn(rowA, rowB) {
|
|
53
|
+
if (sortKey === 'unset') {
|
|
54
|
+
return 0;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
var ascendingComparator = rowA[sortKey] < rowB[sortKey] ? -1 : 1;
|
|
58
|
+
return sortDirection === 'ascending' ? ascendingComparator : -ascendingComparator;
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
return jsx(TableBodyProvider, {
|
|
62
|
+
value: true
|
|
63
|
+
}, jsx(Primitives.TBody, null, typeof children === 'function' && rows ? rows.map(function (row, idx) {
|
|
64
|
+
return _objectSpread(_objectSpread({}, row), {}, {
|
|
65
|
+
idx: idx
|
|
66
|
+
});
|
|
67
|
+
}).sort(sortFn).map(function (_ref2) {
|
|
68
|
+
var idx = _ref2.idx,
|
|
69
|
+
row = _objectWithoutProperties(_ref2, _excluded);
|
|
70
|
+
|
|
71
|
+
return jsx(RowProvider, {
|
|
72
|
+
key: idx,
|
|
73
|
+
value: idx
|
|
74
|
+
}, // @ts-expect-error
|
|
75
|
+
children(row));
|
|
76
|
+
}) : Children.map(children, function (row, idx) {
|
|
77
|
+
return jsx(RowProvider, {
|
|
78
|
+
key: idx,
|
|
79
|
+
value: idx
|
|
80
|
+
}, row);
|
|
81
|
+
})));
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export default TBody;
|