diff --git a/src/lib/Branch.svelte b/src/lib/Branch.svelte index 96924bb..c59696a 100644 --- a/src/lib/Branch.svelte +++ b/src/lib/Branch.svelte @@ -29,15 +29,6 @@ const getNodeId = (node: Node) => `${treeId}-${helper.path(node)}`; - // get children nodes - function getChildren(tree: Tree) { - const directChildren = helper.getDirectChildren(tree, helper.path(branchRootNode)); - - const orderedChildren = helper.dragDrop.OrderByPriority(directChildren); - - return orderedChildren; - } - function setExpansion(node: Node, changeTo: boolean) { dispatch('internal-expand', { node: node, changeTo }); } @@ -135,7 +126,7 @@ class:child-menu={childDepth > 0} class={childDepth === 0 ? classes.treeClass : ''} > - {#each getChildren(tree) as node (getNodeId(node))} + {#each helper.getDirectChildren(tree, helper.path(branchRootNode)) as node (getNodeId(node))} {@const nesthighlighed = highlightNesting(node, highlightedNode, validTarget, canNest)} {@const insertHighlighted = highlightInsert(node, highlightedNode, validTarget, canNest)} {@const expanded = isExpanded(node, childDepth, expandTo)} diff --git a/src/lib/Checkbox.svelte b/src/lib/Checkbox.svelte index 11608b4..1e2bf4d 100644 --- a/src/lib/Checkbox.svelte +++ b/src/lib/Checkbox.svelte @@ -2,6 +2,7 @@ import { createEventDispatcher } from 'svelte'; import { SelectionModes, type Node } from './types.js'; import type { TreeHelper } from '$lib/index.js'; + import { SelectionProvider } from '$lib/providers/selection-provider.js'; export let checkboxes: SelectionModes; export let helper: TreeHelper; @@ -12,6 +13,7 @@ export let readonly = false; let indeterminate: boolean; + $: { if (helper.props.visualState(node) == 'indeterminate') { indeterminate = true; @@ -19,6 +21,8 @@ indeterminate = false; } } + // TODO pass from root + $: selectionProvider = new SelectionProvider(helper, recursive); const dispatch = createEventDispatcher(); @@ -28,7 +32,7 @@ {#if checkboxes == SelectionModes.perNode || checkboxes == SelectionModes.all} - {#if helper.selection.isSelectable(node, checkboxes)} + {#if selectionProvider.isSelectable(node, checkboxes)} {#if !recursive || (recursive && !helper.props.hasChildren(node))} ) { @@ -250,9 +252,9 @@ const nodePath = helper.path(node); - const changeTo = !helper.selection.isSelected(node); + const changeTo = !selectionProvider.isSelected(node); - helper.selection.setSelection(tree, nodePath, changeTo); + selectionProvider.setSelection(tree, nodePath, changeTo); debugLog("changing selection of node '", nodePath, "' to ", !propHelper.selected(node)); @@ -288,202 +290,202 @@ tree = tree; } - //#region drag and drop - - function handleDragStart(e: DragEvent, node: Node) { - // dont allos drag if is draggable is false - if (propHelper.isDraggable(node) === false) { - e.preventDefault(); - return; - } - - console.log('dragstart from: ' + helper.path(node)); - //@ts-ignore - e.dataTransfer.dropEffect = 'move'; - //@ts-ignore - e.dataTransfer.setData('node_id', helper.path(node)); - draggedPath = helper.path(node); - } - - function handleDragDrop(e: DragEvent, node: Node, el: HTMLElement) { - //should be necesary but just in case - highlightedNode = null; - if (readonly || !dragAndDrop) return; - - //@ts-ignore - draggedPath = e.dataTransfer.getData('node_id'); - - console.log(draggedPath + ' dropped on: ' + helper.path(node)); - - //important to check if timetonest is set, otherwise you could spend 30 minutes fixing this shit :) - if (timeToNest) { - const nowTimestamp = new Date(); - canNestTime = - (dragenterTimestamp ? nowTimestamp.getTime() - dragenterTimestamp.getTime() : 1) > - timeToNest; - } - - let newNode = helper.findNode(tree, draggedPath); - - let oldNode = { ...(newNode as any) }; - let oldParent = helper.findNode(tree, helper.getParentNodePath(draggedPath)); - - let insType = canNest ? 0 : helper.dragDrop.getInsertionPosition(e, el); - - //cancel move if its not valid - if (insType == 0 && propHelper.nestDisabled(node) === true) return; - else if ((insType == -1 || insType == 1) && propHelper.insertDisabled(node) === true) return; - - //callback can cancell move - if ( - beforeMovedCallback && - beforeMovedCallback(oldNode, oldParent, node, helper.dragDrop.huminifyInsType(insType)) === - false - ) - return; - - tree = helper.dragDrop.moveNode( - tree, - draggedPath, - helper.path(node), - insType, - recalculateNodePath - ); - - let newParent = helper.findNode(tree, helper.getParentNodePath(helper.path(newNode))) ?? null; - - dispatch('moved', { - oldParent: oldParent, - newParent: newParent, - oldNode: oldNode, - newNode: newNode, - targetNode: node, - insType: helper.dragDrop.huminifyInsType(insType) - }); - - //reset props - dragenterTimestamp = null; - draggedPath = null; - highlightedNode = null; - } - - function handleDragOver(e: DragEvent, node: Node, el: HTMLElement) { - insPos = helper.dragDrop.getInsertionPosition(e, el); - - //if you are further away from right then treshold allow nesting - // @ts-ignore - let diff = e.x - e.target?.getBoundingClientRect()?.x; - if (pixelNestTreshold && diff > pixelNestTreshold) { - canNestPos = true; - } else { - canNestPos = false; - } - - //allow drop if valid target - if (validTarget) e.preventDefault(); - } - - function handleDragEnter(e: DragEvent, node: Node, el: HTMLElement) { - setTimeout(() => { - insPos = helper.dragDrop.getInsertionPosition(e, el); - - validTarget = true; - dragenterTimestamp = new Date(); - // will cause flashing when moving wrom node to node while be able to nest - //* have to be here if you only use time - highlightedNode = node; - - if (timeToNest) { - canNestTime = false; - - //this is so that only one timeout is ticking at one time - clearTimeout(dragTimeout); - - dragTimeout = setTimeout(() => { - canNestTime = true; - }, timeToNest); - } - - //dont allow drop on child element and if both insertDisabled and nestDisabled to true - if ( - helper.path(node)?.startsWith(draggedPath ?? '') || - (propHelper.insertDisabled(node) === true && propHelper.nestDisabled(node) === true) - ) { - validTarget = false; - } - - //if defined calling callback - if (dragEnterCallback) { - //get node for event - let draggedNode = helper.findNode(tree, draggedPath ?? ''); - let oldParent = helper.findNode(tree, helper.getParentNodePath(draggedPath ?? '')); - - //callback returning false means that it isnt valid target - if (dragEnterCallback(draggedNode, oldParent, node) === false) { - validTarget = false; - } - } - }, 1); - e.preventDefault(); - } - - function handleDragEnd(e: DragEvent, node: Node) { - //reset prop on next tick - setTimeout(() => { - draggedPath = null; - highlightedNode = null; - }, 1); - } - - function handleDragleave(e: DragEvent, node: Node, el: HTMLElement) { - // highlightedNode = null; - } - /** - *check if this node is one being hovered over (highlited) and is valid target - */ - function highlighThisNode(node: Node, highlitedNode: Node, validTarget: boolean) { - return validTarget && helper.path(highlitedNode) == helper.path(node); - } - /** - * returns true, it should highlight nesting on this node - * @param node node - * @param highlitedNode highlited node - * @param validTarget valid target - * @param canNest can nest - */ - function highlightNesting( - node: Node, - highlitedNode: Node, - validTarget: boolean, - canNest: boolean - ) { - return ( - canNest && - highlighThisNode(node, highlitedNode, validTarget) && - propHelper.nestDisabled(node) !== true - ); - } - /** - * returns true, it should highlight nesting on this node - * @param node node - * @param highlitedNode highlited node - * @param validTarget valid target - * @param canNest can nest - */ - function highlightInsert( - node: Node, - highlitedNode: Node, - validTarget: boolean, - canNest: boolean - ) { - return ( - !canNest && - highlighThisNode(node, highlitedNode, validTarget) && - propHelper.insertDisabled(node) !== true - ); - } - - //#endregion + // //#region drag and drop + + // function handleDragStart(e: DragEvent, node: Node) { + // // dont allos drag if is draggable is false + // if (propHelper.isDraggable(node) === false) { + // e.preventDefault(); + // return; + // } + + // console.log('dragstart from: ' + helper.path(node)); + // //@ts-ignore + // e.dataTransfer.dropEffect = 'move'; + // //@ts-ignore + // e.dataTransfer.setData('node_id', helper.path(node)); + // draggedPath = helper.path(node); + // } + + // function handleDragDrop(e: DragEvent, node: Node, el: HTMLElement) { + // //should be necesary but just in case + // highlightedNode = null; + // if (readonly || !dragAndDrop) return; + + // //@ts-ignore + // draggedPath = e.dataTransfer.getData('node_id'); + + // console.log(draggedPath + ' dropped on: ' + helper.path(node)); + + // //important to check if timetonest is set, otherwise you could spend 30 minutes fixing this shit :) + // if (timeToNest) { + // const nowTimestamp = new Date(); + // canNestTime = + // (dragenterTimestamp ? nowTimestamp.getTime() - dragenterTimestamp.getTime() : 1) > + // timeToNest; + // } + + // let newNode = helper.findNode(tree, draggedPath); + + // let oldNode = { ...(newNode as any) }; + // let oldParent = helper.findNode(tree, helper.getParentNodePath(draggedPath)); + + // let insType = canNest ? 0 : helper.dragDrop.getInsertionPosition(e, el); + + // //cancel move if its not valid + // if (insType == 0 && propHelper.nestDisabled(node) === true) return; + // else if ((insType == -1 || insType == 1) && propHelper.insertDisabled(node) === true) return; + + // //callback can cancell move + // if ( + // beforeMovedCallback && + // beforeMovedCallback(oldNode, oldParent, node, helper.dragDrop.huminifyInsType(insType)) === + // false + // ) + // return; + + // tree = helper.dragDrop.moveNode( + // tree, + // draggedPath, + // helper.path(node), + // insType, + // recalculateNodePath + // ); + + // let newParent = helper.findNode(tree, helper.getParentNodePath(helper.path(newNode))) ?? null; + + // dispatch('moved', { + // oldParent: oldParent, + // newParent: newParent, + // oldNode: oldNode, + // newNode: newNode, + // targetNode: node, + // insType: helper.dragDrop.huminifyInsType(insType) + // }); + + // //reset props + // dragenterTimestamp = null; + // draggedPath = null; + // highlightedNode = null; + // } + + // function handleDragOver(e: DragEvent, node: Node, el: HTMLElement) { + // insPos = helper.dragDrop.getInsertionPosition(e, el); + + // //if you are further away from right then treshold allow nesting + // // @ts-ignore + // let diff = e.x - e.target?.getBoundingClientRect()?.x; + // if (pixelNestTreshold && diff > pixelNestTreshold) { + // canNestPos = true; + // } else { + // canNestPos = false; + // } + + // //allow drop if valid target + // if (validTarget) e.preventDefault(); + // } + + // function handleDragEnter(e: DragEvent, node: Node, el: HTMLElement) { + // setTimeout(() => { + // insPos = helper.dragDrop.getInsertionPosition(e, el); + + // validTarget = true; + // dragenterTimestamp = new Date(); + // // will cause flashing when moving wrom node to node while be able to nest + // //* have to be here if you only use time + // highlightedNode = node; + + // if (timeToNest) { + // canNestTime = false; + + // //this is so that only one timeout is ticking at one time + // clearTimeout(dragTimeout); + + // dragTimeout = setTimeout(() => { + // canNestTime = true; + // }, timeToNest); + // } + + // //dont allow drop on child element and if both insertDisabled and nestDisabled to true + // if ( + // helper.path(node)?.startsWith(draggedPath ?? '') || + // (propHelper.insertDisabled(node) === true && propHelper.nestDisabled(node) === true) + // ) { + // validTarget = false; + // } + + // //if defined calling callback + // if (dragEnterCallback) { + // //get node for event + // let draggedNode = helper.findNode(tree, draggedPath ?? ''); + // let oldParent = helper.findNode(tree, helper.getParentNodePath(draggedPath ?? '')); + + // //callback returning false means that it isnt valid target + // if (dragEnterCallback(draggedNode, oldParent, node) === false) { + // validTarget = false; + // } + // } + // }, 1); + // e.preventDefault(); + // } + + // function handleDragEnd(e: DragEvent, node: Node) { + // //reset prop on next tick + // setTimeout(() => { + // draggedPath = null; + // highlightedNode = null; + // }, 1); + // } + + // function handleDragleave(e: DragEvent, node: Node, el: HTMLElement) { + // // highlightedNode = null; + // } + // /** + // *check if this node is one being hovered over (highlited) and is valid target + // */ + // function highlighThisNode(node: Node, highlitedNode: Node, validTarget: boolean) { + // return validTarget && helper.path(highlitedNode) == helper.path(node); + // } + // /** + // * returns true, it should highlight nesting on this node + // * @param node node + // * @param highlitedNode highlited node + // * @param validTarget valid target + // * @param canNest can nest + // */ + // function highlightNesting( + // node: Node, + // highlitedNode: Node, + // validTarget: boolean, + // canNest: boolean + // ) { + // return ( + // canNest && + // highlighThisNode(node, highlitedNode, validTarget) && + // propHelper.nestDisabled(node) !== true + // ); + // } + // /** + // * returns true, it should highlight nesting on this node + // * @param node node + // * @param highlitedNode highlited node + // * @param validTarget valid target + // * @param canNest can nest + // */ + // function highlightInsert( + // node: Node, + // highlitedNode: Node, + // validTarget: boolean, + // canNest: boolean + // ) { + // return ( + // !canNest && + // highlighThisNode(node, highlitedNode, validTarget) && + // propHelper.insertDisabled(node) !== true + // ); + // } + + // //#endregion this.getParentNodePath(this.path(x)) === nodePath); } - findNode(tree: Node[], nodePath: NodePath): Node { + findNode(tree: Tree, nodePath: NodePath): Node { return tree.find((node) => this.path(node) === nodePath) ?? null; } @@ -56,38 +50,38 @@ export class TreeHelper { return includesSeparator; } - getDirectChildren(tree: Node[], parentNodePath: NodePath) { + getDirectChildren(tree: Tree, parentNodePath: NodePath) { const children = (tree || []).filter((x) => !parentNodePath ? !this.nodePathIsChild(this.path(x)) : this.getParentNodePath(this.path(x)) === parentNodePath ); - - return children; + const ordered = this.orderByPriority(children); + return ordered; } - allCHildren(tree: Node[], parentNodePath: NodePath) { + allCHildren(tree: Tree, parentNodePath: NodePath) { const children = tree.filter((x) => this.isChildrenOf(parentNodePath, this.path(x))); return children; } - getAllLeafNodes(tree: Node[]) { + getAllLeafNodes(tree: Tree) { return tree.filter((x) => { return this.props.hasChildren(x) == undefined || this.props.hasChildren(x) == false; }); } - joinTrees(filteredTree: Node[], tree: Node[]) { + joinTrees(filteredTree: Tree, tree: Tree) { return tree.map((tnode) => this.findNode(filteredTree, this.path(tnode)) || tnode); } - mergeTrees(oldTree: Node[], addedTree: Node[], nodePath = 'nodePath') { + mergeTrees(oldTree: Tree, addedTree: Tree, nodePath = 'nodePath') { return orderBy(addedTree, oldTree, nodePath); } /** toggles expansion on */ - changeExpansion(tree: Node[], node: Node, changeTo: boolean) { + changeExpansion(tree: Tree, node: Node, changeTo: boolean) { const foundNode = this.findNode(tree, this.path(node)); this.props.setExpanded(foundNode, changeTo); @@ -95,7 +89,7 @@ export class TreeHelper { /** changes expansion of every node that has this.hasChildren set to true */ - changeEveryExpansion(tree: Node[], changeTo: boolean) { + changeEveryExpansion(tree: Tree, changeTo: boolean) { return tree.map((node) => { if (this.props.hasChildren(node) == true) { this.props.setExpanded(node, changeTo); @@ -106,7 +100,7 @@ export class TreeHelper { /** changes expansion of every node that has this.hasChildren set to true if they are abose set level and expansion property isnt set */ - expandToLevel(tree: Node[], level: number) { + expandToLevel(tree: Tree, level: number) { return tree.map((n) => { if ( this.props.expanded(n) == undefined && @@ -130,10 +124,10 @@ export class TreeHelper { //#endregion - searchTree(tree: Node[], filter: (node: unknown) => boolean) { + searchTree(tree: Tree, filter: (node: unknown) => boolean) { const filteredNodes = tree.filter(filter); - const resultNodes: Node[] = []; + const resultNodes: Tree = []; // add all parents from each node // needed so that tree can be rendered @@ -149,7 +143,7 @@ export class TreeHelper { return uniqueNodes; } - getParents(tree: Node[], node: Node) { + getParents(tree: Tree, node: Node) { const parentsPaths: NodePath[] = []; let nodePath = this.path(node); @@ -167,4 +161,14 @@ export class TreeHelper { return parentNodes; } + + /** orders nodes by priorityProp + */ + orderByPriority(tree: Tree) { + // TODO investigata that it really works + tree.sort((a: Node, b: Node) => + this.props.priority(b) ? this.props.priority(a) - this.props.priority(b) : 1 + ); + return tree; + } } diff --git a/src/lib/helpers/drag-drop-helpers.ts b/src/lib/providers/drag-drop-provider.ts similarity index 94% rename from src/lib/helpers/drag-drop-helpers.ts rename to src/lib/providers/drag-drop-provider.ts index b1da482..0a37cc1 100644 --- a/src/lib/helpers/drag-drop-helpers.ts +++ b/src/lib/providers/drag-drop-provider.ts @@ -2,7 +2,7 @@ import type { PropertyHelper } from '$lib/helpers/property-helper.js'; import type { TreeHelper } from '$lib/helpers/tree-helper.js'; import type { InsertionType, Node, NodePath, Tree } from '$lib/types.js'; -export class DragAndDropHelper { +export class DragAndDropProvider { helper: TreeHelper; props: PropertyHelper; separator: string; @@ -173,7 +173,7 @@ export class DragAndDropHelper { insertedPriority = -1 ) { let nextPriority = insertedPriority + 1; - this.OrderByPriority(this.helper.allCHildren(tree, parentNode)).forEach((node) => { + this.helper.orderByPriority(this.helper.allCHildren(tree, parentNode)).forEach((node) => { if (this.props.priority(node) >= insertedPriority && this.path(node) != movedNodePath) { this.props.setPriority(node, nextPriority++); } @@ -215,14 +215,4 @@ export class DragAndDropHelper { return 'after'; } } - - /** orders nodes by priorityProp - */ - OrderByPriority(tree: Tree) { - // TODO investigata that it really works - tree.sort((a: Node, b: Node) => - this.props.priority(b) ? this.props.priority(a) - this.props.priority(b) : 1 - ); - return tree; - } } diff --git a/src/lib/helpers/selection-helpers.ts b/src/lib/providers/selection-provider.ts similarity index 99% rename from src/lib/helpers/selection-helpers.ts rename to src/lib/providers/selection-provider.ts index 4ae6b03..11b4dae 100644 --- a/src/lib/helpers/selection-helpers.ts +++ b/src/lib/providers/selection-provider.ts @@ -2,7 +2,7 @@ import type { PropertyHelper } from '$lib/helpers/property-helper.js'; import type { TreeHelper } from '$lib/helpers/tree-helper.js'; import { SelectionModes, type Node, type NodePath, type Tree, VisualStates } from '$lib/types.js'; -export class SelectionHelper { +export class SelectionProvider { helper: TreeHelper; props: PropertyHelper; recursiveMode: boolean; diff --git a/src/lib/stores/drag-and-drop-store.ts b/src/lib/stores/drag-and-drop-store.ts new file mode 100644 index 0000000..661ca5f --- /dev/null +++ b/src/lib/stores/drag-and-drop-store.ts @@ -0,0 +1,32 @@ +import type { TreeHelper } from '$lib/helpers/tree-helper.js'; +import { type BeforeMovedCallback, type DragEnterCallback, HighlighType } from '$lib/types.js'; +import { derived, type Readable, writable } from 'svelte/store'; + +const storeDefaults = { + dragging: false, + x: 0, + y: 0 +}; + +type dragConfig = { + dragEnterCallback: DragEnterCallback | null; + beforeMovedCallback: BeforeMovedCallback | null; +}; + +export function startDrag(config: dragConfig) { + const draggedNodeStore = writable(null); + + return { + highligh(helper: TreeHelper, node: Node): Readable { + // forces update when gragged nodes is changed + return derived([draggedNodeStore], ([store]) => { + return HighlighType.none; + }); + }, + isDragged(helper: TreeHelper, node: Node): Readable { + return derived([draggedNodeStore], ([draggedNode]) => { + return helper.path(node) === helper.path(draggedNode); + }); + } + }; +} diff --git a/src/lib/types.ts b/src/lib/types.ts index 075c2a1..2f7f649 100644 --- a/src/lib/types.ts +++ b/src/lib/types.ts @@ -58,3 +58,10 @@ export type HelperConfig = { recalculateNodePath?: boolean; checkboxes?: SelectionModes; }; + +export enum HighlighType { + nest = 'nest', + insertAbove = 'insert-above', + insertBelow = 'insert-below', + none = 'none' +} diff --git a/src/test/selection-helper.test.ts b/src/test/selection-helper.test.ts index 688d28d..48eab94 100644 --- a/src/test/selection-helper.test.ts +++ b/src/test/selection-helper.test.ts @@ -1,5 +1,6 @@ import { PropertyHelper } from '$lib/helpers/property-helper.js'; import { TreeHelper } from '$lib/index.js'; +import { SelectionProvider } from '$lib/providers/selection-provider.js'; import { type Props, VisualStates } from '$lib/types.js'; import { expect, test } from 'vitest'; @@ -44,126 +45,128 @@ function getTree(treeHelper: TreeHelper, testSpecifcNodes: any[] = []) { }); } -function getHelper(recursive: boolean): TreeHelper { +function getHelper(recursive: boolean): { helper: TreeHelper; selection: SelectionProvider } { const propertyHelper = new PropertyHelper(testingProperties); - return new TreeHelper(propertyHelper, { recursive }); + const helper = new TreeHelper(propertyHelper, { recursive }); + const selection = new SelectionProvider(helper, recursive); + return { helper, selection }; } test('getChildrenWithCheckboxes test root', () => { - const helper = getHelper(true); + const { helper, selection } = getHelper(true); const tree = getTree(helper); // from root - const children = helper.selection.getSelectableDirectChildren(tree, null); + const children = selection.getSelectableDirectChildren(tree, null); const paths = children.map((node) => helper.path(node)); expect(paths).toEqual(['0', '1', '2', '3']); }); test('getChildrenWithCheckboxes parent is normal node', () => { - const helper = getHelper(true); + const { helper, selection } = getHelper(true); const tree = getTree(helper); // from root - const children = helper.selection.getSelectableDirectChildren(tree, '1'); + const children = selection.getSelectableDirectChildren(tree, '1'); const paths = children.map((node) => helper.path(node)); expect(paths).toEqual(['1.4', '1.6', '1.7', '1.8', '1.9']); }); test('getChildrenWithCheckboxes parent is leaf node', () => { - const helper = getHelper(true); + const { helper, selection } = getHelper(true); const tree = getTree(helper); // from root - const children = helper.selection.getSelectableDirectChildren(tree, '1.4'); + const children = selection.getSelectableDirectChildren(tree, '1.4'); const paths = children.map((node) => helper.path(node)); expect(paths).toEqual([]); }); test('setSelection non-recursive', () => { - const helper = getHelper(false); + const { helper, selection } = getHelper(false); const tree = getTree(helper); const nodePath = '1.7'; const node = helper.findNode(tree, nodePath); - helper.selection.setSelection(tree, nodePath, true); + selection.setSelection(tree, nodePath, true); - expect(helper.selection.isSelected(node)).toBe(true); + expect(selection.isSelected(node)).toBe(true); - helper.selection.setSelection(tree, nodePath, false); + selection.setSelection(tree, nodePath, false); - expect(helper.selection.isSelected(node)).toBe(false); + expect(selection.isSelected(node)).toBe(false); }); test('setSelection recursive all children are leaf', () => { - const helper = getHelper(true); + const { helper, selection } = getHelper(true); const tree = getTree(helper); const parentNodePath = '1.7'; //test it changes all selection not just toggles - helper.selection.setSelection(tree, '1.7.10', true); + selection.setSelection(tree, '1.7.10', true); - helper.selection.setSelection(tree, parentNodePath, true); - helper.selection.recomputeAllVisualStates(tree); + selection.setSelection(tree, parentNodePath, true); + selection.recomputeAllVisualStates(tree); const children = helper.getDirectChildren(tree, parentNodePath); const paths = children.map((node) => helper.path(node)); expect(paths).toEqual(['1.7.10', '1.7.11']); - let newChildrenSelected = children.map((node) => helper.selection.isSelected(node)); + let newChildrenSelected = children.map((node) => selection.isSelected(node)); expect(newChildrenSelected).not.toContain(false); - helper.selection.setSelection(tree, '1.7.10', false); + selection.setSelection(tree, '1.7.10', false); - helper.selection.setSelection(tree, parentNodePath, false); - helper.selection.recomputeAllVisualStates(tree); + selection.setSelection(tree, parentNodePath, false); + selection.recomputeAllVisualStates(tree); - newChildrenSelected = children.map((node) => helper.selection.isSelected(node)); + newChildrenSelected = children.map((node) => selection.isSelected(node)); expect(newChildrenSelected).not.toContain(true); }); test('setSelection recursive all children are not leaf', () => { - const helper = getHelper(true); + const { helper, selection } = getHelper(true); const tree = getTree(helper); const parentNodePath = '1'; //test it changes all selection not just toggles - helper.selection.setSelection(tree, '1.7.10', true); + selection.setSelection(tree, '1.7.10', true); - helper.selection.setSelection(tree, parentNodePath, true); - helper.selection.recomputeAllVisualStates(tree); + selection.setSelection(tree, parentNodePath, true); + selection.recomputeAllVisualStates(tree); const children = helper.allCHildren(tree, parentNodePath); const paths = children.map((node) => helper.path(node)); expect(paths).toEqual(['1.4', '1.6', '1.7', '1.7.10', '1.7.11', '1.8', '1.9']); - let newChildrenSelected = children.map((node) => helper.selection.isSelected(node)); + let newChildrenSelected = children.map((node) => selection.isSelected(node)); expect(newChildrenSelected).not.toContain(false); - helper.selection.setSelection(tree, '1.7.10', false); + selection.setSelection(tree, '1.7.10', false); - helper.selection.setSelection(tree, parentNodePath, false); - helper.selection.recomputeAllVisualStates(tree); + selection.setSelection(tree, parentNodePath, false); + selection.recomputeAllVisualStates(tree); - newChildrenSelected = children.map((node) => helper.selection.isSelected(node)); + newChildrenSelected = children.map((node) => selection.isSelected(node)); expect(newChildrenSelected).not.toContain(true); }); test('setSelection recursive parent is root', () => { - const helper = getHelper(true); + const { helper, selection } = getHelper(true); const tree = getTree(helper); const parentNodePath = null; - helper.selection.setSelection(tree, parentNodePath, true); - helper.selection.recomputeAllVisualStates(tree); + selection.setSelection(tree, parentNodePath, true); + selection.recomputeAllVisualStates(tree); const children = helper.allCHildren(tree, parentNodePath); @@ -171,16 +174,15 @@ test('setSelection recursive parent is root', () => { expect(paths).toEqual(helper.allCHildren(tree, null).map((node) => helper.path(node))); - let newChildrenSelected = children.map((node) => helper.selection.isSelected(node)); + let newChildrenSelected = children.map((node) => selection.isSelected(node)); expect(newChildrenSelected).not.toContain(false); - helper.selection.setSelection(tree, parentNodePath, false); - helper.selection.recomputeAllVisualStates(tree); + selection.setSelection(tree, parentNodePath, false); + selection.recomputeAllVisualStates(tree); newChildrenSelected = children.map( - (node) => - helper.selection.isSelected(node) || helper.props.visualState(node) === VisualStates.selected + (node) => selection.isSelected(node) || helper.props.visualState(node) === VisualStates.selected ); expect(newChildrenSelected).not.toContain(true); }); @@ -189,7 +191,7 @@ test('setSelection recursive if one child has hasChildren set to true but no act // expected behavior is that graphically it will be selected // but logically it will be ignored - const helper = getHelper(true); + const { helper, selection } = getHelper(true); const tree = getTree(helper, [{ nodePath: '2.12', hasChildren: true }]); const parentNodePath = '2'; @@ -197,18 +199,18 @@ test('setSelection recursive if one child has hasChildren set to true but no act const children = helper.allCHildren(tree, parentNodePath); expect(children.length).toBe(2); - helper.selection.setSelection(tree, parentNodePath, true); - helper.selection.recomputeAllVisualStates(tree); + selection.setSelection(tree, parentNodePath, true); + selection.recomputeAllVisualStates(tree); - const selected = children.map((node) => helper.selection.isSelected(node)); + const selected = children.map((node) => selection.isSelected(node)); expect(selected).not.toContain(false); - helper.selection.setSelection(tree, parentNodePath, false); - helper.selection.recomputeAllVisualStates(tree); + selection.setSelection(tree, parentNodePath, false); + selection.recomputeAllVisualStates(tree); // we can never unselect node that has hasChildren set to true but doesnt have any children - expect(helper.selection.isSelected(helper.findNode(tree, '2.12'))).toBe(true); - expect(helper.selection.isSelected(helper.findNode(tree, '2.5'))).toBe(false); - expect(helper.selection.isSelected(helper.findNode(tree, '2'))).toBe(false); + expect(selection.isSelected(helper.findNode(tree, '2.12'))).toBe(true); + expect(selection.isSelected(helper.findNode(tree, '2.5'))).toBe(false); + expect(selection.isSelected(helper.findNode(tree, '2'))).toBe(false); });