@canlooks/can-ui 0.0.110 → 0.0.112

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 (29) hide show
  1. package/dist/cjs/components/curd/curd.js +1 -1
  2. package/dist/cjs/components/image/image.js +1 -1
  3. package/dist/cjs/components/pinchable/pinchable.js +14 -10
  4. package/dist/cjs/components/sortableItem/sortableItem.js +8 -5
  5. package/dist/cjs/components/sortableItem/sortableItem.style.d.ts +5 -0
  6. package/dist/cjs/components/sortableItem/sortableItem.style.js +18 -0
  7. package/dist/cjs/components/tree/treeDnd.js +3 -2
  8. package/dist/cjs/components/tree/treeDnd.style.d.ts +1 -0
  9. package/dist/cjs/components/tree/treeDnd.style.js +6 -1
  10. package/dist/cjs/components/tree/treeNode.js +12 -0
  11. package/dist/cjs/utils/curd.d.ts +1 -0
  12. package/dist/cjs/utils/curd.js +16 -2
  13. package/dist/cjs/utils/tree.d.ts +9 -0
  14. package/dist/cjs/utils/tree.js +56 -0
  15. package/dist/esm/components/curd/curd.js +2 -2
  16. package/dist/esm/components/image/image.js +1 -1
  17. package/dist/esm/components/pinchable/pinchable.js +14 -10
  18. package/dist/esm/components/sortableItem/sortableItem.js +10 -7
  19. package/dist/esm/components/sortableItem/sortableItem.style.d.ts +5 -0
  20. package/dist/esm/components/sortableItem/sortableItem.style.js +15 -0
  21. package/dist/esm/components/tree/treeDnd.js +5 -4
  22. package/dist/esm/components/tree/treeDnd.style.d.ts +1 -0
  23. package/dist/esm/components/tree/treeDnd.style.js +5 -0
  24. package/dist/esm/components/tree/treeNode.js +12 -0
  25. package/dist/esm/utils/curd.d.ts +1 -0
  26. package/dist/esm/utils/curd.js +15 -2
  27. package/dist/esm/utils/tree.d.ts +9 -0
  28. package/dist/esm/utils/tree.js +55 -0
  29. package/package.json +1 -1
@@ -78,7 +78,7 @@ exports.Curd = (0, react_1.memo)((props) => {
78
78
  return columns;
79
79
  }
80
80
  const controlColumn = {
81
- key: '$control',
81
+ key: utils_1.CONTROL_COLUMN_KEY,
82
82
  title: controlColumnTitle,
83
83
  render(row) {
84
84
  const _updatable = typeof updatable === 'function' ? updatable(row) : updatable;
@@ -47,6 +47,6 @@ exports.Image = (0, react_1.memo)(({ src, fallback, onLoad, onError, renderLoadi
47
47
  }, onLoad: loadHandler, onError: errorHandler }), loading.current &&
48
48
  (renderLoading ?? (0, jsx_runtime_1.jsx)(skeleton_1.Skeleton, { className: image_style_1.classes.skeleton })), !!renderedActions && !failed.current &&
49
49
  (0, jsx_runtime_1.jsx)("div", { className: image_style_1.classes.mask, children: renderedActions }), previewable && src &&
50
- (0, jsx_runtime_1.jsx)(gallery_1.Gallery, { src: [src], ...previewProps, open: previewOpen.current, onOpenChange: setPreviewOpen })] }));
50
+ (0, jsx_runtime_1.jsx)(gallery_1.Gallery, { src: [src], ...previewProps, open: previewOpen.current, onOpenChange: setPreviewOpen, onPointerDown: e => e.stopPropagation() })] }));
51
51
  });
52
52
  exports.Image.Gallery = gallery_1.Gallery;
