@mezzanine-ui/react 0.12.9 → 0.13.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/Table/Table.d.ts +18 -2
- package/Table/Table.js +34 -3
- package/Table/TableBody.d.ts +1 -1
- package/Table/TableBody.js +2 -12
- package/Table/TableBodyRow.d.ts +1 -1
- package/Table/TableBodyRow.js +23 -5
- package/Table/TableCell.js +2 -2
- package/Table/TableContext.d.ts +3 -2
- package/Table/TableHeader.d.ts +1 -1
- package/Table/TableHeader.js +18 -7
- package/Table/useTableScroll.d.ts +296 -7
- package/Table/useTableScroll.js +185 -75
- package/package.json +4 -4
package/Table/Table.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ReactNode } from 'react';
|
|
2
|
-
import { TableColumn, TableComponents, TableDataSource, TableRowSelection, TableExpandable, TableFetchMore, TablePagination as TablePaginationType, TableRefresh as TableRefreshType, ExpandRowBySources } from '@mezzanine-ui/core/table';
|
|
2
|
+
import { TableColumn, TableComponents, TableDataSource, TableRowSelection, TableExpandable, TableFetchMore, TablePagination as TablePaginationType, TableRefresh as TableRefreshType, ExpandRowBySources, TableScrolling } from '@mezzanine-ui/core/table';
|
|
3
3
|
import { EmptyProps } from '../Empty';
|
|
4
4
|
import { NativeElementPropsWithoutKeyAndRef } from '../utils/jsx-types';
|
|
5
5
|
export interface TableBaseProps<T> extends Omit<NativeElementPropsWithoutKeyAndRef<'div'>, 'role'> {
|
|
@@ -47,6 +47,11 @@ export interface TableBaseProps<T> extends Omit<NativeElementPropsWithoutKeyAndR
|
|
|
47
47
|
* Whether table is loading or not
|
|
48
48
|
*/
|
|
49
49
|
loading?: boolean;
|
|
50
|
+
/**
|
|
51
|
+
* When loading is true, show specific loadingTip
|
|
52
|
+
* @default '資料載入中...'
|
|
53
|
+
*/
|
|
54
|
+
loadingTip?: string;
|
|
50
55
|
/**
|
|
51
56
|
* `refresh.show` is true, refresh button will display at the top-start of table. <br />
|
|
52
57
|
* `refresh.onClick` is the callback of the refresh button.
|
|
@@ -59,6 +64,17 @@ export interface TableBaseProps<T> extends Omit<NativeElementPropsWithoutKeyAndR
|
|
|
59
64
|
* `rowSelection.actions` are the actions that you want to do for selected data.
|
|
60
65
|
*/
|
|
61
66
|
rowSelection?: TableRowSelection;
|
|
67
|
+
/**
|
|
68
|
+
* Enable table scroll feature <br />
|
|
69
|
+
* `scroll.x` set horizontal scrolling, can also be used to specify the width of the scroll area <br />
|
|
70
|
+
* `scroll.y` Set vertical scrolling, can also be used to specify the height of the scroll area <br />
|
|
71
|
+
* `scroll.fixedFirstColumn` set first column fixed when horizontal scrolling.
|
|
72
|
+
*/
|
|
73
|
+
scroll?: TableScrolling;
|
|
74
|
+
/**
|
|
75
|
+
* customize scroll container className
|
|
76
|
+
*/
|
|
77
|
+
scrollContainerClassName?: string;
|
|
62
78
|
}
|
|
63
79
|
export interface TableWithFetchMore<T> extends TableBaseProps<T> {
|
|
64
80
|
/**
|
|
@@ -84,5 +100,5 @@ export interface TableWithPagination<T> extends TableBaseProps<T> {
|
|
|
84
100
|
fetchMore?: undefined;
|
|
85
101
|
}
|
|
86
102
|
export type TableProps<T> = TableWithFetchMore<T> | TableWithPagination<T>;
|
|
87
|
-
declare const Table: import("react").ForwardRefExoticComponent<TableProps<Record<string, unknown>> & import("react").RefAttributes<
|
|
103
|
+
declare const Table: import("react").ForwardRefExoticComponent<TableProps<Record<string, unknown>> & import("react").RefAttributes<HTMLTableElement>>;
|
|
88
104
|
export default Table;
|
package/Table/Table.js
CHANGED
|
@@ -10,12 +10,14 @@ import { useTableRowSelection } from './rowSelection/useTableRowSelection.js';
|
|
|
10
10
|
import { useTableSorting } from './sorting/useTableSorting.js';
|
|
11
11
|
import { useTableLoading } from './useTableLoading.js';
|
|
12
12
|
import { useTableFetchMore } from './useTableFetchMore.js';
|
|
13
|
+
import useTableScroll from './useTableScroll.js';
|
|
14
|
+
import { useComposeRefs } from '../hooks/useComposeRefs.js';
|
|
13
15
|
import Loading from '../Loading/Loading.js';
|
|
14
16
|
import cx from 'clsx';
|
|
15
17
|
|
|
16
18
|
const Table = forwardRef(function Table(props, ref) {
|
|
17
19
|
var _a;
|
|
18
|
-
const { bodyClassName, bodyRowClassName, className, columns, components, dataSource: dataSourceProp, emptyProps, expandable: expandableProp, fetchMore: fetchMoreProp, headerClassName, loading: loadingProp, pagination: paginationProp, refresh: refreshProp, rowSelection: rowSelectionProp, ...rest } = props;
|
|
20
|
+
const { bodyClassName, bodyRowClassName, className, columns, components, dataSource: dataSourceProp, emptyProps, expandable: expandableProp, fetchMore: fetchMoreProp, headerClassName, loading: loadingProp, loadingTip = '資料載入中...', pagination: paginationProp, refresh: refreshProp, rowSelection: rowSelectionProp, scroll: scrollProp, scrollContainerClassName, ...rest } = props;
|
|
19
21
|
const bodyRef = useRef(null);
|
|
20
22
|
/** Feature rowSelection */
|
|
21
23
|
const [selectedRowKeys, setSelectedRowKey] = useTableRowSelection({
|
|
@@ -56,13 +58,19 @@ const Table = forwardRef(function Table(props, ref) {
|
|
|
56
58
|
/** @default false */
|
|
57
59
|
(_a = refreshProp === null || refreshProp === void 0 ? void 0 : refreshProp.show) !== null && _a !== void 0 ? _a : false);
|
|
58
60
|
}, [refreshProp === null || refreshProp === void 0 ? void 0 : refreshProp.show]);
|
|
61
|
+
/** Feature Scrolling */
|
|
62
|
+
const [scrollBody, scrollElement, isHorizontalScrolling] = useTableScroll({
|
|
63
|
+
onFetchMore,
|
|
64
|
+
loading,
|
|
65
|
+
scrollBarSize: 4,
|
|
66
|
+
});
|
|
59
67
|
/** context */
|
|
60
68
|
const tableContextValue = useMemo(() => {
|
|
61
69
|
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
62
70
|
return ({
|
|
63
|
-
scrollBarSize: 4,
|
|
64
71
|
emptyProps,
|
|
65
72
|
rowSelection,
|
|
73
|
+
isHorizontalScrolling,
|
|
66
74
|
sorting: {
|
|
67
75
|
onSort,
|
|
68
76
|
onResetAll,
|
|
@@ -89,6 +97,7 @@ const Table = forwardRef(function Table(props, ref) {
|
|
|
89
97
|
siblingCount: (_j = (_h = paginationProp.options) === null || _h === void 0 ? void 0 : _h.siblingCount) !== null && _j !== void 0 ? _j : 1,
|
|
90
98
|
},
|
|
91
99
|
} : undefined,
|
|
100
|
+
scroll: scrollProp,
|
|
92
101
|
});
|
|
93
102
|
}, [
|
|
94
103
|
dataSource,
|
|
@@ -105,6 +114,8 @@ const Table = forwardRef(function Table(props, ref) {
|
|
|
105
114
|
isFetching,
|
|
106
115
|
isReachEnd,
|
|
107
116
|
paginationProp,
|
|
117
|
+
isHorizontalScrolling,
|
|
118
|
+
scrollProp,
|
|
108
119
|
]);
|
|
109
120
|
const tableDataContextValue = useMemo(() => ({
|
|
110
121
|
columns,
|
|
@@ -116,7 +127,27 @@ const Table = forwardRef(function Table(props, ref) {
|
|
|
116
127
|
bodyCell: (_a = components === null || components === void 0 ? void 0 : components.body) === null || _a === void 0 ? void 0 : _a.cell,
|
|
117
128
|
});
|
|
118
129
|
}, [(_a = components === null || components === void 0 ? void 0 : components.body) === null || _a === void 0 ? void 0 : _a.cell]);
|
|
119
|
-
|
|
130
|
+
const tableRefs = useComposeRefs([ref, scrollBody.target]);
|
|
131
|
+
return (jsx(TableContext.Provider, { value: tableContextValue, children: jsx(TableDataContext.Provider, { value: tableDataContextValue, children: jsx(TableComponentContext.Provider, { value: tableComponentContextValue, children: jsxs(Loading, { loading: loading, stretch: true, tip: loadingTip, overlayProps: {
|
|
132
|
+
className: tableClasses.loading,
|
|
133
|
+
}, children: [jsx("div", { ref: scrollBody.ref, className: cx(tableClasses.scrollContainer, scrollContainerClassName), onScroll: scrollBody.onScroll, style: tableContextValue.scroll ? {
|
|
134
|
+
'--table-scroll-x': tableContextValue.scroll.x
|
|
135
|
+
? `${tableContextValue.scroll.x}px`
|
|
136
|
+
: '100%',
|
|
137
|
+
'--table-scroll-y': tableContextValue.scroll.y
|
|
138
|
+
? `${tableContextValue.scroll.y}px`
|
|
139
|
+
: 'unset',
|
|
140
|
+
} : undefined, children: jsxs("table", { ref: tableRefs, ...rest, className: cx(tableClasses.host, className), children: [isRefreshShow ? (jsx("tbody", { children: jsx("tr", { children: jsx("td", { children: jsx(TableRefresh, { onClick: refreshProp.onClick }) }) }) })) : null, jsx(TableHeader, { className: headerClassName }), jsx(TableBody, { ref: bodyRef, className: bodyClassName, rowClassName: bodyRowClassName })] }) }), paginationProp ? (jsx(TablePagination, { bodyRef: bodyRef })) : null, jsx("div", { ref: scrollElement.trackRef, style: scrollElement.trackStyle, onMouseDown: scrollElement.onMouseDown, onMouseUp: scrollElement.onMouseUp, role: "button", tabIndex: -1, className: "mzn-table-scroll-bar-track", children: jsx("div", { style: {
|
|
141
|
+
width: '100%',
|
|
142
|
+
height: '100%',
|
|
143
|
+
position: 'relative',
|
|
144
|
+
}, children: jsx("div", { ref: scrollElement.ref, onMouseDown: scrollElement.onMouseDown, onMouseUp: scrollElement.onMouseUp, onMouseEnter: scrollElement.onMouseEnter, onMouseLeave: scrollElement.onMouseLeave, role: "button", style: scrollElement.style, tabIndex: -1, className: "mzn-table-scroll-bar", children: jsx("div", { style: {
|
|
145
|
+
width: `${scrollElement.scrollBarSize}px`,
|
|
146
|
+
height: '100%',
|
|
147
|
+
borderRadius: '10px',
|
|
148
|
+
backgroundColor: '#7d7d7d',
|
|
149
|
+
transition: '0.1s',
|
|
150
|
+
} }) }) }) })] }) }) }) }));
|
|
120
151
|
});
|
|
121
152
|
var Table$1 = Table;
|
|
122
153
|
|
package/Table/TableBody.d.ts
CHANGED
|
@@ -6,5 +6,5 @@ export interface TableBodyProps extends NativeElementPropsWithoutKeyAndRef<'div'
|
|
|
6
6
|
*/
|
|
7
7
|
rowClassName?: string;
|
|
8
8
|
}
|
|
9
|
-
declare const TableBody: import("react").ForwardRefExoticComponent<TableBodyProps & import("react").RefAttributes<
|
|
9
|
+
declare const TableBody: import("react").ForwardRefExoticComponent<TableBodyProps & import("react").RefAttributes<HTMLTableSectionElement>>;
|
|
10
10
|
export default TableBody;
|
package/Table/TableBody.js
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
2
|
import { forwardRef, useContext } from 'react';
|
|
3
3
|
import { tableClasses } from '@mezzanine-ui/core/table';
|
|
4
|
-
import { useComposeRefs } from '../hooks/useComposeRefs.js';
|
|
5
|
-
import useTableScroll from './useTableScroll.js';
|
|
6
4
|
import { TableDataContext, TableContext } from './TableContext.js';
|
|
7
5
|
import TableBodyRow from './TableBodyRow.js';
|
|
8
6
|
import Loading from '../Loading/Loading.js';
|
|
@@ -12,9 +10,7 @@ import cx from 'clsx';
|
|
|
12
10
|
const TableBody = forwardRef(function TableBody(props, ref) {
|
|
13
11
|
const { className, rowClassName, ...rest } = props;
|
|
14
12
|
const { dataSource = [], } = useContext(TableDataContext) || {};
|
|
15
|
-
const { emptyProps, fetchMore,
|
|
16
|
-
const [tableBody, scrollElement] = useTableScroll();
|
|
17
|
-
const composedRefs = useComposeRefs([ref, tableBody.ref]);
|
|
13
|
+
const { emptyProps, fetchMore, pagination, } = useContext(TableContext) || {};
|
|
18
14
|
/** customizing empty */
|
|
19
15
|
const { className: emptyComponentClassName = '', children: emptyComponentChildren = '查無資料', fullHeight: emptyComponentFullHeight = true, ...restEmptyProps } = emptyProps || {};
|
|
20
16
|
/** pagination feature */
|
|
@@ -22,13 +18,7 @@ const TableBody = forwardRef(function TableBody(props, ref) {
|
|
|
22
18
|
const currentStartCount = (paginationOptions === null || paginationOptions === void 0 ? void 0 : paginationOptions.pageSize) && currentPage ? ((paginationOptions.pageSize) * (currentPage - 1)) : 0;
|
|
23
19
|
const currentEndCount = (paginationOptions === null || paginationOptions === void 0 ? void 0 : paginationOptions.pageSize) && currentPage && total ? (Math.min(((paginationOptions.pageSize) * currentPage), total)) : 0;
|
|
24
20
|
const currentDataSource = pagination && !disableAutoSlicing ? (dataSource.slice(currentStartCount, currentEndCount)) : dataSource;
|
|
25
|
-
return (jsxs("
|
|
26
|
-
width: `${scrollBarSize}px`,
|
|
27
|
-
height: '100%',
|
|
28
|
-
borderRadius: '10px',
|
|
29
|
-
backgroundColor: '#7d7d7d',
|
|
30
|
-
transition: '0.1s',
|
|
31
|
-
} }) })] }));
|
|
21
|
+
return (jsxs("tbody", { ...rest, ref: ref, className: cx(tableClasses.body, className), children: [currentDataSource.length ? currentDataSource.map((rowData, index) => (jsx(TableBodyRow, { className: rowClassName, rowData: rowData, rowIndex: index }, (rowData.key || rowData.id)))) : (jsx("tr", { children: jsx("td", { children: jsx(Empty, { ...restEmptyProps, className: cx(tableClasses.bodyEmpty, emptyComponentClassName), fullHeight: emptyComponentFullHeight, children: emptyComponentChildren }) }) })), (fetchMore === null || fetchMore === void 0 ? void 0 : fetchMore.isFetching) ? (jsx("tr", { className: tableClasses.bodyFetchMore, children: jsx("td", { children: jsx(Loading, { loading: true }) }) })) : null] }));
|
|
32
22
|
});
|
|
33
23
|
var TableBody$1 = TableBody;
|
|
34
24
|
|
package/Table/TableBodyRow.d.ts
CHANGED
|
@@ -8,5 +8,5 @@ export interface TableBodyRowProps extends NativeElementPropsWithoutKeyAndRef<'d
|
|
|
8
8
|
rowData: TableDataSource;
|
|
9
9
|
rowIndex: number;
|
|
10
10
|
}
|
|
11
|
-
declare const TableBodyRow: import("react").ForwardRefExoticComponent<TableBodyRowProps & import("react").RefAttributes<
|
|
11
|
+
declare const TableBodyRow: import("react").ForwardRefExoticComponent<TableBodyRowProps & import("react").RefAttributes<HTMLTableRowElement>>;
|
|
12
12
|
export default TableBodyRow;
|
package/Table/TableBodyRow.js
CHANGED
|
@@ -13,7 +13,7 @@ import cx from 'clsx';
|
|
|
13
13
|
|
|
14
14
|
const TableBodyRow = forwardRef(function TableBodyRow(props, ref) {
|
|
15
15
|
const { className, rowData, rowIndex, ...rest } = props;
|
|
16
|
-
const { rowSelection, expanding, } = useContext(TableContext) || {};
|
|
16
|
+
const { rowSelection, expanding, isHorizontalScrolling, scroll, } = useContext(TableContext) || {};
|
|
17
17
|
const { columns, } = useContext(TableDataContext) || {};
|
|
18
18
|
/** Feature rowSelection */
|
|
19
19
|
const [selected, setSelected] = useState(false);
|
|
@@ -27,14 +27,32 @@ const TableBodyRow = forwardRef(function TableBodyRow(props, ref) {
|
|
|
27
27
|
var _a, _b;
|
|
28
28
|
return ((_b = (_a = expanding === null || expanding === void 0 ? void 0 : expanding.expandedRowRender) === null || _a === void 0 ? void 0 : _a.call(expanding, rowData)) !== null && _b !== void 0 ? _b : null);
|
|
29
29
|
}, [expanding, rowData]);
|
|
30
|
-
|
|
30
|
+
/** Feature scrolling */
|
|
31
|
+
const isFirstColumnShouldSticky = useMemo(() => {
|
|
32
|
+
var _a;
|
|
33
|
+
/** 前面有 action 時不可 sticky */
|
|
34
|
+
if (rowSelection || expanding)
|
|
35
|
+
return false;
|
|
36
|
+
return ((_a = scroll === null || scroll === void 0 ? void 0 : scroll.fixedFirstColumn) !== null && _a !== void 0 ? _a : false);
|
|
37
|
+
}, [
|
|
38
|
+
rowSelection,
|
|
39
|
+
expanding,
|
|
40
|
+
scroll === null || scroll === void 0 ? void 0 : scroll.fixedFirstColumn,
|
|
41
|
+
]);
|
|
42
|
+
return (jsxs(Fragment, { children: [jsxs("tr", { ...rest, ref: ref, className: cx(tableClasses.bodyRow, {
|
|
31
43
|
[tableClasses.bodyRowHighlight]: selected || expanded,
|
|
32
|
-
}, className),
|
|
44
|
+
}, className), children: [rowSelection ? (jsx("td", { className: tableClasses.bodyRowCellWrapper, style: {
|
|
45
|
+
flex: 'unset',
|
|
46
|
+
minWidth: 'unset',
|
|
47
|
+
}, children: jsx(TableRowSelection, { rowKey: (rowData.key || rowData.id), setChecked: (status) => setSelected(status), showDropdownIcon: false }) })) : null, expanding ? (jsx("td", { className: tableClasses.bodyRowCellWrapper, style: {
|
|
48
|
+
flex: 'unset',
|
|
49
|
+
minWidth: 'unset',
|
|
50
|
+
}, children: jsx(TableExpandable, { expandable: isExpandable, expanded: expanded, setExpanded: setExpanded, onExpand: (status) => { var _a; return (_a = expanding.onExpand) === null || _a === void 0 ? void 0 : _a.call(expanding, rowData, status); } }) })) : null, (columns !== null && columns !== void 0 ? columns : []).map((column, idx) => {
|
|
33
51
|
var _a, _b, _c, _d;
|
|
34
52
|
const ellipsis = !!(get(rowData, column.dataIndex)) && ((_a = column.ellipsis) !== null && _a !== void 0 ? _a : true);
|
|
35
53
|
const tooltipTitle = ((_c = (_b = column.renderTooltipTitle) === null || _b === void 0 ? void 0 : _b.call(column, rowData)) !== null && _c !== void 0 ? _c : get(rowData, column.dataIndex));
|
|
36
|
-
return (jsx("
|
|
37
|
-
})] }), renderedExpandedContent ? (jsx(AccordionDetails, { className: cx(expanding.className, tableClasses.bodyRowExpandedTableWrapper), expanded: expanded, children: (renderedExpandedContent === null || renderedExpandedContent === void 0 ? void 0 : renderedExpandedContent.dataSource) ? (jsx(TableExpandedTable, { renderedExpandedContent: renderedExpandedContent })) : renderedExpandedContent })) : null] }));
|
|
54
|
+
return (jsx("td", { className: cx(tableClasses.bodyRowCellWrapper, isFirstColumnShouldSticky && idx === 0 && tableClasses.bodyRowCellWrapperFixed, isFirstColumnShouldSticky && idx === 0 && isHorizontalScrolling && tableClasses.bodyRowCellWrapperFixedStuck, column.bodyClassName), style: getColumnStyle(column), children: jsx(TableEditRenderWrapper, { ...column, rowData: rowData, children: jsx(TableCell, { ellipsis: ellipsis, forceShownTooltipWhenHovered: column.forceShownTooltipWhenHovered, style: getCellStyle(column), tooltipTitle: tooltipTitle, children: ((_d = column.render) === null || _d === void 0 ? void 0 : _d.call(column, rowData, rowIndex, column)) || get(rowData, column.dataIndex) }) }) }, `${column.dataIndex}-${column.title}`));
|
|
55
|
+
})] }), renderedExpandedContent ? (jsx("tr", { children: jsx("td", { style: { padding: 0 }, children: jsx(AccordionDetails, { className: cx(expanding.className, tableClasses.bodyRowExpandedTableWrapper), expanded: expanded, children: (renderedExpandedContent === null || renderedExpandedContent === void 0 ? void 0 : renderedExpandedContent.dataSource) ? (jsx(TableExpandedTable, { renderedExpandedContent: renderedExpandedContent })) : renderedExpandedContent }) }) })) : null] }));
|
|
38
56
|
});
|
|
39
57
|
var TableBodyRow$1 = TableBodyRow;
|
|
40
58
|
|
package/Table/TableCell.js
CHANGED
|
@@ -5,9 +5,9 @@ import Tooltip from '../Tooltip/Tooltip.js';
|
|
|
5
5
|
import cx from 'clsx';
|
|
6
6
|
|
|
7
7
|
const TableCell = forwardRef(function TableCell(props, ref) {
|
|
8
|
-
const { children, className, ellipsis = true, forceShownTooltipWhenHovered = false,
|
|
8
|
+
const { children, className, ellipsis = true, forceShownTooltipWhenHovered = false, tooltipTitle, ...rest } = props;
|
|
9
9
|
const ellipsisRef = useRef(null);
|
|
10
|
-
return (jsx("div", { ref: ref, ...rest, className: cx(tableClasses.cell, className),
|
|
10
|
+
return (jsx("div", { ref: ref, ...rest, className: cx(tableClasses.cell, className), children: ellipsis || forceShownTooltipWhenHovered ? (jsx(Tooltip, { title: `${tooltipTitle}`, options: {
|
|
11
11
|
placement: 'top-start',
|
|
12
12
|
}, children: ({ onMouseEnter, onMouseLeave }) => (jsx("div", { ref: ellipsisRef, className: ellipsis ? tableClasses.cellEllipsis : '', onMouseEnter: (e) => {
|
|
13
13
|
if (ellipsisRef.current) {
|
package/Table/TableContext.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ReactNode } from 'react';
|
|
2
|
-
import { TableRowSelection, TableColumn, TableExpandable, TablePagination, TableDataSource, TableRecord, ExpandRowBySources } from '@mezzanine-ui/core/table';
|
|
2
|
+
import { TableRowSelection, TableColumn, TableExpandable, TablePagination, TableDataSource, TableRecord, ExpandRowBySources, TableScrolling } from '@mezzanine-ui/core/table';
|
|
3
3
|
import { EmptyProps } from '../Empty';
|
|
4
4
|
/** typeof rowSelection */
|
|
5
5
|
export interface RowSelectionContext extends Pick<TableRowSelection, 'actions'> {
|
|
@@ -24,7 +24,7 @@ export interface FetchMoreContext {
|
|
|
24
24
|
isReachEnd: boolean;
|
|
25
25
|
}
|
|
26
26
|
export interface TableContextProps {
|
|
27
|
-
|
|
27
|
+
isHorizontalScrolling?: boolean;
|
|
28
28
|
emptyProps?: EmptyProps;
|
|
29
29
|
rowSelection?: RowSelectionContext;
|
|
30
30
|
sorting?: SortingContext;
|
|
@@ -35,6 +35,7 @@ export interface TableContextProps {
|
|
|
35
35
|
};
|
|
36
36
|
fetchMore?: FetchMoreContext;
|
|
37
37
|
pagination?: TablePagination;
|
|
38
|
+
scroll?: TableScrolling;
|
|
38
39
|
}
|
|
39
40
|
export declare const TableContext: import("react").Context<TableContextProps | null>;
|
|
40
41
|
export interface TableDataContextProps {
|
package/Table/TableHeader.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
/// <reference types="react" />
|
|
2
2
|
import { NativeElementPropsWithoutKeyAndRef } from '../utils/jsx-types';
|
|
3
|
-
declare const TableHeader: import("react").ForwardRefExoticComponent<NativeElementPropsWithoutKeyAndRef<"div"> & import("react").RefAttributes<
|
|
3
|
+
declare const TableHeader: import("react").ForwardRefExoticComponent<NativeElementPropsWithoutKeyAndRef<"div"> & import("react").RefAttributes<HTMLTableRowElement>>;
|
|
4
4
|
export default TableHeader;
|
package/Table/TableHeader.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { forwardRef, useContext } from 'react';
|
|
1
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
2
|
+
import { forwardRef, useContext, useMemo } from 'react';
|
|
3
3
|
import { tableClasses, getColumnStyle, getCellStyle } from '@mezzanine-ui/core/table';
|
|
4
4
|
import { TableContext, TableDataContext } from './TableContext.js';
|
|
5
5
|
import { SELECTED_ALL_KEY } from './rowSelection/useTableRowSelection.js';
|
|
@@ -11,12 +11,23 @@ import cx from 'clsx';
|
|
|
11
11
|
|
|
12
12
|
const TableHeader = forwardRef(function TableHeader(props, ref) {
|
|
13
13
|
const { className, ...rest } = props;
|
|
14
|
-
const { rowSelection, expanding, } = useContext(TableContext) || {};
|
|
14
|
+
const { rowSelection, isHorizontalScrolling, scroll, expanding, } = useContext(TableContext) || {};
|
|
15
15
|
const { columns, } = useContext(TableDataContext) || {};
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
16
|
+
const isFirstColumnShouldSticky = useMemo(() => {
|
|
17
|
+
var _a;
|
|
18
|
+
/** 前面有 action 時不可 sticky */
|
|
19
|
+
if (rowSelection || expanding)
|
|
20
|
+
return false;
|
|
21
|
+
return ((_a = scroll === null || scroll === void 0 ? void 0 : scroll.fixedFirstColumn) !== null && _a !== void 0 ? _a : false);
|
|
22
|
+
}, [
|
|
23
|
+
rowSelection,
|
|
24
|
+
expanding,
|
|
25
|
+
scroll === null || scroll === void 0 ? void 0 : scroll.fixedFirstColumn,
|
|
26
|
+
]);
|
|
27
|
+
return (jsx("thead", { className: tableClasses.headerFixed, children: jsxs("tr", { ref: ref, ...rest, className: cx(tableClasses.header, className), children: [rowSelection ? (jsx("th", { style: { display: 'flex' }, children: jsx(TableRowSelection, { rowKey: SELECTED_ALL_KEY, showDropdownIcon: true }) })) : null, expanding && !rowSelection ? (jsx("th", { style: { display: 'flex' }, children: jsx(TableExpandable, { showIcon: false }) })) : null, (columns !== null && columns !== void 0 ? columns : []).map((column, idx) => {
|
|
28
|
+
var _a;
|
|
29
|
+
return (jsx("th", { className: cx(tableClasses.headerCellWrapper, isFirstColumnShouldSticky && idx === 0 && tableClasses.headerCellWrapperFixed, isFirstColumnShouldSticky && idx === 0 && isHorizontalScrolling && tableClasses.headerCellWrapperFixedStuck, column.headerClassName), style: getColumnStyle(column), children: jsxs(TableCell, { ellipsis: false, style: getCellStyle(column), children: [((_a = column.renderTitle) === null || _a === void 0 ? void 0 : _a.call(column, tableClasses)) || column.title, typeof column.sorter === 'function' || typeof column.onSorted === 'function' ? (jsx(TableSortingIcon, { column: column })) : null] }) }, `${column.dataIndex}-${column.title}`));
|
|
30
|
+
})] }) }));
|
|
20
31
|
});
|
|
21
32
|
var TableHeader$1 = TableHeader;
|
|
22
33
|
|
|
@@ -1,10 +1,20 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import { UIEventHandler } from 'react';
|
|
2
|
+
interface TableScrollProps {
|
|
3
|
+
onFetchMore?: VoidFunction;
|
|
4
|
+
loading?: boolean;
|
|
5
|
+
scrollBarSize?: number;
|
|
6
|
+
}
|
|
7
|
+
export default function useTableScroll(props: TableScrollProps): readonly [{
|
|
3
8
|
ref: import("react").RefObject<HTMLDivElement>;
|
|
4
|
-
|
|
9
|
+
target: import("react").RefObject<HTMLTableElement>;
|
|
10
|
+
onScroll: UIEventHandler<HTMLDivElement>;
|
|
5
11
|
}, {
|
|
6
12
|
ref: import("react").RefObject<HTMLDivElement>;
|
|
7
|
-
|
|
13
|
+
trackRef: import("react").RefObject<HTMLDivElement>;
|
|
14
|
+
scrollBarSize: number;
|
|
15
|
+
onMouseDown: ({ clientY }: {
|
|
16
|
+
clientY: number;
|
|
17
|
+
}) => void;
|
|
8
18
|
onMouseUp: () => void;
|
|
9
19
|
onMouseEnter: () => void;
|
|
10
20
|
onMouseLeave: () => void;
|
|
@@ -64,14 +74,18 @@ export default function useTableScroll(): readonly [{
|
|
|
64
74
|
'aria-activedescendant'?: string | undefined;
|
|
65
75
|
'aria-atomic'?: (boolean | "true" | "false") | undefined;
|
|
66
76
|
'aria-autocomplete'?: "none" | "list" | "inline" | "both" | undefined;
|
|
77
|
+
'aria-braillelabel'?: string | undefined;
|
|
78
|
+
'aria-brailleroledescription'?: string | undefined;
|
|
67
79
|
'aria-busy'?: (boolean | "true" | "false") | undefined;
|
|
68
80
|
'aria-checked'?: boolean | "true" | "false" | "mixed" | undefined;
|
|
69
81
|
'aria-colcount'?: number | undefined;
|
|
70
82
|
'aria-colindex'?: number | undefined;
|
|
83
|
+
'aria-colindextext'?: string | undefined;
|
|
71
84
|
'aria-colspan'?: number | undefined;
|
|
72
85
|
'aria-controls'?: string | undefined;
|
|
73
86
|
'aria-current'?: boolean | "true" | "false" | "page" | "step" | "location" | "date" | "time" | undefined;
|
|
74
87
|
'aria-describedby'?: string | undefined;
|
|
88
|
+
'aria-description'?: string | undefined;
|
|
75
89
|
'aria-details'?: string | undefined;
|
|
76
90
|
'aria-disabled'?: (boolean | "true" | "false") | undefined;
|
|
77
91
|
'aria-dropeffect'?: "none" | "link" | "copy" | "execute" | "move" | "popup" | undefined;
|
|
@@ -101,6 +115,7 @@ export default function useTableScroll(): readonly [{
|
|
|
101
115
|
'aria-roledescription'?: string | undefined;
|
|
102
116
|
'aria-rowcount'?: number | undefined;
|
|
103
117
|
'aria-rowindex'?: number | undefined;
|
|
118
|
+
'aria-rowindextext'?: string | undefined;
|
|
104
119
|
'aria-rowspan'?: number | undefined;
|
|
105
120
|
'aria-selected'?: (boolean | "true" | "false") | undefined;
|
|
106
121
|
'aria-setsize'?: number | undefined;
|
|
@@ -263,8 +278,8 @@ export default function useTableScroll(): readonly [{
|
|
|
263
278
|
onGotPointerCaptureCapture?: import("react").PointerEventHandler<HTMLDivElement> | undefined;
|
|
264
279
|
onLostPointerCapture?: import("react").PointerEventHandler<HTMLDivElement> | undefined;
|
|
265
280
|
onLostPointerCaptureCapture?: import("react").PointerEventHandler<HTMLDivElement> | undefined;
|
|
266
|
-
onScroll?:
|
|
267
|
-
onScrollCapture?:
|
|
281
|
+
onScroll?: UIEventHandler<HTMLDivElement> | undefined;
|
|
282
|
+
onScrollCapture?: UIEventHandler<HTMLDivElement> | undefined;
|
|
268
283
|
onWheel?: import("react").WheelEventHandler<HTMLDivElement> | undefined;
|
|
269
284
|
onWheelCapture?: import("react").WheelEventHandler<HTMLDivElement> | undefined;
|
|
270
285
|
onAnimationStart?: import("react").AnimationEventHandler<HTMLDivElement> | undefined;
|
|
@@ -276,4 +291,278 @@ export default function useTableScroll(): readonly [{
|
|
|
276
291
|
onTransitionEnd?: import("react").TransitionEventHandler<HTMLDivElement> | undefined;
|
|
277
292
|
onTransitionEndCapture?: import("react").TransitionEventHandler<HTMLDivElement> | undefined;
|
|
278
293
|
};
|
|
279
|
-
|
|
294
|
+
trackStyle: {
|
|
295
|
+
height: string;
|
|
296
|
+
ref?: import("react").LegacyRef<HTMLDivElement> | undefined;
|
|
297
|
+
key?: import("react").Key | null | undefined;
|
|
298
|
+
defaultChecked?: boolean | undefined;
|
|
299
|
+
defaultValue?: string | number | readonly string[] | undefined;
|
|
300
|
+
suppressContentEditableWarning?: boolean | undefined;
|
|
301
|
+
suppressHydrationWarning?: boolean | undefined;
|
|
302
|
+
accessKey?: string | undefined;
|
|
303
|
+
autoFocus?: boolean | undefined;
|
|
304
|
+
className?: string | undefined;
|
|
305
|
+
contentEditable?: (boolean | "true" | "false") | "inherit" | undefined;
|
|
306
|
+
contextMenu?: string | undefined;
|
|
307
|
+
dir?: string | undefined;
|
|
308
|
+
draggable?: (boolean | "true" | "false") | undefined;
|
|
309
|
+
hidden?: boolean | undefined;
|
|
310
|
+
id?: string | undefined;
|
|
311
|
+
lang?: string | undefined;
|
|
312
|
+
nonce?: string | undefined;
|
|
313
|
+
placeholder?: string | undefined;
|
|
314
|
+
slot?: string | undefined;
|
|
315
|
+
spellCheck?: (boolean | "true" | "false") | undefined;
|
|
316
|
+
style?: import("react").CSSProperties | undefined;
|
|
317
|
+
tabIndex?: number | undefined;
|
|
318
|
+
title?: string | undefined;
|
|
319
|
+
translate?: "yes" | "no" | undefined;
|
|
320
|
+
radioGroup?: string | undefined;
|
|
321
|
+
role?: import("react").AriaRole | undefined;
|
|
322
|
+
about?: string | undefined;
|
|
323
|
+
content?: string | undefined;
|
|
324
|
+
datatype?: string | undefined;
|
|
325
|
+
inlist?: any;
|
|
326
|
+
prefix?: string | undefined;
|
|
327
|
+
property?: string | undefined;
|
|
328
|
+
rel?: string | undefined;
|
|
329
|
+
resource?: string | undefined;
|
|
330
|
+
rev?: string | undefined;
|
|
331
|
+
typeof?: string | undefined;
|
|
332
|
+
vocab?: string | undefined;
|
|
333
|
+
autoCapitalize?: string | undefined;
|
|
334
|
+
autoCorrect?: string | undefined;
|
|
335
|
+
autoSave?: string | undefined;
|
|
336
|
+
color?: string | undefined;
|
|
337
|
+
itemProp?: string | undefined;
|
|
338
|
+
itemScope?: boolean | undefined;
|
|
339
|
+
itemType?: string | undefined;
|
|
340
|
+
itemID?: string | undefined;
|
|
341
|
+
itemRef?: string | undefined;
|
|
342
|
+
results?: number | undefined;
|
|
343
|
+
security?: string | undefined;
|
|
344
|
+
unselectable?: "on" | "off" | undefined;
|
|
345
|
+
inputMode?: "none" | "search" | "text" | "tel" | "url" | "email" | "numeric" | "decimal" | undefined;
|
|
346
|
+
is?: string | undefined;
|
|
347
|
+
'aria-activedescendant'?: string | undefined;
|
|
348
|
+
'aria-atomic'?: (boolean | "true" | "false") | undefined;
|
|
349
|
+
'aria-autocomplete'?: "none" | "list" | "inline" | "both" | undefined;
|
|
350
|
+
'aria-braillelabel'?: string | undefined;
|
|
351
|
+
'aria-brailleroledescription'?: string | undefined;
|
|
352
|
+
'aria-busy'?: (boolean | "true" | "false") | undefined;
|
|
353
|
+
'aria-checked'?: boolean | "true" | "false" | "mixed" | undefined;
|
|
354
|
+
'aria-colcount'?: number | undefined;
|
|
355
|
+
'aria-colindex'?: number | undefined;
|
|
356
|
+
'aria-colindextext'?: string | undefined;
|
|
357
|
+
'aria-colspan'?: number | undefined;
|
|
358
|
+
'aria-controls'?: string | undefined;
|
|
359
|
+
'aria-current'?: boolean | "true" | "false" | "page" | "step" | "location" | "date" | "time" | undefined;
|
|
360
|
+
'aria-describedby'?: string | undefined;
|
|
361
|
+
'aria-description'?: string | undefined;
|
|
362
|
+
'aria-details'?: string | undefined;
|
|
363
|
+
'aria-disabled'?: (boolean | "true" | "false") | undefined;
|
|
364
|
+
'aria-dropeffect'?: "none" | "link" | "copy" | "execute" | "move" | "popup" | undefined;
|
|
365
|
+
'aria-errormessage'?: string | undefined;
|
|
366
|
+
'aria-expanded'?: (boolean | "true" | "false") | undefined;
|
|
367
|
+
'aria-flowto'?: string | undefined;
|
|
368
|
+
'aria-grabbed'?: (boolean | "true" | "false") | undefined;
|
|
369
|
+
'aria-haspopup'?: boolean | "true" | "false" | "dialog" | "grid" | "listbox" | "menu" | "tree" | undefined;
|
|
370
|
+
'aria-hidden'?: (boolean | "true" | "false") | undefined;
|
|
371
|
+
'aria-invalid'?: boolean | "true" | "false" | "grammar" | "spelling" | undefined;
|
|
372
|
+
'aria-keyshortcuts'?: string | undefined;
|
|
373
|
+
'aria-label'?: string | undefined;
|
|
374
|
+
'aria-labelledby'?: string | undefined;
|
|
375
|
+
'aria-level'?: number | undefined;
|
|
376
|
+
'aria-live'?: "off" | "assertive" | "polite" | undefined;
|
|
377
|
+
'aria-modal'?: (boolean | "true" | "false") | undefined;
|
|
378
|
+
'aria-multiline'?: (boolean | "true" | "false") | undefined;
|
|
379
|
+
'aria-multiselectable'?: (boolean | "true" | "false") | undefined;
|
|
380
|
+
'aria-orientation'?: "horizontal" | "vertical" | undefined;
|
|
381
|
+
'aria-owns'?: string | undefined;
|
|
382
|
+
'aria-placeholder'?: string | undefined;
|
|
383
|
+
'aria-posinset'?: number | undefined;
|
|
384
|
+
'aria-pressed'?: boolean | "true" | "false" | "mixed" | undefined;
|
|
385
|
+
'aria-readonly'?: (boolean | "true" | "false") | undefined;
|
|
386
|
+
'aria-relevant'?: "text" | "additions" | "additions removals" | "additions text" | "all" | "removals" | "removals additions" | "removals text" | "text additions" | "text removals" | undefined;
|
|
387
|
+
'aria-required'?: (boolean | "true" | "false") | undefined;
|
|
388
|
+
'aria-roledescription'?: string | undefined;
|
|
389
|
+
'aria-rowcount'?: number | undefined;
|
|
390
|
+
'aria-rowindex'?: number | undefined;
|
|
391
|
+
'aria-rowindextext'?: string | undefined;
|
|
392
|
+
'aria-rowspan'?: number | undefined;
|
|
393
|
+
'aria-selected'?: (boolean | "true" | "false") | undefined;
|
|
394
|
+
'aria-setsize'?: number | undefined;
|
|
395
|
+
'aria-sort'?: "none" | "ascending" | "descending" | "other" | undefined;
|
|
396
|
+
'aria-valuemax'?: number | undefined;
|
|
397
|
+
'aria-valuemin'?: number | undefined;
|
|
398
|
+
'aria-valuenow'?: number | undefined;
|
|
399
|
+
'aria-valuetext'?: string | undefined;
|
|
400
|
+
children?: import("react").ReactNode;
|
|
401
|
+
dangerouslySetInnerHTML?: {
|
|
402
|
+
__html: string | TrustedHTML;
|
|
403
|
+
} | undefined;
|
|
404
|
+
onCopy?: import("react").ClipboardEventHandler<HTMLDivElement> | undefined;
|
|
405
|
+
onCopyCapture?: import("react").ClipboardEventHandler<HTMLDivElement> | undefined;
|
|
406
|
+
onCut?: import("react").ClipboardEventHandler<HTMLDivElement> | undefined;
|
|
407
|
+
onCutCapture?: import("react").ClipboardEventHandler<HTMLDivElement> | undefined;
|
|
408
|
+
onPaste?: import("react").ClipboardEventHandler<HTMLDivElement> | undefined;
|
|
409
|
+
onPasteCapture?: import("react").ClipboardEventHandler<HTMLDivElement> | undefined;
|
|
410
|
+
onCompositionEnd?: import("react").CompositionEventHandler<HTMLDivElement> | undefined;
|
|
411
|
+
onCompositionEndCapture?: import("react").CompositionEventHandler<HTMLDivElement> | undefined;
|
|
412
|
+
onCompositionStart?: import("react").CompositionEventHandler<HTMLDivElement> | undefined;
|
|
413
|
+
onCompositionStartCapture?: import("react").CompositionEventHandler<HTMLDivElement> | undefined;
|
|
414
|
+
onCompositionUpdate?: import("react").CompositionEventHandler<HTMLDivElement> | undefined;
|
|
415
|
+
onCompositionUpdateCapture?: import("react").CompositionEventHandler<HTMLDivElement> | undefined;
|
|
416
|
+
onFocus?: import("react").FocusEventHandler<HTMLDivElement> | undefined;
|
|
417
|
+
onFocusCapture?: import("react").FocusEventHandler<HTMLDivElement> | undefined;
|
|
418
|
+
onBlur?: import("react").FocusEventHandler<HTMLDivElement> | undefined;
|
|
419
|
+
onBlurCapture?: import("react").FocusEventHandler<HTMLDivElement> | undefined;
|
|
420
|
+
onChange?: import("react").FormEventHandler<HTMLDivElement> | undefined;
|
|
421
|
+
onChangeCapture?: import("react").FormEventHandler<HTMLDivElement> | undefined;
|
|
422
|
+
onBeforeInput?: import("react").FormEventHandler<HTMLDivElement> | undefined;
|
|
423
|
+
onBeforeInputCapture?: import("react").FormEventHandler<HTMLDivElement> | undefined;
|
|
424
|
+
onInput?: import("react").FormEventHandler<HTMLDivElement> | undefined;
|
|
425
|
+
onInputCapture?: import("react").FormEventHandler<HTMLDivElement> | undefined;
|
|
426
|
+
onReset?: import("react").FormEventHandler<HTMLDivElement> | undefined;
|
|
427
|
+
onResetCapture?: import("react").FormEventHandler<HTMLDivElement> | undefined;
|
|
428
|
+
onSubmit?: import("react").FormEventHandler<HTMLDivElement> | undefined;
|
|
429
|
+
onSubmitCapture?: import("react").FormEventHandler<HTMLDivElement> | undefined;
|
|
430
|
+
onInvalid?: import("react").FormEventHandler<HTMLDivElement> | undefined;
|
|
431
|
+
onInvalidCapture?: import("react").FormEventHandler<HTMLDivElement> | undefined;
|
|
432
|
+
onLoad?: import("react").ReactEventHandler<HTMLDivElement> | undefined;
|
|
433
|
+
onLoadCapture?: import("react").ReactEventHandler<HTMLDivElement> | undefined;
|
|
434
|
+
onError?: import("react").ReactEventHandler<HTMLDivElement> | undefined;
|
|
435
|
+
onErrorCapture?: import("react").ReactEventHandler<HTMLDivElement> | undefined;
|
|
436
|
+
onKeyDown?: import("react").KeyboardEventHandler<HTMLDivElement> | undefined;
|
|
437
|
+
onKeyDownCapture?: import("react").KeyboardEventHandler<HTMLDivElement> | undefined;
|
|
438
|
+
onKeyPress?: import("react").KeyboardEventHandler<HTMLDivElement> | undefined;
|
|
439
|
+
onKeyPressCapture?: import("react").KeyboardEventHandler<HTMLDivElement> | undefined;
|
|
440
|
+
onKeyUp?: import("react").KeyboardEventHandler<HTMLDivElement> | undefined;
|
|
441
|
+
onKeyUpCapture?: import("react").KeyboardEventHandler<HTMLDivElement> | undefined;
|
|
442
|
+
onAbort?: import("react").ReactEventHandler<HTMLDivElement> | undefined;
|
|
443
|
+
onAbortCapture?: import("react").ReactEventHandler<HTMLDivElement> | undefined;
|
|
444
|
+
onCanPlay?: import("react").ReactEventHandler<HTMLDivElement> | undefined;
|
|
445
|
+
onCanPlayCapture?: import("react").ReactEventHandler<HTMLDivElement> | undefined;
|
|
446
|
+
onCanPlayThrough?: import("react").ReactEventHandler<HTMLDivElement> | undefined;
|
|
447
|
+
onCanPlayThroughCapture?: import("react").ReactEventHandler<HTMLDivElement> | undefined;
|
|
448
|
+
onDurationChange?: import("react").ReactEventHandler<HTMLDivElement> | undefined;
|
|
449
|
+
onDurationChangeCapture?: import("react").ReactEventHandler<HTMLDivElement> | undefined;
|
|
450
|
+
onEmptied?: import("react").ReactEventHandler<HTMLDivElement> | undefined;
|
|
451
|
+
onEmptiedCapture?: import("react").ReactEventHandler<HTMLDivElement> | undefined;
|
|
452
|
+
onEncrypted?: import("react").ReactEventHandler<HTMLDivElement> | undefined;
|
|
453
|
+
onEncryptedCapture?: import("react").ReactEventHandler<HTMLDivElement> | undefined;
|
|
454
|
+
onEnded?: import("react").ReactEventHandler<HTMLDivElement> | undefined;
|
|
455
|
+
onEndedCapture?: import("react").ReactEventHandler<HTMLDivElement> | undefined;
|
|
456
|
+
onLoadedData?: import("react").ReactEventHandler<HTMLDivElement> | undefined;
|
|
457
|
+
onLoadedDataCapture?: import("react").ReactEventHandler<HTMLDivElement> | undefined;
|
|
458
|
+
onLoadedMetadata?: import("react").ReactEventHandler<HTMLDivElement> | undefined;
|
|
459
|
+
onLoadedMetadataCapture?: import("react").ReactEventHandler<HTMLDivElement> | undefined;
|
|
460
|
+
onLoadStart?: import("react").ReactEventHandler<HTMLDivElement> | undefined;
|
|
461
|
+
onLoadStartCapture?: import("react").ReactEventHandler<HTMLDivElement> | undefined;
|
|
462
|
+
onPause?: import("react").ReactEventHandler<HTMLDivElement> | undefined;
|
|
463
|
+
onPauseCapture?: import("react").ReactEventHandler<HTMLDivElement> | undefined;
|
|
464
|
+
onPlay?: import("react").ReactEventHandler<HTMLDivElement> | undefined;
|
|
465
|
+
onPlayCapture?: import("react").ReactEventHandler<HTMLDivElement> | undefined;
|
|
466
|
+
onPlaying?: import("react").ReactEventHandler<HTMLDivElement> | undefined;
|
|
467
|
+
onPlayingCapture?: import("react").ReactEventHandler<HTMLDivElement> | undefined;
|
|
468
|
+
onProgress?: import("react").ReactEventHandler<HTMLDivElement> | undefined;
|
|
469
|
+
onProgressCapture?: import("react").ReactEventHandler<HTMLDivElement> | undefined;
|
|
470
|
+
onRateChange?: import("react").ReactEventHandler<HTMLDivElement> | undefined;
|
|
471
|
+
onRateChangeCapture?: import("react").ReactEventHandler<HTMLDivElement> | undefined;
|
|
472
|
+
onResize?: import("react").ReactEventHandler<HTMLDivElement> | undefined;
|
|
473
|
+
onResizeCapture?: import("react").ReactEventHandler<HTMLDivElement> | undefined;
|
|
474
|
+
onSeeked?: import("react").ReactEventHandler<HTMLDivElement> | undefined;
|
|
475
|
+
onSeekedCapture?: import("react").ReactEventHandler<HTMLDivElement> | undefined;
|
|
476
|
+
onSeeking?: import("react").ReactEventHandler<HTMLDivElement> | undefined;
|
|
477
|
+
onSeekingCapture?: import("react").ReactEventHandler<HTMLDivElement> | undefined;
|
|
478
|
+
onStalled?: import("react").ReactEventHandler<HTMLDivElement> | undefined;
|
|
479
|
+
onStalledCapture?: import("react").ReactEventHandler<HTMLDivElement> | undefined;
|
|
480
|
+
onSuspend?: import("react").ReactEventHandler<HTMLDivElement> | undefined;
|
|
481
|
+
onSuspendCapture?: import("react").ReactEventHandler<HTMLDivElement> | undefined;
|
|
482
|
+
onTimeUpdate?: import("react").ReactEventHandler<HTMLDivElement> | undefined;
|
|
483
|
+
onTimeUpdateCapture?: import("react").ReactEventHandler<HTMLDivElement> | undefined;
|
|
484
|
+
onVolumeChange?: import("react").ReactEventHandler<HTMLDivElement> | undefined;
|
|
485
|
+
onVolumeChangeCapture?: import("react").ReactEventHandler<HTMLDivElement> | undefined;
|
|
486
|
+
onWaiting?: import("react").ReactEventHandler<HTMLDivElement> | undefined;
|
|
487
|
+
onWaitingCapture?: import("react").ReactEventHandler<HTMLDivElement> | undefined;
|
|
488
|
+
onAuxClick?: import("react").MouseEventHandler<HTMLDivElement> | undefined;
|
|
489
|
+
onAuxClickCapture?: import("react").MouseEventHandler<HTMLDivElement> | undefined;
|
|
490
|
+
onClick?: import("react").MouseEventHandler<HTMLDivElement> | undefined;
|
|
491
|
+
onClickCapture?: import("react").MouseEventHandler<HTMLDivElement> | undefined;
|
|
492
|
+
onContextMenu?: import("react").MouseEventHandler<HTMLDivElement> | undefined;
|
|
493
|
+
onContextMenuCapture?: import("react").MouseEventHandler<HTMLDivElement> | undefined;
|
|
494
|
+
onDoubleClick?: import("react").MouseEventHandler<HTMLDivElement> | undefined;
|
|
495
|
+
onDoubleClickCapture?: import("react").MouseEventHandler<HTMLDivElement> | undefined;
|
|
496
|
+
onDrag?: import("react").DragEventHandler<HTMLDivElement> | undefined;
|
|
497
|
+
onDragCapture?: import("react").DragEventHandler<HTMLDivElement> | undefined;
|
|
498
|
+
onDragEnd?: import("react").DragEventHandler<HTMLDivElement> | undefined;
|
|
499
|
+
onDragEndCapture?: import("react").DragEventHandler<HTMLDivElement> | undefined;
|
|
500
|
+
onDragEnter?: import("react").DragEventHandler<HTMLDivElement> | undefined;
|
|
501
|
+
onDragEnterCapture?: import("react").DragEventHandler<HTMLDivElement> | undefined;
|
|
502
|
+
onDragExit?: import("react").DragEventHandler<HTMLDivElement> | undefined;
|
|
503
|
+
onDragExitCapture?: import("react").DragEventHandler<HTMLDivElement> | undefined;
|
|
504
|
+
onDragLeave?: import("react").DragEventHandler<HTMLDivElement> | undefined;
|
|
505
|
+
onDragLeaveCapture?: import("react").DragEventHandler<HTMLDivElement> | undefined;
|
|
506
|
+
onDragOver?: import("react").DragEventHandler<HTMLDivElement> | undefined;
|
|
507
|
+
onDragOverCapture?: import("react").DragEventHandler<HTMLDivElement> | undefined;
|
|
508
|
+
onDragStart?: import("react").DragEventHandler<HTMLDivElement> | undefined;
|
|
509
|
+
onDragStartCapture?: import("react").DragEventHandler<HTMLDivElement> | undefined;
|
|
510
|
+
onDrop?: import("react").DragEventHandler<HTMLDivElement> | undefined;
|
|
511
|
+
onDropCapture?: import("react").DragEventHandler<HTMLDivElement> | undefined;
|
|
512
|
+
onMouseDown?: import("react").MouseEventHandler<HTMLDivElement> | undefined;
|
|
513
|
+
onMouseDownCapture?: import("react").MouseEventHandler<HTMLDivElement> | undefined;
|
|
514
|
+
onMouseEnter?: import("react").MouseEventHandler<HTMLDivElement> | undefined;
|
|
515
|
+
onMouseLeave?: import("react").MouseEventHandler<HTMLDivElement> | undefined;
|
|
516
|
+
onMouseMove?: import("react").MouseEventHandler<HTMLDivElement> | undefined;
|
|
517
|
+
onMouseMoveCapture?: import("react").MouseEventHandler<HTMLDivElement> | undefined;
|
|
518
|
+
onMouseOut?: import("react").MouseEventHandler<HTMLDivElement> | undefined;
|
|
519
|
+
onMouseOutCapture?: import("react").MouseEventHandler<HTMLDivElement> | undefined;
|
|
520
|
+
onMouseOver?: import("react").MouseEventHandler<HTMLDivElement> | undefined;
|
|
521
|
+
onMouseOverCapture?: import("react").MouseEventHandler<HTMLDivElement> | undefined;
|
|
522
|
+
onMouseUp?: import("react").MouseEventHandler<HTMLDivElement> | undefined;
|
|
523
|
+
onMouseUpCapture?: import("react").MouseEventHandler<HTMLDivElement> | undefined;
|
|
524
|
+
onSelect?: import("react").ReactEventHandler<HTMLDivElement> | undefined;
|
|
525
|
+
onSelectCapture?: import("react").ReactEventHandler<HTMLDivElement> | undefined;
|
|
526
|
+
onTouchCancel?: import("react").TouchEventHandler<HTMLDivElement> | undefined;
|
|
527
|
+
onTouchCancelCapture?: import("react").TouchEventHandler<HTMLDivElement> | undefined;
|
|
528
|
+
onTouchEnd?: import("react").TouchEventHandler<HTMLDivElement> | undefined;
|
|
529
|
+
onTouchEndCapture?: import("react").TouchEventHandler<HTMLDivElement> | undefined;
|
|
530
|
+
onTouchMove?: import("react").TouchEventHandler<HTMLDivElement> | undefined;
|
|
531
|
+
onTouchMoveCapture?: import("react").TouchEventHandler<HTMLDivElement> | undefined;
|
|
532
|
+
onTouchStart?: import("react").TouchEventHandler<HTMLDivElement> | undefined;
|
|
533
|
+
onTouchStartCapture?: import("react").TouchEventHandler<HTMLDivElement> | undefined;
|
|
534
|
+
onPointerDown?: import("react").PointerEventHandler<HTMLDivElement> | undefined;
|
|
535
|
+
onPointerDownCapture?: import("react").PointerEventHandler<HTMLDivElement> | undefined;
|
|
536
|
+
onPointerMove?: import("react").PointerEventHandler<HTMLDivElement> | undefined;
|
|
537
|
+
onPointerMoveCapture?: import("react").PointerEventHandler<HTMLDivElement> | undefined;
|
|
538
|
+
onPointerUp?: import("react").PointerEventHandler<HTMLDivElement> | undefined;
|
|
539
|
+
onPointerUpCapture?: import("react").PointerEventHandler<HTMLDivElement> | undefined;
|
|
540
|
+
onPointerCancel?: import("react").PointerEventHandler<HTMLDivElement> | undefined;
|
|
541
|
+
onPointerCancelCapture?: import("react").PointerEventHandler<HTMLDivElement> | undefined;
|
|
542
|
+
onPointerEnter?: import("react").PointerEventHandler<HTMLDivElement> | undefined;
|
|
543
|
+
onPointerEnterCapture?: import("react").PointerEventHandler<HTMLDivElement> | undefined;
|
|
544
|
+
onPointerLeave?: import("react").PointerEventHandler<HTMLDivElement> | undefined;
|
|
545
|
+
onPointerLeaveCapture?: import("react").PointerEventHandler<HTMLDivElement> | undefined;
|
|
546
|
+
onPointerOver?: import("react").PointerEventHandler<HTMLDivElement> | undefined;
|
|
547
|
+
onPointerOverCapture?: import("react").PointerEventHandler<HTMLDivElement> | undefined;
|
|
548
|
+
onPointerOut?: import("react").PointerEventHandler<HTMLDivElement> | undefined;
|
|
549
|
+
onPointerOutCapture?: import("react").PointerEventHandler<HTMLDivElement> | undefined;
|
|
550
|
+
onGotPointerCapture?: import("react").PointerEventHandler<HTMLDivElement> | undefined;
|
|
551
|
+
onGotPointerCaptureCapture?: import("react").PointerEventHandler<HTMLDivElement> | undefined;
|
|
552
|
+
onLostPointerCapture?: import("react").PointerEventHandler<HTMLDivElement> | undefined;
|
|
553
|
+
onLostPointerCaptureCapture?: import("react").PointerEventHandler<HTMLDivElement> | undefined;
|
|
554
|
+
onScroll?: UIEventHandler<HTMLDivElement> | undefined;
|
|
555
|
+
onScrollCapture?: UIEventHandler<HTMLDivElement> | undefined;
|
|
556
|
+
onWheel?: import("react").WheelEventHandler<HTMLDivElement> | undefined;
|
|
557
|
+
onWheelCapture?: import("react").WheelEventHandler<HTMLDivElement> | undefined;
|
|
558
|
+
onAnimationStart?: import("react").AnimationEventHandler<HTMLDivElement> | undefined;
|
|
559
|
+
onAnimationStartCapture?: import("react").AnimationEventHandler<HTMLDivElement> | undefined;
|
|
560
|
+
onAnimationEnd?: import("react").AnimationEventHandler<HTMLDivElement> | undefined;
|
|
561
|
+
onAnimationEndCapture?: import("react").AnimationEventHandler<HTMLDivElement> | undefined;
|
|
562
|
+
onAnimationIteration?: import("react").AnimationEventHandler<HTMLDivElement> | undefined;
|
|
563
|
+
onAnimationIterationCapture?: import("react").AnimationEventHandler<HTMLDivElement> | undefined;
|
|
564
|
+
onTransitionEnd?: import("react").TransitionEventHandler<HTMLDivElement> | undefined;
|
|
565
|
+
onTransitionEndCapture?: import("react").TransitionEventHandler<HTMLDivElement> | undefined;
|
|
566
|
+
};
|
|
567
|
+
}, boolean];
|
|
568
|
+
export {};
|
package/Table/useTableScroll.js
CHANGED
|
@@ -1,141 +1,239 @@
|
|
|
1
|
-
import { useRef,
|
|
2
|
-
import { TableContext, TableDataContext } from './TableContext.js';
|
|
3
|
-
import { usePreviousValue } from '../hooks/usePreviousValue.js';
|
|
1
|
+
import { useRef, useState, useCallback, useEffect, useMemo } from 'react';
|
|
4
2
|
|
|
3
|
+
const HEADER_DEFAULT_HEIGHT = 40; // px
|
|
4
|
+
const SCROLL_BAR_MIN_START_AT = 4; // px
|
|
5
|
+
const SCROLL_BAR_MAX_END_SPACING = 16; // px
|
|
6
|
+
const FETCH_MORE_TRIGGER_AT_BOTTOM = 46; // px
|
|
7
|
+
const SCROLL_BAR_DISPLAY_TIMES = 1500; // ms
|
|
8
|
+
const defaultScrollBarTrackStyle = {
|
|
9
|
+
position: 'absolute',
|
|
10
|
+
right: 0,
|
|
11
|
+
top: `${HEADER_DEFAULT_HEIGHT}px`,
|
|
12
|
+
width: 12,
|
|
13
|
+
height: 0,
|
|
14
|
+
opacity: '0',
|
|
15
|
+
transition: '0.1s opacity ease-in',
|
|
16
|
+
backgroundColor: '#F2F2F2',
|
|
17
|
+
};
|
|
5
18
|
const defaultScrollBarStyle = {
|
|
6
19
|
display: 'flex',
|
|
7
20
|
justifyContent: 'center',
|
|
8
21
|
alignItems: 'flex-start',
|
|
9
22
|
position: 'absolute',
|
|
10
23
|
right: 0,
|
|
11
|
-
top:
|
|
24
|
+
top: `${SCROLL_BAR_MIN_START_AT}px`,
|
|
12
25
|
width: 10,
|
|
13
26
|
height: 0,
|
|
14
27
|
borderRadius: 10,
|
|
28
|
+
transform: 'translate3d(0, 0, 0)',
|
|
15
29
|
outline: 'none',
|
|
16
30
|
opacity: '0',
|
|
17
31
|
transition: '0.1s opacity ease-in',
|
|
18
32
|
backgroundColor: 'transparent',
|
|
19
33
|
};
|
|
20
|
-
|
|
21
|
-
const
|
|
22
|
-
const
|
|
23
|
-
const
|
|
24
|
-
|
|
25
|
-
const bodyRef = useRef(null);
|
|
34
|
+
function useTableScroll(props) {
|
|
35
|
+
const { onFetchMore, loading, scrollBarSize = 4, } = props;
|
|
36
|
+
const scrollRef = useRef(null);
|
|
37
|
+
const tableRef = useRef(null);
|
|
38
|
+
const scrollBarTrackRef = useRef(null);
|
|
26
39
|
const scrollBarRef = useRef(null);
|
|
27
40
|
const scrollBarDisplayTimer = useRef();
|
|
28
|
-
const { fetchMore, loading, scrollBarSize = 4, } = useContext(TableContext) || {};
|
|
29
|
-
const { dataSource = [], } = useContext(TableDataContext) || {};
|
|
30
41
|
const [scrollBarHeight, setScrollBarHeight] = useState(0);
|
|
31
42
|
const [pointerOffset, setPointerOffset] = useState(0);
|
|
43
|
+
const [isHorizontalScrolling, toggleIsHorizontalScrolling] = useState(false);
|
|
32
44
|
/** set scroll bar callback */
|
|
33
45
|
const onSetScrollBarHeight = useCallback(() => {
|
|
34
|
-
|
|
46
|
+
/** @NOTE Scroll bar 高度為可視區域的百分比 */
|
|
47
|
+
if (!scrollRef.current)
|
|
35
48
|
return;
|
|
36
|
-
const { scrollHeight, clientHeight: tableHeight, } =
|
|
37
|
-
const
|
|
49
|
+
const { scrollHeight, clientHeight: tableHeight, } = scrollRef.current;
|
|
50
|
+
const bodyHeight = scrollHeight - HEADER_DEFAULT_HEIGHT;
|
|
51
|
+
const viewAreaHeight = tableHeight - HEADER_DEFAULT_HEIGHT;
|
|
52
|
+
const nextHeight = Math.max((viewAreaHeight - (SCROLL_BAR_MAX_END_SPACING * 2)) * (viewAreaHeight / bodyHeight), tableHeight / 10);
|
|
38
53
|
setScrollBarHeight(nextHeight);
|
|
39
54
|
}, []);
|
|
40
55
|
/** display/hide scroll bar */
|
|
41
56
|
const onHideScrollBar = useCallback(() => {
|
|
42
57
|
if (!scrollBarRef.current)
|
|
43
58
|
return;
|
|
44
|
-
|
|
45
|
-
|
|
59
|
+
if (scrollBarDisplayTimer.current) {
|
|
60
|
+
window.clearTimeout(scrollBarDisplayTimer.current);
|
|
61
|
+
}
|
|
62
|
+
scrollBarDisplayTimer.current = window.setTimeout(() => {
|
|
63
|
+
if (scrollBarRef.current) {
|
|
64
|
+
scrollBarRef.current.style.opacity = '0';
|
|
65
|
+
scrollBarRef.current.style.pointerEvents = 'none';
|
|
66
|
+
}
|
|
67
|
+
if (scrollBarTrackRef.current) {
|
|
68
|
+
scrollBarTrackRef.current.style.opacity = '0';
|
|
69
|
+
scrollBarTrackRef.current.style.pointerEvents = 'none';
|
|
70
|
+
}
|
|
71
|
+
}, SCROLL_BAR_DISPLAY_TIMES);
|
|
46
72
|
}, []);
|
|
47
73
|
const onDisplayScrollBar = useCallback(() => {
|
|
48
|
-
if (!scrollBarRef.current || !
|
|
74
|
+
if (!scrollBarRef.current || !scrollRef.current || !scrollBarTrackRef.current)
|
|
75
|
+
return;
|
|
76
|
+
/** 觸控螢幕不需要 scroll bar */
|
|
77
|
+
const isTouchEnabled = ('ontouchstart' in window) || (navigator.maxTouchPoints > 0);
|
|
78
|
+
/** firefox 的滾軸只能同時顯示 or 取消,所以乾脆就用原生的(除非能單獨關掉直向的滾軸,只顯示橫向的才行) */
|
|
79
|
+
const isFirefox = navigator.userAgent.toLowerCase().indexOf('firefox') > -1;
|
|
80
|
+
if (isTouchEnabled || isFirefox)
|
|
49
81
|
return;
|
|
82
|
+
scrollBarRef.current.style.opacity = '1';
|
|
83
|
+
scrollBarRef.current.style.pointerEvents = 'auto';
|
|
84
|
+
scrollBarTrackRef.current.style.opacity = '1';
|
|
85
|
+
scrollBarTrackRef.current.style.pointerEvents = 'auto';
|
|
50
86
|
if (scrollBarDisplayTimer.current) {
|
|
51
87
|
window.clearTimeout(scrollBarDisplayTimer.current);
|
|
52
88
|
}
|
|
53
|
-
scrollBarRef.current.style.opacity = '1';
|
|
54
|
-
scrollBarRef.current.style.pointerEvents = 'auto';
|
|
55
|
-
scrollBarDisplayTimer.current = window.setTimeout(() => onHideScrollBar(), SCROLL_BAR_DISPLAY_TIMES);
|
|
56
89
|
}, []);
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
const
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
90
|
+
const resetPointerOffset = useCallback(() => setPointerOffset(0), []);
|
|
91
|
+
/** scroll bar style reset when mouse leave */
|
|
92
|
+
const onScrollBarLeave = useCallback(() => {
|
|
93
|
+
if (scrollBarRef.current) {
|
|
94
|
+
scrollBarRef.current.childNodes[0].style.width = `${scrollBarSize}px`;
|
|
95
|
+
}
|
|
96
|
+
resetPointerOffset();
|
|
97
|
+
}, []);
|
|
98
|
+
/** when use mouse to drag scroll bar, get cursor position */
|
|
99
|
+
const onScrollBarMouseDown = useCallback(({ clientY }) => {
|
|
100
|
+
const { current: scrollBar } = scrollBarRef;
|
|
101
|
+
if (!scrollBar)
|
|
102
|
+
return;
|
|
103
|
+
const { top: initScrollBarTop } = scrollBar.getBoundingClientRect();
|
|
104
|
+
setPointerOffset(clientY - initScrollBarTop);
|
|
63
105
|
}, []);
|
|
106
|
+
const onScrollBarMouseUp = useCallback(() => resetPointerOffset(), []);
|
|
107
|
+
/** 偵測 table 高度是否發生變化,有的話就要重新計算 scroll bar 長度 */
|
|
64
108
|
useEffect(() => {
|
|
65
|
-
|
|
66
|
-
|
|
109
|
+
const { current: table } = tableRef;
|
|
110
|
+
function resizing() {
|
|
111
|
+
window.requestAnimationFrame(onSetScrollBarHeight);
|
|
67
112
|
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
113
|
+
if (table) {
|
|
114
|
+
const observer = new ResizeObserver(resizing);
|
|
115
|
+
observer.observe(table);
|
|
116
|
+
return () => {
|
|
117
|
+
observer.disconnect();
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
return () => { };
|
|
74
121
|
}, []);
|
|
75
122
|
useEffect(() => {
|
|
76
|
-
const { current: body } =
|
|
123
|
+
const { current: body } = scrollRef;
|
|
77
124
|
const { current: scrollBar } = scrollBarRef;
|
|
78
|
-
|
|
125
|
+
const { current: scrollBarTrack } = scrollBarTrackRef;
|
|
126
|
+
if (!body || !scrollBar || !scrollBarTrack)
|
|
79
127
|
return;
|
|
128
|
+
/** 游標在滾軸上長按並移動 */
|
|
80
129
|
function onMouseMove({ clientY }) {
|
|
81
|
-
const {
|
|
130
|
+
const { scrollHeight, clientHeight: tableHeight, } = body;
|
|
82
131
|
if (!pointerOffset)
|
|
83
132
|
return;
|
|
84
133
|
// keep scroll bar display when moving
|
|
85
134
|
window.requestAnimationFrame(onDisplayScrollBar);
|
|
86
135
|
const { top: tableTop, } = body.getBoundingClientRect();
|
|
87
|
-
|
|
88
|
-
const
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
136
|
+
/** Table 最大滾動距離 */
|
|
137
|
+
const maxScrollDistance = scrollHeight - tableHeight;
|
|
138
|
+
/** 游標在 scroll bar 上的位置 */
|
|
139
|
+
const scrollBarCurrentPosition = clientY - (tableTop + HEADER_DEFAULT_HEIGHT) - pointerOffset;
|
|
140
|
+
/** 可視區域高度 */
|
|
141
|
+
const viewAreaHeight = tableHeight - HEADER_DEFAULT_HEIGHT;
|
|
142
|
+
/** 最大滑動距離 */
|
|
143
|
+
const maxScrollBarDistance = viewAreaHeight - scrollBarHeight - SCROLL_BAR_MAX_END_SPACING;
|
|
144
|
+
/** 計算出來的距離 */
|
|
145
|
+
const clampScrollBarTop = Math.min(Math.max(scrollBarCurrentPosition, 0), // min boundary
|
|
146
|
+
maxScrollBarDistance);
|
|
147
|
+
scrollBar.style.setProperty('transform', `translate3d(0, ${clampScrollBarTop}px, 0)`);
|
|
148
|
+
body.scrollTop = ((clampScrollBarTop * maxScrollDistance) / maxScrollBarDistance);
|
|
149
|
+
}
|
|
150
|
+
/** 在滾軸滑軌上點擊,直接滾動到指定位置上 */
|
|
151
|
+
function onMouseClick({ clientY }) {
|
|
152
|
+
if (!scrollBar)
|
|
153
|
+
return;
|
|
154
|
+
const { scrollHeight, clientHeight: tableHeight, } = body;
|
|
155
|
+
// keep scroll bar display when moving
|
|
156
|
+
window.requestAnimationFrame(onDisplayScrollBar);
|
|
157
|
+
const { top: tableTop, } = body.getBoundingClientRect();
|
|
158
|
+
/** Table 最大滾動距離 */
|
|
159
|
+
const maxScrollDistance = scrollHeight - tableHeight;
|
|
160
|
+
/** 游標在 Track 上的位置 */
|
|
161
|
+
const scrollBarCurrentPosition = clientY - (tableTop + HEADER_DEFAULT_HEIGHT) - (scrollBarHeight / 2);
|
|
162
|
+
/** 可視區域高度 */
|
|
163
|
+
const viewAreaHeight = tableHeight - HEADER_DEFAULT_HEIGHT;
|
|
164
|
+
/** 最大滑動距離 */
|
|
165
|
+
const maxScrollBarDistance = viewAreaHeight - scrollBarHeight - SCROLL_BAR_MAX_END_SPACING;
|
|
166
|
+
/** 計算出來的距離 */
|
|
167
|
+
const clampScrollBarTop = Math.min(Math.max(scrollBarCurrentPosition, 0), // min boundary
|
|
168
|
+
maxScrollBarDistance);
|
|
169
|
+
scrollBar.style.setProperty('transform', `translate3d(0, ${clampScrollBarTop}px, 0)`);
|
|
170
|
+
body.scrollTop = ((clampScrollBarTop * maxScrollDistance) / maxScrollBarDistance);
|
|
171
|
+
}
|
|
172
|
+
/** 游標移動到滾軸/滑軌上方時 */
|
|
173
|
+
function onMouseOver() {
|
|
174
|
+
scrollBar.style.setProperty('transition', '0s');
|
|
175
|
+
onDisplayScrollBar();
|
|
176
|
+
}
|
|
177
|
+
/** 游標移開滾軸/滑軌上方時 */
|
|
178
|
+
function onMouseLeave() {
|
|
179
|
+
scrollBar.style.setProperty('transition', '0.1s');
|
|
180
|
+
onHideScrollBar();
|
|
94
181
|
}
|
|
95
182
|
scrollBar.addEventListener('mousemove', onMouseMove, false);
|
|
183
|
+
scrollBar.addEventListener('mouseover', onMouseOver, false);
|
|
184
|
+
scrollBar.addEventListener('mouseleave', onMouseLeave, false);
|
|
185
|
+
scrollBarTrack.addEventListener('mousemove', onMouseMove, false);
|
|
186
|
+
scrollBarTrack.addEventListener('mouseover', onMouseOver, false);
|
|
187
|
+
scrollBarTrack.addEventListener('mouseleave', onMouseLeave, false);
|
|
188
|
+
scrollBarTrack.addEventListener('click', onMouseClick, false);
|
|
96
189
|
return () => {
|
|
97
190
|
scrollBar.removeEventListener('mousemove', onMouseMove, false);
|
|
191
|
+
scrollBar.removeEventListener('mouseover', onMouseOver, false);
|
|
192
|
+
scrollBar.removeEventListener('mouseleave', onMouseLeave, false);
|
|
193
|
+
scrollBarTrack.removeEventListener('mousemove', onMouseMove, false);
|
|
194
|
+
scrollBarTrack.removeEventListener('mouseover', onMouseOver, false);
|
|
195
|
+
scrollBarTrack.removeEventListener('mouseleave', onMouseLeave, false);
|
|
196
|
+
scrollBarTrack.removeEventListener('click', onMouseClick, false);
|
|
98
197
|
};
|
|
99
|
-
}, [scrollBarHeight, pointerOffset, onDisplayScrollBar]);
|
|
100
|
-
const resetPointerOffset = useCallback(() => setPointerOffset(0), []);
|
|
198
|
+
}, [scrollBarHeight, pointerOffset, onDisplayScrollBar, onHideScrollBar]);
|
|
101
199
|
/** scroll bar fatter when mouse enter */
|
|
102
200
|
const onScrollBarEnter = useCallback(() => {
|
|
103
201
|
if (scrollBarRef.current) {
|
|
104
202
|
scrollBarRef.current.childNodes[0].style.width = `${scrollBarSize + 6}px`;
|
|
105
203
|
}
|
|
106
204
|
}, []);
|
|
107
|
-
/** scroll bar style reset when mouse leave */
|
|
108
|
-
const onScrollBarLeave = useCallback(() => {
|
|
109
|
-
if (scrollBarRef.current) {
|
|
110
|
-
scrollBarRef.current.childNodes[0].style.width = `${scrollBarSize}px`;
|
|
111
|
-
}
|
|
112
|
-
resetPointerOffset();
|
|
113
|
-
}, []);
|
|
114
|
-
/** when use mouse to drag scroll bar, get cursor position */
|
|
115
|
-
const onScrollBarMouseDown = useCallback(({ target, clientY }) => {
|
|
116
|
-
if (!target)
|
|
117
|
-
return;
|
|
118
|
-
const { top: initScrollBarTop } = target.getBoundingClientRect();
|
|
119
|
-
setPointerOffset(clientY - initScrollBarTop);
|
|
120
|
-
}, []);
|
|
121
|
-
const onScrollBarMouseUp = useCallback(() => resetPointerOffset(), []);
|
|
122
205
|
/** scroll table directly */
|
|
123
206
|
const setScrollBarTop = useCallback(() => {
|
|
124
|
-
if (
|
|
125
|
-
const { clientHeight: tableHeight, scrollTop, scrollHeight, } =
|
|
207
|
+
if (scrollRef.current) {
|
|
208
|
+
const { clientHeight: tableHeight, scrollTop, scrollHeight, } = scrollRef.current;
|
|
126
209
|
/** @NOTE don't apply scroll change when use pointer dragging */
|
|
127
210
|
if (scrollBarRef.current && !pointerOffset) {
|
|
128
|
-
|
|
129
|
-
|
|
211
|
+
const bodyHeight = scrollHeight - HEADER_DEFAULT_HEIGHT;
|
|
212
|
+
const viewAreaHeight = tableHeight - HEADER_DEFAULT_HEIGHT;
|
|
213
|
+
const distance = Math.max((viewAreaHeight * Math.max((scrollTop / bodyHeight), 0)), 0);
|
|
214
|
+
scrollBarRef.current.style.transform = `translate3d(0, ${distance}px, 0)`;
|
|
215
|
+
}
|
|
216
|
+
if (scrollBarTrackRef.current) {
|
|
217
|
+
scrollBarTrackRef.current.style.height = `${tableHeight - HEADER_DEFAULT_HEIGHT}px`;
|
|
130
218
|
}
|
|
131
219
|
}
|
|
132
220
|
}, [scrollBarHeight, pointerOffset]);
|
|
133
|
-
const onScroll = useCallback(() => {
|
|
134
|
-
|
|
221
|
+
const onScroll = useCallback((scrollTarget) => {
|
|
222
|
+
/** 使用者開始橫向滾動 */
|
|
223
|
+
if (scrollTarget.target.scrollLeft) {
|
|
224
|
+
toggleIsHorizontalScrolling(true);
|
|
225
|
+
}
|
|
226
|
+
else {
|
|
227
|
+
toggleIsHorizontalScrolling(false);
|
|
228
|
+
}
|
|
135
229
|
if (loading)
|
|
136
230
|
return;
|
|
137
|
-
if (
|
|
138
|
-
const { clientHeight, scrollTop, scrollHeight, } =
|
|
231
|
+
if (scrollRef.current) {
|
|
232
|
+
const { clientHeight, scrollTop, scrollHeight, } = scrollRef.current;
|
|
233
|
+
/** 如果不需要滾動,則不需要觸發 */
|
|
234
|
+
if (clientHeight >= scrollHeight)
|
|
235
|
+
return;
|
|
236
|
+
window.requestAnimationFrame(onDisplayScrollBar);
|
|
139
237
|
/** @Note safari specific bug fix for scroll bouncing */
|
|
140
238
|
const belowBottom = scrollTop > (scrollHeight - clientHeight);
|
|
141
239
|
if (belowBottom)
|
|
@@ -143,28 +241,40 @@ function useTableScroll() {
|
|
|
143
241
|
window.requestAnimationFrame(setScrollBarTop);
|
|
144
242
|
/** trigger fetchMore when scrolling */
|
|
145
243
|
if ((scrollHeight - (scrollTop + clientHeight)) < FETCH_MORE_TRIGGER_AT_BOTTOM) {
|
|
146
|
-
|
|
244
|
+
onFetchMore === null || onFetchMore === void 0 ? void 0 : onFetchMore();
|
|
147
245
|
}
|
|
148
246
|
}
|
|
149
|
-
|
|
247
|
+
window.requestAnimationFrame(onHideScrollBar);
|
|
248
|
+
}, [loading, setScrollBarTop, onDisplayScrollBar, onFetchMore, onHideScrollBar]);
|
|
150
249
|
const scrollBarStyle = useMemo(() => ({
|
|
151
250
|
...defaultScrollBarStyle,
|
|
152
251
|
height: `${scrollBarHeight}px`,
|
|
153
252
|
}), [scrollBarHeight]);
|
|
253
|
+
const scrollBarTrackStyle = useMemo(() => {
|
|
254
|
+
var _a, _b;
|
|
255
|
+
return ({
|
|
256
|
+
...defaultScrollBarTrackStyle,
|
|
257
|
+
height: `${(_b = (_a = scrollRef.current) === null || _a === void 0 ? void 0 : _a.scrollHeight) !== null && _b !== void 0 ? _b : 0}px`,
|
|
258
|
+
});
|
|
259
|
+
}, [scrollBarHeight]);
|
|
154
260
|
/** composing result */
|
|
155
|
-
const
|
|
156
|
-
ref:
|
|
261
|
+
const tableScrollContainer = {
|
|
262
|
+
ref: scrollRef,
|
|
263
|
+
target: tableRef,
|
|
157
264
|
onScroll,
|
|
158
265
|
};
|
|
159
266
|
const scrollElement = {
|
|
160
267
|
ref: scrollBarRef,
|
|
268
|
+
trackRef: scrollBarTrackRef,
|
|
269
|
+
scrollBarSize,
|
|
161
270
|
onMouseDown: onScrollBarMouseDown,
|
|
162
271
|
onMouseUp: onScrollBarMouseUp,
|
|
163
272
|
onMouseEnter: onScrollBarEnter,
|
|
164
273
|
onMouseLeave: onScrollBarLeave,
|
|
165
274
|
style: scrollBarStyle,
|
|
275
|
+
trackStyle: scrollBarTrackStyle,
|
|
166
276
|
};
|
|
167
|
-
return [
|
|
277
|
+
return [tableScrollContainer, scrollElement, isHorizontalScrolling];
|
|
168
278
|
}
|
|
169
279
|
|
|
170
280
|
export { useTableScroll as default };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mezzanine-ui/react",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.13.0",
|
|
4
4
|
"description": "React components for mezzanine-ui",
|
|
5
5
|
"author": "Mezzanine",
|
|
6
6
|
"repository": {
|
|
@@ -31,9 +31,9 @@
|
|
|
31
31
|
"react-dom": "^18.2.0"
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@mezzanine-ui/core": "^0.
|
|
35
|
-
"@mezzanine-ui/icons": "^0.
|
|
36
|
-
"@mezzanine-ui/system": "^0.
|
|
34
|
+
"@mezzanine-ui/core": "^0.13.0",
|
|
35
|
+
"@mezzanine-ui/icons": "^0.13.0",
|
|
36
|
+
"@mezzanine-ui/system": "^0.13.0",
|
|
37
37
|
"@popperjs/core": "^2.11.6",
|
|
38
38
|
"@types/react-transition-group": "^4.4.5",
|
|
39
39
|
"clsx": "^1.2.1",
|