@ticatec/uniface-element 0.1.46 → 0.1.48

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.
@@ -1,41 +1,62 @@
1
1
  export declare function compareNumber(a: number, b: number): 0 | 1 | -1;
2
2
  export type TreeNode<T> = {
3
3
  item: T;
4
- expand: boolean;
4
+ expand?: boolean;
5
5
  children?: TreeNode<T>[];
6
6
  };
7
7
  export type CheckIsRoot<T> = (data: T) => boolean;
8
8
  export type CompareFun<T> = (o1: T, o2: T) => number | undefined;
9
9
  export type GetText<T> = (data: T) => string;
10
+ export type CheckIsDirectory<T> = (node: TreeNode<T>) => boolean;
10
11
  export interface TreeNodeOptions<T> {
11
12
  keyField?: keyof T;
12
13
  textField?: keyof T | GetText<T>;
13
14
  parentKeyField?: keyof T;
14
15
  checkIsRoot: CheckIsRoot<T>;
15
- compareFun: CompareFun<T>;
16
- expendDeep?: number;
16
+ checkIsDirectory?: CheckIsDirectory<T>;
17
+ compareFun?: CompareFun<T>;
18
+ expendDepth?: number;
17
19
  }
18
- export default class TreeNodes<T> {
19
- #private;
20
+ export declare class CommonTreeNodes<T> {
20
21
  protected readonly checkIsRoot: CheckIsRoot<T>;
21
22
  protected readonly keyField: keyof T;
22
23
  protected readonly parentKeyField: keyof T;
23
24
  protected readonly textField: keyof T | GetText<T>;
25
+ protected readonly checkIsDirectory: CheckIsDirectory<T> | undefined;
24
26
  protected nodeMap: Map<any, TreeNode<T>>;
25
- protected compareFun: any;
26
- protected expendDeep: number;
27
+ protected compareFun: any | undefined;
28
+ protected expendDepth: number;
29
+ protected _nodes: Array<TreeNode<T>>;
27
30
  constructor(options: TreeNodeOptions<T>);
28
31
  setData(list: Array<T>): void;
29
- private appendNode;
30
- private collectExpandedNodes;
32
+ /**
33
+ * 获取节点
34
+ */
35
+ get nodes(): Array<TreeNode<T>>;
36
+ /**
37
+ * 设置展开层级
38
+ * @param nodes
39
+ * @param currentLevel
40
+ * @protected
41
+ */
42
+ protected setExpandForDepth(nodes: TreeNode<T>[], currentLevel: number): void;
43
+ /**
44
+ * 添加一个节点
45
+ * @param node
46
+ * @param doSort
47
+ * @protected
48
+ */
49
+ protected appendNode(node: TreeNode<T>, doSort?: boolean): void;
50
+ }
51
+ export default class TreeNodes<T> extends CommonTreeNodes<T> {
31
52
  /**
32
53
  * 获取展开的展示列表
33
54
  */
34
55
  getHierarchyList(): Array<TreeNode<T>>;
35
56
  /**
36
- * 获取节点
57
+ * 给treeview设定数据,根据数据构建树结构
58
+ * @param list
37
59
  */
38
- get nodes(): Array<TreeNode<T>>;
39
60
  /**
40
61
  * 增加一个新节点
41
62
  * @param item
@@ -53,6 +74,15 @@ export default class TreeNodes<T> {
53
74
  * @param parentId
54
75
  */
55
76
  moveTo(item: T, parentId: string): void;
56
- private extractChildrenDirectories;
57
- extractDirectories(exclusiveValue: any): TreeNode<T>[];
77
+ /**
78
+ * 获取除指定节点外的其他节点
79
+ * @param exclusiveData
80
+ */
81
+ extractDirectories(exclusiveData: T): TreeNode<T>[];
82
+ /**
83
+ * 获取所有展开的节点
84
+ * @param tree
85
+ * @private
86
+ */
87
+ private collectExpandedNodes;
58
88
  }
@@ -1,15 +1,16 @@
1
1
  export function compareNumber(a, b) {
2
2
  return a === b ? 0 : a > b ? 1 : -1;
3
3
  }
4
- export default class TreeNodes {
4
+ export class CommonTreeNodes {
5
5
  checkIsRoot;
6
6
  keyField;
7
7
  parentKeyField;
8
8
  textField;
9
+ checkIsDirectory;
9
10
  nodeMap;
10
11
  compareFun;
11
- expendDeep;
12
- #nodes = [];
12
+ expendDepth;
13
+ _nodes = [];
13
14
  constructor(options) {
14
15
  this.checkIsRoot = options.checkIsRoot;
15
16
  this.compareFun = options.compareFun;
@@ -17,16 +18,17 @@ export default class TreeNodes {
17
18
  this.textField = options.textField ?? 'text';
18
19
  this.parentKeyField = options.parentKeyField ?? 'parentId';
19
20
  this.nodeMap = new Map();
20
- this.expendDeep = options.expendDeep ?? 999;
21
+ this.expendDepth = options.expendDepth ?? 1;
22
+ this.checkIsDirectory = options.checkIsDirectory;
21
23
  }
22
24
  setData(list) {
23
25
  this.nodeMap = new Map();
24
- this.#nodes = [];
26
+ this._nodes = [];
25
27
  // 初始化每个节点
26
28
  for (const item of list) {
27
29
  const node = {
28
30
  item,
29
- expand: true
31
+ expand: false
30
32
  };
31
33
  const key = item[this.keyField];
32
34
  this.nodeMap.set(key, node);
@@ -37,12 +39,41 @@ export default class TreeNodes {
37
39
  this.appendNode(node);
38
40
  }
39
41
  }
42
+ if (this.expendDepth > 1) {
43
+ this.setExpandForDepth(this.nodes, 0);
44
+ }
45
+ }
46
+ /**
47
+ * 获取节点
48
+ */
49
+ get nodes() {
50
+ return this._nodes;
40
51
  }
52
+ /**
53
+ * 设置展开层级
54
+ * @param nodes
55
+ * @param currentLevel
56
+ * @protected
57
+ */
58
+ setExpandForDepth(nodes, currentLevel) {
59
+ for (const node of nodes) {
60
+ node.expand = currentLevel < this.expendDepth;
61
+ if (node.children) {
62
+ this.setExpandForDepth(node.children, currentLevel + 1);
63
+ }
64
+ }
65
+ }
66
+ /**
67
+ * 添加一个节点
68
+ * @param node
69
+ * @param doSort
70
+ * @protected
71
+ */
41
72
  appendNode(node, doSort = false) {
42
73
  let item = node.item;
43
74
  const parentKey = item[this.parentKeyField];
44
- if (this.checkIsRoot(item) || !this.nodeMap.has(parentKey)) {
45
- this.#nodes.push(node);
75
+ if (this.checkIsRoot(item)) { //|| !this.nodeMap.has(parentKey)
76
+ this._nodes.push(node);
46
77
  }
47
78
  else {
48
79
  const parentNode = this.nodeMap.get(parentKey);
@@ -53,33 +84,23 @@ export default class TreeNodes {
53
84
  parentNode.children = parentNode.children.sort(this.compareFun);
54
85
  }
55
86
  }
56
- }
57
- }
58
- collectExpandedNodes(tree) {
59
- const result = [];
60
- function traverse(nodes) {
61
- for (const node of nodes) {
62
- result.push(node);
63
- if (node.expand && node.children) {
64
- traverse(node.children);
65
- }
87
+ else {
88
+ console.warn('Ignore the isolate item:', item);
66
89
  }
67
90
  }
68
- traverse(tree);
69
- return result;
70
91
  }
92
+ }
93
+ export default class TreeNodes extends CommonTreeNodes {
71
94
  /**
72
95
  * 获取展开的展示列表
73
96
  */
74
97
  getHierarchyList() {
75
- return this.collectExpandedNodes(this.#nodes);
98
+ return this.collectExpandedNodes(this._nodes);
76
99
  }
77
100
  /**
78
- * 获取节点
101
+ * 给treeview设定数据,根据数据构建树结构
102
+ * @param list
79
103
  */
80
- get nodes() {
81
- return this.#nodes;
82
- }
83
104
  /**
84
105
  * 增加一个新节点
85
106
  * @param item
@@ -140,33 +161,42 @@ export default class TreeNodes {
140
161
  }
141
162
  }
142
163
  }
143
- extractChildrenDirectories(node, exclusiveValue) {
144
- if (node.children && node.item[this.keyField] != exclusiveValue) {
145
- let newNode = {
146
- item: node.item,
147
- expand: true,
148
- children: []
149
- };
150
- for (let childNode of node.children) {
151
- let ncNode = this.extractChildrenDirectories(childNode, exclusiveValue);
152
- if (ncNode) {
153
- newNode.children?.push(ncNode);
164
+ /**
165
+ * 获取除指定节点外的其他节点
166
+ * @param exclusiveData
167
+ */
168
+ extractDirectories(exclusiveData) {
169
+ const getNodes = (nodes, item) => {
170
+ let list = [];
171
+ for (let node of nodes) {
172
+ if (node.item != item && this.checkIsDirectory?.(node)) {
173
+ list.push({
174
+ item: node.item,
175
+ expand: true,
176
+ children: getNodes(node.children ?? [], item)
177
+ });
154
178
  }
155
179
  }
156
- return newNode;
157
- }
158
- else {
159
- return;
160
- }
180
+ return list;
181
+ };
182
+ return getNodes(this.nodes, exclusiveData);
161
183
  }
162
- extractDirectories(exclusiveValue) {
163
- let dirNodes = [];
164
- for (let node of this.nodes) {
165
- let newNode = this.extractChildrenDirectories(node, exclusiveValue);
166
- if (newNode) {
167
- dirNodes.push(newNode);
184
+ /**
185
+ * 获取所有展开的节点
186
+ * @param tree
187
+ * @private
188
+ */
189
+ collectExpandedNodes(tree) {
190
+ const result = [];
191
+ function traverse(nodes) {
192
+ for (const node of nodes) {
193
+ result.push(node);
194
+ if (node.expand && node.children) {
195
+ traverse(node.children);
196
+ }
168
197
  }
169
198
  }
170
- return dirNodes;
199
+ traverse(tree);
200
+ return result;
171
201
  }
172
202
  }
@@ -0,0 +1,9 @@
1
+ import TreeNodes from "./TreeNodes";
2
+ import type { TreeNode } from "./TreeNodes";
3
+ import { CommonTreeNodes } from "./TreeNodes";
4
+ import type { CheckIsRoot, CompareFun, GetText, CheckIsDirectory, TreeNodeOptions } from "./TreeNodes";
5
+ import { compareNumber } from "./TreeNodes";
6
+ export default TreeNodes;
7
+ export { CommonTreeNodes, compareNumber };
8
+ export type { TreeNode };
9
+ export type { CheckIsRoot, CompareFun, GetText, CheckIsDirectory, TreeNodeOptions };
@@ -0,0 +1,5 @@
1
+ import TreeNodes from "./TreeNodes";
2
+ import { CommonTreeNodes } from "./TreeNodes";
3
+ import { compareNumber } from "./TreeNodes";
4
+ export default TreeNodes;
5
+ export { CommonTreeNodes, compareNumber };
@@ -1,27 +1,4 @@
1
- export default interface MenuItem {
2
- /**
3
- * 菜单编码
4
- */
5
- code?: string;
6
- /**
7
- * 菜单文字
8
- */
9
- text: string;
10
- /**
11
- * 用于i18n的key
12
- */
13
- key?: string;
14
- /**
15
- * 绑定数据,用户处理,通常为uri的跳转地址
16
- */
17
- data?: any;
18
- /**
19
- * 子菜单项
20
- */
21
- children?: Array<MenuItem>;
22
- /**
23
- * 是否打开
24
- */
25
- expand?: boolean;
1
+ import type { TreeNode } from "../lib/TreeNodes";
2
+ export default interface MenuItem extends TreeNode<any> {
26
3
  }
27
4
  export type OnMenuClick = (item: MenuItem) => void;
@@ -0,0 +1,8 @@
1
+ import { CommonTreeNodes } from "../lib/TreeNodes";
2
+ import type MenuItem from "./MenuItem";
3
+ export default class Menus extends CommonTreeNodes<MenuItem> {
4
+ /**
5
+ * 删除所有没有子节点的目录类型节点
6
+ */
7
+ removeEmptyDirectory(): void;
8
+ }
@@ -0,0 +1,23 @@
1
+ import { CommonTreeNodes } from "../lib/TreeNodes";
2
+ export default class Menus extends CommonTreeNodes {
3
+ /**
4
+ * 删除所有没有子节点的目录类型节点
5
+ */
6
+ removeEmptyDirectory() {
7
+ const removeRecursive = (nodes) => {
8
+ for (let i = nodes.length - 1; i >= 0; i--) {
9
+ const node = nodes[i];
10
+ if (node.children && node.children.length > 0) {
11
+ removeRecursive(node.children); // 先处理子节点
12
+ }
13
+ else {
14
+ if (this.checkIsDirectory?.(node)) {
15
+ nodes.splice(i, 1); // 从父节点的 children 中移除
16
+ this.nodeMap.delete(node.item[this.keyField]); // 从 nodeMap 中移除
17
+ }
18
+ }
19
+ }
20
+ };
21
+ removeRecursive(this._nodes);
22
+ }
23
+ }
@@ -2,20 +2,25 @@
2
2
  import type MenuItem from "./MenuItem";
3
3
  import type {OnMenuClick} from "./MenuItem";
4
4
  import NavigatorMenuItem from "./NavigatorMenuItem.svelte";
5
+ import type {GetText} from "../lib/TreeNodes";
5
6
 
6
7
  export let menuItems: Array<MenuItem>;
7
8
  export let style: string = '';
9
+
10
+ export let textField: string | GetText<MenuItem>;
11
+
8
12
  export let onItemClick: OnMenuClick;
9
13
 
10
14
 
15
+
11
16
  </script>
12
17
 
13
18
 
14
19
  <div class="uniface-navigator-menu-panel" {style}>
15
20
  {#if menuItems && menuItems.length > 0}
16
21
  <ul>
17
- {#each menuItems as item}
18
- <NavigatorMenuItem {item} onMenuItemClick={onItemClick} expand={item.expand}/>
22
+ {#each menuItems as menu}
23
+ <NavigatorMenuItem {menu} onMenuItemClick={onItemClick} {textField}/>
19
24
  {/each}
20
25
  </ul>
21
26
  {/if}
@@ -1,5 +1,6 @@
1
1
  import type MenuItem from "./MenuItem";
2
2
  import type { OnMenuClick } from "./MenuItem";
3
+ import type { GetText } from "../lib/TreeNodes";
3
4
  interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
4
5
  new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
5
6
  $$bindings?: Bindings;
@@ -16,6 +17,7 @@ interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> =
16
17
  declare const NavigatorMenu: $$__sveltets_2_IsomorphicComponent<{
17
18
  menuItems: Array<MenuItem>;
18
19
  style?: string;
20
+ textField: string | GetText<MenuItem>;
19
21
  onItemClick: OnMenuClick;
20
22
  }, {
21
23
  [evt: string]: CustomEvent<any>;
@@ -3,19 +3,17 @@
3
3
  import {slide} from "svelte/transition";
4
4
  import type MenuItem from "./MenuItem";
5
5
  import type {OnMenuClick} from "./MenuItem";
6
- import i18n from "@ticatec/i18n";
6
+ import type {GetText} from "../lib/TreeNodes";
7
7
 
8
- export let item: MenuItem;
9
- export let expand: boolean = false;
10
-
11
- export let onMenuItemClick: OnMenuClick;
8
+ export let menu: MenuItem;
9
+ export let textField: string | GetText<MenuItem>;
12
10
 
11
+ let expand: boolean = menu.expand == true;
13
12
 
14
- let expandable: boolean;
13
+ export let onMenuItemClick: OnMenuClick;
15
14
 
16
- $: {
17
- expandable = item.children != null && item.children.length > 0
18
- }
15
+ $: expandable = menu.children != null && menu.children.length > 0
16
+ $: menuText = typeof textField == 'string' ? menu.item?.[textField]??'Unknown item' : textField(menu.item);
19
17
 
20
18
  let respond: boolean = true;
21
19
  const handleMenuItemClick = () => {
@@ -23,10 +21,10 @@
23
21
  respond = false;
24
22
  setTimeout(() => respond = true, 200);
25
23
  if (expandable) {
26
- item.expand = !item.expand;
24
+ menu.expand = !menu.expand;
27
25
  expand = !expand;
28
26
  } else {
29
- onMenuItemClick?.(item);
27
+ onMenuItemClick?.(menu);
30
28
  }
31
29
  }
32
30
 
@@ -34,12 +32,12 @@
34
32
 
35
33
  </script>
36
34
  <li class:expandable class:fold={!expand}>
37
- <span on:click={handleMenuItemClick} aria-hidden="true">{item.key ? i18n.getText(item.key, item.text) : item.text}</span>
38
- {#if item.children}
35
+ <span on:click={handleMenuItemClick} aria-hidden="true">{menuText}</span>
36
+ {#if menu.children}
39
37
  {#if expand}
40
38
  <ul transition:slide={{duration: 200}}>
41
- {#each item.children as el}
42
- <svelte:self item={el} {onMenuItemClick}/>
39
+ {#each menu.children as el}
40
+ <svelte:self menu={el} {onMenuItemClick} {textField}/>
43
41
  {/each}
44
42
  </ul>
45
43
  {/if}
@@ -1,5 +1,6 @@
1
1
  import type MenuItem from "./MenuItem";
2
2
  import type { OnMenuClick } from "./MenuItem";
3
+ import type { GetText } from "../lib/TreeNodes";
3
4
  interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
4
5
  new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
5
6
  $$bindings?: Bindings;
@@ -14,8 +15,8 @@ interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> =
14
15
  z_$$bindings?: Bindings;
15
16
  }
16
17
  declare const NavigatorMenuItem: $$__sveltets_2_IsomorphicComponent<{
17
- item: MenuItem;
18
- expand?: boolean;
18
+ menu: MenuItem;
19
+ textField: string | GetText<MenuItem>;
19
20
  onMenuItemClick: OnMenuClick;
20
21
  }, {
21
22
  [evt: string]: CustomEvent<any>;
@@ -1,5 +1,7 @@
1
1
  import NavigatorMenu from "./NavigatorMenu.svelte";
2
2
  import type MenuItem from "./MenuItem";
3
3
  import type { OnMenuClick } from "./MenuItem";
4
+ import Menus from "./Menus";
4
5
  export default NavigatorMenu;
5
6
  export type { MenuItem, OnMenuClick };
7
+ export { Menus };
@@ -1,2 +1,4 @@
1
1
  import NavigatorMenu from "./NavigatorMenu.svelte";
2
+ import Menus from "./Menus";
2
3
  export default NavigatorMenu;
4
+ export { Menus };
@@ -1,25 +1,26 @@
1
1
  <script lang="ts">
2
- import type TreeNode from "./TreeNode";
3
- import type {LazyLoader, NodeVisibleFun, OnNodeSelectionChange} from "./TreeNode";
2
+
3
+ import type {LazyLoader, NodeVisibleFun, OnNodeSelectionChange} from "./Types";
4
4
  import iconLoading from "../assets/loading.gif"
5
5
  import utils from "../common/utils";
6
6
  import type {OnContextMenu} from "../context-menu/ContextMenuItem";
7
+ import type {CheckIsDirectory, GetText, TreeNode} from "../lib/TreeNodes";
7
8
 
8
- export let node: TreeNode;
9
+ export let node: TreeNode<any>;
10
+ export let textField: string | GetText<any>;
9
11
  export let lazyLoader: LazyLoader | null;
10
12
  export let activeNode: any;
11
13
  export let isVisible: NodeVisibleFun;
12
- export let level: number = 1;
13
- export let dispLevels: number = 1;
14
14
  export let onContextMenu: OnContextMenu;
15
15
  export let onNodeSelectionChange: OnNodeSelectionChange;
16
16
 
17
+ export let checkIsDirectory: CheckIsDirectory<TreeNode<any>>;
17
18
 
18
- let expanded: boolean = dispLevels <= level;
19
19
  let loading: boolean = false;
20
20
 
21
- const isBranch = () => {
22
- return lazyLoader == null ? (node.children && node.children.length > 0) : lazyLoader.isBranch(node);
21
+ const isDirectory = () => {
22
+ console.log('检测目录函数', checkIsDirectory);
23
+ return lazyLoader == null ? checkIsDirectory?.(node) : lazyLoader.isBranch(node);
23
24
  }
24
25
 
25
26
  const loadChildren = async () => {
@@ -38,11 +39,13 @@
38
39
  e.preventDefault();
39
40
  if (respond) {
40
41
  respond = false;
41
- if (isBranch()) {
42
- expanded = !expanded;
43
- await loadChildren();
42
+ if (isDirectory()) {
43
+ if (!node.children) {
44
+ node.expand = false;
45
+ await loadChildren();
46
+ }
47
+ node.expand = !node.expand;
44
48
  }
45
- dispLevels = expanded ? level + 1 : level;
46
49
  await utils.sleep(0.2);
47
50
  respond = true;
48
51
  }
@@ -58,7 +61,6 @@
58
61
  }
59
62
  }
60
63
 
61
- $: expanded = dispLevels > level;
62
64
 
63
65
  const handleContextMenu = (event: MouseEvent) => {
64
66
  onContextMenu?.(event, node);
@@ -68,25 +70,25 @@
68
70
 
69
71
 
70
72
  {#if isVisible == null || isVisible(node)}
71
- <div class="tree-node" class:expanded>
73
+ <div class="tree-node" class:expanded={node.expand}>
72
74
  <div class="node-item" class:selected={activeNode===node} on:click={handleNodeClick} aria-hidden="true"
73
75
  on:contextmenu={handleContextMenu}>
74
76
  <div class="item-icon">
75
- {#if isBranch()}
77
+ {#if isDirectory()}
76
78
  {#if loading}
77
79
  <img alt="" style="cursor: default" src={iconLoading}/>
78
80
  {:else }
79
- <span aria-hidden="true" on:click={handleNodeIconClick}>{expanded ? '▼' : '▶'}</span>
81
+ <span aria-hidden="true" on:click={handleNodeIconClick}>{node.expand ? '▼' : '▶'}</span>
80
82
  {/if}
81
83
  {/if}
82
84
  </div>
83
- <span class="item-text">{node.text}</span>
85
+ <span class="item-text">{typeof textField == "string" ? node.item[textField] : textField(node.item)}</span>
84
86
  </div>
85
- {#if expanded && node.children}
87
+ {#if node.expand && node.children}
86
88
  <div class="sub-tree">
87
89
  {#each node.children as child}
88
- <svelte:self node={child} {lazyLoader} {onContextMenu}
89
- {dispLevels} {isVisible} level={level+1} {activeNode} {onNodeSelectionChange}/>
90
+ <svelte:self node={child} {lazyLoader} {onContextMenu} {textField} {checkIsDirectory}
91
+ {isVisible} {activeNode} {onNodeSelectionChange}/>
90
92
  {/each}
91
93
  </div>
92
94
  {/if}
@@ -1,6 +1,6 @@
1
- import type TreeNode from "./TreeNode";
2
- import type { LazyLoader, NodeVisibleFun, OnNodeSelectionChange } from "./TreeNode";
1
+ import type { LazyLoader, NodeVisibleFun, OnNodeSelectionChange } from "./Types";
3
2
  import type { OnContextMenu } from "../context-menu/ContextMenuItem";
3
+ import type { CheckIsDirectory, GetText, TreeNode } from "../lib/TreeNodes";
4
4
  interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
5
5
  new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
6
6
  $$bindings?: Bindings;
@@ -15,14 +15,14 @@ interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> =
15
15
  z_$$bindings?: Bindings;
16
16
  }
17
17
  declare const TreeNodeView: $$__sveltets_2_IsomorphicComponent<{
18
- node: TreeNode;
18
+ node: TreeNode<any>;
19
+ textField: string | GetText<any>;
19
20
  lazyLoader: LazyLoader | null;
20
21
  activeNode: any;
21
22
  isVisible: NodeVisibleFun;
22
- level?: number;
23
- dispLevels?: number;
24
23
  onContextMenu: OnContextMenu;
25
24
  onNodeSelectionChange: OnNodeSelectionChange;
25
+ checkIsDirectory: CheckIsDirectory<TreeNode<any>>;
26
26
  }, {
27
27
  [evt: string]: CustomEvent<any>;
28
28
  }, {}, {}, string>;
@@ -1,12 +1,14 @@
1
1
  <script lang="ts">
2
2
 
3
- import type TreeNode from "./TreeNode";
4
- import type {LazyLoader, NodeVisibleFun, OnNodeSelectionChange} from "./TreeNode";
3
+
4
+ import type {LazyLoader, NodeVisibleFun, OnNodeSelectionChange} from "./Types";
5
5
  import TreeNodeView from "./TreeNodeView.svelte";
6
6
  import type {OnContextMenu} from "../context-menu/ContextMenuItem";
7
+ import type {CheckIsDirectory, GetText, TreeNode} from "../lib/TreeNodes";
7
8
 
8
9
 
9
- export let nodes: Array<TreeNode>;
10
+ export let nodes: Array<TreeNode<any>>;
11
+ export let textField: string | GetText<any>;
10
12
  export let style: string = "";
11
13
  export let lazyLoader: LazyLoader | null = null;
12
14
  export let activeNode: any = null;
@@ -14,10 +16,10 @@
14
16
  export let isVisible: NodeVisibleFun = null as unknown as NodeVisibleFun;
15
17
  export let onSelectionChange: OnNodeSelectionChange = null as unknown as OnNodeSelectionChange;
16
18
  export let onContextMenu: OnContextMenu = null as unknown as OnContextMenu;
17
-
19
+ export let checkIsDirectory: CheckIsDirectory<any>;
18
20
  let className: string = "";
19
21
 
20
- const onNodeSelectionChange = async (node: TreeNode): Promise<boolean> => {
22
+ const onNodeSelectionChange = async (node: TreeNode<any>): Promise<boolean> => {
21
23
  let accept: boolean = (await onSelectionChange?.(node));
22
24
  accept = accept == null ? true : accept;
23
25
  if (accept == null || accept == true) {
@@ -30,7 +32,7 @@
30
32
  <div class="uniface-tree-view {className}" {style}>
31
33
  <div>
32
34
  {#each nodes as node}
33
- <TreeNodeView {activeNode} {node} {lazyLoader} {isVisible} {onNodeSelectionChange} {onContextMenu}/>
35
+ <TreeNodeView {activeNode} {node} {textField} {lazyLoader} {onNodeSelectionChange} {isVisible} {checkIsDirectory} {onContextMenu}/>
34
36
  {/each}
35
37
  </div>
36
38
  </div>
@@ -1,6 +1,6 @@
1
- import type TreeNode from "./TreeNode";
2
- import type { LazyLoader, NodeVisibleFun, OnNodeSelectionChange } from "./TreeNode";
1
+ import type { LazyLoader, NodeVisibleFun, OnNodeSelectionChange } from "./Types";
3
2
  import type { OnContextMenu } from "../context-menu/ContextMenuItem";
3
+ import type { CheckIsDirectory, GetText, TreeNode } from "../lib/TreeNodes";
4
4
  interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
5
5
  new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
6
6
  $$bindings?: Bindings;
@@ -15,7 +15,8 @@ interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> =
15
15
  z_$$bindings?: Bindings;
16
16
  }
17
17
  declare const TreeView: $$__sveltets_2_IsomorphicComponent<{
18
- nodes: Array<TreeNode>;
18
+ nodes: Array<TreeNode<any>>;
19
+ textField: string | GetText<any>;
19
20
  style?: string;
20
21
  lazyLoader?: LazyLoader | null;
21
22
  activeNode?: any;
@@ -23,6 +24,7 @@ declare const TreeView: $$__sveltets_2_IsomorphicComponent<{
23
24
  isVisible?: NodeVisibleFun;
24
25
  onSelectionChange?: OnNodeSelectionChange;
25
26
  onContextMenu?: OnContextMenu;
27
+ checkIsDirectory: CheckIsDirectory<any>;
26
28
  }, {
27
29
  [evt: string]: CustomEvent<any>;
28
30
  }, {}, {
@@ -0,0 +1,23 @@
1
+ import type { CheckIsDirectory, TreeNode } from "../lib/TreeNodes";
2
+ export type OnNodeSelectionChange = (node: TreeNode<any>) => Promise<boolean>;
3
+ /**
4
+ * 节点是否显示
5
+ */
6
+ export type NodeVisibleFun = (node: TreeNode<any>) => boolean;
7
+ /**
8
+ * 加载子节点
9
+ */
10
+ export type LoadChildrenFun = (item: TreeNode<any>) => Promise<Array<TreeNode<any>>>;
11
+ /**
12
+ * 按需数据加载器
13
+ */
14
+ export interface LazyLoader {
15
+ /**
16
+ * 检查是否是枝节点
17
+ */
18
+ isBranch: CheckIsDirectory<any>;
19
+ /**
20
+ * 数据加载器
21
+ */
22
+ load: LoadChildrenFun;
23
+ }
@@ -1,7 +1,4 @@
1
1
  import TreeView from "./TreeView.svelte";
2
- import type TreeNode from "./TreeNode";
3
- import type { LazyLoader, NodeVisibleFun, OnNodeSelectionChange, CheckBranchFun, LoadChildrenFun, NodeLevelCompare, RootDetermine } from "./TreeNode";
4
- import treeUtils from "./TreeUtils";
2
+ import type { LazyLoader, NodeVisibleFun, OnNodeSelectionChange, LoadChildrenFun } from "./Types";
5
3
  export default TreeView;
6
- export { treeUtils };
7
- export type { TreeNode, LazyLoader, NodeVisibleFun, OnNodeSelectionChange, CheckBranchFun, LoadChildrenFun, NodeLevelCompare, RootDetermine };
4
+ export type { LazyLoader, NodeVisibleFun, OnNodeSelectionChange, LoadChildrenFun };
@@ -1,4 +1,2 @@
1
1
  import TreeView from "./TreeView.svelte";
2
- import treeUtils from "./TreeUtils";
3
2
  export default TreeView;
4
- export { treeUtils };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ticatec/uniface-element",
3
- "version": "0.1.46",
3
+ "version": "0.1.48",
4
4
  "description": "uniface web elements",
5
5
  "scripts": {
6
6
  "dev": "vite dev",
@@ -292,6 +292,10 @@
292
292
  "types": "./dist/tabs/index.d.ts",
293
293
  "import": "./dist/tabs/index.js"
294
294
  },
295
+ "./TreeNodes": {
296
+ "types": "./dist/lib/index.d.ts",
297
+ "import": "./dist/lib/index.js"
298
+ },
295
299
  "./Tag": {
296
300
  "types": "./dist/tag/index.d.ts",
297
301
  "import": "./dist/tag/index.js"
@@ -1,60 +0,0 @@
1
- export type OnNodeSelectionChange = (node: TreeNode) => Promise<boolean>;
2
- export default interface TreeNode {
3
- /**
4
- * 节点的值
5
- */
6
- value: string;
7
- /**
8
- * 节点的文字
9
- */
10
- text: string;
11
- /**
12
- * 对应节点的数据
13
- */
14
- data?: any;
15
- /**
16
- * 子节点
17
- */
18
- children?: Array<TreeNode> | null;
19
- /**
20
- * 父节点
21
- */
22
- parent?: TreeNode | null;
23
- /**
24
- * 是否是叶节点
25
- */
26
- isLeaf?: boolean;
27
- }
28
- /**
29
- * 节点是否显示
30
- */
31
- export type NodeVisibleFun = (node: TreeNode) => boolean;
32
- /**
33
- * 检查当前是否是叶节点
34
- */
35
- export type CheckBranchFun = (item: TreeNode) => boolean;
36
- /**
37
- * 加载子节点
38
- */
39
- export type LoadChildrenFun = (item: TreeNode) => Promise<Array<TreeNode>>;
40
- /**
41
- * 按需数据加载器
42
- */
43
- export interface LazyLoader {
44
- /**
45
- * 检查是否是枝节点
46
- */
47
- isBranch: CheckBranchFun;
48
- /**
49
- * 数据加载器
50
- */
51
- load: LoadChildrenFun;
52
- }
53
- /**
54
- * 判断是否是根节点
55
- */
56
- export type RootDetermine = (item: any) => boolean;
57
- /**
58
- * 层级排序
59
- */
60
- export type NodeLevelCompare = (e1: any, e2: any) => number;
@@ -1,6 +0,0 @@
1
- import type TreeNode from "./TreeNode";
2
- import type { NodeLevelCompare, RootDetermine } from "./TreeNode";
3
- declare const _default: {
4
- buildTreeNode: (list: Array<any>, idKey: string, joinKey: string, textField: string, valueField?: string, isRoot?: RootDetermine, sortFun?: NodeLevelCompare) => Array<TreeNode>;
5
- };
6
- export default _default;
@@ -1,53 +0,0 @@
1
- /**
2
- * 将一个数组转换成树状结构
3
- * @param list 待转换的数组
4
- * @param idKey 元素的主键
5
- * @param joinKey 父子间连接字段
6
- * @param valueField 取值的字段
7
- * @param textField 显示文字的字段
8
- * @param isRoot 判断是否是根节点,如果函数不存在,通过连接字段查询,无法获取到父节点就是根节点
9
- * @param sortFun 比较函数,用于曾经排序
10
- */
11
- const buildTreeNode = (list, idKey, joinKey, textField, valueField, isRoot, sortFun) => {
12
- if (sortFun != null) {
13
- list = list.sort(sortFun);
14
- }
15
- let nodes = [];
16
- let map = new Map();
17
- list.forEach(item => {
18
- let node = { value: item[valueField ?? idKey], text: item[textField], data: item };
19
- if (isRoot != null) {
20
- if (isRoot(item)) {
21
- nodes.push(node);
22
- map.set(item[idKey], node);
23
- }
24
- else {
25
- let parent = map.get(item[joinKey]);
26
- if (parent != null) {
27
- parent.children = [...(parent.children ?? []), node];
28
- node.parent = parent;
29
- map.set(item[idKey], node);
30
- }
31
- else {
32
- console.warn('Isolated node:', item);
33
- }
34
- }
35
- }
36
- else {
37
- let parent = map.get(item[joinKey]);
38
- if (parent != null) {
39
- parent.children = [...(parent.children ?? []), item];
40
- node.parent = parent;
41
- map.set(item[idKey], node);
42
- }
43
- else {
44
- nodes.push(node);
45
- map.set(item[idKey], node);
46
- }
47
- }
48
- });
49
- return nodes;
50
- };
51
- export default {
52
- buildTreeNode
53
- };
File without changes