Skip to content

Commit

Permalink
Preparation for adding drag and drop
Browse files Browse the repository at this point in the history
  • Loading branch information
ZelvaMan committed Apr 9, 2024
1 parent f4f55a1 commit 566dded
Show file tree
Hide file tree
Showing 6 changed files with 52 additions and 31 deletions.
6 changes: 3 additions & 3 deletions src/lib/Branch.svelte
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<script lang="ts">
import { createEventDispatcher } from 'svelte';
import Checkbox from './Checkbox.svelte';
import { SelectionModes, type InsertionType, type Node, type Tree } from '$lib/types.js';
import { SelectionModes, InsertionType, type Node, type Tree } from '$lib/types.js';
import type { CustomizableClasses, TreeHelper } from '$lib/index.js';
const dispatch = createEventDispatcher();
Expand Down Expand Up @@ -148,7 +148,7 @@
on:dragleave|stopPropagation={(e) => handleDragLeave(e, node, liElements[getNodeId(node)])}
bind:this={liElements[getNodeId(node)]}
>
{#if insPos == 1 && insertHighlighted}
{#if insPos == InsertionType.above && insertHighlighted}
<div class="insert-line-wrapper">
<div class="insert-line {classes.inserLineClass}" />
</div>
Expand Down Expand Up @@ -234,7 +234,7 @@
<ul class:child-menu={childDepth > 0} />
{/if}
<!-- Show line if insering -->
{#if insPos == -1 && insertHighlighted}
{#if insPos === InsertionType.below && insertHighlighted}
<div class="insert-line-wrapper">
<div class="insert-line {classes.inserLineClass}" />
</div>
Expand Down
12 changes: 11 additions & 1 deletion src/lib/constants.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import type { CustomizableClasses, Props } from '$lib/types.js';
import {
type HelperConfig,
SelectionModes,
type CustomizableClasses,
type Props
} from '$lib/types.js';

export const defaultPropNames: Props = {
nodePath: 'nodePath',
Expand Down Expand Up @@ -26,3 +31,8 @@ export const defaultClasses: CustomizableClasses = {
inserLineClass: '',
inserLineNestClass: ''
};

export const defaultConfig: HelperConfig = {
separator: '.',
checkboxes: SelectionModes.none
};
12 changes: 11 additions & 1 deletion src/lib/helpers/tree-helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@ import orderBy from 'lodash.unionby'; // used by tree merge
import uniqueBy from 'lodash.uniqby'; // used by tree merge
import type { Node, NodePath, HelperConfig, Tree } from '$lib/types.js';
import type { PropertyHelper } from '$lib/helpers/property-helper.js';
import { defaultConfig } from '$lib/constants.js';

export class TreeHelper {
props: PropertyHelper;
config: HelperConfig;

constructor(props: PropertyHelper, config: HelperConfig = {}) {
constructor(props: PropertyHelper, config: HelperConfig = defaultConfig) {
this.props = props;
this.config = config;
}
Expand Down Expand Up @@ -171,4 +172,13 @@ export class TreeHelper {
);
return tree;
}

getNodeId(nodePath: NodePath) {
if (nodePath == null) {
console.warn('getting node id of null node path');
return null;
}

return nodePath?.split(this.config.separator).slice(-1)[0];
}
}
40 changes: 17 additions & 23 deletions src/lib/providers/drag-drop-provider.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
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';
import { InsertionType, type Node, type NodePath, type Tree } from '$lib/types.js';

export class DragAndDropProvider {
export class DragDropProvider {
helper: TreeHelper;
props: PropertyHelper;
separator: string;
Expand Down Expand Up @@ -30,13 +30,13 @@ export class DragAndDropProvider {
tree: Node[],
movedNodePath: NodePath,
targetNodePath: NodePath,
insType: -1 | 0 | 1,
insType: InsertionType,
recalculateNodePath: boolean
): Node[] {
// cannot move root node
if (!movedNodePath) return tree;

const isNesting = insType == 0;
const isNesting = insType === InsertionType.nest;
// if you are not isNestinging, you want to be on same level
//so you will have same parent as target node
const parentNodePath = isNesting
Expand Down Expand Up @@ -100,7 +100,7 @@ export class DragAndDropProvider {

const index = tree.findIndex((x) => this.path(x) == this.path(targetNode));

tree.splice(index + (insType == 1 ? 0 : 1), 0, movedNode);
tree.splice(index + (insType == InsertionType.above ? 0 : 1), 0, movedNode);

//TODO maybe add option to setting this.hasChildren to false when moved last children

Expand All @@ -124,13 +124,17 @@ export class DragAndDropProvider {
) {
//node id is last part of nodePath
let nodeId;

if (recalculateNodePath) {
nodeId = this.getNextNodeId(tree, parentNodePath);
} else {
//get last segment of path
nodeId = movedNodePath?.split(this.separator).slice(-1)[0];
nodeId = this.helper.getNodeId(movedNodePath);
}
return (parentNodePath ? parentNodePath + this.separator : '') + nodeId;

if (parentNodePath === null) return nodeId as string;

return `${parentNodePath}${this.separator}${nodeId}`;
}

updatePriority(
Expand All @@ -141,14 +145,14 @@ export class DragAndDropProvider {
targetNode: Node,
insType: InsertionType
) {
const isNesting = insType == 0;
const isNesting = insType == InsertionType.nest;

if (isNesting || this.props.priority(targetNode) != null) {
let newpriority = 0;
if (!isNesting) {
//calculate next
newpriority = this.props.priority(targetNode) ?? 0;
if (insType == -1) {
if (insType == InsertionType.below) {
newpriority += 1;
} else {
//targetNode[this.props.priority] -= 1;
Expand Down Expand Up @@ -192,27 +196,17 @@ export class DragAndDropProvider {
max = Math.max(max, num);
}
});
return max + 1;

return (max + 1).toString();
}

getInsertionPosition(e: DragEvent, element: HTMLElement): InsertionType {
const targetCords = element.getBoundingClientRect();
const half = targetCords.bottom - targetCords.height / 2;

if (e.y < half) {
return 1;
}
return -1;
}

huminifyInsType(insType: InsertionType): string {
switch (insType) {
case 1:
return 'before';
case 0:
return 'inside';
case -1:
return 'after';
return InsertionType.below;
}
return InsertionType.above;
}
}
11 changes: 9 additions & 2 deletions src/lib/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,11 @@ export enum SelectionModes {
export type Node = unknown;

export type Tree = Node[];
export type InsertionType = -1 | 0 | 1;
export enum InsertionType {
above = 'above',
below = 'below',
nest = 'nest'
}
export type NodePath = string | null;

export type CustomizableClasses = {
Expand All @@ -45,15 +49,18 @@ export type CustomizableClasses = {
};

export type DragEnterCallback = (draggendNode: Node, oldParent: Node, newParent: Node) => boolean;

export type BeforeMovedCallback = (
draggendNode: Node,
oldParent: Node,
newParent: Node,
insertionType: string
) => boolean;

export type ExpandedCallback = (node: Node) => Promise<Node[]>;

export type HelperConfig = {
separator?: string;
separator: string;
recursive?: boolean;
recalculateNodePath?: boolean;
checkboxes?: SelectionModes;
Expand Down
2 changes: 1 addition & 1 deletion src/test/selection-helper.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ function getTree(treeHelper: TreeHelper, testSpecifcNodes: any[] = []) {

function getHelper(recursive: boolean): { helper: TreeHelper; selection: SelectionProvider } {
const propertyHelper = new PropertyHelper(testingProperties);
const helper = new TreeHelper(propertyHelper, { recursive });
const helper = new TreeHelper(propertyHelper, { recursive, separator: '.' });
const selection = new SelectionProvider(helper, recursive);
return { helper, selection };
}
Expand Down

0 comments on commit 566dded

Please sign in to comment.