@@ -15,12 +15,12 @@ exports.Pinchable = (({ component: Component = 'div', ref, gestureOptions, defau
15
15
  zoomFn(innerScale.current * .5);
16
16
  };
17
17
  wrapperRef.current.zoomTo = zoomFn;
18
- wrapperRef.current.rotate =
19
- wrapperRef.current.rotateLeft = () => {
20
- rotateFn(innerRotate.current - 90);
21
- };
18
+ wrapperRef.current.rotate = rotateFn;
19
+ wrapperRef.current.rotateLeft = () => {
20
+ rotateFn(innerRotate.current - 90);
21
+ };
22
22
  wrapperRef.current.rotateRight = () => {
23
- rotateFn(innerRotate.current + 90);
23
+ rotateFn(innerRotate.current - 90);
24
24
  };
25
25
  wrapperRef.current.reset = resetAll;
26
26
  }
@@ -134,7 +134,7 @@ exports.Pinchable = (({ component: Component = 'div', ref, gestureOptions, defau
134
134
  resetZoom(false);
135
135
  setInnerRotate(0);
136
136
  };
137
- const doubleClickHandler = (e) => {
137
+ const onDoubleClick = (e) => {
138
138
  childrenProps.onDoubleClick?.(e);
139
139
  if (innerScale.current < 1.5) {
140
140
  zoomFn(3, e.clientX, e.clientY);
@@ -143,12 +143,16 @@ exports.Pinchable = (({ component: Component = 'div', ref, gestureOptions, defau
143
143
  resetZoom();
144
144
  }
145
145
  };
146
- const wheelHandler = (e) => {
146
+ const onWheel = (e) => {
147
147
  childrenProps.onMouseWheel?.(e);
148
148
  e.deltaY > 0
149
149
  ? zoomFn(innerScale.current * .8, e.clientX, e.clientY)
150
150
  : zoomFn(innerScale.current * 1.2, e.clientX, e.clientY);
151
151
  };
152
+ const onTransitionEnd = (e) => {
153
+ e.currentTarget.dataset.transition = 'false';
154
+ setInnerRotate(innerRotate.current % 360);
155
+ };
152
156
  return ((0, jsx_runtime_1.jsx)(Component, { ...props, ref: wrapperRef, css: pinchable_style_1.style, className: (0, utils_1.clsx)(pinchable_style_1.classes.root, props.className), ...pinchableHandles, children: (0, react_1.cloneElement)(children, {
153
157
  ref: (0, utils_1.cloneRef)(contentRef, childrenProps.ref),
154
158
  className: (0, utils_1.clsx)(pinchable_style_1.classes.content, childrenProps.className),
@@ -160,8 +164,8 @@ exports.Pinchable = (({ component: Component = 'div', ref, gestureOptions, defau
160
164
  transformOrigin: 'center'
161
165
  },
162
166
  ...draggableHandles,
163
- onDoubleClick: doubleClickHandler,
164
- onWheel: wheelHandler,
165
- onTransitionEnd: e => e.currentTarget.dataset.transition = 'false'
167
+ onDoubleClick,
168
+ onWheel,
169
+ onTransitionEnd
166
170
  }) }));
167
171
  });
@@ -6,6 +6,9 @@ const react_1 = require("react");
6
6
  const sortable_1 = require("@dnd-kit/sortable");
7
7
  const utilities_1 = require("@dnd-kit/utilities");
8
8
  const utils_1 = require("../../utils");
9
+ const react_2 = require("@emotion/react");
10
+ const treeDnd_style_1 = require("../tree/treeDnd.style");
11
+ const sortableItem_style_1 = require("./sortableItem.style");
9
12
  exports.SortableItem = (({ component: Component = 'div', id, disabled, sortableArguments, ...props }) => {
10
13
  const { attributes, isDragging, listeners, setNodeRef, transform, transition } = (0, sortable_1.useSortable)({
11
14
  ...sortableArguments,
@@ -30,9 +33,9 @@ exports.SortableItem = (({ component: Component = 'div', id, disabled, sortableA
30
33
  addEventListener('pointerup', onPointerUp);
31
34
  }, []);
32
35
  (0, react_1.useEffect)(() => removeListener, []);
33
- return ((0, jsx_runtime_1.jsx)(Component, { ...attributes, ...listeners, ...props, ref: (0, utils_1.cloneRef)(setNodeRef, props.ref), style: {
34
- transform: utilities_1.CSS.Transform.toString(transform),
35
- transition,
36
- ...props.style
37
- }, onTouchStart: disabled ? void 0 : onTouchStart, "data-dragging": isDragging }));
36
+ return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(Component, { ...attributes, ...listeners, ...props, ref: (0, utils_1.cloneRef)(setNodeRef, props.ref), css: sortableItem_style_1.style, className: (0, utils_1.clsx)(sortableItem_style_1.classes.root, props.className), style: {
37
+ transform: utilities_1.CSS.Transform.toString(transform),
38
+ transition,
39
+ ...props.style
40
+ }, onTouchStart: disabled ? void 0 : onTouchStart, "data-dragging": isDragging }), isDragging && (0, jsx_runtime_1.jsx)(react_2.Global, { styles: treeDnd_style_1.globalGrabbingStyle })] }));
38
41
  });
@@ -0,0 +1,5 @@
1
+ export declare const classes: {
2
+ root: string;
3
+ };
4
+ export declare const style: import("@emotion/react").SerializedStyles;
5
+ export declare const globalGrabbingStyle: import("@emotion/react").SerializedStyles;
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.globalGrabbingStyle = exports.style = exports.classes = void 0;
4
+ const react_1 = require("@emotion/react");
5
+ const utils_1 = require("../../utils");
6
+ exports.classes = (0, utils_1.defineInnerClasses)('sortable-item');
7
+ exports.style = (0, react_1.css) `
8
+ cursor: grab;
9
+
10
+ &:active {
11
+ cursor: grabbing;
12
+ }
13
+ `;
14
+ exports.globalGrabbingStyle = (0, react_1.css) `
15
+ * {
16
+ cursor: grabbing;
17
+ }
18
+ `;
@@ -5,6 +5,7 @@ exports.useTreeDndContext = useTreeDndContext;
5
5
  const jsx_runtime_1 = require("@emotion/react/jsx-runtime");
6
6
  const react_1 = require("react");
7
7
  const treeDnd_style_1 = require("./treeDnd.style");
8
+ const react_2 = require("@emotion/react");
8
9
  exports.TreeDndContext = (0, react_1.createContext)({});
9
10
  function useTreeDndContext() {
10
11
  return (0, react_1.useContext)(exports.TreeDndContext);
@@ -13,8 +14,8 @@ exports.TreeDnd = (0, react_1.memo)(({ sortable, showDragHandle, onSort, childre
13
14
  const dragging = (0, react_1.useState)(void 0);
14
15
  const overing = (0, react_1.useRef)(void 0);
15
16
  const placement = (0, react_1.useRef)(void 0);
16
- return ((0, jsx_runtime_1.jsx)(exports.TreeDndContext, { value: {
17
+ return ((0, jsx_runtime_1.jsxs)(exports.TreeDndContext, { value: {
17
18
  sortable, showDragHandle, onSort,
18
19
  dragging, overing, placement
19
- }, children: (0, jsx_runtime_1.jsx)("div", { className: treeDnd_style_1.treeDndClasses.levelBlock, children: children }) }));
20
+ }, children: [(0, jsx_runtime_1.jsx)("div", { className: treeDnd_style_1.treeDndClasses.levelBlock, children: children }), !!dragging[0] && (0, jsx_runtime_1.jsx)(react_2.Global, { styles: treeDnd_style_1.globalGrabbingStyle })] }));
20
21
  });
@@ -13,3 +13,4 @@ export declare const treeDndClasses: {
13
13
  export declare function useStyle({ indent }: {
14
14
  indent: number;
15
15
  }): import("@emotion/react").SerializedStyles;
16
+ export declare const globalGrabbingStyle: import("@emotion/react").SerializedStyles;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.treeDndClasses = void 0;
3
+ exports.globalGrabbingStyle = exports.treeDndClasses = void 0;
4
4
  exports.useStyle = useStyle;
5
5
  const tslib_1 = require("tslib");
6
6
  const utils_1 = require("../../utils");
@@ -191,3 +191,8 @@ function useStyle({ indent }) {
191
191
  }
192
192
  `, [indent]);
193
193
  }
194
+ exports.globalGrabbingStyle = (0, react_1.css) `
195
+ * {
196
+ cursor: grabbing;
197
+ }
198
+ `;
@@ -64,6 +64,7 @@ exports.TreeNode = (0, react_1.memo)(({ id, label, prefix, suffix, disabled, _le
64
64
  const pointerLeavePredecessor = (e) => {
65
65
  inactiveBlock(e.currentTarget);
66
66
  };
67
+ const overingTimeout = (0, react_1.useRef)(void 0);
67
68
  const activeBlock = (el, _placement, upLevel = 0) => {
68
69
  if (_placement === 'parent') {
69
70
  let i = upLevel;
@@ -93,6 +94,13 @@ exports.TreeNode = (0, react_1.memo)(({ id, label, prefix, suffix, disabled, _le
93
94
  return true;
94
95
  }
95
96
  });
97
+ // 如果有children且为折叠状态,over在该节点上一定时间后,需要展开该节点
98
+ if (hasChildren && !currentExpanded) {
99
+ overingTimeout.current ||= setTimeout(() => {
100
+ overingTimeout.current = void 0;
101
+ toggleExpanded(id);
102
+ }, 600);
103
+ }
96
104
  };
97
105
  const inactiveBlock = (el) => {
98
106
  if (el) {
@@ -105,6 +113,10 @@ exports.TreeNode = (0, react_1.memo)(({ id, label, prefix, suffix, disabled, _le
105
113
  el.dataset.active = 'false';
106
114
  });
107
115
  overing.current = void 0;
116
+ if (overingTimeout.current) {
117
+ clearTimeout(overingTimeout.current);
118
+ overingTimeout.current = void 0;
119
+ }
108
120
  };
109
121
  /**
110
122
  * ---------------------------------------------------------------------
@@ -14,6 +14,7 @@ export declare function columnsToFilterItem(columns?: (CurdColumn<any> | symbol)
14
14
  * @param row
15
15
  */
16
16
  export declare function columnsToFormItem(columns?: (CurdColumn<any> | symbol)[], row?: Obj): (ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | CurdFormItemProps)[] | undefined;
17
+ export declare const CONTROL_COLUMN_KEY = "$control";
17
18
  /**
18
19
  * 统一处理Columns
19
20
  */
@@ -1,5 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CONTROL_COLUMN_KEY = void 0;
3
4
  exports.columnsToFilterItem = columnsToFilterItem;
4
5
  exports.columnsToFormItem = columnsToFormItem;
5
6
  exports.useCurdColumns = useCurdColumns;
@@ -58,6 +59,7 @@ function columnsTransfer(columns, type = 'filter', row) {
58
59
  })
59
60
  .sort((a, b) => (a.order || 0) - (b.order || 0));
60
61
  }
62
+ exports.CONTROL_COLUMN_KEY = '$control';
61
63
  /**
62
64
  * 统一处理Columns
63
65
  */
@@ -68,8 +70,20 @@ function useCurdColumns({ columns, columnConfigurable }) {
68
70
  }
69
71
  let { defaultVisible, visible, onVisibleChange, defaultOrder, order, onOrderChange } = columnConfigurable;
70
72
  if (!defaultVisible || !defaultOrder) {
71
- const defaultKeys = columns?.flatMap((col) => col.hideInTable ? [] : (col._key ?? [])) || [];
72
- defaultKeys.push('$control');
73
+ let hasControlColumn = false;
74
+ const defaultKeys = columns?.flatMap((col) => {
75
+ if (col.hideInTable) {
76
+ return [];
77
+ }
78
+ if (col._key) {
79
+ if (col._key === exports.CONTROL_COLUMN_KEY) {
80
+ hasControlColumn = true;
81
+ }
82
+ return col._key;
83
+ }
84
+ return [];
85
+ }) || [];
86
+ !hasControlColumn && defaultKeys.push(exports.CONTROL_COLUMN_KEY);
73
87
  defaultVisible ||= defaultKeys;
74
88
  defaultOrder ||= defaultKeys;
75
89
  }
@@ -1,4 +1,5 @@
1
1
  import { Id, Obj } from '../types';
2
+ import { NodeType, SortInfo } from '../components/tree';
2
3
  /**
3
4
  * ------------------------------------------------------------------------
4
5
  * 统一处理树形搜索
@@ -25,3 +26,11 @@ export declare function useTreeSearch<N extends Obj, V extends Id = Id>({ nodes,
25
26
  setInnerSearchValue: import("react").Dispatch<import("react").SetStateAction<string>>;
26
27
  filteredTreeData: N[] | undefined;
27
28
  };
29
+ /**
30
+ * 得到排序后的树结构
31
+ */
32
+ export declare function sortTreeNodes<N extends NodeType<V>, V extends Id = Id>(props: {
33
+ nodes: N[];
34
+ primaryKey?: keyof N;
35
+ childrenKey?: keyof N;
36
+ }, sortInfo: SortInfo<V>): N[];
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.useTreeSearch = useTreeSearch;
4
+ exports.sortTreeNodes = sortTreeNodes;
4
5
  const react_1 = require("react");
5
6
  const hooks_1 = require("./hooks");
6
7
  function useTreeSearch({ nodes, primaryKey = 'id', labelKey = 'label', childrenKey = 'children', searchTokenKey = 'searchToken', defaultExpanded = [], expanded, onExpandedChange, defaultSearchValue = '', searchValue, onSearchChange }) {
@@ -61,3 +62,58 @@ function useTreeSearch({ nodes, primaryKey = 'id', labelKey = 'label', childrenK
61
62
  filteredTreeData
62
63
  };
63
64
  }
65
+ /**
66
+ * 得到排序后的树结构
67
+ */
68
+ function sortTreeNodes(props, sortInfo) {
69
+ let { nodes, primaryKey = 'id', childrenKey = 'children' } = props;
70
+ const { source, destination, placement } = sortInfo;
71
+ nodes = structuredClone(nodes);
72
+ const pickUp = (nodes) => {
73
+ if (!nodes?.length) {
74
+ return null;
75
+ }
76
+ for (let i = 0, { length } = nodes; i < length; i++) {
77
+ const node = nodes[i];
78
+ if (node[primaryKey] === source) {
79
+ nodes.splice(i, 1);
80
+ return node;
81
+ }
82
+ const foundInChildren = pickUp(node[childrenKey]);
83
+ if (foundInChildren) {
84
+ return foundInChildren;
85
+ }
86
+ }
87
+ return null;
88
+ };
89
+ pickUp(nodes);
90
+ const putDown = (nodes) => {
91
+ if (!nodes?.length) {
92
+ return false;
93
+ }
94
+ for (let i = 0, { length } = nodes; i < length; i++) {
95
+ const node = nodes[i];
96
+ if (node[primaryKey] === destination) {
97
+ switch (placement) {
98
+ case 'before':
99
+ nodes.splice(i, 0, node);
100
+ return true;
101
+ case 'after':
102
+ nodes.splice(i + 1, 0, node);
103
+ return true;
104
+ default:
105
+ node.children ||= [];
106
+ node.children.push(node);
107
+ return true;
108
+ }
109
+ }
110
+ const foundInChildren = pickUp(node[childrenKey]);
111
+ if (foundInChildren) {
112
+ return foundInChildren;
113
+ }
114
+ }
115
+ return false;
116
+ };
117
+ putDown(nodes);
118
+ return nodes;
119
+ }
@@ -4,7 +4,7 @@ import { DataGrid } from '../dataGrid';
4
4
  import { Form } from '../form';
5
5
  import { CurdFilterable } from './curdFilterable';
6
6
  import { classes, style } from './curd.style';
7
- import { clsx, useControlled, useCurdColumns, useDerivedState, useLoading, useSync, mergeComponentProps } from '../../utils';
7
+ import { clsx, useControlled, useCurdColumns, useDerivedState, useLoading, useSync, mergeComponentProps, CONTROL_COLUMN_KEY } from '../../utils';
8
8
  import { Button } from '../button';
9
9
  import { Tooltip } from '../tooltip';
10
10
  import { CurdColumnConfig } from './curdColumnConfig';
@@ -75,7 +75,7 @@ export const Curd = memo((props) => {
75
75
  return columns;
76
76
  }
77
77
  const controlColumn = {
78
- key: '$control',
78
+ key: CONTROL_COLUMN_KEY,
79
79
  title: controlColumnTitle,
80
80
  render(row) {
81
81
  const _updatable = typeof updatable === 'function' ? updatable(row) : updatable;
@@ -44,6 +44,6 @@ export const Image = memo(({ src, fallback, onLoad, onError, renderLoading, alt
44
44
  }, onLoad: loadHandler, onError: errorHandler }), loading.current &&
45
45
  (renderLoading ?? _jsx(Skeleton, { className: classes.skeleton })), !!renderedActions && !failed.current &&
46
46
  _jsx("div", { className: classes.mask, children: renderedActions }), previewable && src &&
47
- _jsx(Gallery, { src: [src], ...previewProps, open: previewOpen.current, onOpenChange: setPreviewOpen })] }));
47
+ _jsx(Gallery, { src: [src], ...previewProps, open: previewOpen.current, onOpenChange: setPreviewOpen, onPointerDown: e => e.stopPropagation() })] }));
48
48
  });
49
49
  Image.Gallery = Gallery;
@@ -12,12 +12,12 @@ export const Pinchable = (({ component: Component = 'div', ref, gestureOptions,
12
12
  zoomFn(innerScale.current * .5);
13
13
  };
14
14
  wrapperRef.current.zoomTo = zoomFn;
15
- wrapperRef.current.rotate =
16
- wrapperRef.current.rotateLeft = () => {
17
- rotateFn(innerRotate.current - 90);
18
- };
15
+ wrapperRef.current.rotate = rotateFn;
16
+ wrapperRef.current.rotateLeft = () => {
17
+ rotateFn(innerRotate.current - 90);
18
+ };
19
19
  wrapperRef.current.rotateRight = () => {
20
- rotateFn(innerRotate.current + 90);
20
+ rotateFn(innerRotate.current - 90);
21
21
  };
22
22
  wrapperRef.current.reset = resetAll;
23
23
  }
@@ -131,7 +131,7 @@ export const Pinchable = (({ component: Component = 'div', ref, gestureOptions,
131
131
  resetZoom(false);
132
132
  setInnerRotate(0);
133
133
  };
134
- const doubleClickHandler = (e) => {
134
+ const onDoubleClick = (e) => {
135
135
  childrenProps.onDoubleClick?.(e);
136
136
  if (innerScale.current < 1.5) {
137
137
  zoomFn(3, e.clientX, e.clientY);
@@ -140,12 +140,16 @@ export const Pinchable = (({ component: Component = 'div', ref, gestureOptions,
140
140
  resetZoom();
141
141
  }
142
142
  };
143
- const wheelHandler = (e) => {
143
+ const onWheel = (e) => {
144
144
  childrenProps.onMouseWheel?.(e);
145
145
  e.deltaY > 0
146
146
  ? zoomFn(innerScale.current * .8, e.clientX, e.clientY)
147
147
  : zoomFn(innerScale.current * 1.2, e.clientX, e.clientY);
148
148
  };
149
+ const onTransitionEnd = (e) => {
150
+ e.currentTarget.dataset.transition = 'false';
151
+ setInnerRotate(innerRotate.current % 360);
152
+ };
149
153
  return (_jsx(Component, { ...props, ref: wrapperRef, css: style, className: clsx(classes.root, props.className), ...pinchableHandles, children: cloneElement(children, {
150
154
  ref: cloneRef(contentRef, childrenProps.ref),
151
155
  className: clsx(classes.content, childrenProps.className),
@@ -157,8 +161,8 @@ export const Pinchable = (({ component: Component = 'div', ref, gestureOptions,
157
161
  transformOrigin: 'center'
158
162
  },
159
163
  ...draggableHandles,
160
- onDoubleClick: doubleClickHandler,
161
- onWheel: wheelHandler,
162
- onTransitionEnd: e => e.currentTarget.dataset.transition = 'false'
164
+ onDoubleClick,
165
+ onWheel,
166
+ onTransitionEnd
163
167
  }) }));
164
168
  });
@@ -1,8 +1,11 @@
1
- import { jsx as _jsx } from "@emotion/react/jsx-runtime";
1
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "@emotion/react/jsx-runtime";
2
2
  import { useCallback, useEffect, useRef } from 'react';
3
3
  import { useSortable } from '@dnd-kit/sortable';
4
4
  import { CSS } from '@dnd-kit/utilities';
5
- import { cloneRef, useSync } from '../../utils';
5
+ import { cloneRef, clsx, useSync } from '../../utils';
6
+ import { Global } from '@emotion/react';
7
+ import { globalGrabbingStyle } from '../tree/treeDnd.style';
8
+ import { classes, style } from './sortableItem.style';
6
9
  export const SortableItem = (({ component: Component = 'div', id, disabled, sortableArguments, ...props }) => {
7
10
  const { attributes, isDragging, listeners, setNodeRef, transform, transition } = useSortable({
8
11
  ...sortableArguments,
@@ -27,9 +30,9 @@ export const SortableItem = (({ component: Component = 'div', id, disabled, sort
27
30
  addEventListener('pointerup', onPointerUp);
28
31
  }, []);
29
32
  useEffect(() => removeListener, []);
30
- return (_jsx(Component, { ...attributes, ...listeners, ...props, ref: cloneRef(setNodeRef, props.ref), style: {
31
- transform: CSS.Transform.toString(transform),
32
- transition,
33
- ...props.style
34
- }, onTouchStart: disabled ? void 0 : onTouchStart, "data-dragging": isDragging }));
33
+ return (_jsxs(_Fragment, { children: [_jsx(Component, { ...attributes, ...listeners, ...props, ref: cloneRef(setNodeRef, props.ref), css: style, className: clsx(classes.root, props.className), style: {
34
+ transform: CSS.Transform.toString(transform),
35
+ transition,
36
+ ...props.style
37
+ }, onTouchStart: disabled ? void 0 : onTouchStart, "data-dragging": isDragging }), isDragging && _jsx(Global, { styles: globalGrabbingStyle })] }));
35
38
  });
@@ -0,0 +1,5 @@
1
+ export declare const classes: {
2
+ root: string;
3
+ };
4
+ export declare const style: import("@emotion/react").SerializedStyles;
5
+ export declare const globalGrabbingStyle: import("@emotion/react").SerializedStyles;
@@ -0,0 +1,15 @@
1
+ import { css } from '@emotion/react';
2
+ import { defineInnerClasses } from '../../utils';
3
+ export const classes = defineInnerClasses('sortable-item');
4
+ export const style = css `
5
+ cursor: grab;
6
+
7
+ &:active {
8
+ cursor: grabbing;
9
+ }
10
+ `;
11
+ export const globalGrabbingStyle = css `
12
+ * {
13
+ cursor: grabbing;
14
+ }
15
+ `;
@@ -1,6 +1,7 @@
1
- import { jsx as _jsx } from "@emotion/react/jsx-runtime";
1
+ import { jsx as _jsx, jsxs as _jsxs } from "@emotion/react/jsx-runtime";
2
2
  import { createContext, memo, useContext, useRef, useState } from 'react';
3
- import { treeDndClasses } from './treeDnd.style';
3
+ import { globalGrabbingStyle, treeDndClasses } from './treeDnd.style';
4
+ import { Global } from '@emotion/react';
4
5
  export const TreeDndContext = createContext({});
5
6
  export function useTreeDndContext() {
6
7
  return useContext(TreeDndContext);
@@ -9,8 +10,8 @@ export const TreeDnd = memo(({ sortable, showDragHandle, onSort, children }) =>
9
10
  const dragging = useState(void 0);
10
11
  const overing = useRef(void 0);
11
12
  const placement = useRef(void 0);
12
- return (_jsx(TreeDndContext, { value: {
13
+ return (_jsxs(TreeDndContext, { value: {
13
14
  sortable, showDragHandle, onSort,
14
15
  dragging, overing, placement
15
- }, children: _jsx("div", { className: treeDndClasses.levelBlock, children: children }) }));
16
+ }, children: [_jsx("div", { className: treeDndClasses.levelBlock, children: children }), !!dragging[0] && _jsx(Global, { styles: globalGrabbingStyle })] }));
16
17
  });
@@ -13,3 +13,4 @@ export declare const treeDndClasses: {
13
13
  export declare function useStyle({ indent }: {
14
14
  indent: number;
15
15
  }): import("@emotion/react").SerializedStyles;
16
+ export declare const globalGrabbingStyle: import("@emotion/react").SerializedStyles;
@@ -186,3 +186,8 @@ export function useStyle({ indent }) {
186
186
  }
187
187
  `, [indent]);
188
188
  }
189
+ export const globalGrabbingStyle = css `
190
+ * {
191
+ cursor: grabbing;
192
+ }
193
+ `;
@@ -61,6 +61,7 @@ export const TreeNode = memo(({ id, label, prefix, suffix, disabled, _level = 0,
61
61
  const pointerLeavePredecessor = (e) => {
62
62
  inactiveBlock(e.currentTarget);
63
63
  };
64
+ const overingTimeout = useRef(void 0);
64
65
  const activeBlock = (el, _placement, upLevel = 0) => {
65
66
  if (_placement === 'parent') {
66
67
  let i = upLevel;
@@ -90,6 +91,13 @@ export const TreeNode = memo(({ id, label, prefix, suffix, disabled, _level = 0,
90
91
  return true;
91
92
  }
92
93
  });
94
+ // 如果有children且为折叠状态,over在该节点上一定时间后,需要展开该节点
95
+ if (hasChildren && !currentExpanded) {
96
+ overingTimeout.current ||= setTimeout(() => {
97
+ overingTimeout.current = void 0;
98
+ toggleExpanded(id);
99
+ }, 600);
100
+ }
93
101
  };
94
102
  const inactiveBlock = (el) => {
95
103
  if (el) {
@@ -102,6 +110,10 @@ export const TreeNode = memo(({ id, label, prefix, suffix, disabled, _level = 0,
102
110
  el.dataset.active = 'false';
103
111
  });
104
112
  overing.current = void 0;
113
+ if (overingTimeout.current) {
114
+ clearTimeout(overingTimeout.current);
115
+ overingTimeout.current = void 0;
116
+ }
105
117
  };
106
118
  /**
107
119
  * ---------------------------------------------------------------------
@@ -14,6 +14,7 @@ export declare function columnsToFilterItem(columns?: (CurdColumn<any> | symbol)
14
14
  * @param row
15
15
  */
16
16
  export declare function columnsToFormItem(columns?: (CurdColumn<any> | symbol)[], row?: Obj): (ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | CurdFormItemProps)[] | undefined;
17
+ export declare const CONTROL_COLUMN_KEY = "$control";
17
18
  /**
18
19
  * 统一处理Columns
19
20
  */
@@ -53,6 +53,7 @@ function columnsTransfer(columns, type = 'filter', row) {
53
53
  })
54
54
  .sort((a, b) => (a.order || 0) - (b.order || 0));
55
55
  }
56
+ export const CONTROL_COLUMN_KEY = '$control';
56
57
  /**
57
58
  * 统一处理Columns
58
59
  */
@@ -63,8 +64,20 @@ export function useCurdColumns({ columns, columnConfigurable }) {
63
64
  }
64
65
  let { defaultVisible, visible, onVisibleChange, defaultOrder, order, onOrderChange } = columnConfigurable;
65
66
  if (!defaultVisible || !defaultOrder) {
66
- const defaultKeys = columns?.flatMap((col) => col.hideInTable ? [] : (col._key ?? [])) || [];
67
- defaultKeys.push('$control');
67
+ let hasControlColumn = false;
68
+ const defaultKeys = columns?.flatMap((col) => {
69
+ if (col.hideInTable) {
70
+ return [];
71
+ }
72
+ if (col._key) {
73
+ if (col._key === CONTROL_COLUMN_KEY) {
74
+ hasControlColumn = true;
75
+ }
76
+ return col._key;
77
+ }
78
+ return [];
79
+ }) || [];
80
+ !hasControlColumn && defaultKeys.push(CONTROL_COLUMN_KEY);
68
81
  defaultVisible ||= defaultKeys;
69
82
  defaultOrder ||= defaultKeys;
70
83
  }
@@ -1,4 +1,5 @@
1
1
  import { Id, Obj } from '../types';
2
+ import { NodeType, SortInfo } from '../components/tree';
2
3
  /**
3
4
  * ------------------------------------------------------------------------
4
5
  * 统一处理树形搜索
@@ -25,3 +26,11 @@ export declare function useTreeSearch<N extends Obj, V extends Id = Id>({ nodes,
25
26
  setInnerSearchValue: import("react").Dispatch<import("react").SetStateAction<string>>;
26
27
  filteredTreeData: N[] | undefined;
27
28
  };
29
+ /**
30
+ * 得到排序后的树结构
31
+ */
32
+ export declare function sortTreeNodes<N extends NodeType<V>, V extends Id = Id>(props: {
33
+ nodes: N[];
34
+ primaryKey?: keyof N;
35
+ childrenKey?: keyof N;
36
+ }, sortInfo: SortInfo<V>): N[];
@@ -58,3 +58,58 @@ export function useTreeSearch({ nodes, primaryKey = 'id', labelKey = 'label', ch
58
58
  filteredTreeData
59
59
  };
60
60
  }
61
+ /**
62
+ * 得到排序后的树结构
63
+ */
64
+ export function sortTreeNodes(props, sortInfo) {
65
+ let { nodes, primaryKey = 'id', childrenKey = 'children' } = props;
66
+ const { source, destination, placement } = sortInfo;
67
+ nodes = structuredClone(nodes);
68
+ const pickUp = (nodes) => {
69
+ if (!nodes?.length) {
70
+ return null;
71
+ }
72
+ for (let i = 0, { length } = nodes; i < length; i++) {
73
+ const node = nodes[i];
74
+ if (node[primaryKey] === source) {
75
+ nodes.splice(i, 1);
76
+ return node;
77
+ }
78
+ const foundInChildren = pickUp(node[childrenKey]);
79
+ if (foundInChildren) {
80
+ return foundInChildren;
81
+ }
82
+ }
83
+ return null;
84
+ };
85
+ pickUp(nodes);
86
+ const putDown = (nodes) => {
87
+ if (!nodes?.length) {
88
+ return false;
89
+ }
90
+ for (let i = 0, { length } = nodes; i < length; i++) {
91
+ const node = nodes[i];
92
+ if (node[primaryKey] === destination) {
93
+ switch (placement) {
94
+ case 'before':
95
+ nodes.splice(i, 0, node);
96
+ return true;
97
+ case 'after':
98
+ nodes.splice(i + 1, 0, node);
99
+ return true;
100
+ default:
101
+ node.children ||= [];
102
+ node.children.push(node);
103
+ return true;
104
+ }
105
+ }
106
+ const foundInChildren = pickUp(node[childrenKey]);
107
+ if (foundInChildren) {
108
+ return foundInChildren;
109
+ }
110
+ }
111
+ return false;
112
+ };
113
+ putDown(nodes);
114
+ return nodes;
115
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@canlooks/can-ui",
3
- "version": "0.0.110",
3
+ "version": "0.0.112",
4
4
  "author": "C.CanLiang <canlooks@gmail.com>",
5
5
  "description": "My ui framework",
6
6
  "license": "MIT",