@keenmate/svelte-treeview 1.0.0-beta.1 → 1.0.0-beta.3

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.
package/README.md CHANGED
@@ -5,34 +5,34 @@ The most elaborate treeview for svelte on earth (or even in our galaxy).
5
5
  ## Features
6
6
 
7
7
  - load new nodes whne expanding
8
- - automatically expanding to given depth
9
8
  - customization of all object properties
10
9
  - checkboxes enabled on whole tree or based on property
11
10
  - recursive seletion mode, where leafes can be selected
12
11
  - build-in support for search
12
+ - drag and drop functionality controlable per node
13
+ - context menu
13
14
 
14
15
  ## Instalation
15
16
 
16
17
  install the package `@keenmate/svelte-treeview` using your favourite package manager.
17
18
 
18
- Font awesome is required for expand/collapse icons.
19
+ **Font awesome is required for expand/collapse icons.**
19
20
 
20
21
  ## Minimal usage
21
22
 
22
-
23
23
  ```svelte
24
24
  <script lang="ts">
25
- import { TreeView } from '$lib/index.js';
25
+ import { TreeView } from '$lib/index.js';
26
26
 
27
- let tree = [
28
- { nodePath: 'animals', title: 'Animals', hasChildren: true },
27
+ let tree = [
28
+ { nodePath: 'animals', title: 'Animals', hasChildren: true },
29
29
  //...
30
- { nodePath: 'animals.insects.butterflies', title: 'Butterflies' }
31
- ];
30
+ { nodePath: 'animals.insects.butterflies', title: 'Butterflies' }
31
+ ];
32
32
  </script>
33
33
 
34
34
  <TreeView {tree} treeId="my-tree" let:node>
35
- {node.title}
35
+ {node.title}
36
36
  </TreeView>
37
37
 
38
38
  ```
@@ -14,13 +14,11 @@ export let readonly;
14
14
  export let expandTo;
15
15
  export let classes;
16
16
  export let helper;
17
- export let draggedPath;
18
- export let highlightedNode;
19
17
  export let childDepth;
20
18
  export let branchRootNode;
21
- export let canNest;
22
- export let validTarget;
23
- export let insPos;
19
+ export let draggedNode;
20
+ export let highlightedNode;
21
+ export let insertionType;
24
22
  const getNodeId = (node) => `${treeId}-${node.path}`;
