@canlooks/can-ui 0.0.96 → 0.0.98

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 (83) hide show
  1. package/dist/cjs/components/accordion/accordion.style.d.ts +1 -1
  2. package/dist/cjs/components/alert/alert.style.d.ts +3 -3
  3. package/dist/cjs/components/button/button.style.d.ts +1 -1
  4. package/dist/cjs/components/checkboxBase/checkboxBase.style.d.ts +2 -2
  5. package/dist/cjs/components/clickAway/clickAway.d.ts +27 -27
  6. package/dist/cjs/components/dataGrid/dataGrid.style.d.ts +1 -1
  7. package/dist/cjs/components/descriptions/descriptions.style.d.ts +1 -1
  8. package/dist/cjs/components/dialog/dialog.style.d.ts +3 -3
  9. package/dist/cjs/components/inputBase/inputBase.style.d.ts +2 -2
  10. package/dist/cjs/components/menuItem/menuItem.d.ts +5 -1
  11. package/dist/cjs/components/menuItem/menuItem.js +1 -1
  12. package/dist/cjs/components/menuItem/menuItem.style.d.ts +2 -2
  13. package/dist/cjs/components/palette/palette.style.d.ts +1 -1
  14. package/dist/cjs/components/pickerDialog/pickerDialog.style.d.ts +1 -1
  15. package/dist/cjs/components/popper/popper.js +26 -21
  16. package/dist/cjs/components/progress/progress.js +2 -1
  17. package/dist/cjs/components/progress/progress.style.d.ts +1 -1
  18. package/dist/cjs/components/resizable/resizable.style.d.ts +1 -1
  19. package/dist/cjs/components/segmented/segmented.style.d.ts +1 -1
  20. package/dist/cjs/components/select/select.d.ts +1 -1
  21. package/dist/cjs/components/selectionContext/selectionContext.d.ts +2 -0
  22. package/dist/cjs/components/selectionContext/selectionHook.js +2 -1
  23. package/dist/cjs/components/snackbarBase/snackbarBase.style.d.ts +1 -1
  24. package/dist/cjs/components/status/status.style.d.ts +1 -1
  25. package/dist/cjs/components/tabs/tabs.style.d.ts +4 -4
  26. package/dist/cjs/components/tag/tag.style.d.ts +2 -2
  27. package/dist/cjs/components/transfer/transfer.style.d.ts +2 -2
  28. package/dist/cjs/components/tree/tree.d.ts +2 -2
  29. package/dist/cjs/components/tree/tree.js +15 -13
  30. package/dist/cjs/components/tree/tree.style.d.ts +5 -9
  31. package/dist/cjs/components/tree/tree.style.js +96 -206
  32. package/dist/cjs/components/tree/treeDnd.d.ts +3 -7
  33. package/dist/cjs/components/tree/treeDnd.js +7 -19
  34. package/dist/cjs/components/tree/treeDnd.style.d.ts +15 -0
  35. package/dist/cjs/components/tree/treeDnd.style.js +191 -0
  36. package/dist/cjs/components/tree/treeNode.d.ts +4 -4
  37. package/dist/cjs/components/tree/treeNode.js +82 -69
  38. package/dist/cjs/components/upload/upload.style.d.ts +1 -1
  39. package/dist/cjs/utils/dnd.d.ts +11 -3
  40. package/dist/cjs/utils/dnd.js +45 -2
  41. package/dist/cjs/utils/utils.d.ts +1 -1
  42. package/dist/esm/components/accordion/accordion.style.d.ts +1 -1
  43. package/dist/esm/components/alert/alert.style.d.ts +3 -3
  44. package/dist/esm/components/button/button.style.d.ts +1 -1
  45. package/dist/esm/components/checkboxBase/checkboxBase.style.d.ts +2 -2
  46. package/dist/esm/components/clickAway/clickAway.d.ts +27 -27
  47. package/dist/esm/components/dataGrid/dataGrid.style.d.ts +1 -1
  48. package/dist/esm/components/descriptions/descriptions.style.d.ts +1 -1
  49. package/dist/esm/components/dialog/dialog.style.d.ts +3 -3
  50. package/dist/esm/components/inputBase/inputBase.style.d.ts +2 -2
  51. package/dist/esm/components/menuItem/menuItem.d.ts +5 -1
  52. package/dist/esm/components/menuItem/menuItem.js +1 -1
  53. package/dist/esm/components/menuItem/menuItem.style.d.ts +2 -2
  54. package/dist/esm/components/palette/palette.style.d.ts +1 -1
  55. package/dist/esm/components/pickerDialog/pickerDialog.style.d.ts +1 -1
  56. package/dist/esm/components/popper/popper.js +26 -21
  57. package/dist/esm/components/progress/progress.js +2 -1
  58. package/dist/esm/components/progress/progress.style.d.ts +1 -1
  59. package/dist/esm/components/resizable/resizable.style.d.ts +1 -1
  60. package/dist/esm/components/segmented/segmented.style.d.ts +1 -1
  61. package/dist/esm/components/select/select.d.ts +1 -1
  62. package/dist/esm/components/selectionContext/selectionContext.d.ts +2 -0
  63. package/dist/esm/components/selectionContext/selectionHook.js +2 -1
  64. package/dist/esm/components/snackbarBase/snackbarBase.style.d.ts +1 -1
  65. package/dist/esm/components/status/status.style.d.ts +1 -1
  66. package/dist/esm/components/tabs/tabs.style.d.ts +4 -4
  67. package/dist/esm/components/tag/tag.style.d.ts +2 -2
  68. package/dist/esm/components/transfer/transfer.style.d.ts +2 -2
  69. package/dist/esm/components/tree/tree.d.ts +2 -2
  70. package/dist/esm/components/tree/tree.js +18 -16
  71. package/dist/esm/components/tree/tree.style.d.ts +5 -9
  72. package/dist/esm/components/tree/tree.style.js +95 -206
  73. package/dist/esm/components/tree/treeDnd.d.ts +3 -7
  74. package/dist/esm/components/tree/treeDnd.js +8 -20
  75. package/dist/esm/components/tree/treeDnd.style.d.ts +15 -0
  76. package/dist/esm/components/tree/treeDnd.style.js +186 -0
  77. package/dist/esm/components/tree/treeNode.d.ts +4 -4
  78. package/dist/esm/components/tree/treeNode.js +82 -69
  79. package/dist/esm/components/upload/upload.style.d.ts +1 -1
  80. package/dist/esm/utils/dnd.d.ts +11 -3
  81. package/dist/esm/utils/dnd.js +44 -2
  82. package/dist/esm/utils/utils.d.ts +1 -1
  83. package/package.json +1 -1
