@canlooks/can-ui 0.0.203 → 0.0.205
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/components/autocomplete/autocomplete.js +6 -1
- package/dist/cjs/components/curd/curd.js +1 -0
- package/dist/cjs/components/curd/curd.style.d.ts +1 -0
- package/dist/cjs/components/curd/curd.style.js +2 -1
- package/dist/cjs/components/curd/curdColumnConfig.js +3 -2
- package/dist/cjs/components/curd/curdColumnConfig.style.js +3 -12
- package/dist/cjs/components/dataGrid/dataGrid.d.ts +2 -1
- package/dist/cjs/components/dataGrid/dataGrid.js +7 -2
- package/dist/cjs/components/dataGrid/dataGrid.style.js +27 -16
- package/dist/cjs/components/dataGrid/dataGridHead.d.ts +2 -1
- package/dist/cjs/components/dataGrid/dataGridHead.js +2 -2
- package/dist/cjs/components/dataGrid/dataGridRows.js +5 -3
- package/dist/cjs/components/dataGrid/stickyRow.d.ts +5 -0
- package/dist/cjs/components/dataGrid/stickyRow.js +28 -0
- package/dist/cjs/components/popper/popper.js +67 -67
- package/dist/cjs/components/select/select.js +10 -1
- package/dist/cjs/components/selectedList/selectedList.style.js +1 -1
- package/dist/cjs/components/selectionContext/selectionHook.js +6 -1
- package/dist/cjs/components/table/table.style.js +1 -1
- package/dist/cjs/components/table/tableSticky.js +3 -1
- package/dist/cjs/components/table/tableSticky.style.js +1 -1
- package/dist/cjs/utils/dataGrid.js +6 -1
- package/dist/esm/components/autocomplete/autocomplete.js +6 -1
- package/dist/esm/components/curd/curd.js +1 -0
- package/dist/esm/components/curd/curd.style.d.ts +1 -0
- package/dist/esm/components/curd/curd.style.js +2 -1
- package/dist/esm/components/curd/curdColumnConfig.js +3 -2
- package/dist/esm/components/curd/curdColumnConfig.style.js +3 -12
- package/dist/esm/components/dataGrid/dataGrid.d.ts +2 -1
- package/dist/esm/components/dataGrid/dataGrid.js +8 -3
- package/dist/esm/components/dataGrid/dataGrid.style.js +27 -16
- package/dist/esm/components/dataGrid/dataGridHead.d.ts +2 -1
- package/dist/esm/components/dataGrid/dataGridHead.js +2 -2
- package/dist/esm/components/dataGrid/dataGridRows.js +5 -3
- package/dist/esm/components/dataGrid/stickyRow.d.ts +5 -0
- package/dist/esm/components/dataGrid/stickyRow.js +25 -0
- package/dist/esm/components/popper/popper.js +67 -67
- package/dist/esm/components/select/select.js +10 -1
- package/dist/esm/components/selectedList/selectedList.style.js +1 -1
- package/dist/esm/components/selectionContext/selectionHook.js +6 -1
- package/dist/esm/components/table/table.style.js +1 -1
- package/dist/esm/components/table/tableSticky.js +3 -1
- package/dist/esm/components/table/tableSticky.style.js +1 -1
- package/dist/esm/utils/dataGrid.js +6 -1
- package/package.json +1 -1
|
@@ -48,7 +48,12 @@ exports.Autocomplete = (0, react_1.memo)(({ children, loading, options, loadOpti
|
|
|
48
48
|
actualOptions?.forEach(opt => {
|
|
49
49
|
if (opt && typeof opt === 'object') {
|
|
50
50
|
const key = opt[primaryKey];
|
|
51
|
-
!(0, utils_1.isUnset)(key)
|
|
51
|
+
if (!(0, utils_1.isUnset)(key)) {
|
|
52
|
+
if (map.has(key)) {
|
|
53
|
+
console.warn(`[@canlooks/can-ui/<Autocomple/>] option key "${key}" was duplicated`);
|
|
54
|
+
}
|
|
55
|
+
map.set(key, opt);
|
|
56
|
+
}
|
|
52
57
|
}
|
|
53
58
|
});
|
|
54
59
|
return map;
|
|
@@ -97,6 +97,7 @@ exports.Curd = (0, react_1.memo)((props) => {
|
|
|
97
97
|
const controlColumn = {
|
|
98
98
|
key: utils_1.CONTROL_COLUMN_KEY,
|
|
99
99
|
title: controlColumnTitle,
|
|
100
|
+
className: curd_style_1.classes.controlColumn,
|
|
100
101
|
render(row) {
|
|
101
102
|
const _updatable = typeof updatable === 'function' ? updatable(row) : updatable;
|
|
102
103
|
const _deletable = typeof deletable === 'function' ? deletable(row) : deletable;
|
|
@@ -20,6 +20,7 @@ exports.classes = (0, utils_1.defineInnerClasses)('curd', [
|
|
|
20
20
|
'toolbarRight',
|
|
21
21
|
'divider',
|
|
22
22
|
'card',
|
|
23
|
+
'controlColumn',
|
|
23
24
|
'control',
|
|
24
25
|
'dialogTitle',
|
|
25
26
|
'copyButton'
|
|
@@ -32,7 +33,7 @@ exports.style = (0, utils_1.defineCss)(({ spacing, text, background, borderRadiu
|
|
|
32
33
|
min-height: 0;
|
|
33
34
|
display: flex;
|
|
34
35
|
flex-direction: column;
|
|
35
|
-
|
|
36
|
+
|
|
36
37
|
.${exports.classes.filterForm} {
|
|
37
38
|
min-height: 0;
|
|
38
39
|
display: flex;
|
|
@@ -13,6 +13,7 @@ const utils_1 = require("../../utils");
|
|
|
13
13
|
const icon_1 = require("../icon");
|
|
14
14
|
const faGear_1 = require("@fortawesome/free-solid-svg-icons/faGear");
|
|
15
15
|
const react_2 = require("@dnd-kit/react");
|
|
16
|
+
const tooltip_1 = require("../tooltip");
|
|
16
17
|
exports.CurdColumnConfig = (0, react_1.memo)((props) => {
|
|
17
18
|
const dragEndHandler = e => {
|
|
18
19
|
const newColumns = (0, utils_1.onDndDragEnd)(e, props.columns || [], '_key');
|
|
@@ -41,12 +42,12 @@ const CurdColumnConfigContent = (0, react_1.memo)(({ columns, innerVisible, setI
|
|
|
41
42
|
? [...o, key]
|
|
42
43
|
: o.filter(k => k !== key));
|
|
43
44
|
};
|
|
44
|
-
return ((0, jsx_runtime_1.jsx)(bubble_1.Bubble, { placement: "bottomRight", trigger:
|
|
45
|
+
return ((0, jsx_runtime_1.jsx)(bubble_1.Bubble, { placement: "bottomRight", trigger: "click", ...columnConfigBubbleProps, css: curdColumnConfig_style_1.style, open: open, onOpenChange: openChangeHandler, content: (0, jsx_runtime_1.jsxs)("div", { className: curdColumnConfig_style_1.classes.content, children: [(0, jsx_runtime_1.jsxs)("div", { className: curdColumnConfig_style_1.classes.title, children: [(0, jsx_runtime_1.jsx)("div", { className: curdColumnConfig_style_1.classes.titleText, children: "\u5217\u8BBE\u7F6E" }), (0, jsx_runtime_1.jsx)("div", { className: curdColumnConfig_style_1.classes.description, children: "\u62D6\u62FD\u8C03\u6574\u987A\u5E8F" })] }), columns?.map((col, i) => {
|
|
45
46
|
const id = col._key;
|
|
46
47
|
const checked = !(0, utils_1.isUnset)(id) && (!visibleSet || visibleSet.has(id));
|
|
47
48
|
return ((0, jsx_runtime_1.jsx)(sortableItem_1.SortableItem, { id: id ?? i, index: i, component: menuItem_1.MenuItem, className: curdColumnConfig_style_1.classes.item, prefix: (0, jsx_runtime_1.jsx)(checkbox_1.Checkbox, { className: curdColumnConfig_style_1.classes.checkbox, checked: checked, onChange: e => {
|
|
48
49
|
e.stopPropagation();
|
|
49
50
|
toggleVisible(id, e.target.checked);
|
|
50
51
|
} }), onClick: () => toggleVisible(id, !checked), label: col.titleText ?? col.title, noStyle: true }, id ?? i));
|
|
51
|
-
})] }), autoClose: false, children: (0, jsx_runtime_1.jsx)(button_1.Button, { shape: "circular", variant: "text", color: "text.secondary", children: (0, jsx_runtime_1.jsx)(icon_1.Icon, { icon: faGear_1.faGear }) }) }));
|
|
52
|
+
})] }), autoClose: false, children: (0, jsx_runtime_1.jsx)(tooltip_1.Tooltip, { title: "\u5217\u8BBE\u7F6E", clickToClose: true, children: (0, jsx_runtime_1.jsx)(button_1.Button, { shape: "circular", variant: "text", color: "text.secondary", children: (0, jsx_runtime_1.jsx)(icon_1.Icon, { icon: faGear_1.faGear }) }) }) }));
|
|
52
53
|
});
|
|
@@ -21,25 +21,16 @@ exports.style = (0, utils_1.defineCss)(({ spacing, text }) => (0, react_1.css) `
|
|
|
21
21
|
align-items: center;
|
|
22
22
|
justify-content: space-between;
|
|
23
23
|
padding: ${spacing[3]}px;
|
|
24
|
-
|
|
24
|
+
|
|
25
25
|
.${exports.classes.titleText} {
|
|
26
26
|
font-weight: bold;
|
|
27
27
|
}
|
|
28
|
-
|
|
28
|
+
|
|
29
29
|
.${exports.classes.description} {
|
|
30
30
|
color: ${text.disabled};
|
|
31
31
|
}
|
|
32
32
|
}
|
|
33
|
-
|
|
34
|
-
.${exports.classes.item} {
|
|
35
|
-
cursor: pointer;
|
|
36
|
-
|
|
37
|
-
&[data-dragging=true] {
|
|
38
|
-
position: relative;
|
|
39
|
-
z-index: 1;
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
|
|
33
|
+
|
|
43
34
|
.${exports.classes.checkbox} {
|
|
44
35
|
display: flex;
|
|
45
36
|
margin-right: ${spacing[1]}px;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { ComponentProps, ReactElement, ReactNode } from 'react';
|
|
1
|
+
import React, { ComponentProps, ReactElement, ReactNode, RefObject } from 'react';
|
|
2
2
|
import { DivProps, Id, Obj, SlotsAndProps, ToRequired } from '../../types';
|
|
3
3
|
import { SelectionContextProps } from '../selectionContext';
|
|
4
4
|
import { PaginationProps } from '../pagination';
|
|
@@ -136,6 +136,7 @@ interface IDataGridContext<R extends RowType = RowType> extends ToRequired<DataG
|
|
|
136
136
|
expandedSet: Set<Id>;
|
|
137
137
|
flattedColumns: (symbol | ColumnType<R>)[] | undefined;
|
|
138
138
|
toggleExpanded(key: Id): void;
|
|
139
|
+
theadRef: RefObject<HTMLTableSectionElement | null>;
|
|
139
140
|
}
|
|
140
141
|
export declare function useDataGridContext<R extends RowType>(): IDataGridContext<R>;
|
|
141
142
|
export declare const DataGrid: {
|
|
@@ -130,13 +130,18 @@ exports.DataGrid = (0, react_1.memo)(({ slots, slotProps, columns, rows, rowProp
|
|
|
130
130
|
const { page, pageSize } = _paginationProps;
|
|
131
131
|
return orderedRows?.slice((page - 1) * pageSize, page * pageSize);
|
|
132
132
|
}, [orderedRows, _paginationProps.page, _paginationProps.pageSize, paginatable]);
|
|
133
|
+
/**
|
|
134
|
+
* ---------------------------------------------------------------
|
|
135
|
+
* 渲染
|
|
136
|
+
*/
|
|
137
|
+
const theadRef = (0, react_1.useRef)(null);
|
|
133
138
|
const { container: Container = table_1.TableContainer } = slots || {};
|
|
134
139
|
const { container: containerProps } = slotProps || {};
|
|
135
140
|
const renderedContent = ((0, jsx_runtime_1.jsx)(columnResize_1.ColumnResizeContext, { columnResizable: columnResizable, children: ({ scrollerRef, tableRef }) => (0, jsx_runtime_1.jsxs)(Container, { ...(0, utils_1.mergeComponentProps)(containerProps, {
|
|
136
141
|
ref: scrollerRef,
|
|
137
142
|
className: dataGrid_style_1.classes.container
|
|
138
|
-
}), children: [(0, jsx_runtime_1.jsx)(table_1.Table, { size: size, bordered: bordered, striped: striped, ...tableProps, ref: (0, utils_1.cloneRef)(tableProps?.ref, tableRef), children: (0, jsx_runtime_1.jsxs)(selectionContext_1.SelectionContext, { options: rows, primaryKey: primaryKey, childrenKey: childrenKey !== null ? childrenKey : void 0, relation: relation, integration: integration, disabled: !selectable, multiple: multiple, defaultValue: defaultValue, value: value, onChange: onChange, onToggle: onToggle, children: [(0, jsx_runtime_1.jsx)(dataGridHead_1.DataGridHead, { rows: rows, flattedColumns: flattedColumns, completedColumns: completedColumns, primaryKey: primaryKey, allowSelectAll: allowSelectAll, columnResizable: columnResizable, orderColumn: innerOrderColumn.current, orderType: innerOrderType.current, onOrderChange: orderChangeHandler, filterBubbleProps: filterBubbleProps, onFilterClick: onFilterClick }), (0, jsx_runtime_1.jsx)("tbody", { children: (0, jsx_runtime_1.jsx)(DataGridContext, { value: (0, react_1.useMemo)(() => ({
|
|
139
|
-
slots, slotProps,
|
|
143
|
+
}), children: [(0, jsx_runtime_1.jsx)(table_1.Table, { size: size, bordered: bordered, striped: striped, ...tableProps, ref: (0, utils_1.cloneRef)(tableProps?.ref, tableRef), children: (0, jsx_runtime_1.jsxs)(selectionContext_1.SelectionContext, { options: rows, primaryKey: primaryKey, childrenKey: childrenKey !== null ? childrenKey : void 0, relation: relation, integration: integration, disabled: !selectable, multiple: multiple, defaultValue: defaultValue, value: value, onChange: onChange, onToggle: onToggle, children: [(0, jsx_runtime_1.jsx)(dataGridHead_1.DataGridHead, { ref: theadRef, rows: rows, flattedColumns: flattedColumns, completedColumns: completedColumns, primaryKey: primaryKey, allowSelectAll: allowSelectAll, columnResizable: columnResizable, orderColumn: innerOrderColumn.current, orderType: innerOrderType.current, onOrderChange: orderChangeHandler, filterBubbleProps: filterBubbleProps, onFilterClick: onFilterClick }), (0, jsx_runtime_1.jsx)("tbody", { children: (0, jsx_runtime_1.jsx)(DataGridContext, { value: (0, react_1.useMemo)(() => ({
|
|
144
|
+
slots, slotProps, theadRef,
|
|
140
145
|
rowProps, primaryKey, childrenKey, clickRowToSelect, indent, renderExpandIcon,
|
|
141
146
|
expandedSet, flattedColumns, toggleExpanded
|
|
142
147
|
}), [
|
|
@@ -92,25 +92,36 @@ exports.style = (0, utils_1.defineCss)(({ spacing, mode, gray, text, colors, eas
|
|
|
92
92
|
}
|
|
93
93
|
}
|
|
94
94
|
}
|
|
95
|
+
|
|
96
|
+
tr {
|
|
97
|
+
position: relative;
|
|
98
|
+
z-index: 2;
|
|
99
|
+
|
|
100
|
+
&[data-expanded=true] {
|
|
101
|
+
position: sticky;
|
|
102
|
+
z-index: 1;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
&.${exports.classes.sub} {
|
|
106
|
+
z-index: 0;
|
|
107
|
+
background-color: ${gray(mode === 'light' ? .02 : .22)};
|
|
95
108
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
td.${exports.classes.subTd} {
|
|
100
|
-
padding: 0;
|
|
101
|
-
border: none;
|
|
109
|
+
td.${exports.classes.subTd} {
|
|
110
|
+
padding: 0;
|
|
111
|
+
border: none;
|
|
102
112
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
113
|
+
.${exports.classes.children} {
|
|
114
|
+
padding: ${spacing[4]}px ${spacing[5]}px;
|
|
115
|
+
border-bottom: 1px solid ${gray(mode === 'light' ? .12 : .32)};
|
|
106
116
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
117
|
+
thead, tfoot {
|
|
118
|
+
z-index: 5;
|
|
119
|
+
}
|
|
110
120
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
121
|
+
th, td {
|
|
122
|
+
&[data-sticky=left], &[data-sticky=right] {
|
|
123
|
+
z-index: 4;
|
|
124
|
+
}
|
|
114
125
|
}
|
|
115
126
|
}
|
|
116
127
|
}
|
|
@@ -157,7 +168,7 @@ exports.style = (0, utils_1.defineCss)(({ spacing, mode, gray, text, colors, eas
|
|
|
157
168
|
position: absolute;
|
|
158
169
|
top: 0;
|
|
159
170
|
right: -4px;
|
|
160
|
-
z-index:
|
|
171
|
+
z-index: 3;
|
|
161
172
|
}
|
|
162
173
|
|
|
163
174
|
th:last-of-type {
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { ReactElement } from 'react';
|
|
1
|
+
import { ReactElement, RefObject } from 'react';
|
|
2
2
|
import { ColumnType, DataGridProps, RowType } from './dataGrid';
|
|
3
3
|
import { Id } from '../../types';
|
|
4
4
|
interface DataGridHeadProps<R extends RowType, V extends Id = Id> extends Required<Pick<DataGridProps<R, V>, 'primaryKey' | 'orderType' | 'onOrderChange' | 'allowSelectAll' | 'columnResizable'>> {
|
|
5
|
+
ref: RefObject<HTMLTableSectionElement | null>;
|
|
5
6
|
rows: R[] | undefined;
|
|
6
7
|
orderColumn: Id | undefined;
|
|
7
8
|
flattedColumns: (symbol | ColumnType<R>)[] | undefined;
|
|
@@ -18,7 +18,7 @@ const bubble_1 = require("../bubble");
|
|
|
18
18
|
const filterBubbleContent_1 = require("./filterBubbleContent");
|
|
19
19
|
const form_1 = require("../form");
|
|
20
20
|
const utils_1 = require("../../utils");
|
|
21
|
-
exports.DataGridHead = (0, react_2.memo)(({ allowSelectAll, columnResizable, flattedColumns, completedColumns, rows, primaryKey, orderColumn, orderType, onOrderChange, filterBubbleProps, onFilterClick }) => {
|
|
21
|
+
exports.DataGridHead = (0, react_2.memo)(({ ref, allowSelectAll, columnResizable, flattedColumns, completedColumns, rows, primaryKey, orderColumn, orderType, onOrderChange, filterBubbleProps, onFilterClick }) => {
|
|
22
22
|
const { multiple, setValue, selectionStatus } = (0, selectionContext_1.useSelectionContext)();
|
|
23
23
|
const allSelectionStatus = (0, react_2.useMemo)(() => {
|
|
24
24
|
if (multiple && allowSelectAll) {
|
|
@@ -116,5 +116,5 @@ exports.DataGridHead = (0, react_2.memo)(({ allowSelectAll, columnResizable, fla
|
|
|
116
116
|
];
|
|
117
117
|
}) }, i));
|
|
118
118
|
});
|
|
119
|
-
return (0, jsx_runtime_1.jsx)("thead", { children: renderedHead });
|
|
119
|
+
return (0, jsx_runtime_1.jsx)("thead", { ref: ref, children: renderedHead });
|
|
120
120
|
});
|
|
@@ -16,10 +16,11 @@ const icon_1 = require("../icon");
|
|
|
16
16
|
const faMinusSquare_1 = require("@fortawesome/free-regular-svg-icons/faMinusSquare");
|
|
17
17
|
const faPlusSquare_1 = require("@fortawesome/free-regular-svg-icons/faPlusSquare");
|
|
18
18
|
const dataGrid_style_1 = require("./dataGrid.style");
|
|
19
|
+
const stickyRow_1 = require("./stickyRow");
|
|
19
20
|
exports.DataGridRows = (0, react_2.memo)(({ rows, _level = 0 }) => {
|
|
20
21
|
const { multiple, toggleSelected, selectionStatus } = (0, selectionContext_1.useSelectionContext)();
|
|
21
22
|
const { slots, slotProps, rowProps, primaryKey, childrenKey, clickRowToSelect, indent, renderExpandIcon, expandedSet, flattedColumns, toggleExpanded } = (0, dataGrid_1.useDataGridContext)();
|
|
22
|
-
const { tr: Tr =
|
|
23
|
+
const { tr: Tr = stickyRow_1.StickyRow } = slots || {};
|
|
23
24
|
const { tr: TrProps } = slotProps || {};
|
|
24
25
|
return rows?.flatMap((row, i, arr) => {
|
|
25
26
|
const trKey = row[primaryKey];
|
|
@@ -37,8 +38,9 @@ exports.DataGridRows = (0, react_2.memo)(({ rows, _level = 0 }) => {
|
|
|
37
38
|
className: (0, utils_1.clsx)(_rowProps, _level > 0 && dataGrid_style_1.classes.sub),
|
|
38
39
|
onClick() {
|
|
39
40
|
clickRowToSelect && toggleSelected(trKey);
|
|
40
|
-
}
|
|
41
|
-
|
|
41
|
+
},
|
|
42
|
+
sticky: currentExpanded
|
|
43
|
+
}), key: trKey, "data-selected": status === 2, "data-expanded": currentExpanded }, flattedColumns?.flatMap((col, j) => {
|
|
42
44
|
if (typeof col === 'symbol') {
|
|
43
45
|
if (col === dataGrid_1.DataGrid.EXPAND_COLUMN) {
|
|
44
46
|
expandableIndex = j;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.StickyRow = StickyRow;
|
|
4
|
+
const jsx_runtime_1 = require("@emotion/react/jsx-runtime");
|
|
5
|
+
const react_1 = require("react");
|
|
6
|
+
const dataGrid_1 = require("./dataGrid");
|
|
7
|
+
const utils_1 = require("../../utils");
|
|
8
|
+
function StickyRow({ sticky, ...props }) {
|
|
9
|
+
const [offset, setOffset] = (0, react_1.useState)(0);
|
|
10
|
+
const { theadRef } = (0, dataGrid_1.useDataGridContext)();
|
|
11
|
+
(0, react_1.useEffect)(() => {
|
|
12
|
+
if (!sticky || !theadRef.current) {
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
const resizeObserver = new ResizeObserver(() => {
|
|
16
|
+
setOffset(theadRef.current.offsetHeight);
|
|
17
|
+
});
|
|
18
|
+
resizeObserver.observe(theadRef.current);
|
|
19
|
+
return () => {
|
|
20
|
+
resizeObserver.disconnect();
|
|
21
|
+
};
|
|
22
|
+
}, [sticky]);
|
|
23
|
+
return ((0, jsx_runtime_1.jsx)("tr", { ...(0, utils_1.mergeComponentProps)(props, {
|
|
24
|
+
...sticky && {
|
|
25
|
+
style: { top: offset }
|
|
26
|
+
}
|
|
27
|
+
}) }));
|
|
28
|
+
}
|
|
@@ -9,18 +9,56 @@ const clickAway_1 = require("../clickAway");
|
|
|
9
9
|
const popper_style_1 = require("./popper.style");
|
|
10
10
|
const popperContext_1 = require("./popperContext");
|
|
11
11
|
const theme_1 = require("../theme");
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
12
|
+
const defaultAttemptOrder = ['top', 'bottom', 'left', 'right', 'topLeft', 'topRight', 'rightTop', 'rightBottom', 'bottomRight', 'bottomLeft', 'leftBottom', 'leftTop'];
|
|
13
|
+
const contextMenuOrder = [
|
|
14
|
+
'bottomRight',
|
|
15
|
+
'rightBottom',
|
|
16
|
+
'bottomLeft',
|
|
17
|
+
'leftBottom',
|
|
18
|
+
'topLeft',
|
|
19
|
+
'leftTop',
|
|
20
|
+
'topRight',
|
|
21
|
+
'rightTop'
|
|
22
|
+
];
|
|
23
|
+
const getAttemptOrder = (startPlacement, contextMenu, sizeAdaptable, callback) => {
|
|
24
|
+
if (contextMenu) {
|
|
25
|
+
const startIndex = Math.max(contextMenuOrder.indexOf(startPlacement), 0);
|
|
26
|
+
for (let i = 0; i <= contextMenuOrder.length + 1; i += 2) {
|
|
27
|
+
const index = (startIndex + i) % contextMenuOrder.length;
|
|
28
|
+
if (callback(contextMenuOrder[index]) === false) {
|
|
29
|
+
break;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
let order = defaultAttemptOrder;
|
|
35
|
+
let startIndex;
|
|
36
|
+
if (sizeAdaptable) {
|
|
37
|
+
switch (startPlacement) {
|
|
38
|
+
case 'top':
|
|
39
|
+
order = [startPlacement, 'bottom', startPlacement];
|
|
40
|
+
break;
|
|
41
|
+
case 'bottom':
|
|
42
|
+
order = [startPlacement, 'top', startPlacement];
|
|
43
|
+
break;
|
|
44
|
+
case 'left':
|
|
45
|
+
order = [startPlacement, 'right', startPlacement];
|
|
46
|
+
break;
|
|
47
|
+
case 'right':
|
|
48
|
+
order = [startPlacement, 'left', startPlacement];
|
|
49
|
+
}
|
|
50
|
+
startIndex = 0;
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
startIndex = Math.max(order.indexOf(startPlacement), 0);
|
|
54
|
+
}
|
|
55
|
+
for (let i = 0; i <= order.length; i++) {
|
|
56
|
+
const index = (startIndex + i) % order.length;
|
|
57
|
+
if (callback(order[index]) === false) {
|
|
58
|
+
break;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
22
61
|
}
|
|
23
|
-
return order;
|
|
24
62
|
};
|
|
25
63
|
const splitPlacement = {
|
|
26
64
|
top: ['top'],
|
|
@@ -141,33 +179,6 @@ function Popper({ ref, popperRef, anchorElement, container, effectContainer, con
|
|
|
141
179
|
const mouseY = contextMenuEvent.current.clientY - containerRect.top;
|
|
142
180
|
attempt = placement => {
|
|
143
181
|
switch (placement) {
|
|
144
|
-
case 'topLeft':
|
|
145
|
-
case 'leftTop':
|
|
146
|
-
top = void 0;
|
|
147
|
-
bottom = -mouseY;
|
|
148
|
-
left = void 0;
|
|
149
|
-
right = containerRect.width - mouseX;
|
|
150
|
-
originX = '100%';
|
|
151
|
-
originY = '100%';
|
|
152
|
-
break;
|
|
153
|
-
case 'topRight':
|
|
154
|
-
case 'rightTop':
|
|
155
|
-
top = void 0;
|
|
156
|
-
bottom = -mouseY;
|
|
157
|
-
left = mouseX;
|
|
158
|
-
right = void 0;
|
|
159
|
-
originX = '0%';
|
|
160
|
-
originY = '100%';
|
|
161
|
-
break;
|
|
162
|
-
case 'bottomLeft':
|
|
163
|
-
case 'leftBottom':
|
|
164
|
-
top = mouseY;
|
|
165
|
-
bottom = void 0;
|
|
166
|
-
left = void 0;
|
|
167
|
-
right = containerRect.width - mouseX;
|
|
168
|
-
originX = '100%';
|
|
169
|
-
originY = '0%';
|
|
170
|
-
break;
|
|
171
182
|
case 'bottomRight':
|
|
172
183
|
case 'rightBottom':
|
|
173
184
|
top = mouseY;
|
|
@@ -177,37 +188,32 @@ function Popper({ ref, popperRef, anchorElement, container, effectContainer, con
|
|
|
177
188
|
originX = '0%';
|
|
178
189
|
originY = '0%';
|
|
179
190
|
break;
|
|
180
|
-
case '
|
|
181
|
-
|
|
182
|
-
bottom = void 0;
|
|
183
|
-
left = mouseX - popperWidth / 2;
|
|
184
|
-
right = void 0;
|
|
185
|
-
originX = '50%';
|
|
186
|
-
originY = '100%';
|
|
187
|
-
break;
|
|
188
|
-
case 'bottom':
|
|
191
|
+
case 'bottomLeft':
|
|
192
|
+
case 'leftBottom':
|
|
189
193
|
top = mouseY;
|
|
190
194
|
bottom = void 0;
|
|
191
|
-
left =
|
|
192
|
-
right =
|
|
193
|
-
originX = '
|
|
195
|
+
left = void 0;
|
|
196
|
+
right = containerRect.width - mouseX;
|
|
197
|
+
originX = '100%';
|
|
194
198
|
originY = '0%';
|
|
195
199
|
break;
|
|
196
|
-
case '
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
200
|
+
case 'topLeft':
|
|
201
|
+
case 'leftTop':
|
|
202
|
+
top = void 0;
|
|
203
|
+
bottom = -mouseY;
|
|
204
|
+
left = void 0;
|
|
205
|
+
right = containerRect.width - mouseX;
|
|
201
206
|
originX = '100%';
|
|
202
|
-
originY = '
|
|
207
|
+
originY = '100%';
|
|
203
208
|
break;
|
|
204
|
-
case '
|
|
205
|
-
|
|
206
|
-
|
|
209
|
+
case 'topRight':
|
|
210
|
+
case 'rightTop':
|
|
211
|
+
top = void 0;
|
|
212
|
+
bottom = -mouseY;
|
|
207
213
|
left = mouseX;
|
|
208
214
|
right = void 0;
|
|
209
215
|
originX = '0%';
|
|
210
|
-
originY = '
|
|
216
|
+
originY = '100%';
|
|
211
217
|
}
|
|
212
218
|
popperEl.style.top = typeof top === 'undefined' ? '' : top + 'px';
|
|
213
219
|
popperEl.style.bottom = typeof bottom === 'undefined' ? '' : bottom + 'px';
|
|
@@ -311,13 +317,7 @@ function Popper({ ref, popperRef, anchorElement, container, effectContainer, con
|
|
|
311
317
|
else {
|
|
312
318
|
popperEl.style.transition = 'none';
|
|
313
319
|
popperEl.style.transform = 'scale(1)';
|
|
314
|
-
|
|
315
|
-
for (let i = 0; i < attemptOrder.length; i++) {
|
|
316
|
-
const t = attempt(attemptOrder[i]);
|
|
317
|
-
if (t === false) {
|
|
318
|
-
break;
|
|
319
|
-
}
|
|
320
|
-
}
|
|
320
|
+
getAttemptOrder(placement, !!contextMenuEvent.current, sizeAdaptable, attempt);
|
|
321
321
|
}
|
|
322
322
|
beforeOpen?.();
|
|
323
323
|
placeA.current = pA;
|
|
@@ -7,6 +7,7 @@ const selectBase_1 = require("../selectBase");
|
|
|
7
7
|
const optionsBase_1 = require("../optionsBase");
|
|
8
8
|
const menuItem_1 = require("../menuItem");
|
|
9
9
|
const selectionContext_1 = require("../selectionContext");
|
|
10
|
+
const utils_1 = require("../../utils");
|
|
10
11
|
exports.Select = (0, react_1.memo)(({ children,
|
|
11
12
|
// 从SelectableProps继承
|
|
12
13
|
multiple = false, // 同时转发至<SelectBase/>
|
|
@@ -19,7 +20,15 @@ showCheckbox = multiple, loading = false, options, labelKey = 'label', primaryKe
|
|
|
19
20
|
const optionsMap = (0, react_1.useMemo)(() => {
|
|
20
21
|
const map = new Map();
|
|
21
22
|
optionsArr?.forEach(opt => {
|
|
22
|
-
opt && typeof opt === 'object'
|
|
23
|
+
if (opt && typeof opt === 'object') {
|
|
24
|
+
const key = opt[primaryKey];
|
|
25
|
+
if (!(0, utils_1.isUnset)(key)) {
|
|
26
|
+
if (map.has(key)) {
|
|
27
|
+
console.warn(`[@canlooks/can-ui/<Select/>] option key "${key}" was duplicated`);
|
|
28
|
+
}
|
|
29
|
+
map.set(opt[primaryKey], opt);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
23
32
|
});
|
|
24
33
|
return map;
|
|
25
34
|
}, [optionsArr, primaryKey]);
|
|
@@ -9,7 +9,7 @@ exports.classes = (0, utils_1.defineInnerClasses)('selected-list', [
|
|
|
9
9
|
'optionWrap'
|
|
10
10
|
]);
|
|
11
11
|
exports.style = (0, utils_1.defineCss)(({ spacing }) => (0, react_1.css) `
|
|
12
|
-
@layer
|
|
12
|
+
@layer override {
|
|
13
13
|
.${exports.classes.optionWrap} {
|
|
14
14
|
margin-bottom: ${spacing[3]}px;
|
|
15
15
|
}
|
|
@@ -32,7 +32,12 @@ function useSelection({ ...props }) {
|
|
|
32
32
|
item._parentId = parentId;
|
|
33
33
|
item._isLast = i === arr.length - 1;
|
|
34
34
|
const id = item[props.primaryKey];
|
|
35
|
-
!(0, utils_1.isUnset)(id)
|
|
35
|
+
if (!(0, utils_1.isUnset)(id)) {
|
|
36
|
+
if (map.has(id)) {
|
|
37
|
+
console.warn(`[@canlooks/can-ui/<SelectionContext/>] option key "${id}" was duplicated`);
|
|
38
|
+
}
|
|
39
|
+
map.set(id, item);
|
|
40
|
+
}
|
|
36
41
|
fn(item[props.childrenKey], id);
|
|
37
42
|
});
|
|
38
43
|
};
|
|
@@ -73,7 +73,9 @@ function useStickyCellProps({ sticky, ...props }) {
|
|
|
73
73
|
ref: innerRef,
|
|
74
74
|
css: tableSticky_style_1.style,
|
|
75
75
|
className: table_style_1.classes.cell,
|
|
76
|
-
|
|
76
|
+
...sticky && {
|
|
77
|
+
style: { [sticky]: offset }
|
|
78
|
+
},
|
|
77
79
|
'data-sticky': sticky
|
|
78
80
|
});
|
|
79
81
|
}
|
|
@@ -26,7 +26,12 @@ function useColumnMap(columns) {
|
|
|
26
26
|
columns?.forEach((col, i) => {
|
|
27
27
|
if (typeof col !== 'symbol') {
|
|
28
28
|
const _key = setDefaultColumnKey(col, i);
|
|
29
|
-
!(0, utils_1.isUnset)(_key)
|
|
29
|
+
if (!(0, utils_1.isUnset)(_key)) {
|
|
30
|
+
if (map.has(_key)) {
|
|
31
|
+
console.warn(`[@canlooks/can-ui/<DataGrid/>] column key "${_key}" was duplicated`);
|
|
32
|
+
}
|
|
33
|
+
map.set(_key, col);
|
|
34
|
+
}
|
|
30
35
|
}
|
|
31
36
|
});
|
|
32
37
|
return map;
|
|
@@ -45,7 +45,12 @@ export const Autocomplete = memo(({ children, loading, options, loadOptions, pri
|
|
|
45
45
|
actualOptions?.forEach(opt => {
|
|
46
46
|
if (opt && typeof opt === 'object') {
|
|
47
47
|
const key = opt[primaryKey];
|
|
48
|
-
!isUnset(key)
|
|
48
|
+
if (!isUnset(key)) {
|
|
49
|
+
if (map.has(key)) {
|
|
50
|
+
console.warn(`[@canlooks/can-ui/<Autocomple/>] option key "${key}" was duplicated`);
|
|
51
|
+
}
|
|
52
|
+
map.set(key, opt);
|
|
53
|
+
}
|
|
49
54
|
}
|
|
50
55
|
});
|
|
51
56
|
return map;
|
|
@@ -94,6 +94,7 @@ export const Curd = memo((props) => {
|
|
|
94
94
|
const controlColumn = {
|
|
95
95
|
key: CONTROL_COLUMN_KEY,
|
|
96
96
|
title: controlColumnTitle,
|
|
97
|
+
className: classes.controlColumn,
|
|
97
98
|
render(row) {
|
|
98
99
|
const _updatable = typeof updatable === 'function' ? updatable(row) : updatable;
|
|
99
100
|
const _deletable = typeof deletable === 'function' ? deletable(row) : deletable;
|
|
@@ -17,6 +17,7 @@ export const classes = defineInnerClasses('curd', [
|
|
|
17
17
|
'toolbarRight',
|
|
18
18
|
'divider',
|
|
19
19
|
'card',
|
|
20
|
+
'controlColumn',
|
|
20
21
|
'control',
|
|
21
22
|
'dialogTitle',
|
|
22
23
|
'copyButton'
|
|
@@ -29,7 +30,7 @@ export const style = defineCss(({ spacing, text, background, borderRadius }) =>
|
|
|
29
30
|
min-height: 0;
|
|
30
31
|
display: flex;
|
|
31
32
|
flex-direction: column;
|
|
32
|
-
|
|
33
|
+
|
|
33
34
|
.${classes.filterForm} {
|
|
34
35
|
min-height: 0;
|
|
35
36
|
display: flex;
|
|
@@ -10,6 +10,7 @@ import { defaultSensors, isUnset, onDndDragEnd } from '../../utils/index.js';
|
|
|
10
10
|
import { Icon } from '../icon/index.js';
|
|
11
11
|
import { faGear } from '@fortawesome/free-solid-svg-icons/faGear';
|
|
12
12
|
import { DragDropProvider, useDragDropMonitor } from '@dnd-kit/react';
|
|
13
|
+
import { Tooltip } from '../tooltip/index.js';
|
|
13
14
|
export const CurdColumnConfig = memo((props) => {
|
|
14
15
|
const dragEndHandler = e => {
|
|
15
16
|
const newColumns = onDndDragEnd(e, props.columns || [], '_key');
|
|
@@ -38,12 +39,12 @@ const CurdColumnConfigContent = memo(({ columns, innerVisible, setInnerVisible,
|
|
|
38
39
|
? [...o, key]
|
|
39
40
|
: o.filter(k => k !== key));
|
|
40
41
|
};
|
|
41
|
-
return (_jsx(Bubble, { placement: "bottomRight", trigger:
|
|
42
|
+
return (_jsx(Bubble, { placement: "bottomRight", trigger: "click", ...columnConfigBubbleProps, css: style, open: open, onOpenChange: openChangeHandler, content: _jsxs("div", { className: classes.content, children: [_jsxs("div", { className: classes.title, children: [_jsx("div", { className: classes.titleText, children: "\u5217\u8BBE\u7F6E" }), _jsx("div", { className: classes.description, children: "\u62D6\u62FD\u8C03\u6574\u987A\u5E8F" })] }), columns?.map((col, i) => {
|
|
42
43
|
const id = col._key;
|
|
43
44
|
const checked = !isUnset(id) && (!visibleSet || visibleSet.has(id));
|
|
44
45
|
return (_jsx(SortableItem, { id: id ?? i, index: i, component: MenuItem, className: classes.item, prefix: _jsx(Checkbox, { className: classes.checkbox, checked: checked, onChange: e => {
|
|
45
46
|
e.stopPropagation();
|
|
46
47
|
toggleVisible(id, e.target.checked);
|
|
47
48
|
} }), onClick: () => toggleVisible(id, !checked), label: col.titleText ?? col.title, noStyle: true }, id ?? i));
|
|
48
|
-
})] }), autoClose: false, children: _jsx(Button, { shape: "circular", variant: "text", color: "text.secondary", children: _jsx(Icon, { icon: faGear }) }) }));
|
|
49
|
+
})] }), autoClose: false, children: _jsx(Tooltip, { title: "\u5217\u8BBE\u7F6E", clickToClose: true, children: _jsx(Button, { shape: "circular", variant: "text", color: "text.secondary", children: _jsx(Icon, { icon: faGear }) }) }) }));
|
|
49
50
|
});
|
|
@@ -18,25 +18,16 @@ export const style = defineCss(({ spacing, text }) => css `
|
|
|
18
18
|
align-items: center;
|
|
19
19
|
justify-content: space-between;
|
|
20
20
|
padding: ${spacing[3]}px;
|
|
21
|
-
|
|
21
|
+
|
|
22
22
|
.${classes.titleText} {
|
|
23
23
|
font-weight: bold;
|
|
24
24
|
}
|
|
25
|
-
|
|
25
|
+
|
|
26
26
|
.${classes.description} {
|
|
27
27
|
color: ${text.disabled};
|
|
28
28
|
}
|
|
29
29
|
}
|
|
30
|
-
|
|
31
|
-
.${classes.item} {
|
|
32
|
-
cursor: pointer;
|
|
33
|
-
|
|
34
|
-
&[data-dragging=true] {
|
|
35
|
-
position: relative;
|
|
36
|
-
z-index: 1;
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
30
|
+
|
|
40
31
|
.${classes.checkbox} {
|
|
41
32
|
display: flex;
|
|
42
33
|
margin-right: ${spacing[1]}px;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { ComponentProps, ReactElement, ReactNode } from 'react';
|
|
1
|
+
import React, { ComponentProps, ReactElement, ReactNode, RefObject } from 'react';
|
|
2
2
|
import { DivProps, Id, Obj, SlotsAndProps, ToRequired } from '../../types.js';
|
|
3
3
|
import { SelectionContextProps } from '../selectionContext/index.js';
|
|
4
4
|
import { PaginationProps } from '../pagination/index.js';
|
|
@@ -136,6 +136,7 @@ interface IDataGridContext<R extends RowType = RowType> extends ToRequired<DataG
|
|
|
136
136
|
expandedSet: Set<Id>;
|
|
137
137
|
flattedColumns: (symbol | ColumnType<R>)[] | undefined;
|
|
138
138
|
toggleExpanded(key: Id): void;
|
|
139
|
+
theadRef: RefObject<HTMLTableSectionElement | null>;
|
|
139
140
|
}
|
|
140
141
|
export declare function useDataGridContext<R extends RowType>(): IDataGridContext<R>;
|
|
141
142
|
export declare const DataGrid: {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "@emotion/react/jsx-runtime";
|
|
2
|
-
import { createContext, memo, useCallback, useContext, useMemo, useState } from 'react';
|
|
2
|
+
import { createContext, memo, useCallback, useContext, useMemo, useRef, useState } from 'react';
|
|
3
3
|
import { classes, style } from './dataGrid.style.js';
|
|
4
4
|
import { SelectionContext, useSelectionContext } from '../selectionContext/index.js';
|
|
5
5
|
import { Pagination } from '../pagination/index.js';
|
|
@@ -126,13 +126,18 @@ export const DataGrid = memo(({ slots, slotProps, columns, rows, rowProps, prima
|
|
|
126
126
|
const { page, pageSize } = _paginationProps;
|
|
127
127
|
return orderedRows?.slice((page - 1) * pageSize, page * pageSize);
|
|
128
128
|
}, [orderedRows, _paginationProps.page, _paginationProps.pageSize, paginatable]);
|
|
129
|
+
/**
|
|
130
|
+
* ---------------------------------------------------------------
|
|
131
|
+
* 渲染
|
|
132
|
+
*/
|
|
133
|
+
const theadRef = useRef(null);
|
|
129
134
|
const { container: Container = TableContainer } = slots || {};
|
|
130
135
|
const { container: containerProps } = slotProps || {};
|
|
131
136
|
const renderedContent = (_jsx(ColumnResizeContext, { columnResizable: columnResizable, children: ({ scrollerRef, tableRef }) => _jsxs(Container, { ...mergeComponentProps(containerProps, {
|
|
132
137
|
ref: scrollerRef,
|
|
133
138
|
className: classes.container
|
|
134
|
-
}), children: [_jsx(Table, { size: size, bordered: bordered, striped: striped, ...tableProps, ref: cloneRef(tableProps?.ref, tableRef), children: _jsxs(SelectionContext, { options: rows, primaryKey: primaryKey, childrenKey: childrenKey !== null ? childrenKey : void 0, relation: relation, integration: integration, disabled: !selectable, multiple: multiple, defaultValue: defaultValue, value: value, onChange: onChange, onToggle: onToggle, children: [_jsx(DataGridHead, { rows: rows, flattedColumns: flattedColumns, completedColumns: completedColumns, primaryKey: primaryKey, allowSelectAll: allowSelectAll, columnResizable: columnResizable, orderColumn: innerOrderColumn.current, orderType: innerOrderType.current, onOrderChange: orderChangeHandler, filterBubbleProps: filterBubbleProps, onFilterClick: onFilterClick }), _jsx("tbody", { children: _jsx(DataGridContext, { value: useMemo(() => ({
|
|
135
|
-
slots, slotProps,
|
|
139
|
+
}), children: [_jsx(Table, { size: size, bordered: bordered, striped: striped, ...tableProps, ref: cloneRef(tableProps?.ref, tableRef), children: _jsxs(SelectionContext, { options: rows, primaryKey: primaryKey, childrenKey: childrenKey !== null ? childrenKey : void 0, relation: relation, integration: integration, disabled: !selectable, multiple: multiple, defaultValue: defaultValue, value: value, onChange: onChange, onToggle: onToggle, children: [_jsx(DataGridHead, { ref: theadRef, rows: rows, flattedColumns: flattedColumns, completedColumns: completedColumns, primaryKey: primaryKey, allowSelectAll: allowSelectAll, columnResizable: columnResizable, orderColumn: innerOrderColumn.current, orderType: innerOrderType.current, onOrderChange: orderChangeHandler, filterBubbleProps: filterBubbleProps, onFilterClick: onFilterClick }), _jsx("tbody", { children: _jsx(DataGridContext, { value: useMemo(() => ({
|
|
140
|
+
slots, slotProps, theadRef,
|
|
136
141
|
rowProps, primaryKey, childrenKey, clickRowToSelect, indent, renderExpandIcon,
|
|
137
142
|
expandedSet, flattedColumns, toggleExpanded
|
|
138
143
|
}), [
|
|
@@ -89,25 +89,36 @@ export const style = defineCss(({ spacing, mode, gray, text, colors, easing }) =
|
|
|
89
89
|
}
|
|
90
90
|
}
|
|
91
91
|
}
|
|
92
|
+
|
|
93
|
+
tr {
|
|
94
|
+
position: relative;
|
|
95
|
+
z-index: 2;
|
|
96
|
+
|
|
97
|
+
&[data-expanded=true] {
|
|
98
|
+
position: sticky;
|
|
99
|
+
z-index: 1;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
&.${classes.sub} {
|
|
103
|
+
z-index: 0;
|
|
104
|
+
background-color: ${gray(mode === 'light' ? .02 : .22)};
|
|
92
105
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
td.${classes.subTd} {
|
|
97
|
-
padding: 0;
|
|
98
|
-
border: none;
|
|
106
|
+
td.${classes.subTd} {
|
|
107
|
+
padding: 0;
|
|
108
|
+
border: none;
|
|
99
109
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
110
|
+
.${classes.children} {
|
|
111
|
+
padding: ${spacing[4]}px ${spacing[5]}px;
|
|
112
|
+
border-bottom: 1px solid ${gray(mode === 'light' ? .12 : .32)};
|
|
103
113
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
114
|
+
thead, tfoot {
|
|
115
|
+
z-index: 5;
|
|
116
|
+
}
|
|
107
117
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
118
|
+
th, td {
|
|
119
|
+
&[data-sticky=left], &[data-sticky=right] {
|
|
120
|
+
z-index: 4;
|
|
121
|
+
}
|
|
111
122
|
}
|
|
112
123
|
}
|
|
113
124
|
}
|
|
@@ -154,7 +165,7 @@ export const style = defineCss(({ spacing, mode, gray, text, colors, easing }) =
|
|
|
154
165
|
position: absolute;
|
|
155
166
|
top: 0;
|
|
156
167
|
right: -4px;
|
|
157
|
-
z-index:
|
|
168
|
+
z-index: 3;
|
|
158
169
|
}
|
|
159
170
|
|
|
160
171
|
th:last-of-type {
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { ReactElement } from 'react';
|
|
1
|
+
import { ReactElement, RefObject } from 'react';
|
|
2
2
|
import { ColumnType, DataGridProps, RowType } from './dataGrid.js';
|
|
3
3
|
import { Id } from '../../types.js';
|
|
4
4
|
interface DataGridHeadProps<R extends RowType, V extends Id = Id> extends Required<Pick<DataGridProps<R, V>, 'primaryKey' | 'orderType' | 'onOrderChange' | 'allowSelectAll' | 'columnResizable'>> {
|
|
5
|
+
ref: RefObject<HTMLTableSectionElement | null>;
|
|
5
6
|
rows: R[] | undefined;
|
|
6
7
|
orderColumn: Id | undefined;
|
|
7
8
|
flattedColumns: (symbol | ColumnType<R>)[] | undefined;
|
|
@@ -15,7 +15,7 @@ import { Bubble } from '../bubble/index.js';
|
|
|
15
15
|
import { FilterBubbleContent } from './filterBubbleContent.js';
|
|
16
16
|
import { useFormValueContext } from '../form/index.js';
|
|
17
17
|
import { isUnset, mergeComponentProps } from '../../utils/index.js';
|
|
18
|
-
export const DataGridHead = memo(({ allowSelectAll, columnResizable, flattedColumns, completedColumns, rows, primaryKey, orderColumn, orderType, onOrderChange, filterBubbleProps, onFilterClick }) => {
|
|
18
|
+
export const DataGridHead = memo(({ ref, allowSelectAll, columnResizable, flattedColumns, completedColumns, rows, primaryKey, orderColumn, orderType, onOrderChange, filterBubbleProps, onFilterClick }) => {
|
|
19
19
|
const { multiple, setValue, selectionStatus } = useSelectionContext();
|
|
20
20
|
const allSelectionStatus = useMemo(() => {
|
|
21
21
|
if (multiple && allowSelectAll) {
|
|
@@ -113,5 +113,5 @@ export const DataGridHead = memo(({ allowSelectAll, columnResizable, flattedColu
|
|
|
113
113
|
];
|
|
114
114
|
}) }, i));
|
|
115
115
|
});
|
|
116
|
-
return _jsx("thead", { children: renderedHead });
|
|
116
|
+
return _jsx("thead", { ref: ref, children: renderedHead });
|
|
117
117
|
});
|
|
@@ -13,10 +13,11 @@ import { Icon } from '../icon/index.js';
|
|
|
13
13
|
import { faMinusSquare } from '@fortawesome/free-regular-svg-icons/faMinusSquare';
|
|
14
14
|
import { faPlusSquare } from '@fortawesome/free-regular-svg-icons/faPlusSquare';
|
|
15
15
|
import { classes } from './dataGrid.style.js';
|
|
16
|
+
import { StickyRow } from './stickyRow.js';
|
|
16
17
|
export const DataGridRows = memo(({ rows, _level = 0 }) => {
|
|
17
18
|
const { multiple, toggleSelected, selectionStatus } = useSelectionContext();
|
|
18
19
|
const { slots, slotProps, rowProps, primaryKey, childrenKey, clickRowToSelect, indent, renderExpandIcon, expandedSet, flattedColumns, toggleExpanded } = useDataGridContext();
|
|
19
|
-
const { tr: Tr =
|
|
20
|
+
const { tr: Tr = StickyRow } = slots || {};
|
|
20
21
|
const { tr: TrProps } = slotProps || {};
|
|
21
22
|
return rows?.flatMap((row, i, arr) => {
|
|
22
23
|
const trKey = row[primaryKey];
|
|
@@ -34,8 +35,9 @@ export const DataGridRows = memo(({ rows, _level = 0 }) => {
|
|
|
34
35
|
className: clsx(_rowProps, _level > 0 && classes.sub),
|
|
35
36
|
onClick() {
|
|
36
37
|
clickRowToSelect && toggleSelected(trKey);
|
|
37
|
-
}
|
|
38
|
-
|
|
38
|
+
},
|
|
39
|
+
sticky: currentExpanded
|
|
40
|
+
}), key: trKey, "data-selected": status === 2, "data-expanded": currentExpanded }, flattedColumns?.flatMap((col, j) => {
|
|
39
41
|
if (typeof col === 'symbol') {
|
|
40
42
|
if (col === DataGrid.EXPAND_COLUMN) {
|
|
41
43
|
expandableIndex = j;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { jsx as _jsx } from "@emotion/react/jsx-runtime";
|
|
2
|
+
import { useEffect, useState } from 'react';
|
|
3
|
+
import { useDataGridContext } from './dataGrid.js';
|
|
4
|
+
import { mergeComponentProps } from '../../utils/index.js';
|
|
5
|
+
export function StickyRow({ sticky, ...props }) {
|
|
6
|
+
const [offset, setOffset] = useState(0);
|
|
7
|
+
const { theadRef } = useDataGridContext();
|
|
8
|
+
useEffect(() => {
|
|
9
|
+
if (!sticky || !theadRef.current) {
|
|
10
|
+
return;
|
|
11
|
+
}
|
|
12
|
+
const resizeObserver = new ResizeObserver(() => {
|
|
13
|
+
setOffset(theadRef.current.offsetHeight);
|
|
14
|
+
});
|
|
15
|
+
resizeObserver.observe(theadRef.current);
|
|
16
|
+
return () => {
|
|
17
|
+
resizeObserver.disconnect();
|
|
18
|
+
};
|
|
19
|
+
}, [sticky]);
|
|
20
|
+
return (_jsx("tr", { ...mergeComponentProps(props, {
|
|
21
|
+
...sticky && {
|
|
22
|
+
style: { top: offset }
|
|
23
|
+
}
|
|
24
|
+
}) }));
|
|
25
|
+
}
|
|
@@ -6,18 +6,56 @@ import { ClickAway } from '../clickAway/index.js';
|
|
|
6
6
|
import { classes, style } from './popper.style.js';
|
|
7
7
|
import { PopperContext, usePopperContext } from './popperContext.js';
|
|
8
8
|
import { useTheme } from '../theme/index.js';
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
9
|
+
const defaultAttemptOrder = ['top', 'bottom', 'left', 'right', 'topLeft', 'topRight', 'rightTop', 'rightBottom', 'bottomRight', 'bottomLeft', 'leftBottom', 'leftTop'];
|
|
10
|
+
const contextMenuOrder = [
|
|
11
|
+
'bottomRight',
|
|
12
|
+
'rightBottom',
|
|
13
|
+
'bottomLeft',
|
|
14
|
+
'leftBottom',
|
|
15
|
+
'topLeft',
|
|
16
|
+
'leftTop',
|
|
17
|
+
'topRight',
|
|
18
|
+
'rightTop'
|
|
19
|
+
];
|
|
20
|
+
const getAttemptOrder = (startPlacement, contextMenu, sizeAdaptable, callback) => {
|
|
21
|
+
if (contextMenu) {
|
|
22
|
+
const startIndex = Math.max(contextMenuOrder.indexOf(startPlacement), 0);
|
|
23
|
+
for (let i = 0; i <= contextMenuOrder.length + 1; i += 2) {
|
|
24
|
+
const index = (startIndex + i) % contextMenuOrder.length;
|
|
25
|
+
if (callback(contextMenuOrder[index]) === false) {
|
|
26
|
+
break;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
let order = defaultAttemptOrder;
|
|
32
|
+
let startIndex;
|
|
33
|
+
if (sizeAdaptable) {
|
|
34
|
+
switch (startPlacement) {
|
|
35
|
+
case 'top':
|
|
36
|
+
order = [startPlacement, 'bottom', startPlacement];
|
|
37
|
+
break;
|
|
38
|
+
case 'bottom':
|
|
39
|
+
order = [startPlacement, 'top', startPlacement];
|
|
40
|
+
break;
|
|
41
|
+
case 'left':
|
|
42
|
+
order = [startPlacement, 'right', startPlacement];
|
|
43
|
+
break;
|
|
44
|
+
case 'right':
|
|
45
|
+
order = [startPlacement, 'left', startPlacement];
|
|
46
|
+
}
|
|
47
|
+
startIndex = 0;
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
startIndex = Math.max(order.indexOf(startPlacement), 0);
|
|
51
|
+
}
|
|
52
|
+
for (let i = 0; i <= order.length; i++) {
|
|
53
|
+
const index = (startIndex + i) % order.length;
|
|
54
|
+
if (callback(order[index]) === false) {
|
|
55
|
+
break;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
19
58
|
}
|
|
20
|
-
return order;
|
|
21
59
|
};
|
|
22
60
|
const splitPlacement = {
|
|
23
61
|
top: ['top'],
|
|
@@ -138,33 +176,6 @@ export function Popper({ ref, popperRef, anchorElement, container, effectContain
|
|
|
138
176
|
const mouseY = contextMenuEvent.current.clientY - containerRect.top;
|
|
139
177
|
attempt = placement => {
|
|
140
178
|
switch (placement) {
|
|
141
|
-
case 'topLeft':
|
|
142
|
-
case 'leftTop':
|
|
143
|
-
top = void 0;
|
|
144
|
-
bottom = -mouseY;
|
|
145
|
-
left = void 0;
|
|
146
|
-
right = containerRect.width - mouseX;
|
|
147
|
-
originX = '100%';
|
|
148
|
-
originY = '100%';
|
|
149
|
-
break;
|
|
150
|
-
case 'topRight':
|
|
151
|
-
case 'rightTop':
|
|
152
|
-
top = void 0;
|
|
153
|
-
bottom = -mouseY;
|
|
154
|
-
left = mouseX;
|
|
155
|
-
right = void 0;
|
|
156
|
-
originX = '0%';
|
|
157
|
-
originY = '100%';
|
|
158
|
-
break;
|
|
159
|
-
case 'bottomLeft':
|
|
160
|
-
case 'leftBottom':
|
|
161
|
-
top = mouseY;
|
|
162
|
-
bottom = void 0;
|
|
163
|
-
left = void 0;
|
|
164
|
-
right = containerRect.width - mouseX;
|
|
165
|
-
originX = '100%';
|
|
166
|
-
originY = '0%';
|
|
167
|
-
break;
|
|
168
179
|
case 'bottomRight':
|
|
169
180
|
case 'rightBottom':
|
|
170
181
|
top = mouseY;
|
|
@@ -174,37 +185,32 @@ export function Popper({ ref, popperRef, anchorElement, container, effectContain
|
|
|
174
185
|
originX = '0%';
|
|
175
186
|
originY = '0%';
|
|
176
187
|
break;
|
|
177
|
-
case '
|
|
178
|
-
|
|
179
|
-
bottom = void 0;
|
|
180
|
-
left = mouseX - popperWidth / 2;
|
|
181
|
-
right = void 0;
|
|
182
|
-
originX = '50%';
|
|
183
|
-
originY = '100%';
|
|
184
|
-
break;
|
|
185
|
-
case 'bottom':
|
|
188
|
+
case 'bottomLeft':
|
|
189
|
+
case 'leftBottom':
|
|
186
190
|
top = mouseY;
|
|
187
191
|
bottom = void 0;
|
|
188
|
-
left =
|
|
189
|
-
right =
|
|
190
|
-
originX = '
|
|
192
|
+
left = void 0;
|
|
193
|
+
right = containerRect.width - mouseX;
|
|
194
|
+
originX = '100%';
|
|
191
195
|
originY = '0%';
|
|
192
196
|
break;
|
|
193
|
-
case '
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
197
|
+
case 'topLeft':
|
|
198
|
+
case 'leftTop':
|
|
199
|
+
top = void 0;
|
|
200
|
+
bottom = -mouseY;
|
|
201
|
+
left = void 0;
|
|
202
|
+
right = containerRect.width - mouseX;
|
|
198
203
|
originX = '100%';
|
|
199
|
-
originY = '
|
|
204
|
+
originY = '100%';
|
|
200
205
|
break;
|
|
201
|
-
case '
|
|
202
|
-
|
|
203
|
-
|
|
206
|
+
case 'topRight':
|
|
207
|
+
case 'rightTop':
|
|
208
|
+
top = void 0;
|
|
209
|
+
bottom = -mouseY;
|
|
204
210
|
left = mouseX;
|
|
205
211
|
right = void 0;
|
|
206
212
|
originX = '0%';
|
|
207
|
-
originY = '
|
|
213
|
+
originY = '100%';
|
|
208
214
|
}
|
|
209
215
|
popperEl.style.top = typeof top === 'undefined' ? '' : top + 'px';
|
|
210
216
|
popperEl.style.bottom = typeof bottom === 'undefined' ? '' : bottom + 'px';
|
|
@@ -308,13 +314,7 @@ export function Popper({ ref, popperRef, anchorElement, container, effectContain
|
|
|
308
314
|
else {
|
|
309
315
|
popperEl.style.transition = 'none';
|
|
310
316
|
popperEl.style.transform = 'scale(1)';
|
|
311
|
-
|
|
312
|
-
for (let i = 0; i < attemptOrder.length; i++) {
|
|
313
|
-
const t = attempt(attemptOrder[i]);
|
|
314
|
-
if (t === false) {
|
|
315
|
-
break;
|
|
316
|
-
}
|
|
317
|
-
}
|
|
317
|
+
getAttemptOrder(placement, !!contextMenuEvent.current, sizeAdaptable, attempt);
|
|
318
318
|
}
|
|
319
319
|
beforeOpen?.();
|
|
320
320
|
placeA.current = pA;
|
|
@@ -4,6 +4,7 @@ import { SelectBase } from '../selectBase/index.js';
|
|
|
4
4
|
import { OptionsBase } from '../optionsBase/index.js';
|
|
5
5
|
import { MenuItem } from '../menuItem/index.js';
|
|
6
6
|
import { useFlatSelection } from '../selectionContext/index.js';
|
|
7
|
+
import { isUnset } from '../../utils/index.js';
|
|
7
8
|
export const Select = memo(({ children,
|
|
8
9
|
// 从SelectableProps继承
|
|
9
10
|
multiple = false, // 同时转发至<SelectBase/>
|
|
@@ -16,7 +17,15 @@ showCheckbox = multiple, loading = false, options, labelKey = 'label', primaryKe
|
|
|
16
17
|
const optionsMap = useMemo(() => {
|
|
17
18
|
const map = new Map();
|
|
18
19
|
optionsArr?.forEach(opt => {
|
|
19
|
-
opt && typeof opt === 'object'
|
|
20
|
+
if (opt && typeof opt === 'object') {
|
|
21
|
+
const key = opt[primaryKey];
|
|
22
|
+
if (!isUnset(key)) {
|
|
23
|
+
if (map.has(key)) {
|
|
24
|
+
console.warn(`[@canlooks/can-ui/<Select/>] option key "${key}" was duplicated`);
|
|
25
|
+
}
|
|
26
|
+
map.set(opt[primaryKey], opt);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
20
29
|
});
|
|
21
30
|
return map;
|
|
22
31
|
}, [optionsArr, primaryKey]);
|
|
@@ -28,7 +28,12 @@ export function useSelection({ ...props }) {
|
|
|
28
28
|
item._parentId = parentId;
|
|
29
29
|
item._isLast = i === arr.length - 1;
|
|
30
30
|
const id = item[props.primaryKey];
|
|
31
|
-
!isUnset(id)
|
|
31
|
+
if (!isUnset(id)) {
|
|
32
|
+
if (map.has(id)) {
|
|
33
|
+
console.warn(`[@canlooks/can-ui/<SelectionContext/>] option key "${id}" was duplicated`);
|
|
34
|
+
}
|
|
35
|
+
map.set(id, item);
|
|
36
|
+
}
|
|
32
37
|
fn(item[props.childrenKey], id);
|
|
33
38
|
});
|
|
34
39
|
};
|
|
@@ -20,7 +20,12 @@ export function useColumnMap(columns) {
|
|
|
20
20
|
columns?.forEach((col, i) => {
|
|
21
21
|
if (typeof col !== 'symbol') {
|
|
22
22
|
const _key = setDefaultColumnKey(col, i);
|
|
23
|
-
!isUnset(_key)
|
|
23
|
+
if (!isUnset(_key)) {
|
|
24
|
+
if (map.has(_key)) {
|
|
25
|
+
console.warn(`[@canlooks/can-ui/<DataGrid/>] column key "${_key}" was duplicated`);
|
|
26
|
+
}
|
|
27
|
+
map.set(_key, col);
|
|
28
|
+
}
|
|
24
29
|
}
|
|
25
30
|
});
|
|
26
31
|
return map;
|