25
23
  function setExpansion(node, changeTo) {
26
24
  dispatch('internal-expand', { node: node, changeTo });
@@ -42,10 +40,10 @@ function handleDragStart(e, node) {
42
40
  dispatch('internal-handleDragStart', { node: node, e: e });
43
41
  }
44
42
  function handleDragDrop(e, node, el) {
45
- dispatch('internal-handleDragStart', { node: node, event: e, element: el });
43
+ dispatch('internal-handleDragDrop', { node: node, event: e, element: el });
46
44
  }
47
- function handleDragOver(e, node, el) {
48
- dispatch('internal-handleDragOver', { node: node, event: e, element: el });
45
+ function handleDragOver(e, node, el, nest) {
46
+ dispatch('internal-handleDragOver', { node: node, event: e, element: el, nest });
49
47
  }
50
48
  function handleDragEnter(e, node, el) {
51
49
  dispatch('internal-handleDragEnter', { node: node, event: e, element: el });
@@ -56,36 +54,13 @@ function handleDragEnd(e, node) {
56
54
  function handleDragLeave(e, node, el) {
57
55
  dispatch('internal-handleDragLeave', { node: node, event: e, element: el });
58
56
  }
59
- /**
60
- *check if this node is one being hovered over (highlited) and is valid target
61
- */
62
- function highlighThisNode(node, highlitedNode, validTarget) {
63
- return validTarget && highlitedNode.path == node.path;
64
- }
65
- /**
66
- * returns true, it should highlight nesting on this node
67
- * @param node node
68
- * @param highlitedNode highlited node
69
- * @param validTarget valid target
70
- * @param canNest can nest
71
- */
72
- function highlightNesting(node, highlitedNode, validTarget, canNest) {
73
- if (!highlitedNode)
74
- return false;
75
- return (canNest && highlighThisNode(node, highlitedNode, validTarget) && node.nestDisabled !== true);
76
- }
77
- /**
78
- * returns true, it should highlight nesting on this node
79
- * @param node node
80
- * @param highlitedNode highlited node
81
- * @param validTarget valid target
82
- * @param canNest can nest
83
- */
84
- function highlightInsert(node, highlitedNode, validTarget, canNest) {
85
- if (!highlitedNode)
86
- return false;
87
- return (!canNest && highlighThisNode(node, highlitedNode, validTarget) && node.nestDisabled !== true);
57
+ function getHighlighMode(node, highlightedNode, insertionType) {
58
+ // return InsertionType.insertAbove;
59
+ if (highlightedNode?.path !== node.path)
60
+ return InsertionType.none;
61
+ return insertionType;
88
62
  }
63
+ // TODO maybe this can be removed?
89
64
  let liElements = {};
90
65
  </script>
91
66
 
@@ -95,27 +70,24 @@ let liElements = {};
95
70
  class={childDepth === 0 ? classes.treeClass : ''}
96
71
  >
97
72
  {#each helper.getDirectChildren(tree, branchRootNode?.path ?? null) as node (getNodeId(node))}
98
- {@const nesthighlighed = highlightNesting(node, highlightedNode, validTarget, canNest)}
99
- {@const insertHighlighted = highlightInsert(node, highlightedNode, validTarget, canNest)}
100
73
  {@const expanded = isExpanded(node, childDepth, expandTo)}
101
- {@const hasChildren = node.hasChildren}
102
- {@const draggable = !readonly && dragAndDrop && node.isDraggable}
103
- {@const isCurrentlyDragged =
104
- draggedPath == node.path || (draggedPath && node.path?.startsWith(draggedPath))}
105
-
74
+ {@const draggable = !readonly && dragAndDrop && !node.dragDisabled}
75
+ {@const isCurrentlyDragged = draggedNode && node.path.startsWith(draggedNode?.path)}
76
+ {@const effectiveHighlight = getHighlighMode(node, highlightedNode, insertionType)}
106
77
  <li
107
78
  class:is-child={helper.nodePathIsChild(node.path)}
108
- class:has-children={hasChildren}
79
+ class:has-children={node.hasChildren}
109
80
  on:contextmenu|stopPropagation={(e) => {
110
81
  dispatch('open-ctxmenu', { e: e, node: Node });
111
82
  }}
112
83
  on:drop|stopPropagation={(e) => handleDragDrop(e, node, liElements[getNodeId(node)])}
113
- on:dragover|stopPropagation={(e) => handleDragOver(e, node, liElements[getNodeId(node)])}
84
+ on:dragover|stopPropagation={(e) =>
85
+ handleDragOver(e, node, liElements[getNodeId(node)], false)}
114
86
  on:dragenter|stopPropagation={(e) => handleDragEnter(e, node, liElements[getNodeId(node)])}
115
87
  on:dragleave|stopPropagation={(e) => handleDragLeave(e, node, liElements[getNodeId(node)])}
116
88
  bind:this={liElements[getNodeId(node)]}
117
89
  >
118
- {#if insPos == InsertionType.above && insertHighlighted}
90
+ {#if effectiveHighlight == InsertionType.insertAbove}
119
91
  <div class="insert-line-wrapper">
120
92
  <div class="insert-line {classes.inserLineClass}" />
121
93
  </div>
@@ -124,26 +96,24 @@ let liElements = {};
124
96
  <!-- svelte-ignore a11y-no-static-element-interactions -->
125
97
  <div
126
98
  class="tree-item
127
- {nesthighlighed ? classes.expandClass : ''}
99
+ {effectiveHighlight === InsertionType.nest ? classes.expandClass : ''}
128
100
  {classes.nodeClass} {isCurrentlyDragged ? classes.currentlyDraggedClass : ''}"
129
- class:div-has-children={hasChildren}
130
- class:hover={insertHighlighted || nesthighlighed}
101
+ class:div-has-children={node.hasChildren}
102
+ class:hover={effectiveHighlight !== InsertionType.none}
131
103
  {draggable}
132
104
  on:dragstart={(e) => handleDragStart(e, node)}
133
105
  on:dragend={(e) => handleDragEnd(e, node)}
134
106
  >
135
- {#if hasChildren}
136
- <!-- svelte-ignore a11y-click-events-have-key-events -->
137
- <span on:click={() => setExpansion(node, !expanded)}>
138
- <!-- use callback overrides expanded -->
139
- <i
140
- class="far {expanded ? classes.expandedToggleClass : classes.collapsedToggleClass}"
141
- class:fa-minus-square={expanded}
142
- class:fa-plus-square={!expanded || node.useCallback}
143
- />
144
- </span>
107
+ {#if node.hasChildren}
108
+ <button
109
+ class="expansion-button"
110
+ on:click={() => setExpansion(node, !expanded)}
111
+ type="button"
112
+ >
113
+ <i class="fa-fw {expanded ? classes.collapseIcon : classes.expandIcon}" />
114
+ </button>
145
115
  {:else}
146
- <span />
116
+ <span class="fa-fw" />
147
117
  {/if}
148
118
 
149
119
  <Checkbox
@@ -158,16 +128,21 @@ let liElements = {};
158
128
  <span class:pointer-cursor={draggable}>
159
129
  <slot node={node.originalNode} />
160
130
  </span>
161
- </div>
162
131
 
163
- {#if nesthighlighed}
164
- <div class="insert-line-wrapper">
165
- <div
166
- class="insert-line insert-line-child {classes.inserLineClass} {classes.inserLineNestClass}"
167
- />
168
- </div>
169
- {/if}
170
- {#if expanded && hasChildren}
132
+ {#if dragAndDrop && node.nestAllowed}
133
+ <span
134
+ on:dragover|stopPropagation={(e) =>
135
+ handleDragOver(e, node, liElements[getNodeId(node)], true)}
136
+ >
137
+ <i class="fa-fw {classes.nestIcon}" />
138
+
139
+ {#if effectiveHighlight === InsertionType.nest}
140
+ <slot name="nest-highlight" />
141
+ {/if}
142
+ </span>
143
+ {/if}
144
+ </div>
145
+ {#if expanded && node.hasChildren}
171
146
  <svelte:self
172
147
  branchRootNode={node}
173
148
  childDepth={childDepth + 1}
@@ -181,26 +156,33 @@ let liElements = {};
181
156
  {onlyLeafCheckboxes}
182
157
  {hideDisabledCheckboxes}
183
158
  {expandTo}
184
- {draggedPath}
185
159
  {dragAndDrop}
186
160
  {verticalLines}
187
- {canNest}
188
- {insPos}
189
- {validTarget}
161
+ {draggedNode}
190
162
  {highlightedNode}
163
+ {insertionType}
191
164
  on:open-ctxmenu
192
165
  on:internal-expand
193
166
  on:internal-selectionChanged
167
+ on:internal-handleDragStart
168
+ on:internal-handleDragDrop
169
+ on:internal-handleDragOver
170
+ on:internal-handleDragEnter
171
+ on:internal-handleDragEnd
172
+ on:internal-handleDragLeave
194
173
  let:node={nodeNested}
195
174
  >
196
175
  <slot node={nodeNested} />
176
+ <svelte:fragment slot="nest-highlight">
177
+ <slot name="nest-highlight" />
178
+ </svelte:fragment>
197
179
  </svelte:self>
198
180
  {/if}
199
- {#if !expanded && hasChildren}
181
+ {#if !expanded && node.hasChildren}
200
182
  <ul class:child-menu={childDepth > 0} />
201
183
  {/if}
202
184
  <!-- Show line if insering -->
203
- {#if insPos === InsertionType.below && insertHighlighted}
185
+ {#if effectiveHighlight === InsertionType.insertBelow}
204
186
  <div class="insert-line-wrapper">
205
187
  <div class="insert-line {classes.inserLineClass}" />
206
188
  </div>
@@ -1,6 +1,6 @@
1
1
  import { SvelteComponent } from "svelte";
2
- import { SelectionModes, InsertionType, type Node } from './types.js';
3
- import type { CustomizableClasses, TreeHelper } from './index.js';
2
+ import { SelectionModes, InsertionType, type Node, type CustomizableClasses } from './types.js';
3
+ import type { TreeHelper } from './helpers/tree-helper.js';
4
4
  declare const __propDef: {
5
5
  props: {
6
6
  tree: Node[];
@@ -15,19 +15,18 @@ declare const __propDef: {
15
15
  expandTo: number;
16
16
  classes: CustomizableClasses;
17
17
  helper: TreeHelper;
18
- draggedPath: string | null;
19
- highlightedNode: Node | null;
20
18
  childDepth: number;
21
19
  branchRootNode: Node | null;
22
- canNest: boolean;
23
- validTarget: boolean;
24
- insPos: InsertionType;
20
+ draggedNode: Node | null;
21
+ highlightedNode: Node | null;
22
+ insertionType: InsertionType;
25
23
  };
26
24
  events: {
27
25
  'open-ctxmenu': CustomEvent<any>;
28
26
  'internal-expand': CustomEvent<any>;
29
27
  'internal-selectionChanged': CustomEvent<any>;
30
28
  'internal-handleDragStart': CustomEvent<any>;
29
+ 'internal-handleDragDrop': CustomEvent<any>;
31
30
  'internal-handleDragOver': CustomEvent<any>;
32
31
  'internal-handleDragEnter': CustomEvent<any>;
33
32
  'internal-handleDragEnd': CustomEvent<any>;
@@ -39,6 +38,7 @@ declare const __propDef: {
39
38
  default: {
40
39
  node: any;
41
40
  };
41
+ 'nest-highlight': {};
42
42
  };
43
43
  };
44
44
  export type BranchProps = typeof __propDef.props;
@@ -8,8 +8,10 @@ export let onlyLeafCheckboxes;
8
8
  export let hideDisabledCheckboxes;
9
9
  export let readonly = false;
10
10
  const dispatch = createEventDispatcher();
11
- function onSelect(node) {
11
+ function onSelect(e, node) {
12
+ // e.preventDefault();
12
13
  dispatch('select', { node });
14
+ return false;
13
15
  }
14
16
  </script>
15
17
 
@@ -18,7 +20,8 @@ function onSelect(node) {
18
20
  {#if !recursive || (recursive && !node.hasChildren) || !onlyLeafCheckboxes}
19
21
  <input
20
22
  type="checkbox"
21
- on:change={() => onSelect(node)}
23
+ on:click={(e) => onSelect(e, node)}
24
+ on:keypress={(e) => e.key === 'Enter' && onSelect(e, node)}
22
25
  checked={node.visualState === VisualState.selected}
23
26
  indeterminate={node.visualState === VisualState.indeterminate}
24
27
  disabled={readonly}
@@ -1,10 +1,11 @@
1
- <script generics="T">import ContextMenu from './menu/ContextMenu.svelte';
2
- import { createEventDispatcher, onMount } from 'svelte';
3
- import { defaultClasses, defaultPixelTreshold, defaultPropNames } from './constants.js';
4
- import { SelectionModes as SelectionModes, VisualState } from './types.js';
1
+ <script>import ContextMenu from './menu/ContextMenu.svelte';
2
+ import { createEventDispatcher } from 'svelte';
3
+ import { defaultClasses, defaultPropNames } from './constants.js';
4
+ import { SelectionModes as SelectionModes, InsertionType } from './types.js';
5
5
  import { TreeHelper } from './index.js';
6
6
  import Branch from './Branch.svelte';
7
7
  import { SelectionProvider } from './providers/selection-provider.js';
8
+ import { DragDropProvider } from './providers/drag-drop-provider.js';
8
9
  const dispatch = createEventDispatcher();
9
10
  export let treeId;
10
11
  /**
@@ -76,8 +77,7 @@ export let expandTo = 0;
76
77
  * Classes used in tree. You can override default classes with this prop.
77
78
  * It is recommended to use default classes and add aditinal styles in your css
78
79
  */
79
- export let customClasses = defaultClasses;
80
- // use any so use doesnt have to cast from unknown
80
+ export let customClasses = {};
81
81
  /**
82
82
  * Function used to filter what nodes should be shown.
83
83
  * Tree automatically adds all parents for nodes.
@@ -91,43 +91,54 @@ export let filter = null;
91
91
  * Used mostly for debugging
92
92
  */
93
93
  export let logger = null;
94
- // props for drag and drop
94
+ // TODO rewrite documentation
95
+ /*
96
+ * Drag and drop mode allows all nodes, that dont have dragDisabled property set to true
97
+ * to be dragged and dropped. By default you can only insert at same level node you are dropping on,
98
+ * but you can allow nesting by setting nestAllowed to true on node. If you want to disable insertion,
99
+ * set dropDisabled to true on node. if both is disabled, you wont be able to drop on node.
100
+ */
95
101
  export let dragAndDrop = false; //bool
96
- export let timeToNest = null;
97
- export let pixelNestTreshold = defaultPixelTreshold;
98
- export let recalculateNodePath = true;
99
- export let dragEnterCallback = null;
100
- export let beforeMovedCallback = null;
102
+ /**
103
+ * Callback that will be called when user drags above node.
104
+ * It should return true, if drop is disabled on that node.
105
+ */
106
+ export let dropDisabledCallback = null;
101
107
  let ctxMenu;
102
108
  let expandedIds = [];
103
- // OLD variables, will be removed/changed in future
104
- let draggedPath = null;
109
+ let draggedNode = null;
105
110
  let highlightedNode = null;
106
- let canNest = false;
107
- let validTarget = false;
108
- let insPos;
111
+ let insertionType = InsertionType.none;
112
+ $: computedClasses = { ...defaultClasses, ...(customClasses ?? {}) };
109
113
  $: dragAndDrop && console.warn('Drag and drop is not supported in this version');
110
114
  $: helper = new TreeHelper({
111
115
  separator
112
116
  });
117
+ $: dragAndDropProvider = new DragDropProvider(helper);
113
118
  $: selectionProvider = new SelectionProvider(helper, recursiveSelection);
114
119
  $: computedTree = computeTree(helper, selectionProvider, tree, filter, props, expandedIds, value);
115
120
  $: debugLog('computedTree', computedTree);
116
121
  export function changeAllExpansion(changeTo) {
117
122
  debugLog('chaning expantion of every node to ', changeTo ? 'expanded' : 'collapsed');
118
- expandedIds = computedTree.map((node) => node.id);
123
+ if (changeTo) {
124
+ expandedIds = computedTree.map((node) => node.id);
125
+ }
126
+ else {
127
+ expandedIds = [];
128
+ }
119
129
  }
120
130
  function computeTree(helper, selectionProvider, userProvidedTree, filter, props, expandedIds, value) {
121
131
  if (!Array.isArray(userProvidedTree) || !Array.isArray(value)) {
122
132
  console.error('value and tree must be arrays!!');
123
133
  return [];
124
134
  }
125
- let mappedTree = helper.mapTree(userProvidedTree, filter, { ...defaultPropNames, ...props });
126
- helper.markExpanded(mappedTree, expandedIds);
135
+ const mappedTree = helper.mapTree(userProvidedTree, { ...defaultPropNames, ...props });
136
+ const filteredTree = helper.searchTree(mappedTree, filter);
137
+ helper.markExpanded(filteredTree, expandedIds);
127
138
  // TODO here we could save last value and only recompute visual state if value changed
128
139
  // or use diff to only update affected nodes
129
- selectionProvider.markSelected(mappedTree, value);
130
- return mappedTree;
140
+ selectionProvider.markSelected(filteredTree, value);
141
+ return filteredTree;
131
142
  }
132
143
  function onExpand(event) {
133
144
  const { node, changeTo } = event.detail;
@@ -160,6 +171,7 @@ function handleCallback(node) {
160
171
  }
161
172
  debugLog('calling callback for node', node);
162
173
  // TODO mark node as loaded and dont call callback again
174
+ // this is now responsibility of user
163
175
  loadChildrenAsync(node);
164
176
  }
165
177
  function onSelectionChanged(event) {
@@ -187,6 +199,69 @@ function openContextMenu(ce) {
187
199
  e.preventDefault();
188
200
  ctxMenu.onRightClick(e, node);
189
201
  }
202
+ function onDragStart(event) {
203
+ const { node, e } = event.detail;
204
+ draggedNode = null;
205
+ if (!dragAndDrop || node.dragDisabled) {
206
+ return;
207
+ }
208
+ draggedNode = node;
209
+ }
210
+ function onDragEnd({ detail: { node, event, element } }) {
211
+ // fires when you stop dragging element
212
+ draggedNode = null;
213
+ highlightedNode = null;
214
+ }
215
+ function onDragDrop({ detail: { node, event, element } }) {
216
+ // here we asume that highlightType is correctly calculated in handleDragOver
217
+ if (!dragAndDrop || draggedNode === null || insertionType === InsertionType.none) {
218
+ event.preventDefault();
219
+ return;
220
+ }
221
+ highlightedNode = null;
222
+ debugLog('DROPPED: ', draggedNode, 'on', node);
223
+ dispatch('moved', {
224
+ node: draggedNode,
225
+ target: node,
226
+ insertType: insertionType
227
+ });
228
+ }
229
+ // handle highlihting
230
+ function onDragEnter({ detail: { node, event, element } }) {
231
+ highlightedNode = null;
232
+ if (!draggedNode || !dragAndDrop) {
233
+ return;
234
+ }
235
+ // static rules
236
+ if (!dragAndDropProvider.isDropAllowed(draggedNode, node)) {
237
+ return;
238
+ }
239
+ if (typeof dropDisabledCallback === 'function') {
240
+ // possible bug, if the promise is resolved, when user is over another node
241
+ dropDisabledCallback(draggedNode, node).then((dropDisabled) => {
242
+ if (!dropDisabled) {
243
+ highlightedNode = node;
244
+ }
245
+ });
246
+ }
247
+ else {
248
+ highlightedNode = node;
249
+ }
250
+ }
251
+ function onDragOver({ detail: { node, event, element, nest } }) {
252
+ if (!dragAndDrop || draggedNode === null || node.dropDisabled) {
253
+ return;
254
+ }
255
+ const insertType = dragAndDropProvider.getInsertionPosition(draggedNode, node, event, element, nest);
256
+ if (insertType === InsertionType.none) {
257
+ return;
258
+ }
259
+ event.preventDefault();
260
+ insertionType = insertType;
261
+ }
262
+ function onDragLeave({ detail: { node, event, element } }) {
263
+ insertionType = InsertionType.none;
264
+ }
190
265
  function debugLog(...data) {
191
266
  if (logger) {
192
267
  logger(...data);
@@ -203,25 +278,31 @@ function debugLog(...data) {
203
278
  {onlyLeafCheckboxes}
204
279
  {hideDisabledCheckboxes}
205
280
  {expandTo}
206
- {draggedPath}
207
281
  {dragAndDrop}
208
- {highlightedNode}
209
282
  {readonly}
210
283
  {helper}
211
- classes={customClasses}
284
+ classes={computedClasses}
212
285
  {verticalLines}
213
286
  on:open-ctxmenu={openContextMenu}
214
287
  on:internal-expand={onExpand}
215
288
  on:internal-selectionChanged={onSelectionChanged}
216
289
  let:node={nodeInSlot}
217
290
  childDepth={0}
218
- {canNest}
219
- {validTarget}
220
- {insPos}
291
+ {insertionType}
292
+ {highlightedNode}
293
+ {draggedNode}
294
+ on:internal-handleDragStart={onDragStart}
295
+ on:internal-handleDragDrop={onDragDrop}
296
+ on:internal-handleDragOver={onDragOver}
297
+ on:internal-handleDragEnter={onDragEnter}
298
+ on:internal-handleDragEnd={onDragEnd}
299
+ on:internal-handleDragLeave={onDragLeave}
221
300
  >
222
301
  <slot node={nodeInSlot} />
302
+ <svelte:fragment slot="nest-highlight">
303
+ <slot name="nest-highlight" />
304
+ </svelte:fragment>
223
305
  </Branch>
224
-
225
306
  <ContextMenu bind:this={ctxMenu}>
226
307
  <svelte:fragment let:node>
227
308
  <slot name="context-menu" {node} />
@@ -285,9 +366,6 @@ function debugLog(...data) {
285
366
  font-weight: 700;
286
367
  position: relative;
287
368
  }
288
- :global(.treeview) :global(li:not(.has-children)) :global(.tree-item) {
289
- margin-left: 14px;
290
- }
291
369
  :global(.treeview) :global(.tree-item) {
292
370
  display: flex;
293
371
  column-gap: 0.4em;
@@ -323,8 +401,7 @@ function debugLog(...data) {
323
401
  display: block;
324
402
  border-radius: 3px;
325
403
  margin-left: 28px;
326
- margin-bottom: -2px;
327
- margin-top: -2px;
404
+ pointer-events: none;
328
405
  }
329
406
  :global(.treeview) :global(.insert-line-child) {
330
407
  margin-left: calc(28px + 5em);
@@ -339,4 +416,7 @@ function debugLog(...data) {
339
416
  }
340
417
  :global(.treeview) :global(.pointer-cursor) {
341
418
  cursor: grab;
419
+ }
420
+ :global(.treeview) :global(.expansion-button) {
421
+ all: unset;
342
422
  }</style>
@@ -1,7 +1,7 @@
1
1
  import { SvelteComponent } from "svelte";
2
- import { SelectionModes as SelectionModes, type Props, type CustomizableClasses, type DragEnterCallback, type BeforeMovedCallback, type ExpandedCallback, type NodeId, type ProvidedTree, type FilterFunction } from './types.js';
3
- declare class __sveltets_Render<T> {
4
- props(): {
2
+ import { SelectionModes as SelectionModes, type Props, type CustomizableClasses, type DragEnterCallback, type ExpandedCallback, type NodeId, type ProvidedTree, type FilterFunction } from './types.js';
3
+ declare const __propDef: {
4
+ props: {
5
5
  treeId: string;
6
6
  /**
7
7
  * Array of nodes that represent tree structure.
@@ -58,7 +58,7 @@ declare class __sveltets_Render<T> {
58
58
  /**
59
59
  * Classes used in tree. You can override default classes with this prop.
60
60
  * It is recommended to use default classes and add aditinal styles in your css
61
- */ customClasses?: CustomizableClasses | undefined;
61
+ */ customClasses?: Partial<CustomizableClasses> | undefined;
62
62
  /**
63
63
  * Function used to filter what nodes should be shown.
64
64
  * Tree automatically adds all parents for nodes.
@@ -71,14 +71,13 @@ declare class __sveltets_Render<T> {
71
71
  * Used mostly for debugging
72
72
  */ logger?: ((...data: any[]) => void) | null | undefined;
73
73
  dragAndDrop?: boolean | undefined;
74
- timeToNest?: number | null | undefined;
75
- pixelNestTreshold?: number | undefined;
76
- recalculateNodePath?: boolean | undefined;
77
- dragEnterCallback?: DragEnterCallback | null | undefined;
78
- beforeMovedCallback?: BeforeMovedCallback | null | undefined;
74
+ /**
75
+ * Callback that will be called when user drags above node.
76
+ * It should return true, if drop is disabled on that node.
77
+ */ dropDisabledCallback?: DragEnterCallback | null | undefined;
79
78
  changeAllExpansion?: ((changeTo: boolean) => void) | undefined;
80
79
  };
81
- events(): {
80
+ events: {
82
81
  expansion: CustomEvent<any>;
83
82
  expanded: CustomEvent<any>;
84
83
  closed: CustomEvent<any>;
@@ -86,22 +85,24 @@ declare class __sveltets_Render<T> {
86
85
  selection: CustomEvent<any>;
87
86
  selected: CustomEvent<any>;
88
87
  unselected: CustomEvent<any>;
88
+ moved: CustomEvent<any>;
89
89
  } & {
90
90
  [evt: string]: CustomEvent<any>;
91
91
  };
92
- slots(): {
92
+ slots: {
93
93
  default: {
94
94
  node: any;
95
95
  };
96
+ 'nest-highlight': {};
96
97
  'context-menu': {
97
98
  node: any;
98
99
  };
99
100
  };
100
- }
101
- export type TreeViewProps<T> = ReturnType<__sveltets_Render<T>['props']>;
102
- export type TreeViewEvents<T> = ReturnType<__sveltets_Render<T>['events']>;
103
- export type TreeViewSlots<T> = ReturnType<__sveltets_Render<T>['slots']>;
104
- export default class TreeView<T> extends SvelteComponent<TreeViewProps<T>, TreeViewEvents<T>, TreeViewSlots<T>> {
101
+ };
102
+ export type TreeViewProps = typeof __propDef.props;
103
+ export type TreeViewEvents = typeof __propDef.events;
104
+ export type TreeViewSlots = typeof __propDef.slots;
105
+ export default class TreeView extends SvelteComponent<TreeViewProps, TreeViewEvents, TreeViewSlots> {
105
106
  get changeAllExpansion(): (changeTo: boolean) => void;
106
107
  }
107
108
  export {};
@@ -1,5 +1,4 @@
1
- import { type HelperConfig, type CustomizableClasses, type Props } from './types.js';
1
+ import type { HelperConfig, CustomizableClasses, Props } from './types.js';
2
2
  export declare const defaultPropNames: Props;
3
- export declare const defaultPixelTreshold = 50;
4
3
  export declare const defaultClasses: CustomizableClasses;
5
4
  export declare const defaultConfig: HelperConfig;
package/dist/constants.js CHANGED
@@ -1,25 +1,23 @@
1
- import { SelectionModes } from './types.js';
2
1
  export const defaultPropNames = {
3
2
  nodePath: 'nodePath',
4
3
  nodeId: 'nodePath',
5
4
  hasChildren: 'hasChildren',
6
5
  useCallback: '__useCallback',
7
6
  priority: 'priority',
8
- isDraggable: 'isDraggable',
7
+ dragDisabled: 'dragDisabled',
9
8
  insertDisabled: 'insertDisabled',
10
- nestDisabled: 'nestDisabled',
9
+ nestAllowed: 'nestAllowed',
11
10
  checkbox: 'checkbox'
12
11
  };
13
- export const defaultPixelTreshold = 50;
14
12
  export const defaultClasses = {
15
13
  treeClass: 'treeview',
16
14
  expandClass: 'inserting-highlighted',
17
15
  currentlyDraggedClass: 'currently-dragged',
18
16
  nodeClass: '',
19
- expandedToggleClass: '',
20
- collapsedToggleClass: '',
17
+ expandIcon: 'far fa-fw fa-plus-square',
18
+ collapseIcon: 'far fa-fw fa-minus-square',
21
19
  inserLineClass: '',
22
- inserLineNestClass: ''
20
+ nestIcon: 'fas fa-level-down-alt'
23
21
  };
24
22
  export const defaultConfig = {
25
23
  separator: '.'
@@ -1,16 +1,16 @@
1
- import { type Node, type NodePath, type HelperConfig, type Tree, type NodeId, type Props, type FilterFunction } from '../types.js';
1
+ import { type Node, type HelperConfig, type Tree, type NodeId, type Props, type FilterFunction } from '../types.js';
2
2
  export declare class TreeHelper {
3
3
  config: HelperConfig;
4
4
  constructor(config?: HelperConfig);
5
- mapTree(tree: Tree, filter: FilterFunction | null, properties: Props): Node[];
5
+ mapTree(tree: Tree, properties: Props): Node[];
6
6
  markExpanded(tree: Tree, expandedNodeIds: NodeId[]): void;
7
- getParentNodePath(nodePath: NodePath): NodePath;
8
- isChildrenOf(parentNodePath: NodePath, childrenNodePath: NodePath): boolean | undefined;
9
- hasChildren(tree: Tree, nodePath: NodePath): Node | undefined;
10
- findNode(tree: Tree, nodePath: NodePath): Node | null;
11
- nodePathIsChild(nodePath: NodePath): boolean | undefined;
12
- getDirectChildren(tree: Tree, parentNodePath: NodePath): Tree;
13
- allCHildren(tree: Tree, parentNodePath: NodePath): Node[];
7
+ getParentNodePath(nodePath: string): string | null;
8
+ isChildrenOf(parentNodePath: string | null, childrenNodePath: string): boolean;
9
+ hasChildren(tree: Tree, nodePath: string): Node | undefined;
10
+ findNode(tree: Tree, nodePath: string): Node | null;
11
+ nodePathIsChild(nodePath: string): boolean;
12
+ getDirectChildren(tree: Tree, parentNodePath: string | null): Tree;
13
+ allCHildren(tree: Tree, parentNodePath: string | null): Node[];
14
14
  getAllLeafNodes(tree: Tree): Node[];
15
15
  joinTrees(filteredTree: Tree, tree: Tree): Node[];
16
16
  mergeTrees(oldTree: Tree, addedTree: Tree, nodePath?: string): Node[];
@@ -20,7 +20,7 @@ export declare class TreeHelper {
20
20
  /** changes expansion of every node that has this.hasChildren set to true if they are abose set level and expansion property isnt set
21
21
  */
22
22
  expandToLevel(tree: Tree, level: number): NodeId[];
23
- getDepthLevel(nodePath: NodePath): number;
23
+ getDepthLevel(nodePath: string): number;
24
24
  searchTree(tree: Tree, filter: FilterFunction | null): Tree;
25
25
  getParents(tree: Tree, targetNode: Node): Node[];
26
26
  /** orders nodes by priorityProp
@@ -7,25 +7,27 @@ export class TreeHelper {
7
7
  constructor(config = defaultConfig) {
8
8
  this.config = config;
9
9
  }
10
- mapTree(tree, filter, properties) {
10
+ mapTree(tree, properties) {
11
11
  {
12
- return this.searchTree(tree, filter).map((node) => {
12
+ return tree.map((node) => {
13
13
  // TODO maybe create class for nodes
14
14
  const mappedNode = {
15
15
  originalNode: node,
16
16
  id: node[properties.nodeId],
17
17
  path: node[properties.nodePath],
18
- hasChildren: node[properties.hasChildren],
19
- useCallback: node[properties.useCallback],
18
+ hasChildren: node[properties.hasChildren] === true,
19
+ useCallback: node[properties.useCallback] === true,
20
20
  priority: node[properties.priority],
21
- isDraggable: node[properties.isDraggable],
22
- insertDisabled: node[properties.insertDisabled],
23
- nestDisabled: node[properties.nestDisabled],
24
- checkbox: node[properties.checkbox],
21
+ dragDisabled: node[properties.dragDisabled] === true,
22
+ insertDisabled: node[properties.insertDisabled] === true,
23
+ nestAllowed: node[properties.nestAllowed] === true,
24
+ checkbox: node[properties.checkbox] === true,
25
25
  expanded: false,
26
26
  selected: false,
27
- visualState: VisualState.notSelected
27
+ visualState: VisualState.notSelected,
28
+ dropDisabled: false
28
29
  };
30
+ mappedNode.dropDisabled = mappedNode.insertDisabled && !mappedNode.nestAllowed;
29
31
  return mappedNode;
30
32
  });
31
33
  }
@@ -129,10 +131,14 @@ export class TreeHelper {
129
131
  }
130
132
  getParents(tree, targetNode) {
131
133
  const parentsPaths = [];
132
- let nodePath = targetNode.path;
134
+ // TODO refactor
135
+ let nodePath = this.getParentNodePath(targetNode.path);
133
136
  // get all parents
134
- while (nodePath && nodePath.length > 0) {
137
+ while (nodePath !== null && nodePath !== '') {
135
138
  nodePath = this.getParentNodePath(nodePath);
139
+ if (nodePath === null) {
140
+ break;
141
+ }
136
142
  parentsPaths.push(nodePath);
137
143
  }
138
144
  //find nodes for given ids
@@ -47,5 +47,4 @@
47
47
  background: white;
48
48
  z-index: 999;
49
49
  }
50
-
51
50
  </style>
@@ -4,7 +4,6 @@
4
4
  width: 100%;
5
5
  margin: 2px 0;
6
6
  }
7
-
8
7
  </style>
9
8
 
10
9
 
@@ -46,5 +46,4 @@
46
46
  div.disabled:hover {
47
47
  background: white;
48
48
  }
49
-
50
49
  </style>
@@ -0,0 +1,9 @@
1
+ import type { TreeHelper } from '../helpers/tree-helper.js';
2
+ import { type Node, InsertionType } from '../types.js';
3
+ export declare class DragDropProvider {
4
+ helper: TreeHelper;
5
+ constructor(treeHelper: TreeHelper);
6
+ getInsertionPosition(draggendNode: Node, draggedOverNode: Node, e: DragEvent, element: HTMLElement, nest: boolean): InsertionType;
7
+ getRelativePosition(element: Element, e: DragEvent): InsertionType;
8
+ isDropAllowed(draggedNode: Node, targeNode: Node): boolean;
9
+ }
@@ -1,186 +1,33 @@
1
- "use strict";
2
- // import type { PropertyHelper } from '../helpers/property-helper.js';
3
- // import type { TreeHelper } from '../helpers/tree-helper.js';
4
- // import { InsertionType, type Node, type NodePath, type Tree } from '../types.js';
5
- // export class DragDropProvider {
6
- // helper: TreeHelper;
7
- // props: PropertyHelper;
8
- // separator: string;
9
- // constructor(treeHelper: TreeHelper) {
10
- // this.helper = treeHelper;
11
- // this.props = treeHelper.props;
12
- // this.separator = this.helper.config.separator ?? '.';
13
- // }
14
- // path(node: Node) {
15
- // return this.helper.path(node);
16
- // }
17
- // /**
18
- // * moves node from one parent to another
19
- // * @param {Object[]} tree - tree
20
- // * @param {nodePath} movedNodePath - nodepath of moved(dragged) node
21
- // * @param {nodePath} targetNodePath - nodepath of node where it should be moved ( either bellow it in priority or as child)
22
- // * @param {int} insType - if true, it will insert moved node as child of target node, if false, it will insert it bellow it in priority
23
- // * @param {boolean} recalculateNodePath - wont recalculare id of moved node, used when last part of nodePath is always unique
24
- // */
25
- // moveNode(
26
- // tree: Node[],
27
- // movedNodePath: NodePath,
28
- // targetNodePath: NodePath,
29
- // insType: InsertionType,
30
- // recalculateNodePath: boolean
31
- // ): Node[] {
32
- // // cannot move root node
33
- // if (!movedNodePath) return tree;
34
- // const isNesting = insType === InsertionType.nest;
35
- // // if you are not isNestinging, you want to be on same level
36
- // //so you will have same parent as target node
37
- // const parentNodePath = isNesting
38
- // ? targetNodePath
39
- // : this.helper.getParentNodePath(targetNodePath);
40
- // //trying to move parent to child
41
- // if (parentNodePath?.startsWith(movedNodePath)) {
42
- // return tree;
43
- // }
44
- // const changedParent = this.helper.getParentNodePath(movedNodePath) !== parentNodePath;
45
- // let newNodePath = movedNodePath;
46
- // //dont create new node if you only moved inside same parent
47
- // if (changedParent) {
48
- // newNodePath = this.calculateNewNodePath(
49
- // tree,
50
- // parentNodePath,
51
- // movedNodePath,
52
- // recalculateNodePath
53
- // );
54
- // }
55
- // //* find target node
56
- // const targetNode = this.helper.findNode(tree, targetNodePath);
57
- // if (!targetNode) return tree;
58
- // let movedNode;
59
- // //move nodes
60
- // tree = tree.map((node) => {
61
- // //make sure that parent's haschild is set to true, so that children are visible
62
- // if (this.path(node) == parentNodePath) {
63
- // this.props.setHasChildren(node, true);
64
- // this.props.setExpanded(node, true);
65
- // }
66
- // //move moved nodes to new location ( if location is being changed)
67
- // if (changedParent && this.path(node)?.startsWith(movedNodePath)) {
68
- // //replace old parent with new one
69
- // const newPath = this.path(node)?.replace(movedNodePath, newNodePath) ?? null;
70
- // this.props.setPath(node, newPath);
71
- // }
72
- // //if it is moved node
73
- // if (this.path(node) === newNodePath) {
74
- // movedNode = node;
75
- // //? not sure if this is best
76
- // this.updatePriority(tree, movedNode, parentNodePath, newNodePath, targetNode, insType);
77
- // }
78
- // return node;
79
- // });
80
- // if (!movedNode) return tree;
81
- // //* insert node at right possition of array
82
- // const oldIndex = tree.findIndex((x) => this.path(x) == newNodePath);
83
- // tree.splice(oldIndex, 1);
84
- // const index = tree.findIndex((x) => this.path(x) == this.path(targetNode));
85
- // tree.splice(index + (insType == InsertionType.above ? 0 : 1), 0, movedNode);
86
- // //TODO maybe add option to setting this.hasChildren to false when moved last children
87
- // //hide plus icon if parent of moved node doesnt have any more children
88
- // const oldParent = this.helper.findNode(tree, this.helper.getParentNodePath(movedNodePath));
89
- // if (!oldParent) return tree;
90
- // //moved last node
91
- // const oldParentHasChildren = this.helper.allCHildren(tree, this.path(oldParent)).length;
92
- // if (oldParent && !oldParentHasChildren) {
93
- // this.props.setHasChildren(oldParent, false);
94
- // }
95
- // return tree;
96
- // }
97
- // calculateNewNodePath(
98
- // tree: Tree,
99
- // parentNodePath: NodePath,
100
- // movedNodePath: NodePath,
101
- // recalculateNodePath: boolean
102
- // ) {
103
- // //node id is last part of nodePath
104
- // let nodeId;
105
- // if (recalculateNodePath) {
106
- // nodeId = this.getNextNodeId(tree, parentNodePath);
107
- // } else {
108
- // //get last segment of path
109
- // // nodeId = this.helper.getNodeIdFromPath(movedNodePath);
110
- // }
111
- // if (parentNodePath === null) return nodeId as string;
112
- // return `${parentNodePath}${this.separator}${nodeId}`;
113
- // }
114
- // updatePriority(
115
- // tree: Tree,
116
- // node: Node,
117
- // parentNodePath: NodePath,
118
- // newNodePath: NodePath,
119
- // targetNode: Node,
120
- // insType: InsertionType
121
- // ) {
122
- // const isNesting = insType == InsertionType.nest;
123
- // if (isNesting || this.props.priority(targetNode) != null) {
124
- // let newpriority = 0;
125
- // if (!isNesting) {
126
- // //calculate next
127
- // newpriority = this.props.priority(targetNode) ?? 0;
128
- // if (insType == InsertionType.below) {
129
- // newpriority += 1;
130
- // } else {
131
- // //targetNode[this.props.priority] -= 1;
132
- // }
133
- // }
134
- // this.recalculatesPriorities(tree, parentNodePath, newNodePath, newpriority);
135
- // this.props.setPriority(targetNode, newpriority);
136
- // } else {
137
- // //so old priority doesnt mess up orderring
138
- // this.props.setPriority(targetNode, undefined);
139
- // }
140
- // }
141
- // /** recomputes all priorities after inserted priority.F
142
- // * Also changes all priorities to be one apart (1,5,6 => 1,2,3)
143
- // */
144
- // //? maybe it will recalculate properly if dont set insertedPriority
145
- // recalculatesPriorities(
146
- // tree: Tree,
147
- // parentNode: NodePath,
148
- // movedNodePath: NodePath,
149
- // insertedPriority = -1
150
- // ) {
151
- // let nextPriority = insertedPriority + 1;
152
- // this.helper.orderByPriority(this.helper.allCHildren(tree, parentNode)).forEach((node) => {
153
- // if (this.props.priority(node) >= insertedPriority && this.path(node) != movedNodePath) {
154
- // this.props.setPriority(node, nextPriority++);
155
- // }
156
- // });
157
- // }
158
- // /** return biggest value of nodepath number that children are using +1 */
159
- // getNextNodeId(tree: Tree, parentPath: NodePath) {
160
- // let max = 0;
161
- // //findes biggest nodeNumber for
162
- // this.helper.allCHildren(tree, parentPath).forEach((node) => {
163
- // const parent = this.helper.getParentNodePath(this.path(node));
164
- // if (parent === parentPath) {
165
- // const num = parseInt(this.path(node)?.substring(parent ? parent.length + 1 : 0) ?? '0');
166
- // max = Math.max(max, num);
167
- // }
168
- // });
169
- // return (max + 1).toString();
170
- // }
171
- // getInsertionPosition(e: DragEvent, element: HTMLElement): InsertionType {
172
- // const targetCords = element.getBoundingClientRect();
173
- // const half = targetCords.bottom - targetCords.height / 2;
174
- // if (e.y < half) {
175
- // return InsertionType.below;
176
- // }
177
- // return InsertionType.above;
178
- // }
179
- // getNodeIdFromPath(nodePath: NodePath) {
180
- // if (nodePath == null) {
181
- // console.warn('getting node id of null node path');
182
- // return null;
183
- // }
184
- // return nodePath?.split(this.helper.config.separator).slice(-1)[0];
185
- // }
186
- // }
1
+ import { InsertionType } from '../types.js';
2
+ export class DragDropProvider {
3
+ helper;
4
+ constructor(treeHelper) {
5
+ this.helper = treeHelper;
6
+ }
7
+ getInsertionPosition(draggendNode, draggedOverNode, e, element, nest) {
8
+ if (nest && draggedOverNode.nestAllowed) {
9
+ return InsertionType.nest;
10
+ }
11
+ if (draggedOverNode.insertDisabled) {
12
+ return InsertionType.none;
13
+ }
14
+ return this.getRelativePosition(element, e);
15
+ }
16
+ getRelativePosition(element, e) {
17
+ const targetCords = element.getBoundingClientRect();
18
+ const half = targetCords.bottom - targetCords.height / 2;
19
+ if (e.y < half) {
20
+ return InsertionType.insertAbove;
21
+ }
22
+ return InsertionType.insertBelow;
23
+ }
24
+ isDropAllowed(draggedNode, targeNode) {
25
+ if (targeNode.dropDisabled) {
26
+ return false;
27
+ }
28
+ if (targeNode.path.startsWith(draggedNode.path + this.helper.config.separator)) {
29
+ return false;
30
+ }
31
+ return true;
32
+ }
33
+ }
@@ -1,5 +1,5 @@
1
1
  import type { TreeHelper } from '../helpers/tree-helper.js';
2
- import { SelectionModes, type NodePath, type Tree, type TreeVisualStates, type Node, type NodeId } from '../types.js';
2
+ import { SelectionModes, type Tree, type TreeVisualStates, type Node, type NodeId } from '../types.js';
3
3
  export declare class SelectionProvider {
4
4
  helper: TreeHelper;
5
5
  recursiveMode: boolean;
@@ -8,7 +8,7 @@ export declare class SelectionProvider {
8
8
  isNodeSelected(node: Node): boolean;
9
9
  isSelected(nodeId: string, visualStates: TreeVisualStates, selectedNodeIds: NodeId[]): boolean;
10
10
  getSelectableDirectChildren(tree: Tree, parentNodePath: string | null): Node[];
11
- setSelection(tree: Tree, nodePath: NodePath, changeTo: boolean, oldSelection: NodeId[]): NodeId[];
11
+ setSelection(tree: Tree, nodePath: string | null, changeTo: boolean, oldSelection: NodeId[]): NodeId[];
12
12
  /** Computes visual states for all nodes. Used for computing initial visual states when tree changes */
13
13
  computeVisualStates(tree: Tree, selectedNodeIds: (string | number)[]): TreeVisualStates;
14
14
  private computeVisualState;
@@ -38,7 +38,7 @@ export class SelectionProvider {
38
38
  .filter((node) => isSelectable(node, SelectionModes.all));
39
39
  }
40
40
  setSelection(tree, nodePath, changeTo, oldSelection) {
41
- const node = this.helper.findNode(tree, nodePath);
41
+ const node = nodePath ? this.helper.findNode(tree, nodePath) : null;
42
42
  const nodeHasChildren = node ? node.hasChildren : false;
43
43
  // allow selection of root node
44
44
  if (nodePath === null || (this.recursiveMode && nodeHasChildren)) {
@@ -52,9 +52,6 @@ $treeview-lines: solid black 1px
52
52
  color: #555
53
53
  font-weight: 700
54
54
  position: relative
55
- &:not(.has-children)
56
- .tree-item
57
- margin-left: 14px
58
55
 
59
56
  .tree-item
60
57
  display: flex
@@ -89,8 +86,9 @@ $treeview-lines: solid black 1px
89
86
  display: block
90
87
  border-radius: 3px
91
88
  margin-left: 28px
92
- margin-bottom: -2px
93
- margin-top: -2px
89
+ pointer-events: none //! this is needed to fix flickering issue
90
+ // margin-bottom: -2px
91
+ // margin-top: -2px
94
92
  .insert-line-child
95
93
  margin-left: calc( 28px + 5em )
96
94
  background-color: red
@@ -103,3 +101,5 @@ $treeview-lines: solid black 1px
103
101
  color: LightGray
104
102
  .pointer-cursor
105
103
  cursor: grab
104
+ .expansion-button
105
+ all: unset
package/dist/types.d.ts CHANGED
@@ -4,14 +4,14 @@ export type Props = {
4
4
  hasChildren: string;
5
5
  useCallback: string;
6
6
  priority: string;
7
- isDraggable: string;
7
+ dragDisabled: string;
8
8
  insertDisabled: string;
9
- nestDisabled: string;
9
+ nestAllowed: string;
10
10
  checkbox: string;
11
11
  };
12
12
  export type MappedNode = {
13
13
  id: NodeId;
14
- path: NodePath;
14
+ path: string;
15
15
  hasChildren: boolean;
16
16
  useCallback: boolean;
17
17
  priority: number;
@@ -23,17 +23,18 @@ export type MappedNode = {
23
23
  export type Node = {
24
24
  originalNode: any;
25
25
  id: NodeId;
26
- path: NodePath;
26
+ path: string;
27
27
  hasChildren: boolean;
28
28
  useCallback: boolean;
29
29
  priority: number;
30
- isDraggable: boolean;
30
+ dragDisabled: boolean;
31
31
  insertDisabled: boolean;
32
- nestDisabled: boolean;
32
+ nestAllowed: boolean;
33
33
  checkbox: boolean;
34
34
  visualState: VisualState;
35
35
  expanded: boolean;
36
36
  selected: boolean;
37
+ dropDisabled: boolean;
37
38
  };
38
39
  export declare enum VisualState {
39
40
  indeterminate = "indeterminate",
@@ -46,30 +47,24 @@ export declare enum SelectionModes {
46
47
  none = "none"
47
48
  }
48
49
  export type Tree = Node[];
49
- export declare enum InsertionType {
50
- above = "above",
51
- below = "below",
52
- nest = "nest"
53
- }
54
- export type NodePath = string | null;
55
50
  export type NodeId = string | number;
56
51
  export type CustomizableClasses = {
57
52
  treeClass: string;
58
53
  nodeClass: string;
59
- expandedToggleClass: string;
60
- collapsedToggleClass: string;
54
+ expandIcon: string;
55
+ collapseIcon: string;
56
+ nestIcon: string;
61
57
  expandClass: string;
62
58
  inserLineClass: string;
63
- inserLineNestClass: string;
64
59
  currentlyDraggedClass: string;
65
60
  };
66
- export type DragEnterCallback = (draggendNode: Node, oldParent: Node, newParent: Node) => boolean;
61
+ export type DragEnterCallback = (draggendNode: Node, targetNode: Node) => Promise<boolean>;
67
62
  export type BeforeMovedCallback = (draggendNode: Node, oldParent: Node, newParent: Node, insertionType: string) => boolean;
68
63
  export type ExpandedCallback = (node: Node) => Promise<void>;
69
64
  export type HelperConfig = {
70
65
  separator: string;
71
66
  };
72
- export declare enum HighlighType {
67
+ export declare enum InsertionType {
73
68
  nest = "nest",
74
69
  insertAbove = "insert-above",
75
70
  insertBelow = "insert-below",
package/dist/types.js CHANGED
@@ -12,14 +12,8 @@ export var SelectionModes;
12
12
  })(SelectionModes || (SelectionModes = {}));
13
13
  export var InsertionType;
14
14
  (function (InsertionType) {
15
- InsertionType["above"] = "above";
16
- InsertionType["below"] = "below";
17
15
  InsertionType["nest"] = "nest";
16
+ InsertionType["insertAbove"] = "insert-above";
17
+ InsertionType["insertBelow"] = "insert-below";
18
+ InsertionType["none"] = "none";
18
19
  })(InsertionType || (InsertionType = {}));
19
- export var HighlighType;
20
- (function (HighlighType) {
21
- HighlighType["nest"] = "nest";
22
- HighlighType["insertAbove"] = "insert-above";
23
- HighlighType["insertBelow"] = "insert-below";
24
- HighlighType["none"] = "none";
25
- })(HighlighType || (HighlighType = {}));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@keenmate/svelte-treeview",
3
- "version": "1.0.0-beta.1",
3
+ "version": "1.0.0-beta.3",
4
4
  "scripts": {
5
5
  "dev": "vite dev",
6
6
  "build": "vite build && npm run package",
@@ -61,6 +61,7 @@
61
61
  "types": "./dist/index.d.ts",
62
62
  "type": "module",
63
63
  "dependencies": {
64
+ "@keenmate/js-common-helpers": "^1.2.0",
64
65
  "@types/lodash.unionby": "^4.8.9",
65
66
  "@types/lodash.uniq": "^4.5.9",
66
67
  "@types/lodash.uniqby": "^4.7.9",