@apia/tree 2.0.9 → 2.0.11

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 (54) hide show
  1. package/dist/OOTree/OOTreeChildren.d.ts +14 -0
  2. package/dist/OOTree/OOTreeChildren.d.ts.map +1 -0
  3. package/dist/OOTree/OOTreeChildren.js +17 -0
  4. package/dist/OOTree/OOTreeChildren.js.map +1 -0
  5. package/dist/OOTree/OOTreeNode.d.ts +30 -0
  6. package/dist/OOTree/OOTreeNode.d.ts.map +1 -0
  7. package/dist/OOTree/OOTreeNode.js +133 -0
  8. package/dist/OOTree/OOTreeNode.js.map +1 -0
  9. package/dist/OOTree/index.d.ts +36 -0
  10. package/dist/OOTree/index.d.ts.map +1 -0
  11. package/dist/OOTree/index.js +126 -0
  12. package/dist/OOTree/index.js.map +1 -0
  13. package/dist/OOTree/types.d.ts +11 -0
  14. package/dist/OOTree/types.d.ts.map +1 -0
  15. package/dist/SearchLabel.js +31 -0
  16. package/dist/SearchLabel.js.map +1 -0
  17. package/dist/Tree.d.ts +7 -0
  18. package/dist/Tree.d.ts.map +1 -0
  19. package/dist/Tree.js +131 -0
  20. package/dist/Tree.js.map +1 -0
  21. package/dist/TreeContext.d.ts +13 -0
  22. package/dist/TreeContext.d.ts.map +1 -0
  23. package/dist/TreeContext.js +22 -0
  24. package/dist/TreeContext.js.map +1 -0
  25. package/dist/TreeDataController.d.ts +116 -0
  26. package/dist/TreeDataController.d.ts.map +1 -0
  27. package/dist/TreeDataController.js +616 -0
  28. package/dist/TreeDataController.js.map +1 -0
  29. package/dist/TreeItem.js +51 -0
  30. package/dist/TreeItem.js.map +1 -0
  31. package/dist/TreeItemChildren.js +20 -0
  32. package/dist/TreeItemChildren.js.map +1 -0
  33. package/dist/TreeItemLabel.js +72 -0
  34. package/dist/TreeItemLabel.js.map +1 -0
  35. package/dist/getDomProps.js +37 -0
  36. package/dist/getDomProps.js.map +1 -0
  37. package/dist/index.d.ts +7 -417
  38. package/dist/index.js +6 -1546
  39. package/dist/index.js.map +1 -1
  40. package/dist/renderers/DefaultIconRenderer.js +18 -0
  41. package/dist/renderers/DefaultIconRenderer.js.map +1 -0
  42. package/dist/renderers/DefaultLabelRenderer.js +10 -0
  43. package/dist/renderers/DefaultLabelRenderer.js.map +1 -0
  44. package/dist/renderers/Spacer.js +10 -0
  45. package/dist/renderers/Spacer.js.map +1 -0
  46. package/dist/types.d.ts +211 -0
  47. package/dist/types.d.ts.map +1 -0
  48. package/dist/useTreeData.d.ts +25 -0
  49. package/dist/useTreeData.d.ts.map +1 -0
  50. package/dist/useTreeData.js +131 -0
  51. package/dist/useTreeData.js.map +1 -0
  52. package/dist/util.js +220 -0
  53. package/dist/util.js.map +1 -0
  54. package/package.json +6 -6
