@canlooks/can-ui 0.0.204 → 0.0.206

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.
Files changed (51) hide show
  1. package/dist/cjs/components/autocomplete/autocomplete.js +6 -1
  2. package/dist/cjs/components/curd/curd.js +1 -0
  3. package/dist/cjs/components/curd/curd.style.d.ts +1 -0
  4. package/dist/cjs/components/curd/curd.style.js +2 -1
  5. package/dist/cjs/components/curd/curdColumnConfig.js +3 -2
  6. package/dist/cjs/components/curd/curdColumnConfig.style.js +3 -12
  7. package/dist/cjs/components/dataGrid/dataGrid.d.ts +2 -1
  8. package/dist/cjs/components/dataGrid/dataGrid.js +7 -2
  9. package/dist/cjs/components/dataGrid/dataGrid.style.js +27 -16
  10. package/dist/cjs/components/dataGrid/dataGridHead.d.ts +2 -1
  11. package/dist/cjs/components/dataGrid/dataGridHead.js +2 -2
  12. package/dist/cjs/components/dataGrid/dataGridRows.js +5 -3
  13. package/dist/cjs/components/dataGrid/stickyRow.d.ts +5 -0
  14. package/dist/cjs/components/dataGrid/stickyRow.js +28 -0
  15. package/dist/cjs/components/popper/popper.js +67 -67
  16. package/dist/cjs/components/select/select.js +10 -1
  17. package/dist/cjs/components/selectedList/selectedItem.js +2 -1
  18. package/dist/cjs/components/selectedList/selectedList.js +6 -1
  19. package/dist/cjs/components/selectionContext/selectionHook.js +6 -1
  20. package/dist/cjs/components/table/table.style.js +1 -1
  21. package/dist/cjs/components/table/tableSticky.js +3 -1
  22. package/dist/cjs/components/table/tableSticky.style.js +1 -1
  23. package/dist/cjs/utils/dataGrid.js +6 -1
  24. package/dist/cjs/utils/dnd.d.ts +1 -0
  25. package/dist/cjs/utils/dnd.js +12 -9
  26. package/dist/esm/components/autocomplete/autocomplete.js +6 -1
  27. package/dist/esm/components/curd/curd.js +1 -0
  28. package/dist/esm/components/curd/curd.style.d.ts +1 -0
  29. package/dist/esm/components/curd/curd.style.js +2 -1
  30. package/dist/esm/components/curd/curdColumnConfig.js +3 -2
  31. package/dist/esm/components/curd/curdColumnConfig.style.js +3 -12
  32. package/dist/esm/components/dataGrid/dataGrid.d.ts +2 -1
  33. package/dist/esm/components/dataGrid/dataGrid.js +8 -3
  34. package/dist/esm/components/dataGrid/dataGrid.style.js +27 -16
  35. package/dist/esm/components/dataGrid/dataGridHead.d.ts +2 -1
  36. package/dist/esm/components/dataGrid/dataGridHead.js +2 -2
  37. package/dist/esm/components/dataGrid/dataGridRows.js +5 -3
  38. package/dist/esm/components/dataGrid/stickyRow.d.ts +5 -0
  39. package/dist/esm/components/dataGrid/stickyRow.js +25 -0
  40. package/dist/esm/components/popper/popper.js +67 -67
  41. package/dist/esm/components/select/select.js +10 -1
  42. package/dist/esm/components/selectedList/selectedItem.js +2 -1
  43. package/dist/esm/components/selectedList/selectedList.js +7 -2
  44. package/dist/esm/components/selectionContext/selectionHook.js +6 -1
  45. package/dist/esm/components/table/table.style.js +1 -1
  46. package/dist/esm/components/table/tableSticky.js +3 -1
  47. package/dist/esm/components/table/tableSticky.style.js +1 -1
  48. package/dist/esm/utils/dataGrid.js +6 -1
  49. package/dist/esm/utils/dnd.d.ts +1 -0
  50. package/dist/esm/utils/dnd.js +12 -9
  51. package/package.json +1 -1