@@ -11,114 +11,127 @@ import { Icon } from '../icon';
11
11
  import { faChevronRight } from '@fortawesome/free-solid-svg-icons/faChevronRight';
12
12
  import { faGripVertical } from '@fortawesome/free-solid-svg-icons';
13
13
  import { useTreeDndContext } from './treeDnd';
14
- export const TreeNode = memo(({ value, label, prefix, suffix, disabled, _level = 0, ...props }) => {
14
+ import { treeDndClasses } from './treeDnd.style';
15
+ export const TreeNode = memo(({ id, label, prefix, suffix, disabled, _level = 0, ...props }) => {
15
16
  const { expandedSet, toggleExpanded, indent, renderExpandIcon, showCheckbox, readOnly, clickLabelToExpand, ...context } = useTreeContext();
16
17
  disabled ??= context.disabled;
17
- const { selectionStatus, toggleSelected } = useSelectionContext();
18
- const currentExpanded = expandedSet.has(value);
19
- const status = selectionStatus.get(value);
18
+ const { optionsMap: nodesMap, selectionStatus, toggleSelected } = useSelectionContext();
19
+ const currentExpanded = expandedSet.has(id);
20
+ const status = selectionStatus.get(id);
20
21
  const clickHandler = () => {
21
- !readOnly && !disabled && toggleSelected(value);
22
- clickLabelToExpand && toggleExpanded(value);
22
+ !readOnly && !disabled && toggleSelected(id);
23
+ clickLabelToExpand && toggleExpanded(id);
23
24
  };
24
25
  const hasChildren = !!props.children && (!Array.isArray(props.children) || props.children.length > 0);
25
26
  /**
26
27
  * ---------------------------------------------------------------------
27
28
  * 拖拽部分
28
29
  */
29
- const { sortable, showDragHandle, onSort, containerRef, isOffsetSatisfied: [isOffsetSatisfied, setIsOffsetSatisfied], dragging: [dragging, setDragging], overing: [overing, setOvering], placement: [placement, setPlacement], overingTimer } = useTreeDndContext();
30
- const onClick = (e) => {
31
- props.onClick?.(e);
32
- !showCheckbox && clickHandler();
33
- };
30
+ const { sortable, showDragHandle, onSort, dragging: [dragging, setDragging], overing, placement } = useTreeDndContext();
31
+ const isDraggingNode = dragging === id;
32
+ const nodeRef = useRef(null);
34
33
  const dragHandleProps = useDraggable({
35
34
  disabled: !sortable,
36
- onDragStart(e) {
37
- setDragging(value);
38
- setOvering(void 0);
39
- currentExpanded && toggleExpanded(value);
40
- },
41
- onDrag({ diff: [diffX] }) {
42
- setIsOffsetSatisfied(diffX > indent * 2);
35
+ onDragStart() {
36
+ overing.current = void 0;
37
+ setDragging(id);
38
+ currentExpanded && toggleExpanded(id);
43
39
  },
44
40
  onDragEnd() {
45
- inactiveParentBlock();
46
- leaveMask();
41
+ overing.current && placement.current && onSort?.({
42
+ source: dragging,
43
+ destination: overing.current,
44
+ placement: placement.current
45
+ });
47
46
  setDragging(void 0);
48
- if (typeof overing !== 'undefined' && placement.current) {
49
- onSort?.({
50
- source: dragging,
51
- destination: overing,
52
- placement: isOffsetSatisfied ? 'child' : placement.current
53
- });
54
- }
55
- },
56
- onClick
47
+ inactiveBlock();
48
+ }
57
49
  });
58
- const nodeRef = useRef(null);
59
- const activeParentBlock = (target) => {
60
- return findPredecessor(target, parent => {
61
- const ret = parent.classList.contains(classes.levelBlock);
62
- if (ret) {
50
+ const pointerEnterMaskArea = (e, _placement) => {
51
+ if (!isDraggingNode) {
52
+ activeBlock(e.currentTarget, _placement);
53
+ }
54
+ };
55
+ const pointerLeaveMaskArea = (e) => {
56
+ !isDraggingNode && inactiveBlock(e.currentTarget);
57
+ };
58
+ const pointerEnterPredecessor = (e, upLevel) => {
59
+ activeBlock(e.currentTarget, 'parent', upLevel);
60
+ };
61
+ const pointerLeavePredecessor = (e) => {
62
+ inactiveBlock(e.currentTarget);
63
+ };
64
+ const activeBlock = (el, _placement, upLevel = 0) => {
65
+ if (_placement === 'parent') {
66
+ let i = upLevel;
67
+ let parentId = id;
68
+ do {
69
+ const currentNode = nodesMap.get(parentId);
70
+ if (!currentNode._isLast) {
71
+ return;
72
+ }
73
+ parentId = currentNode._parentId;
74
+ } while (--i && parentId);
75
+ overing.current = parentId;
76
+ placement.current = 'after';
77
+ }
78
+ else {
79
+ overing.current = id;
80
+ placement.current = _placement;
81
+ }
82
+ el.dataset.active = 'true';
83
+ _placement !== 'child' && findPredecessor(el, parent => {
84
+ if (parent.classList.contains(treeDndClasses.levelBlock) && !upLevel--) {
63
85
  parent.dataset.active = 'true';
86
+ const parentNode = parent.previousElementSibling;
87
+ if (parentNode && parentNode.classList.contains(classes.node)) {
88
+ parentNode.dataset.active = 'true';
89
+ }
64
90
  return true;
65
91
  }
66
92
  });
67
93
  };
68
- const inactiveParentBlock = () => {
69
- const fn = (el) => {
94
+ const inactiveBlock = (el) => {
95
+ if (el) {
70
96
  el.dataset.active = 'false';
71
- };
72
- fn(containerRef.current);
73
- containerRef.current.querySelectorAll('.' + classes.levelBlock).forEach(fn);
74
- };
75
- const overingMask = (e) => {
76
- if (hasChildren && !expandedSet.has(value)) {
77
- overingTimer.current ||= setTimeout(() => {
78
- toggleExpanded(value);
79
- placement.current === 'after' && inactiveParentBlock();
80
- }, 800);
81
97
  }
82
- };
83
- const leaveMask = () => {
84
- clearTimeout(overingTimer.current);
85
- overingTimer.current = void 0;
86
- };
87
- const onPointerEnter = (e, placement) => {
88
- setOvering(value);
89
- setPlacement(placement);
90
- activeParentBlock(e.currentTarget);
91
- };
92
- const onPointerLeave = () => {
93
- setOvering(void 0);
94
- inactiveParentBlock();
98
+ document.querySelectorAll('.' + treeDndClasses.levelBlock).forEach(el => {
99
+ el.dataset.active = 'false';
100
+ });
101
+ document.querySelectorAll('.' + classes.node).forEach(el => {
102
+ el.dataset.active = 'false';
103
+ });
104
+ overing.current = void 0;
95
105
  };
96
106
  /**
97
107
  * ---------------------------------------------------------------------
98
108
  * 渲染部分
99
109
  */
100
110
  const renderedIndents = useMemo(() => {
101
- return Array(_level).fill(void 0).map((_, i) => _jsx("div", { className: classes.indent, style: { width: indent } }, i));
102
- }, [_level, indent]);
103
- return (_jsxs(_Fragment, { children: [_jsxs("div", { ...props, ref: cloneRef(nodeRef, props.ref), className: clsx(classes.node, props.className), "data-selected": status === 2, "data-read-only": readOnly, "data-disabled": disabled, "data-dragging": dragging === value, ...!showDragHandle && dragHandleProps, onClick: showDragHandle ? onClick : props.onClick, children: [renderedIndents, _jsx(Button, { className: classes.expand, variant: "plain", color: "text.secondary", onClick: e => {
111
+ return Array(_level).fill(void 0).map((_, i) => _jsx("div", { className: classes.indent }, i));
112
+ }, [_level]);
113
+ return (_jsxs(_Fragment, { children: [_jsxs("div", { ...props, ref: cloneRef(nodeRef, props.ref), className: clsx(classes.node, props.className), "data-selected": status === 2, "data-read-only": readOnly, "data-disabled": disabled, "data-dragging": isDraggingNode, onClick: clickHandler, ...!showDragHandle && dragHandleProps, children: [renderedIndents, _jsx(Button, { className: classes.expand, variant: "plain", color: "text.secondary", onClick: e => {
104
114
  e.stopPropagation();
105
- toggleExpanded(value);
115
+ toggleExpanded(id);
106
116
  }, onPointerDown: e => e.stopPropagation(), children: renderExpandIcon
107
- ? renderExpandIcon(value, currentExpanded, [...expandedSet])
117
+ ? renderExpandIcon(id, currentExpanded, [...expandedSet])
108
118
  : hasChildren &&
109
119
  _jsx(Icon, { icon: faChevronRight, className: classes.icon, style: {
110
120
  rotate: currentExpanded ? '90deg' : '0deg'
111
121
  } }) }), _jsxs("div", { className: classes.contentWrap, children: [sortable && showDragHandle &&
112
- _jsx("div", { className: classes.dragHandle, ...dragHandleProps, onClick: e => e.stopPropagation(), children: _jsx(Icon, { icon: faGripVertical }) }), showCheckbox &&
122
+ _jsx("div", { className: treeDndClasses.dragHandle, ...dragHandleProps, onClick: e => e.stopPropagation(), children: _jsx(Icon, { icon: faGripVertical }) }), showCheckbox &&
113
123
  _jsx(Checkbox, { className: classes.checkbox, checked: status === 2, indeterminate: status === 1, onClick: e => {
114
124
  e.stopPropagation();
115
125
  clickHandler();
116
126
  } }), !!prefix &&
117
127
  _jsx("div", { className: classes.prefix, children: prefix }), _jsx("div", { className: classes.label, children: label }), !!suffix &&
118
- _jsx("div", { className: classes.suffix, children: suffix }), typeof dragging !== 'undefined' && dragging !== value &&
119
- _jsxs("div", { className: classes.dragMask, onPointerOver: overingMask, onPointerLeave: leaveMask, children: [_jsx("div", { className: classes.dragMaskPrev, "data-overing": overing === value && placement.current === 'before', onPointerEnter: e => onPointerEnter(e, 'before'), onPointerLeave: onPointerLeave }), (!hasChildren || !expandedSet.has(value)) &&
120
- _jsx("div", { className: classes.dragMaskNext, "data-offset": !hasChildren && isOffsetSatisfied, "data-overing": overing === value && placement.current === 'after', onPointerEnter: e => onPointerEnter(e, 'after'), onPointerLeave: onPointerLeave })] })] })] }), hasChildren &&
121
- _jsx(Collapse, { className: classes.levelBlock, in: currentExpanded, children: Children.map(props.children, child => {
128
+ _jsx("div", { className: classes.suffix, children: suffix })] }), typeof dragging !== 'undefined' &&
129
+ _jsxs("div", { className: treeDndClasses.mask, children: [Array(_level + 1).fill(void 0).map((_, i) => _jsx("div", { className: treeDndClasses.predecessor, ...i && {
130
+ onPointerEnter: e => pointerEnterPredecessor(e, _level + 1 - i),
131
+ onPointerLeave: pointerLeavePredecessor
132
+ } }, i)), _jsxs("div", { className: treeDndClasses.sibling, children: [_jsx("div", { className: treeDndClasses.siblingPrev, onPointerEnter: e => pointerEnterMaskArea(e, 'before'), onPointerLeave: pointerLeaveMaskArea }), _jsx("div", { className: treeDndClasses.siblingNext, onPointerEnter: e => pointerEnterMaskArea(e, 'after'), onPointerLeave: pointerLeaveMaskArea }), !hasChildren &&
133
+ _jsx("div", { className: treeDndClasses.child, onPointerEnter: e => pointerEnterMaskArea(e, 'child'), onPointerLeave: pointerLeaveMaskArea })] })] })] }), hasChildren &&
134
+ _jsx(Collapse, { className: treeDndClasses.levelBlock, in: currentExpanded, children: Children.map(props.children, child => {
122
135
  return isValidElement(child)
123
136
  ? cloneElement(child, { _level: _level + 1 })
124
137
  : child;
@@ -8,8 +8,8 @@ export declare const classes: {
8
8
  file: string;
9
9
  files: string;
10
10
  images: string;
11
- control: string;
12
11
  sortable: string;
12
+ control: string;
13
13
  imageWrap: string;
14
14
  } & {
15
15
  root: string;
@@ -1,13 +1,21 @@
1
1
  import { DragEndEvent } from '@dnd-kit/core';
2
- import { Obj } from '../types';
2
+ import { Id, Obj } from '../types';
3
+ import { NodeType, SortInfo } from '../components/tree';
3
4
  /**
4
5
  * 默认提供给@dnd-kit的sensors属性
5
6
  */
6
7
  export declare function useDndSensors(): import("@dnd-kit/core").SensorDescriptor<import("@dnd-kit/core").SensorOptions>[];
7
8
  /**
8
9
  * <DndContext>组件通用的onDragEnd方法
9
- * @param e
10
+ * @param e 事件
10
11
  * @param prevState 传入需要排序的数组
11
- * @param primaryKey 索引用的主键
12
+ * @param primaryKey 索引用的主键,默认为`id`
12
13
  */
13
14
  export declare function onDndDragEnd<S extends Obj>(e: DragEndEvent, prevState: S[], primaryKey?: string): S[] | undefined;
15
+ /**
16
+ * <Tree>组件通用的onSort方法,注意:该方法会原地修改{@link treeNodes}
17
+ * @param info 信息
18
+ * @param treeNodes 树节点
19
+ * @param primaryKey 索引用的主键,默认为`id`
20
+ */
21
+ export declare function onTreeNodeSort<N extends NodeType<V>, V extends Id = Id>(info: SortInfo<V>, treeNodes: N[], primaryKey?: string): N[];
@@ -12,9 +12,9 @@ export function useDndSensors() {
12
12
  }
13
13
  /**
14
14
  * <DndContext>组件通用的onDragEnd方法
15
- * @param e
15
+ * @param e 事件
16
16
  * @param prevState 传入需要排序的数组
17
- * @param primaryKey 索引用的主键
17
+ * @param primaryKey 索引用的主键,默认为`id`
18
18
  */
19
19
  export function onDndDragEnd(e, prevState, primaryKey = 'id') {
20
20
  const { active, over } = e;
@@ -26,3 +26,45 @@ export function onDndDragEnd(e, prevState, primaryKey = 'id') {
26
26
  const newIndex = prevState.findIndex(v => v[primaryKey] === over.id);
27
27
  return arrayMove(prevState, oldIndex, newIndex);
28
28
  }
29
+ /**
30
+ * <Tree>组件通用的onSort方法,注意:该方法会原地修改{@link treeNodes}
31
+ * @param info 信息
32
+ * @param treeNodes 树节点
33
+ * @param primaryKey 索引用的主键,默认为`id`
34
+ */
35
+ export function onTreeNodeSort(info, treeNodes, primaryKey = 'id') {
36
+ const find = (arr, id) => {
37
+ let target = null;
38
+ let targetIndex = -1;
39
+ let siblings = null;
40
+ const recurse = (arr) => {
41
+ return !!arr?.some((v, i, _siblings) => {
42
+ if (v[primaryKey] === id) {
43
+ target = v;
44
+ targetIndex = i;
45
+ siblings = _siblings;
46
+ return true;
47
+ }
48
+ return v.children?.length && recurse(v.children);
49
+ });
50
+ };
51
+ recurse(arr);
52
+ return target ? { target, targetIndex, siblings: siblings } : null;
53
+ };
54
+ const source = find(treeNodes, info.source);
55
+ source.siblings.splice(source.targetIndex, 1);
56
+ const destination = find(treeNodes, info.destination);
57
+ switch (info.placement) {
58
+ case 'before':
59
+ destination.siblings.splice(destination.targetIndex, 0, source.target);
60
+ break;
61
+ case 'after':
62
+ destination.siblings.splice(destination.targetIndex + 1, 0, source.target);
63
+ break;
64
+ default:
65
+ // children
66
+ destination.target.children ||= [];
67
+ destination.target.children.push(source.target);
68
+ }
69
+ return treeNodes;
70
+ }
@@ -145,5 +145,5 @@ export declare function filterProperties<T extends Record<string, any>>(obj: T,
145
145
  * 合并属性
146
146
  */
147
147
  type ExtendableProps<T> = (T extends ElementType ? ComponentProps<T> : T) & Obj;
148
- export declare function mergeComponentProps<T>(...props: (Partial<ExtendableProps<T>> | undefined)[]): ExtendableProps<T>;
148
+ export declare function mergeComponentProps<T>(...props: (Partial<ExtendableProps<T>> | null | false | undefined)[]): ExtendableProps<T>;
149
149
  export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@canlooks/can-ui",
3
- "version": "0.0.96",
3
+ "version": "0.0.98",
4
4
  "author": "C.CanLiang <canlooks@gmail.com>",
5
5
  "description": "My ui framework",
6
6
  "license": "MIT",