package/dist/index.js CHANGED
@@ -1,1547 +1,7 @@
1
- import { jsx, jsxs, Fragment } from '@apia/theme/jsx-runtime';
2
- import { useMount as useMount$1, useDebounceFn, useUnmount } from 'ahooks';
3
- import React, { useState, useEffect, memo } from 'react';
4
- import { shallowEqual as shallowEqual$1 } from 'react-redux';
5
- import { makeStyledComponent, Spinner, getVariant, Box } from '@apia/theme';
6
- import { EventEmitter, PropsStore, addBoundary, getSpecificParent, usePropsSelector, useLatest, useMount, shallowEqual, formatMessage } from '@apia/util';
7
- import { IconButton } from '@apia/components';
8
- import { Icon } from '@apia/icons';
9
- import uniqueId from 'lodash-es/uniqueId';
10
-
11
- const getLastVisibleChild = (handler, id, avoidFiltered) => {
12
- const nodeProps = handler.propsStore.getFieldProps(id);
13
- if (id !== "root" && (nodeProps.isDisabled || !nodeProps.isExpanded) || nodeProps.children.length === 0)
14
- return null;
15
- for (let i = nodeProps.children.length - 1; i >= 0; i--) {
16
- const currentId = nodeProps.children[i];
17
- const currentProps = handler.propsStore.getFieldProps(currentId);
18
- if (!currentProps.isFiltered) {
19
- const lastChildrenLastChildren = getLastVisibleChild(
20
- handler,
21
- currentId);
22
- return lastChildrenLastChildren !== null ? lastChildrenLastChildren : currentId;
23
- }
24
- }
25
- return null;
26
- };
27
- const getPreviousChild = (handler, id, avoidFiltered) => {
28
- const nodeProps = handler.propsStore.getFieldProps(id);
29
- const fatherProps = handler.propsStore.getFieldProps(nodeProps.parentId);
30
- let childPosition = fatherProps.children?.findIndex((current) => current === nodeProps.id) ?? -1;
31
- while (childPosition > 0) {
32
- const prevSibling = handler.propsStore.getFieldProps(
33
- fatherProps.children[childPosition - 1]
34
- );
35
- const prevSiblingLastChild = getLastVisibleChild(
36
- handler,
37
- prevSibling.id);
38
- if (prevSiblingLastChild !== null)
39
- return prevSiblingLastChild;
40
- if (!prevSibling.isFiltered)
41
- return prevSibling.id;
42
- childPosition--;
43
- }
44
- if (nodeProps.parentId === "root")
45
- return null;
46
- return nodeProps.parentId;
47
- };
48
- const getFirstNonFilteredChild = (handler, id) => {
49
- const nodeProps = handler.propsStore.getFieldProps(id);
50
- for (const child of nodeProps.children) {
51
- if (!handler.propsStore.getFieldProps(child).isFiltered)
52
- return child;
53
- }
54
- return null;
55
- };
56
- const getNextChild = (handler, id, avoidChildren, avoidFiltered) => {
57
- const nodeProps = handler.propsStore.getFieldProps(id);
58
- const fatherProps = handler.propsStore.getFieldProps(nodeProps.parentId);
59
- let childPosition = fatherProps.children?.findIndex((current) => current === nodeProps.id) ?? Infinity;
60
- if (!avoidChildren && nodeProps.isExpanded) {
61
- const firstNonFilteredChild = getFirstNonFilteredChild(
62
- handler,
63
- nodeProps.id
64
- );
65
- if (firstNonFilteredChild !== null)
66
- return firstNonFilteredChild;
67
- }
68
- while (childPosition < fatherProps.children.length - 1) {
69
- const nextSibling = fatherProps.children[childPosition + 1];
70
- if (!handler.propsStore.getFieldProps(nextSibling).isFiltered)
71
- return nextSibling;
72
- childPosition++;
73
- }
74
- if (nodeProps.parentId === "root")
75
- return null;
76
- return getNextChild(handler, fatherProps.id, true);
77
- };
78
- const getNextNodeWithKey = (handler, id, firstKey, avoidFiltered) => {
79
- let nextChildWithKey = id;
80
- do {
81
- nextChildWithKey = getNextChild(
82
- handler,
83
- nextChildWithKey,
84
- false);
85
- if (nextChildWithKey !== null) {
86
- const nodeProps2 = handler.propsStore.getFieldProps(nextChildWithKey);
87
- if ((!nodeProps2.isFiltered || !avoidFiltered) && nodeProps2.label.toUpperCase().startsWith(firstKey.toUpperCase()))
88
- return nextChildWithKey;
89
- }
90
- } while (nextChildWithKey !== null);
91
- const nodeProps = handler.propsStore.getFieldProps(id);
92
- const positionInParent = handler.propsStore.getFieldProps(nodeProps.parentId).children.findIndex((current) => current === id);
93
- if (nodeProps.parentId !== "root" || positionInParent > 0) {
94
- const [firstChildOfTree] = handler.propsStore.getFieldProps("root").children;
95
- const firstChildProps = handler.propsStore.getFieldProps(firstChildOfTree);
96
- if (firstChildOfTree && (!firstChildProps.isFiltered) && firstChildProps.label.toUpperCase().startsWith(firstKey.toUpperCase()))
97
- return firstChildOfTree;
98
- nextChildWithKey = firstChildOfTree;
99
- do {
100
- nextChildWithKey = getNextChild(
101
- handler,
102
- nextChildWithKey,
103
- false);
104
- if (nextChildWithKey) {
105
- const currentNodeProps = handler.propsStore.getFieldProps(nextChildWithKey);
106
- if ((!currentNodeProps.isFiltered) && currentNodeProps.label.toUpperCase().startsWith(firstKey.toUpperCase()))
107
- return nextChildWithKey;
108
- }
109
- } while (nextChildWithKey !== id && nextChildWithKey !== null);
110
- }
111
- return null;
112
- };
113
- const getNodePath = (handler, nodeId) => {
114
- const path = [nodeId];
115
- let currentStep = nodeId;
116
- do {
117
- currentStep = handler.propsStore.getFieldProps(currentStep).parentId;
118
- path.unshift(currentStep);
119
- } while (currentStep !== "root");
120
- return path;
121
- };
122
- const getCommonAncestor = (handler, oneNodeId, anotherNodeId) => {
123
- const oneNodePath = getNodePath(handler, oneNodeId);
124
- const anotherNodePath = getNodePath(handler, anotherNodeId);
125
- for (let i = oneNodePath.length - 1; i >= 0; i--) {
126
- const anotherNodeIndex = anotherNodePath.indexOf(oneNodePath[i]);
127
- if (anotherNodeIndex !== -1)
128
- return {
129
- commonAncestor: oneNodePath[i],
130
- oneNodeAncestorChild: oneNodePath[i + 1],
131
- anotherNodeAncestorChild: anotherNodePath[anotherNodeIndex + 1]
132
- };
133
- }
134
- console.warn(
135
- "This point should have never been reached since the root node is common to all nodes",
136
- { oneNodeId, anotherNodeId, oneNodePath, anotherNodePath }
137
- );
138
- return null;
139
- };
140
- const unfilterNodes = (handler) => {
141
- handler.state.filteredNodes.forEach((current) => {
142
- handler.propsStore.updateField(
143
- current,
144
- { isFiltered: false },
145
- { noEmit: true }
146
- );
147
- });
148
- const firstChild = handler.propsStore.getFieldProps("root").children[0];
149
- if (firstChild)
150
- handler.setFocusedNode(firstChild);
151
- handler.setState({ filteredNodes: [] });
152
- };
153
- const matchNodesAgainstString = (handler, searchString, nodeId = "root") => {
154
- let hasMatched = false;
155
- let matchNode = null;
156
- const nodeProps = handler.propsStore.getFieldProps(nodeId);
157
- if (nodeId !== "root" && nodeProps.label.match(new RegExp(searchString, "i"))) {
158
- handler.propsStore.updateField(nodeId, { isFiltered: false });
159
- hasMatched = true;
160
- matchNode = nodeProps.id;
161
- handler.setState({
162
- filteredNodes: handler.state.filteredNodes.filter(
163
- (current) => current !== nodeId
164
- )
165
- });
166
- }
167
- let hasChildrenMatched = false;
168
- nodeProps.children.forEach((current) => {
169
- hasChildrenMatched = matchNodesAgainstString(handler, searchString, current) || hasMatched;
170
- hasMatched = hasChildrenMatched || hasMatched;
171
- if (hasMatched && !matchNode)
172
- matchNode = current;
173
- });
174
- if (hasChildrenMatched) {
175
- handler.propsStore.updateField(nodeId, { isExpanded: true });
176
- if (hasMatched && !matchNode)
177
- matchNode = nodeId;
178
- }
179
- if (!hasMatched) {
180
- handler.propsStore.updateField(
181
- nodeId,
182
- { isFiltered: true },
183
- { noEmit: true }
184
- );
185
- handler.setState({
186
- filteredNodes: [...handler.state.filteredNodes, nodeId]
187
- });
188
- }
189
- if (matchNode !== null)
190
- handler.setFocusedNode(matchNode);
191
- return hasMatched;
192
- };
193
- const selectAllNodesBetweenTwoNodes = (handler, oneNodeId, anotherNodeId, avoidFiltered) => {
194
- const commonAncestorData = getCommonAncestor(
195
- handler,
196
- oneNodeId,
197
- anotherNodeId
198
- );
199
- if (commonAncestorData) {
200
- const { anotherNodeAncestorChild, commonAncestor, oneNodeAncestorChild } = commonAncestorData;
201
- const ancestorProps = handler.propsStore.getFieldProps(commonAncestor);
202
- const oneNodePosition = ancestorProps.children.findIndex(
203
- (current) => current === oneNodeAncestorChild
204
- );
205
- const anotherNodePosition = ancestorProps.children.findIndex(
206
- (current) => current === anotherNodeAncestorChild
207
- );
208
- let currentId = oneNodePosition >= anotherNodePosition ? anotherNodeId : oneNodeId;
209
- const lastNodeId = oneNodePosition < anotherNodePosition ? anotherNodeId : oneNodeId;
210
- handler.toggleNodeSelectedState(currentId, true);
211
- do {
212
- currentId = getNextChild(handler, currentId, false);
213
- if (currentId !== null)
214
- handler.toggleNodeSelectedState(currentId, true);
215
- } while (currentId !== lastNodeId && currentId !== null);
216
- }
217
- };
218
-
219
- var __defProp$2 = Object.defineProperty;
220
- var __defNormalProp$2 = (obj, key, value) => key in obj ? __defProp$2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
221
- var __publicField$2 = (obj, key, value) => {
222
- __defNormalProp$2(obj, typeof key !== "symbol" ? key + "" : key, value);
223
- return value;
224
- };
225
- const trees = {};
226
- const treesRecordEmitter = new class TreesRecordEmitter extends EventEmitter {
227
- emit(eventName, params) {
228
- super.emit(eventName, params);
229
- trees[params.name] = params.controller;
230
- }
231
- }();
232
- function useTreeDataController(name) {
233
- const [controller, setDataController] = useState(
234
- trees[name]
235
- );
236
- useEffect(() => {
237
- if (trees[name] !== controller)
238
- setDataController(trees[name]);
239
- return treesRecordEmitter.on("addController", (ev) => {
240
- if (ev.name === name)
241
- setDataController(ev.controller);
242
- });
243
- }, []);
244
- return controller;
245
- }
246
- function getTreeDataController(name) {
247
- return trees[name];
248
- }
249
- class TreeDataController extends EventEmitter {
250
- constructor(name, configuration, propsStore = new PropsStore({
251
- logCommands: {
252
- propsStore: `treeProps_${name}`,
253
- propsLog: `treeLog_${name}`,
254
- propsSuscriptors: `propsSuscriptors_${name}`,
255
- updateProp: `updateProp_${name}`
256
- }
257
- })) {
258
- super();
259
- this.name = name;
260
- this.propsStore = propsStore;
261
- __publicField$2(this, "_configuration");
262
- __publicField$2(this, "hasApendedFirstChild", false);
263
- /**
264
- * Este array se usa para conocer los padres faltantes al momento de la
265
- * construcción del árbol, de forma de optimizar el proceso
266
- */
267
- __publicField$2(this, "missingParents", []);
268
- __publicField$2(this, "nonEmittedUpdates", []);
269
- __publicField$2(this, "stateKey", "treeState");
270
- __publicField$2(this, "previousNodes", []);
271
- __publicField$2(this, "setState", (updateProps, conf) => {
272
- this.propsStore.updateField(
273
- this.stateKey,
274
- {
275
- ...this.state,
276
- ...updateProps
277
- },
278
- conf
279
- );
280
- this.emit("stateUpdate", null);
281
- });
282
- __publicField$2(this, "useState", (selector) => {
283
- const [selectedState, setSelectedState] = useState(selector(this.state));
284
- const latestState = useLatest(selectedState);
285
- useMount(() => {
286
- return this.on("stateUpdate", () => {
287
- const newSelection = selector(this.state);
288
- if (!shallowEqual(newSelection, latestState.current)) {
289
- setSelectedState(newSelection);
290
- }
291
- });
292
- });
293
- return selectedState;
294
- });
295
- this._configuration = configuration ?? {
296
- current: { emitUpdates: true }
297
- };
298
- this._configuration.current.emitUpdates = this._configuration.current.emitUpdates ?? true;
299
- this.setState(this.getInitialState());
300
- treesRecordEmitter.emit("addController", {
301
- name,
302
- controller: this
303
- });
304
- this.initRoot();
305
- }
306
- get configuration() {
307
- return { ...this._configuration };
308
- }
309
- get state() {
310
- return this.propsStore.getFieldProps(
311
- this.stateKey
312
- );
313
- }
314
- get stateStore() {
315
- return this.propsStore;
316
- }
317
- destructor() {
318
- this.propsStore.destructor();
319
- }
320
- append(node) {
321
- const newNode = { ...node, nodeProps: node.nodeProps ?? {} };
322
- let father;
323
- if (newNode.parentId !== void 0 && this.propsStore.getFieldProps(newNode.parentId)?.children) {
324
- father = newNode.parentId;
325
- } else {
326
- father = "root";
327
- if (newNode.parentId)
328
- this.missingParents.push(newNode.parentId);
329
- newNode.actualParentId = newNode.parentId;
330
- newNode.parentId = "root";
331
- }
332
- this.propsStore.updateField(
333
- newNode.id,
334
- {
335
- ...newNode,
336
- children: newNode.children ?? []
337
- },
338
- { isUrgent: true }
339
- );
340
- this.setState({ length: this.state.length + 1 });
341
- if (this.missingParents.includes(newNode.id)) {
342
- this.propsStore.getFieldProps("root").children.forEach((currentChild) => {
343
- if (this.propsStore.getFieldProps(currentChild).actualParentId === newNode.id) {
344
- this.move(currentChild, newNode.id);
345
- }
346
- });
347
- this.missingParents = this.missingParents.filter(
348
- (current) => current !== newNode.id
349
- );
350
- }
351
- this.propsStore.updateField(
352
- father,
353
- {
354
- children: [
355
- ...this.propsStore.getFieldProps(father).children,
356
- newNode.id
357
- ],
358
- hasLoaded: true
359
- },
360
- { noEmit: this._configuration.current?.emitUpdates === false }
361
- );
362
- if (this._configuration.current?.emitUpdates === false)
363
- this.nonEmittedUpdates.push(father);
364
- if (!this.hasApendedFirstChild) {
365
- this.hasApendedFirstChild = true;
366
- this.setFocusedNode(newNode.id, true);
367
- }
368
- if (newNode.isExpanded)
369
- this.toggleNodeExpandedState(newNode.id, true);
370
- }
371
- /**
372
- * Cuando se quieren agregar muchos nodos, es conveniente llamar primero al
373
- * método batchInit y luego de finalizar, al método batchFinish()
374
- */
375
- batchInit() {
376
- this.config({ emitUpdates: false });
377
- this.setState({ isLoading: true }, { isUrgent: true });
378
- }
379
- getNodesRecursive(nodeId = "root") {
380
- const node = this.propsStore.getFieldProps(nodeId);
381
- return node.children.reduce(
382
- (prev, current) => [...prev, ...this.getNodesRecursive(current)],
383
- [...node.children]
384
- );
385
- }
386
- /**
387
- * Cuando se quieren agregar muchos nodos, es conveniente llamar primero al
388
- * método batchInit y luego de finalizar, al método batchFinish()
389
- */
390
- batchFinish() {
391
- this.config({ emitUpdates: true });
392
- setTimeout(() => this.setState({ isLoading: false }), 0);
393
- const children = [...this.getNodesRecursive()];
394
- const deleteNodes = this.previousNodes.filter(
395
- (current) => !children.find((search) => search === current)
396
- );
397
- deleteNodes.forEach((current) => this.remove(current));
398
- this.config({ emitUpdates: true });
399
- setTimeout(() => this.setState({ isLoading: false }), 0);
400
- }
401
- config(newConf) {
402
- if (this._configuration.current?.emitUpdates === false && newConf.emitUpdates !== false) {
403
- this.nonEmittedUpdates.forEach(
404
- (current) => this.propsStore.updateField(current, {
405
- children: [...this.propsStore.getFieldProps(current).children]
406
- })
407
- );
408
- this.nonEmittedUpdates = [];
409
- }
410
- Object.assign(
411
- this._configuration.current,
412
- newConf
413
- );
414
- }
415
- deselectAll() {
416
- this.state.selectedNodes.forEach(
417
- (currentId) => this.propsStore.updateField(currentId, { isSelected: false })
418
- );
419
- this.setState({ selectedNodes: [] });
420
- }
421
- forceEmitUpdate() {
422
- this.propsStore.updateField("root", {
423
- forceUpdate: (this.propsStore.getFieldProps("root").forceUpdate ?? 0) + 1
424
- });
425
- }
426
- getInitialState() {
427
- return {
428
- expandedNodes: [],
429
- filteredNodes: [],
430
- focusedNode: null,
431
- isLoading: false,
432
- length: 0,
433
- selectedNodes: []
434
- };
435
- }
436
- getNodesAsArray() {
437
- const allFields = { ...this.propsStore.fields };
438
- delete allFields[this.stateKey];
439
- delete allFields.root;
440
- return Object.values(allFields);
441
- }
442
- /**
443
- * Devuelve un array que contiene el id de todos los nodos pertenecientes al
444
- * árbol
445
- */
446
- getNodesIds() {
447
- const allFields = { ...this.propsStore.fields };
448
- delete allFields[this.stateKey];
449
- delete allFields.root;
450
- return Object.keys(allFields);
451
- }
452
- getParentId(parentId) {
453
- return this.propsStore.getFieldProps(parentId).parentId;
454
- }
455
- /**
456
- * Este método permite controlar el comportamiento con el teclado desde fuera
457
- * del componente.
458
- */
459
- handleKey(ev) {
460
- const focusedId = this.state.focusedNode;
461
- const nodeProps = this.propsStore.getFieldProps(focusedId);
462
- if (ev.key === "*") {
463
- if (this.state.focusedNode === null)
464
- return;
465
- const parent = this.propsStore.getFieldProps(
466
- this.propsStore.getFieldProps(this.state.focusedNode).parentId
467
- );
468
- parent.children.forEach(
469
- (current) => this.toggleNodeExpandedState(current, true)
470
- );
471
- } else if (ev.key.match(/^\w$/)) {
472
- const nextChildWithKey = getNextNodeWithKey(
473
- this,
474
- focusedId,
475
- ev.key,
476
- true
477
- );
478
- if (nextChildWithKey !== null) {
479
- this.setFocusedNode(nextChildWithKey);
480
- this.emit("mustFocus", nextChildWithKey);
481
- }
482
- } else
483
- switch (ev.code) {
484
- case "Home": {
485
- const firstChild = getFirstNonFilteredChild(this, "root");
486
- if (firstChild === null)
487
- return;
488
- if (ev.shiftKey && ev.ctrlKey && this.state.focusedNode !== null) {
489
- selectAllNodesBetweenTwoNodes(
490
- this,
491
- firstChild,
492
- this.state.focusedNode);
493
- }
494
- this.setFocusedNode(firstChild);
495
- this.emit("mustFocus", firstChild);
496
- break;
497
- }
498
- case "End": {
499
- const lastVisibleChild = getLastVisibleChild(this, "root");
500
- if (lastVisibleChild !== null) {
501
- if (ev.shiftKey && ev.ctrlKey && this.state.focusedNode !== null) {
502
- selectAllNodesBetweenTwoNodes(
503
- this,
504
- lastVisibleChild,
505
- this.state.focusedNode);
506
- }
507
- this.setFocusedNode(lastVisibleChild);
508
- this.emit("mustFocus", lastVisibleChild);
509
- }
510
- break;
511
- }
512
- case "ArrowRight": {
513
- if (nodeProps.isLeaf)
514
- return;
515
- ev.preventDefault();
516
- if (nodeProps.isExpanded) {
517
- const firstChild = getFirstNonFilteredChild(this, nodeProps.id);
518
- if (firstChild !== null) {
519
- this.setFocusedNode(firstChild);
520
- this.emit("mustFocus", firstChild);
521
- }
522
- } else
523
- this.toggleNodeExpandedState(nodeProps.id, true);
524
- break;
525
- }
526
- case "ArrowLeft": {
527
- ev.preventDefault();
528
- if (nodeProps.isLeaf || !nodeProps.isExpanded) {
529
- if (nodeProps.parentId !== "root" && nodeProps.parentId !== void 0) {
530
- this.setFocusedNode(nodeProps.parentId);
531
- this.emit("mustFocus", nodeProps.parentId);
532
- }
533
- } else
534
- this.toggleNodeExpandedState(nodeProps.id, false);
535
- break;
536
- }
537
- case "ArrowUp": {
538
- ev.preventDefault();
539
- const prevChild = getPreviousChild(this, nodeProps.id);
540
- if (prevChild !== null) {
541
- if (ev.shiftKey)
542
- this.toggleNodeSelectedState(prevChild, true);
543
- this.setFocusedNode(prevChild);
544
- this.emit("mustFocus", prevChild);
545
- } else
546
- this.emit("onArrowUpOnFirstElement", true);
547
- break;
548
- }
549
- case "ArrowDown": {
550
- ev.preventDefault();
551
- const nextChild = getNextChild(this, nodeProps.id, false);
552
- if (nextChild !== null) {
553
- if (ev.shiftKey)
554
- this.toggleNodeSelectedState(nextChild, true);
555
- this.setFocusedNode(nextChild);
556
- this.emit("mustFocus", nextChild);
557
- }
558
- break;
559
- }
560
- case "Space": {
561
- if (this._configuration.current?.disableSelection)
562
- return;
563
- ev.preventDefault();
564
- this.toggleNodeSelectedState(nodeProps.id);
565
- break;
566
- }
567
- }
568
- }
569
- isNode(node) {
570
- return typeof node === "object" && "parentId" in node;
571
- }
572
- isNodeContainer(node) {
573
- return typeof node === "object" && !this.isNode(node);
574
- }
575
- includes(searchNode) {
576
- return !!this.propsStore.getFieldProps(searchNode.id);
577
- }
578
- initRoot() {
579
- this.propsStore.updateField(
580
- "root",
581
- { children: [], id: "root" },
582
- { isUrgent: true }
583
- );
584
- }
585
- move(moveNode, destinationNode, afterOrBefore) {
586
- const currentFather = this.propsStore.getFieldProps(
587
- this.propsStore.getFieldProps(moveNode).parentId
588
- );
589
- const newFather = this.propsStore.getFieldProps(destinationNode);
590
- if (!currentFather) {
591
- console.warn("The current node does not belong to the tree.", moveNode);
592
- return;
593
- }
594
- if (!newFather) {
595
- console.warn(
596
- "The destination node does not belong to the tree. No action will be made",
597
- destinationNode
598
- );
599
- return;
600
- }
601
- currentFather.children = currentFather.children?.filter(
602
- (search) => search !== moveNode
603
- );
604
- if (!newFather.children)
605
- newFather.children = [];
606
- if (!afterOrBefore)
607
- newFather.children.push(moveNode);
608
- else if (afterOrBefore.position) {
609
- newFather.children.splice(afterOrBefore.position - 1, 0, moveNode);
610
- } else {
611
- const key = afterOrBefore.after ? afterOrBefore.after : afterOrBefore.before;
612
- const relatedNodeKey = key && this.isNode(key) ? key.id : key;
613
- const relatedNodeIndex = newFather.children.findIndex(
614
- (search) => search === relatedNodeKey
615
- );
616
- const actualIndex = addBoundary(
617
- afterOrBefore.before !== void 0 ? relatedNodeIndex : relatedNodeIndex + 1,
618
- 0
619
- );
620
- if (actualIndex === -1 || actualIndex === newFather.children.length)
621
- newFather.children.push(moveNode);
622
- else
623
- newFather.children.splice(actualIndex, 0, moveNode);
624
- }
625
- this.propsStore.updateField(currentFather.id, {
626
- children: [...currentFather.children ?? []]
627
- });
628
- this.propsStore.updateField(newFather.id, {
629
- children: [...newFather.children]
630
- });
631
- this.propsStore.updateField(moveNode, {
632
- parentId: newFather.id
633
- });
634
- }
635
- /**
636
- * Borra el nodo del árbol, y dependiendo del parámetro removeChildren, borra
637
- * también sus hijos.
638
- *
639
- * @param removeChildren - Si se pasa en false, los nodos hijos son movidos al root
640
- */
641
- remove(removeNode, removeChildren = true) {
642
- const removeNodeId = this.isNode(removeNode) ? removeNode.id : removeNode;
643
- const removingNode = this.propsStore.getFieldProps(removeNodeId);
644
- if (!removingNode)
645
- return;
646
- const father = this.propsStore.getFieldProps(removingNode.parentId);
647
- if (father) {
648
- this.propsStore.updateField(father.id, {
649
- children: father.children?.filter((search) => search !== removeNodeId)
650
- });
651
- }
652
- removingNode.children?.forEach((current) => {
653
- if (removeChildren) {
654
- this.remove(current);
655
- } else {
656
- this.move(current, "root");
657
- }
658
- });
659
- this.setState({
660
- selectedNodes: this.state.selectedNodes.filter(
661
- (current) => current !== removeNodeId
662
- ),
663
- focusedNode: this.state.focusedNode === removeNodeId ? null : this.state.focusedNode,
664
- length: this.state.length - 1
665
- });
666
- this.propsStore.removeField(removeNodeId);
667
- }
668
- removeMultiple(nodes, removeChildren = true) {
669
- nodes.forEach((current) => this.remove(current, removeChildren));
670
- }
671
- /**
672
- * Borra todos los nodos del árbol.
673
- */
674
- removeAll() {
675
- if (this.configuration.current?.emitUpdates === false) {
676
- this.previousNodes = this.getNodesIds();
677
- this.propsStore.updateField(
678
- "root",
679
- { children: [], id: "root" },
680
- { isUrgent: true, noEmit: true }
681
- );
682
- } else {
683
- this.hasApendedFirstChild = false;
684
- this.setState({ focusedNode: null }, { isUrgent: true });
685
- this.setSelectedNodes([]);
686
- this.initRoot();
687
- Object.keys(this.propsStore.fields).forEach((current) => {
688
- if (!["root", this.stateKey].includes(current))
689
- this.propsStore.removeField(current);
690
- });
691
- }
692
- }
693
- selectAll() {
694
- this.setState({
695
- selectedNodes: this.getNodesIds()
696
- });
697
- this.state.selectedNodes.forEach(
698
- (currentId) => this.propsStore.updateField(currentId, { isSelected: true })
699
- );
700
- }
701
- setExpandedNodes(nodes) {
702
- this.state.expandedNodes.forEach(
703
- (current) => this.propsStore.updateField(current, { isExpanded: false })
704
- );
705
- this.setState({ expandedNodes: nodes });
706
- nodes.forEach(
707
- (current) => this.propsStore.updateField(current, { isExpanded: true })
708
- );
709
- }
710
- setFocusedNode(key, avoidSelection) {
711
- if (this.state.focusedNode !== null)
712
- this.propsStore.updateField(this.state.focusedNode, { isFocused: false });
713
- this.setState({
714
- focusedNode: key
715
- });
716
- if (!this._configuration.current?.isMultiple && !avoidSelection && (this._configuration.current?.selectionMode ?? "onFocus") === "onFocus")
717
- this.setSelectedNodes([key]);
718
- this.propsStore.updateField(key, { isFocused: true });
719
- }
720
- setSelectedNodes(nodes, force = false) {
721
- if (this._configuration.current?.disableSelection && !force)
722
- return;
723
- this.state.selectedNodes.forEach(
724
- (current) => this.propsStore.updateField(current, { isSelected: false })
725
- );
726
- this.setState({
727
- selectedNodes: nodes.filter((current) => {
728
- const { isSelectable } = this.propsStore.getFieldProps(current);
729
- if (isSelectable !== false)
730
- this.propsStore.updateField(current, { isSelected: true });
731
- return isSelectable !== false;
732
- })
733
- });
734
- }
735
- setSelectedNodesByClickEvent(ev) {
736
- if (this._configuration.current?.disableSelection)
737
- return;
738
- const nodeKey = getSpecificParent(
739
- ev.target,
740
- (current) => current.getAttribute("role") === "treeitem"
741
- )?.getAttribute("data-key");
742
- if (nodeKey) {
743
- const nodeProps = this.propsStore.getFieldProps(nodeKey);
744
- if (nodeProps.isDisabled || nodeProps.isSelectable === false)
745
- return;
746
- const previousSelectionKeys = [...this.state.selectedNodes];
747
- const allowMultiple = this._configuration.current?.isMultiple && (this._configuration.current?.selectionMode !== "explicitMultiple" || ev.ctrlKey || ev.shiftKey);
748
- const newSelection = allowMultiple ? nodeProps.isSelected ? previousSelectionKeys.filter((current) => current !== nodeKey) : [...previousSelectionKeys, nodeKey] : [nodeKey];
749
- this.setSelectedNodes(newSelection);
750
- } else
751
- console.warn("Cannot set selection, no treeitem found", ev);
752
- }
753
- toggleNodeExpandedState(key, shouldExpand) {
754
- const nodeProps = this.propsStore.getFieldProps(key);
755
- if (nodeProps.isDisabled || nodeProps.isLeaf || nodeProps.isLoading)
756
- return;
757
- if (this._configuration.current?.onLoadData && !nodeProps.hasLoaded) {
758
- this.propsStore.updateField(key, { isLoading: true });
759
- this._configuration.current?.onLoadData(nodeProps).finally(() => {
760
- this.propsStore.updateField(key, {
761
- isLoading: false,
762
- isExpanded: true,
763
- hasLoaded: true
764
- });
765
- this.setState({
766
- expandedNodes: [...this.state.expandedNodes, key]
767
- });
768
- this._configuration.current?.onExpand?.(
769
- this.propsStore.getFieldProps(key)
770
- );
771
- });
772
- } else {
773
- const { expandedNodes } = this.state;
774
- const shouldExpandInner = shouldExpand !== void 0 ? shouldExpand : !expandedNodes.includes(key);
775
- if (this.propsStore.getFieldProps(key)?.isDisabled)
776
- return;
777
- this.setState({
778
- expandedNodes: shouldExpandInner ? [...expandedNodes, key] : expandedNodes.filter((current) => current !== key)
779
- });
780
- this.propsStore.updateField(key, { isExpanded: shouldExpandInner });
781
- this._configuration.current?.onExpand?.(
782
- this.propsStore.getFieldProps(key)
783
- );
784
- }
785
- }
786
- toggleNodeSelectedState(key, isSelected) {
787
- if (this._configuration.current?.disableSelection)
788
- return;
789
- const nodeProps = this.propsStore.getFieldProps(key);
790
- if (nodeProps.isDisabled || nodeProps.isSelectable === false)
791
- return;
792
- const shouldSelect = isSelected !== void 0 ? isSelected : !this.state.selectedNodes.includes(key);
793
- if (shouldSelect && nodeProps.isSelected || isSelected === false && !nodeProps.isSelected)
794
- return;
795
- if (shouldSelect && !this._configuration.current?.isMultiple && this.state.selectedNodes[0])
796
- this.toggleNodeSelectedState(this.state.selectedNodes[0], false);
797
- this.propsStore.updateField(key, { isSelected: shouldSelect });
798
- this.setState({
799
- selectedNodes: shouldSelect ? [...this.state.selectedNodes, key] : this.state.selectedNodes.filter((current) => current !== key)
800
- });
801
- }
802
- }
803
- function useTreeSelector(handler, configuration) {
804
- return usePropsSelector(
805
- handler?.stateKey ?? "__NO__TREE__KEY__",
806
- {
807
- propsStore: handler?.propsStore,
808
- ...configuration
809
- }
810
- );
811
- }
812
- function useTreeSelectorByName(treeName, configuration) {
813
- const handler = useTreeDataController(treeName);
814
- const selection = usePropsSelector(
815
- handler?.stateKey ?? "__NO__TREE__KEY__",
816
- {
817
- propsStore: handler?.propsStore,
818
- ...configuration
819
- }
820
- );
821
- return { selection, handler };
822
- }
823
-
824
- function getActiveDescendantName(treeName, nodeId) {
825
- return `${treeName}__${nodeId}`;
826
- }
827
- function getDomProps(_, treeName, type, par) {
828
- switch (type) {
829
- case "node": {
830
- const node = par;
831
- const tree = getTreeDataController(treeName);
832
- return {
833
- "aria-disabled": node.isDisabled,
834
- "aria-expanded": node.isLeaf ? void 0 : !!node.isExpanded,
835
- "aria-label": node.label,
836
- ...tree.configuration.current?.disableSelection ? void 0 : {
837
- "aria-selected": node.isSelectable !== false && !node.isDisabled ? !!node.isSelected : void 0
838
- },
839
- className: node.className,
840
- color: node.color,
841
- "data-key": node.id,
842
- id: getActiveDescendantName(treeName, node.id),
843
- role: "treeitem",
844
- title: node.title
845
- };
846
- }
847
- default: {
848
- const tree = par;
849
- return {
850
- role: "tree",
851
- "aria-multiselectable": tree.isMultiple
852
- };
853
- }
854
- }
855
- }
856
-
857
- const styles = {
858
- height: "iconmd",
859
- width: "iconmd",
860
- background: "palette.background.paper"
861
- };
862
- const LoaderSpinner = makeStyledComponent(
863
- "LoaderSpinner",
864
- "layout.common.components.loaderSpinner",
865
- styles,
866
- ({ className }) => {
867
- return /* @__PURE__ */ jsx(
868
- Spinner,
869
- {
870
- ...getVariant("layout.common.components.loaderSpinner"),
871
- className
872
- }
873
- );
874
- }
875
- );
876
-
877
- const SearchLabel = ({
878
- isLoading: isSearching,
879
- onDelete,
880
- searchString
881
- }) => {
882
- if (!searchString && !isSearching)
883
- return null;
884
- return /* @__PURE__ */ jsx(Box, { className: `tree__searchLabelBox ${isSearching ? "isLoading" : ""}`, children: isSearching ? /* @__PURE__ */ jsx(LoaderSpinner, { className: "tree__loading" }) : /* @__PURE__ */ jsxs(Box, { as: "label", className: "tree__searchLabel", children: [
885
- formatMessage(window.LBL_FILTERING_BY, { TOK1: searchString }),
886
- /* @__PURE__ */ jsx(
887
- IconButton,
888
- {
889
- icon: "Close",
890
- "aria-label": window.LBL_DELETE_FILTER,
891
- onClick: onDelete,
892
- title: window.LBL_DELETE_FILTER,
893
- size: "Sm",
894
- ...getVariant("icon-inherit")
895
- }
896
- )
897
- ] }) });
898
- };
899
-
900
- const TreeContext = React.createContext({});
901
- function useTreeContext() {
902
- const context = React.useContext(TreeContext);
903
- if (!context)
904
- throw new Error("There is no tree context");
905
- return context;
906
- }
907
- const TreeContextProvider = ({
908
- children,
909
- value
910
- }) => {
911
- const Provider = React.useMemo(() => {
912
- return TreeContext.Provider;
913
- }, []);
914
- return /* @__PURE__ */ jsx(Provider, { value, children });
915
- };
916
-
917
- const DefaultIconRenderer = (props) => {
918
- return /* @__PURE__ */ jsx(
919
- Icon,
920
- {
921
- name: props.icon,
922
- title: "",
923
- size: props.iconSize ?? "iconSm",
924
- className: "tree__node__icon"
925
- }
926
- );
927
- };
928
-
929
- const DefaultLabelRenderer = (props) => {
930
- return /* @__PURE__ */ jsx(Box, { as: "span", children: props.label });
931
- };
932
-
933
- const Spacer = ({ level }) => {
934
- return /* @__PURE__ */ jsx(Fragment, { children: Array(level).fill("").map((_, i) => i).map((current) => /* @__PURE__ */ jsx(Box, { className: "spacer" }, current)) });
935
- };
936
-
937
- const TreeItemLabel = ({ level, treeKey }) => {
938
- const {
939
- handler,
940
- treeProps: { toggleNodesOnLabelClick }
941
- } = useTreeContext();
942
- const props = usePropsSelector(treeKey, {
943
- selector: (current) => current,
944
- comparator: (prevProps, newProps) => {
945
- return shallowEqual$1(prevProps, newProps) && shallowEqual$1(prevProps?.children, newProps?.children);
946
- },
947
- propsStore: handler.propsStore
948
- });
949
- const Renderer = React.useMemo(
950
- () => props.labelRenderer ?? DefaultLabelRenderer,
951
- [props.labelRenderer]
952
- );
953
- const handleToggle = React.useCallback(() => {
954
- handler.toggleNodeExpandedState(treeKey);
955
- }, [handler, treeKey]);
956
- const IconRenderer = React.useMemo(() => {
957
- return typeof props.icon === "string" ? DefaultIconRenderer : props.icon;
958
- }, [props.icon]);
959
- const onClick = React.useCallback(() => {
960
- if (props.allowToggleExpandedFromLabel !== false)
961
- handler.toggleNodeExpandedState(treeKey);
962
- }, [handler, props.allowToggleExpandedFromLabel, treeKey]);
963
- return /* @__PURE__ */ jsxs(
964
- Box,
965
- {
966
- as: "span",
967
- className: `tree__nodeItemLabel ${props.isFocused ? "focus" : ""}`,
968
- children: [
969
- /* @__PURE__ */ jsx(Spacer, { level }),
970
- (props.isLoading || props.isExpanded && props.isLeaf !== true || props.isLeaf === false || (props.children?.length ?? 0) > 0 || props.isLeaf === void 0 && !props.hasLoaded && handler.configuration.current?.onLoadData) && /* @__PURE__ */ jsx(Box, { className: "tree__expanderWrapper", children: props.isLoading ? /* @__PURE__ */ jsx(Spinner, { sx: { width: "iconSm", height: "iconSm" } }) : /* @__PURE__ */ jsx(
971
- Icon,
972
- {
973
- className: "tree__expandIcon",
974
- onClick: handleToggle,
975
- name: props.isExpanded ? "ArrowDownThin" : "ArrowRightThin",
976
- title: "",
977
- size: 20
978
- }
979
- ) }),
980
- props.icon && IconRenderer && /* @__PURE__ */ jsx(IconRenderer, { ...props }),
981
- /* @__PURE__ */ jsx(
982
- Box,
983
- {
984
- as: "span",
985
- className: "tree__nodeItemLabelRenderer",
986
- onClick: toggleNodesOnLabelClick !== false ? onClick : void 0,
987
- children: /* @__PURE__ */ jsx(Renderer, { ...props, level })
988
- }
989
- )
990
- ]
991
- }
992
- );
993
- };
994
- var TreeItemLabel$1 = React.memo(TreeItemLabel);
995
-
996
- const TreeItem = ({ level, treeKey }) => {
997
- const { handler, name, forceUpdate, treeProps } = useTreeContext();
998
- const props = usePropsSelector(treeKey, {
999
- selector: (current) => current,
1000
- comparator: (prevProps, newProps) => {
1001
- return shallowEqual$1(prevProps, newProps) && shallowEqual$1(prevProps?.children, newProps?.children);
1002
- },
1003
- propsStore: handler.propsStore
1004
- });
1005
- const nodes = React.useMemo(
1006
- () => props.children?.map(
1007
- (current) => handler.propsStore.getFieldProps(current)
1008
- ) ?? [],
1009
- [props.children, handler.propsStore]
1010
- );
1011
- const domProps = getDomProps(treeProps, name, "node", props);
1012
- return /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsxs(
1013
- Box,
1014
- {
1015
- as: "li",
1016
- ...domProps,
1017
- className: `${domProps.className ?? ""} tree__item`,
1018
- children: [
1019
- /* @__PURE__ */ jsx(TreeItemLabel$1, { level, treeKey }),
1020
- props.isExpanded && /* @__PURE__ */ jsx(
1021
- TreeItemChildren$1,
1022
- {
1023
- forceUpdate,
1024
- role: "group",
1025
- level,
1026
- nodes
1027
- }
1028
- )
1029
- ]
1030
- }
1031
- ) });
1032
- };
1033
- var TreeItem$1 = React.memo(TreeItem);
1034
-
1035
- const TreeItemChildren = React.forwardRef(({ level, nodes, forceUpdate, ...props }, ref) => {
1036
- const { handler } = useTreeContext();
1037
- return /* @__PURE__ */ jsx(Box, { ref, as: "ul", ...props, children: nodes?.map((current) => {
1038
- const currentProps = handler.propsStore.getFieldProps(current.id);
1039
- if (!currentProps)
1040
- return null;
1041
- return currentProps.isFiltered ? null : /* @__PURE__ */ jsx(TreeItem$1, { level: level + 1, treeKey: current.id }, current.id);
1042
- }) });
1043
- });
1044
- TreeItemChildren.displayName = "TreeItemChildren";
1045
- var TreeItemChildren$1 = React.memo(TreeItemChildren);
1046
-
1047
- function useTreeData({ name, treeProps }) {
1048
- const props = useLatest(treeProps);
1049
- const handler = React.useMemo(
1050
- () => props?.current.controller ?? new TreeDataController(name, props),
1051
- // eslint-disable-next-line react-hooks/exhaustive-deps
1052
- []
1053
- );
1054
- useMount$1(() => {
1055
- treeProps?.initialNodes?.forEach((current) => handler.append(current));
1056
- });
1057
- const data = usePropsSelector(
1058
- "root",
1059
- {
1060
- comparator: shallowEqual$1,
1061
- propsStore: handler.propsStore,
1062
- selector: (current) => ({
1063
- children: current.children ?? [],
1064
- // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any
1065
- forceUpdate: current.forceUpdate
1066
- })
1067
- }
1068
- );
1069
- const keyHandlerId = React.useMemo(() => `keyHandler${uniqueId()}`, []);
1070
- const keyHandlerRef = React.useRef(null);
1071
- const focusOnNode = React.useCallback(
1072
- (key, retry = 3) => {
1073
- if (keyHandlerRef.current) {
1074
- const focusElement = keyHandlerRef.current.querySelector(
1075
- `[data-key="${key}"]`
1076
- );
1077
- keyHandlerRef.current?.focus();
1078
- if (focusElement) {
1079
- const actualFocusElement = (treeProps.focusGetter ?? ((liElement) => liElement.querySelector(
1080
- ":scope > .tree__nodeItemLabel"
1081
- )))(focusElement);
1082
- const nodeProps = handler.propsStore.getFieldProps(key);
1083
- if (!treeProps.focusGetter || !nodeProps.labelRenderer)
1084
- actualFocusElement.classList.add("focused");
1085
- actualFocusElement.scrollIntoView({
1086
- inline: "nearest",
1087
- block: "nearest"
1088
- });
1089
- } else if (retry > 0)
1090
- setTimeout(() => focusOnNode(key, retry - 1), 30);
1091
- }
1092
- },
1093
- [handler.propsStore, treeProps.focusGetter]
1094
- );
1095
- React.useEffect(() => {
1096
- const unsuscribe1 = handler.on("mustFocus", (node) => focusOnNode(node));
1097
- const unsuscribe2 = handler.on(
1098
- "onArrowUpOnFirstElement",
1099
- () => treeProps.onArrowUpOnFirstElement?.()
1100
- );
1101
- return () => {
1102
- unsuscribe1();
1103
- unsuscribe2();
1104
- };
1105
- }, [focusOnNode, handler, treeProps]);
1106
- return {
1107
- data,
1108
- handler,
1109
- keyHandler: {
1110
- id: keyHandlerId,
1111
- onKeyDown: React.useCallback(
1112
- (ev) => {
1113
- if (ev.key === "Enter") {
1114
- const key = handler.state.focusedNode;
1115
- if (key) {
1116
- const nodeProps = handler.propsStore.getFieldProps(key);
1117
- treeProps.onNodeClick?.(ev, nodeProps);
1118
- }
1119
- } else {
1120
- handler.handleKey(ev);
1121
- }
1122
- },
1123
- [handler, treeProps]
1124
- ),
1125
- onMouseDown: React.useCallback(
1126
- (ev) => {
1127
- const previousFocused = handler.state.focusedNode;
1128
- if (previousFocused !== null && ev.shiftKey && handler.configuration.current?.isMultiple)
1129
- ev.preventDefault();
1130
- },
1131
- [handler.configuration, handler.state.focusedNode]
1132
- ),
1133
- onClick: React.useCallback(
1134
- (ev) => {
1135
- if (getSpecificParent(
1136
- ev.target,
1137
- (current) => current.classList.contains("tree__expandIcon")
1138
- ))
1139
- return;
1140
- const node = getSpecificParent(
1141
- ev.target,
1142
- (current) => !!current.getAttribute("data-key")
1143
- );
1144
- if (node) {
1145
- const previousFocused = handler.state.focusedNode;
1146
- const key = node.getAttribute("data-key");
1147
- const nodeProps = handler.propsStore.getFieldProps(key);
1148
- treeProps.onNodeClick?.(ev, nodeProps);
1149
- if (previousFocused !== null && ev.shiftKey && handler.configuration.current?.isMultiple) {
1150
- selectAllNodesBetweenTwoNodes(
1151
- handler,
1152
- previousFocused,
1153
- key);
1154
- } else {
1155
- handler.setFocusedNode(key);
1156
- handler.setSelectedNodesByClickEvent(ev);
1157
- }
1158
- if (key)
1159
- focusOnNode(key);
1160
- }
1161
- },
1162
- [focusOnNode, handler, treeProps]
1163
- ),
1164
- ref: keyHandlerRef
1165
- }
1166
- };
1167
- }
1168
-
1169
- const Tree = (props) => {
1170
- const { data, handler, keyHandler } = useTreeData({
1171
- name: props.name,
1172
- treeProps: { ...props }
1173
- });
1174
- const [isLoading, setIsLoading] = React.useState(false);
1175
- const [currentSearchString, setCurrentSearchString] = React.useState("");
1176
- const isTreeLoading = useTreeSelector(handler, {
1177
- selector: (current) => current.isLoading
1178
- });
1179
- React.useEffect(() => {
1180
- setIsLoading(isTreeLoading);
1181
- }, [isTreeLoading]);
1182
- const search = useDebounceFn(
1183
- () => {
1184
- if (props.filterString === void 0)
1185
- return;
1186
- setIsLoading(true);
1187
- React.startTransition(() => {
1188
- setCurrentSearchString(props.filterString);
1189
- });
1190
- if (props.filterString !== void 0 && props.filterString !== "") {
1191
- unfilterNodes(handler);
1192
- matchNodesAgainstString(handler, props.filterString);
1193
- handler.forceEmitUpdate();
1194
- } else {
1195
- unfilterNodes(handler);
1196
- handler.forceEmitUpdate();
1197
- }
1198
- setTimeout(() => setIsLoading(false), 0);
1199
- },
1200
- { wait: 200 }
1201
- );
1202
- React.useEffect(() => {
1203
- search.run();
1204
- if (!props.filterString)
1205
- search.flush();
1206
- }, [props.filterString]);
1207
- usePropsSelector(
1208
- handler.stateKey,
1209
- {
1210
- propsStore: handler.propsStore,
1211
- selector: (current) => current,
1212
- comparator: (prevProps, newProps) => {
1213
- if (props.onSelect && !shallowEqual$1(prevProps?.selectedNodes, newProps?.selectedNodes)) {
1214
- props.onSelect(
1215
- (newProps?.selectedNodes ?? []).map(
1216
- (currentId) => handler.propsStore.getFieldProps(currentId)
1217
- )
1218
- );
1219
- }
1220
- return true;
1221
- }
1222
- }
1223
- );
1224
- const { focusedNode } = usePropsSelector(handler.stateKey, {
1225
- propsStore: handler.propsStore,
1226
- selector: (current) => ({
1227
- focusedNode: current.focusedNode
1228
- })
1229
- });
1230
- useMount$1(() => {
1231
- if (props.getHandler)
1232
- props.getHandler(handler);
1233
- });
1234
- useUnmount(() => handler.destructor());
1235
- const contextValue = React.useMemo(() => {
1236
- const actualValue = {
1237
- handler,
1238
- name: props.name,
1239
- forceUpdate: data.forceUpdate,
1240
- focusGetter: props.focusGetter,
1241
- treeProps: props
1242
- };
1243
- return actualValue;
1244
- }, [handler, props, data.forceUpdate]);
1245
- return /* @__PURE__ */ jsx(TreeContextProvider, { value: contextValue, children: /* @__PURE__ */ jsxs(
1246
- Box,
1247
- {
1248
- className: `tree ${props.className ?? ""}`,
1249
- ...getVariant(props.variant ?? "layout.common.trees.primary"),
1250
- children: [
1251
- /* @__PURE__ */ jsx(
1252
- SearchLabel,
1253
- {
1254
- isLoading: props.isLoading ?? isLoading,
1255
- onDelete: props.onDeleteFilterString,
1256
- searchString: props.hideSearchLabel ? "" : currentSearchString
1257
- }
1258
- ),
1259
- /* @__PURE__ */ jsx(
1260
- TreeItemChildren$1,
1261
- {
1262
- "aria-activedescendant": focusedNode !== null ? getActiveDescendantName(props.name, focusedNode) : void 0,
1263
- "aria-label": props.label,
1264
- as: "ul",
1265
- forceUpdate: data.forceUpdate,
1266
- level: -1,
1267
- nodes: React.useMemo(
1268
- () => data.children.map(
1269
- (current) => handler.propsStore.getFieldProps(current)
1270
- ),
1271
- [data.children, handler.propsStore]
1272
- ),
1273
- role: "tree",
1274
- tabIndex: 0,
1275
- ...keyHandler
1276
- }
1277
- )
1278
- ]
1279
- }
1280
- ) });
1281
- };
1282
- var Tree$1 = memo(Tree);
1283
-
1284
- var __defProp$1 = Object.defineProperty;
1285
- var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
1286
- var __publicField$1 = (obj, key, value) => {
1287
- __defNormalProp$1(obj, typeof key !== "symbol" ? key + "" : key, value);
1288
- return value;
1289
- };
1290
- var __accessCheck$1 = (obj, member, msg) => {
1291
- if (!member.has(obj))
1292
- throw TypeError("Cannot " + msg);
1293
- };
1294
- var __privateGet$1 = (obj, member, getter) => {
1295
- __accessCheck$1(obj, member, "read from private field");
1296
- return getter ? getter.call(obj) : member.get(obj);
1297
- };
1298
- var __privateAdd$1 = (obj, member, value) => {
1299
- if (member.has(obj))
1300
- throw TypeError("Cannot add the same private member more than once");
1301
- member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
1302
- };
1303
- var _getByAbsoluteId;
1304
- function isOOTreeNode(element) {
1305
- return typeof element.attachToTree === "function";
1306
- }
1307
- const _OOTreeNode = class _OOTreeNode {
1308
- constructor(tree, parent, props) {
1309
- this.tree = tree;
1310
- this.parent = parent;
1311
- this.props = props;
1312
- __publicField$1(this, "id", "");
1313
- __publicField$1(this, "prefix", "");
1314
- __privateAdd$1(this, _getByAbsoluteId, (id) => {
1315
- const props = this.tree.getController().propsStore.getFieldProps(id);
1316
- if (props === void 0)
1317
- return void 0;
1318
- return new _OOTreeNode(this.tree, props, props);
1319
- });
1320
- if (parent) {
1321
- if (isOOTreeNode(parent)) {
1322
- Object.assign(
1323
- this,
1324
- this.tree.calculateNodePrefix(props.id, parent?.prefix)
1325
- );
1326
- } else {
1327
- this.prefix = props.nodeProps.__prefix;
1328
- this.id = String(props.id);
1329
- }
1330
- }
1331
- }
1332
- attachToTree() {
1333
- const parentId = this.parent?.id ?? void 0;
1334
- this.tree.getController().append({
1335
- ...this.props,
1336
- id: this.id,
1337
- label: this.props.label,
1338
- parentId,
1339
- nodeProps: {
1340
- ...this.props.nodeProps,
1341
- __prefix: this.prefix,
1342
- __id: this.props.id
1343
- }
1344
- });
1345
- }
1346
- append(props) {
1347
- const newNode = new _OOTreeNode(this.tree, this, props);
1348
- newNode.attachToTree();
1349
- return newNode;
1350
- }
1351
- collapse() {
1352
- this.tree.getController().setExpandedNodes(
1353
- this.tree.getController().state.expandedNodes.filter(
1354
- (current) => current !== this.getProps().id
1355
- )
1356
- );
1357
- }
1358
- expand() {
1359
- this.tree.getController().setExpandedNodes([
1360
- ...this.tree.getController().state.expandedNodes,
1361
- this.getProps().id
1362
- ]);
1363
- this.parent.expand?.();
1364
- }
1365
- focus(expand) {
1366
- this.tree.getController().setFocusedNode(this.getProps().id);
1367
- if (expand) {
1368
- this.expand();
1369
- }
1370
- }
1371
- getAll() {
1372
- return this.tree.getController().propsStore.getFieldProps(this.id).children.map((current) => {
1373
- return () => {
1374
- return __privateGet$1(this, _getByAbsoluteId).call(this, String(current));
1375
- };
1376
- });
1377
- }
1378
- getById(id) {
1379
- const { id: actualId } = this.tree.calculateNodePrefix(id, this.prefix);
1380
- const props = this.tree.getController().propsStore.getFieldProps(actualId);
1381
- if (props === void 0)
1382
- return void 0;
1383
- return new _OOTreeNode(this.tree, props, props);
1384
- }
1385
- getOriginalId() {
1386
- return this.getProps().nodeProps.__id;
1387
- }
1388
- getParent() {
1389
- if (!this.parent)
1390
- return null;
1391
- const props = this.tree.getController().propsStore.getFieldProps(this.parent.id);
1392
- const parent = props.parentId;
1393
- const parentProps = this.tree.getController().propsStore.getFieldProps(parent);
1394
- return new _OOTreeNode(this.tree, parentProps, props);
1395
- }
1396
- getProps() {
1397
- return this.tree.getController().propsStore.getFieldProps(this.id);
1398
- }
1399
- remove() {
1400
- this.tree.getController().remove(this.id, true);
1401
- }
1402
- sort(sortFunction) {
1403
- const children = this.getProps().children.map(
1404
- (current) => this.tree.getController().propsStore.getFieldProps(current)
1405
- ).sort((a, b) => sortFunction(a, b)).map((current) => current.id);
1406
- this.tree.getController().propsStore.updateField(this.id, { children });
1407
- }
1408
- update(props) {
1409
- this.tree.getController().propsStore.updateField(this.id, props);
1410
- }
1411
- };
1412
- _getByAbsoluteId = new WeakMap();
1413
- let OOTreeNode = _OOTreeNode;
1414
-
1415
- class OOTreeChildren extends OOTreeNode {
1416
- constructor(tree) {
1417
- super(tree, null, {});
1418
- this.tree = tree;
1419
- this.prefix = "c";
1420
- }
1421
- /**
1422
- * Se sobreescribe para evitar problemas
1423
- */
1424
- expand() {
1425
- }
1426
- }
1427
-
1428
- var __defProp = Object.defineProperty;
1429
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
1430
- var __publicField = (obj, key, value) => {
1431
- __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
1432
- return value;
1433
- };
1434
- var __accessCheck = (obj, member, msg) => {
1435
- if (!member.has(obj))
1436
- throw TypeError("Cannot " + msg);
1437
- };
1438
- var __privateGet = (obj, member, getter) => {
1439
- __accessCheck(obj, member, "read from private field");
1440
- return getter ? getter.call(obj) : member.get(obj);
1441
- };
1442
- var __privateAdd = (obj, member, value) => {
1443
- if (member.has(obj))
1444
- throw TypeError("Cannot add the same private member more than once");
1445
- member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
1446
- };
1447
- var __privateSet = (obj, member, value, setter) => {
1448
- __accessCheck(obj, member, "write to private field");
1449
- member.set(obj, value);
1450
- return value;
1451
- };
1452
- var _children, _controller, _makeHandler;
1453
- class OOTree extends EventEmitter {
1454
- constructor(props) {
1455
- super();
1456
- this.props = props;
1457
- /**
1458
- * Accessors
1459
- */
1460
- __privateAdd(this, _children, null);
1461
- __privateAdd(this, _controller, {});
1462
- __publicField(this, "getChildren", () => {
1463
- if (__privateGet(this, _children) === null)
1464
- throw new Error(
1465
- "Children was not assigned yet, maybe you forgot to listen to onReady event on OOTree component."
1466
- );
1467
- return __privateGet(this, _children);
1468
- });
1469
- __publicField(this, "getController", () => {
1470
- if (__privateGet(this, _controller) === null)
1471
- throw new Error(
1472
- "Controller was not assigned yet, maybe you forgot to listen to onReady event on OOTree component."
1473
- );
1474
- const c = this;
1475
- return new Proxy(__privateGet(this, _controller), {
1476
- get(target, prop) {
1477
- if (prop === "removeAll") {
1478
- return () => {
1479
- c.prefixesMap = {};
1480
- __privateGet(c, _controller)?.removeAll();
1481
- };
1482
- }
1483
- return target[prop];
1484
- }
1485
- });
1486
- });
1487
- /**
1488
- * Component
1489
- */
1490
- __privateAdd(this, _makeHandler, () => {
1491
- __privateSet(this, _controller, new TreeDataController(this.props.name, {
1492
- current: this.props
1493
- }));
1494
- __privateSet(this, _children, new OOTreeChildren(this));
1495
- });
1496
- __publicField(this, "Component", (props) => {
1497
- return /* @__PURE__ */ jsx(
1498
- Tree$1,
1499
- {
1500
- controller: __privateGet(this, _controller),
1501
- ...this.props,
1502
- ...props
1503
- }
1504
- );
1505
- });
1506
- /**
1507
- * Data manipulation
1508
- */
1509
- __publicField(this, "prefixJoinCharacter", "$$");
1510
- __publicField(this, "prefixWithIdJoinCharacter", "__");
1511
- __publicField(this, "prefixesMap", {});
1512
- __publicField(this, "calculateDepth", (id) => {
1513
- return [...String(id).matchAll(/\$\$/g)].length;
1514
- });
1515
- /**
1516
- * Calcula el prefijo de un nodo que se está agregando al árbol evitando
1517
- * colisiones. Ese prefijo estará asociado a cada nodo y se utilizará para dar
1518
- * nombres únicos a sus hijos, no para el nodo en sí. Entonces, cada vez que
1519
- * se construye un nodo, se le asigna un prefijo considerando el prefijo de su
1520
- * padre, pero su nombre se hace a partir del prefijo del padre y su id.
1521
- */
1522
- __publicField(this, "calculateNodePrefix", (id, prefix) => {
1523
- const expectedPrefix = [prefix, String(id).charAt(0)].filter(Boolean).join(this.prefixJoinCharacter);
1524
- let i = 1;
1525
- let actualPrefix = expectedPrefix;
1526
- while (this.prefixesMap[actualPrefix] !== void 0) {
1527
- actualPrefix = `${expectedPrefix}${i++}`;
1528
- }
1529
- this.prefixesMap[actualPrefix] = {
1530
- nodeId: id,
1531
- prefix: actualPrefix
1532
- };
1533
- const data = {
1534
- prefix: actualPrefix,
1535
- id: [[prefix].filter(Boolean).join(this.prefixJoinCharacter), id].filter(Boolean).join(this.prefixWithIdJoinCharacter)
1536
- };
1537
- return data;
1538
- });
1539
- __privateGet(this, _makeHandler).call(this);
1540
- }
1541
- }
1542
- _children = new WeakMap();
1543
- _controller = new WeakMap();
1544
- _makeHandler = new WeakMap();
1545
-
1546
- export { OOTree, OOTreeNode, Tree$1 as Tree, TreeDataController, isOOTreeNode, useTreeContext, useTreeData, useTreeDataController, useTreeSelector, useTreeSelectorByName };
1
+ export { default as Tree } from './Tree.js';
2
+ export { useTreeContext } from './TreeContext.js';
3
+ export { default as TreeDataController, useTreeDataController, useTreeSelector, useTreeSelectorByName } from './TreeDataController.js';
4
+ export { default as useTreeData } from './useTreeData.js';
5
+ export { OOTree } from './OOTree/index.js';
6
+ export { OOTreeNode, isOOTreeNode } from './OOTree/OOTreeNode.js';
1547
7
  //# sourceMappingURL=index.js.map