@@ -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) && map.set(key, opt);
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;
@@ -14,6 +14,7 @@ export declare const classes: {
14
14
  toolbarLeft: string;
15
15
  toolbarRight: string;
16
16
  card: string;
17
+ controlColumn: string;
17
18
  dialogTitle: string;
18
19
  copyButton: string;
19
20
  } & {
@@ -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: ['hover', '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
+ 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
- tr.${classes.sub} {
94
- background-color: ${gray(mode === 'light' ? .02 : .22)};
95
-
96
- td.${classes.subTd} {
97
- padding: 0;
98
- border: none;
106
+ td.${classes.subTd} {
107
+ padding: 0;
108
+ border: none;
99
109
 
100
- .${classes.children} {
101
- padding: ${spacing[4]}px ${spacing[5]}px;
102
- border-bottom: 1px solid ${gray(mode === 'light' ? .12 : .32)};
110
+ .${classes.children} {
111
+ padding: ${spacing[4]}px ${spacing[5]}px;
112
+ border-bottom: 1px solid ${gray(mode === 'light' ? .12 : .32)};
103
113
 
104
- thead, tfoot {
105
- z-index: 3;
106
- }
114
+ thead, tfoot {
115
+ z-index: 5;
116
+ }
107
117
 
108
- th, td {
109
- &[data-sticky=left], &[data-sticky=right] {
110
- z-index: 2;
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: 1;
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 = 'tr' } = slots || {};
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
- }), key: trKey, "data-selected": status === 2 }, flattedColumns?.flatMap((col, j) => {
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,5 @@
1
+ import { ComponentProps } from 'react';
2
+ export interface StickyRowProps extends ComponentProps<'tr'> {
3
+ sticky?: boolean;
4
+ }
5
+ export declare function StickyRow({ sticky, ...props }: StickyRowProps): import("@emotion/react/jsx-runtime").JSX.Element;
@@ -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 getAttemptOrder = (placement) => {
10
- const order = ['top', 'bottom', 'left', 'right', 'topLeft', 'topRight', 'rightTop', 'rightBottom', 'bottomRight', 'bottomLeft', 'leftBottom', 'leftTop'];
11
- const index = order.indexOf(placement);
12
- if (index > -1) {
13
- return [
14
- placement,
15
- ...order.slice(index + 1),
16
- ...order.slice(0, index),
17
- placement
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 'top':
178
- top = mouseY - popperHeight;
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 = mouseX - popperWidth / 2;
189
- right = void 0;
190
- originX = '50%';
192
+ left = void 0;
193
+ right = containerRect.width - mouseX;
194
+ originX = '100%';
191
195
  originY = '0%';
192
196
  break;
193
- case 'left':
194
- top = mouseY - popperHeight / 2;
195
- bottom = void 0;
196
- left = mouseX - popperWidth;
197
- right = void 0;
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 = '50%';
204
+ originY = '100%';
200
205
  break;
201
- case 'right':
202
- top = mouseY - popperHeight / 2;
203
- bottom = void 0;
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 = '50%';
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
- const attemptOrder = getAttemptOrder(placement);
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' && map.set(opt[primaryKey], opt);
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]);
@@ -4,6 +4,7 @@ import { clsx, useLoading, useSyncState } from '../../utils/index.js';
4
4
  import { useMemo } from 'react';
5
5
  import { Collapse } from '../transitionBase/index.js';
6
6
  import { classes } from './selectedList.style.js';
7
+ import { SortableItem } from '../sortableItem/index.js';
7
8
  export function SelectedItem({ value, index, itemProps, onClose, ...props }) {
8
9
  const [alertProps, setAlertProps] = useSyncState();
9
10
  const [loading, requestFn] = useLoading(async () => {
@@ -14,5 +15,5 @@ export function SelectedItem({ value, index, itemProps, onClose, ...props }) {
14
15
  alertProps.current?.onClose?.(e);
15
16
  onClose?.(value, index);
16
17
  };
17
- return (_jsx(Collapse, { ...props, className: classes.option, children: _jsx(Alert, { closable: true, color: "info", showIcon: false, ...alertProps.current, className: clsx(classes.optionWrap, alertProps.current?.className), onClose: closeHandler, loading: loading.current }) }));
18
+ return (_jsx(Collapse, { ...props, className: classes.option, children: _jsx(SortableItem, { component: Alert, id: value, index: index, closable: true, color: "info", showIcon: false, ...alertProps.current, className: clsx(classes.optionWrap, alertProps.current?.className), onClose: closeHandler, loading: loading.current }) }));
18
19
  }
@@ -1,10 +1,11 @@
1
1
  import { jsx as _jsx } from "@emotion/react/jsx-runtime";
2
2
  import { memo } from 'react';
3
- import { clsx, toArray } from '../../utils/index.js';
3
+ import { clsx, defaultSensors, onDndDragEnd, toArray } from '../../utils/index.js';
4
4
  import { classes, style } from './selectedList.style.js';
5
5
  import { TransitionGroup } from 'react-transition-group';
6
6
  import { useSelectionContext } from '../selectionContext/index.js';
7
7
  import { SelectedItem } from './selectedItem.js';
8
+ import { DragDropProvider } from '@dnd-kit/react';
8
9
  export const SelectedList = memo(({ value, itemProps, onClose, ...props }) => {
9
10
  const { value: innerValue, setValue: setInnerValue } = useSelectionContext();
10
11
  const arr = toArray(value || innerValue);
@@ -12,5 +13,9 @@ export const SelectedList = memo(({ value, itemProps, onClose, ...props }) => {
12
13
  onClose?.(v, i);
13
14
  setInnerValue?.(arr?.filter(_v => _v !== v));
14
15
  };
15
- return (_jsx(TransitionGroup, { ...props, css: style, className: clsx(classes.root, props.className), children: arr?.map((v, i) => _jsx(SelectedItem, { value: v, index: i, itemProps: itemProps, onClose: closeHandler }, v)) }));
16
+ const dragEndHandler = e => {
17
+ const newValue = onDndDragEnd(e, arr);
18
+ newValue && setInnerValue(newValue);
19
+ };
20
+ return (_jsx(DragDropProvider, { sensors: defaultSensors, onDragEnd: dragEndHandler, children: _jsx(TransitionGroup, { ...props, css: style, className: clsx(classes.root, props.className), children: arr?.map((v, i) => _jsx(SelectedItem, { value: v, index: i, itemProps: itemProps, onClose: closeHandler }, v)) }) }));
16
21
  });
@@ -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) && map.set(id, item);
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
  };
@@ -16,7 +16,7 @@ export const style = defineCss(({ mode, spacing, gray, divider, background, easi
16
16
 
17
17
  thead, tfoot {
18
18
  position: sticky;
19
- z-index: 5;
19
+ z-index: 7;
20
20
 
21
21
  th, td {
22
22
  background-color: ${headerBg};
@@ -68,7 +68,9 @@ function useStickyCellProps({ sticky, ...props }) {
68
68
  ref: innerRef,
69
69
  css: style,
70
70
  className: classes.cell,
71
- style: sticky && { [sticky]: offset },
71
+ ...sticky && {
72
+ style: { [sticky]: offset }
73
+ },
72
74
  'data-sticky': sticky
73
75
  });
74
76
  }
@@ -8,7 +8,7 @@ export const style = defineCss(({ easing }) => css `
8
8
  &[data-sticky=left], &[data-sticky=right] {
9
9
  overflow: visible;
10
10
  position: sticky;
11
- z-index: 4;
11
+ z-index: 6;
12
12
 
13
13
  &::after {
14
14
  content: '';
@@ -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) && map.set(_key, col);
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;
@@ -13,6 +13,7 @@ export declare const defaultSensors: Customizable<Sensors>;
13
13
  * @param primaryKey 索引用的主键,默认为`id`
14
14
  * @return 返回新的数组,但如果顺序未改变,会得到null
15
15
  */
16
+ export declare function onDndDragEnd<T>({ operation }: Parameters<DragDropEvents<any, any, any>['dragend']>[0], items: T[]): T[] | null;
16
17
  export declare function onDndDragEnd<T extends Obj>({ operation }: Parameters<DragDropEvents<any, any, any>['dragend']>[0], items: T[], primaryKey?: keyof T): T[] | null;
17
18
  export declare function arrayMove<T>(array: T[], from: number, to: number): T[];
18
19
  /**
@@ -13,20 +13,23 @@ export const defaultSensors = defaults => [
13
13
  ]
14
14
  })
15
15
  ];
16
- /**
17
- * <DragDropProvider>组件通用的onDragEnd方法
18
- * @param e 事件
19
- * @param items 传入需要排序的数组
20
- * @param primaryKey 索引用的主键,默认为`id`
21
- * @return 返回新的数组,但如果顺序未改变,会得到null
22
- */
23
16
  export function onDndDragEnd({ operation }, items, primaryKey = 'id') {
24
17
  const { source, target, canceled } = operation;
25
18
  if (!source || !target || canceled) {
26
19
  return null;
27
20
  }
28
- const sourceIndex = items.findIndex(item => item[primaryKey] === source.id);
29
- const targetIndex = items.findIndex(item => item[primaryKey] === target.id);
21
+ const sourceIndex = items.findIndex(item => {
22
+ if (typeof item === 'object' && item !== null) {
23
+ return item[primaryKey] === source.id;
24
+ }
25
+ return item === source.id;
26
+ });
27
+ const targetIndex = items.findIndex(item => {
28
+ if (typeof item === 'object' && item !== null) {
29
+ return item[primaryKey] === target.id;
30
+ }
31
+ return item === target.id;
32
+ });
30
33
  if (sourceIndex === -1 || targetIndex === -1) {
31
34
  if (typeof source.initialIndex === 'number' && typeof source.index === 'number') {
32
35
  const from = source.initialIndex;