@keenmate/svelte-treeview 4.1.0 → 4.2.0

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
@@ -12,7 +12,7 @@ A high-performance, feature-rich hierarchical tree view component for Svelte 5 w
12
12
  - **Drag & Drop**: Built-in drag and drop support with validation and visual feedback
13
13
  - **Search & Filter**: Integrated FlexSearch for fast, full-text search capabilities
14
14
  - **Flexible Data Sources**: Works with any hierarchical data structure
15
- - **Context Menus**: Right-click context menus with customizable actions
15
+ - **Context Menus**: Dynamic right-click menus with callback-based generation, icons, disabled states
16
16
  - **Visual Customization**: Extensive styling options and icon customization
17
17
  - **TypeScript Support**: Full TypeScript support with comprehensive type definitions
18
18
  - **Accessibility**: Built with accessibility in mind
@@ -258,6 +258,104 @@ For complete FlexSearch documentation, visit: [FlexSearch Options](https://githu
258
258
  </div>
259
259
  ```
260
260
 
261
+ ### With Context Menus
262
+
263
+ The tree supports context menus with two approaches: callback-based (recommended) and snippet-based.
264
+
265
+ #### Callback-Based Context Menus
266
+
267
+ ```svelte
268
+ <script lang="ts">
269
+ import { Tree } from '@keenmate/svelte-treeview';
270
+ import type { ContextMenuItem } from '@keenmate/svelte-treeview';
271
+
272
+ const data = [
273
+ { path: '1', name: 'Documents', type: 'folder', canEdit: true, canDelete: true },
274
+ { path: '1.1', name: 'report.pdf', type: 'file', canEdit: true, canDelete: false },
275
+ { path: '2', name: 'Images', type: 'folder', canEdit: false, canDelete: true }
276
+ ];
277
+
278
+ function createContextMenu(node): ContextMenuItem[] {
279
+ const items: ContextMenuItem[] = [];
280
+
281
+ // Always available
282
+ items.push({
283
+ icon: '📂',
284
+ title: 'Open',
285
+ callback: () => alert(`Opening ${node.data.name}`)
286
+ });
287
+
288
+ // Conditional actions based on node data
289
+ if (node.data.canEdit) {
290
+ items.push({
291
+ icon: '✏️',
292
+ title: 'Edit',
293
+ callback: () => alert(`Editing ${node.data.name}`)
294
+ });
295
+ }
296
+
297
+ if (node.data.canDelete) {
298
+ items.push({
299
+ icon: '🗑️',
300
+ title: 'Delete',
301
+ callback: () => confirm(`Delete ${node.data.name}?`) && alert('Deleted!')
302
+ });
303
+ }
304
+
305
+ // Divider
306
+ items.push({ isDivider: true });
307
+
308
+ // Disabled item example
309
+ items.push({
310
+ icon: '🔒',
311
+ title: 'Restricted Action',
312
+ isDisabled: true,
313
+ callback: () => {}
314
+ });
315
+
316
+ return items;
317
+ }
318
+ </script>
319
+
320
+ <Tree
321
+ {data}
322
+ idMember="path"
323
+ pathMember="path"
324
+ contextMenuCallback={createContextMenu}
325
+ contextMenuXOffset={8}
326
+ contextMenuYOffset={0}
327
+ />
328
+ ```
329
+
330
+ #### Snippet-Based Context Menus
331
+
332
+ ```svelte
333
+ <Tree
334
+ {data}
335
+ idMember="path"
336
+ pathMember="path"
337
+ >
338
+ {#snippet contextMenu(node, closeMenu)}
339
+ <div class="context-menu-item" onclick={() => { alert(`Open ${node.data.name}`); closeMenu(); }}>
340
+ 📂 Open
341
+ </div>
342
+ <div class="context-menu-divider"></div>
343
+ <div class="context-menu-item" onclick={() => { alert(`Delete ${node.data.name}`); closeMenu(); }}>
344
+ 🗑️ Delete
345
+ </div>
346
+ {/snippet}
347
+ </Tree>
348
+ ```
349
+
350
+ #### Context Menu Features
351
+
352
+ - **Dynamic menus**: Generate menu items based on node properties
353
+ - **Icons and dividers**: Visual organization and identification
354
+ - **Disabled states**: Context-sensitive menu availability
355
+ - **Position offset**: `contextMenuXOffset`/`contextMenuYOffset` for cursor clearance
356
+ - **Auto-close**: Closes on scroll, click outside, or programmatically
357
+ - **Type safety**: Full TypeScript support with `ContextMenuItem` interface
358
+
261
359
  ## 🎨 Styling and Customization
262
360
 
263
361
  The component comes with default styles that provide a clean, modern look. You can customize it extensively:
@@ -598,7 +696,7 @@ Custom template for rendering node content.
598
696
  ```
599
697
 
600
698
  #### contextMenu
601
- Custom context menu template.
699
+ Custom context menu template (snippet-based approach).
602
700
 
603
701
  ```svelte
604
702
  {#snippet contextMenu(node, closeMenu)}
@@ -608,6 +706,32 @@ Custom context menu template.
608
706
  {/snippet}
609
707
  ```
610
708
 
709
+ ### Context Menu Properties
710
+
711
+ #### contextMenuCallback
712
+ Function that generates context menu items dynamically.
713
+
714
+ ```typescript
715
+ contextMenuCallback: (node: LTreeNode<T>) => ContextMenuItem[]
716
+ ```
717
+
718
+ Where `ContextMenuItem` is:
719
+ ```typescript
720
+ interface ContextMenuItem {
721
+ icon?: string; // Optional icon (emoji or text)
722
+ title: string; // Menu item text
723
+ isDisabled?: boolean; // Whether item is disabled
724
+ callback: () => void; // Action to perform
725
+ isDivider?: boolean; // Render as divider instead of item
726
+ }
727
+ ```
728
+
729
+ #### contextMenuXOffset
730
+ Horizontal offset from cursor position (default: 8px).
731
+
732
+ #### contextMenuYOffset
733
+ Vertical offset from cursor position (default: 0px).
734
+
611
735
  ## 🏗️ Data Structure
612
736
 
613
737
  The component expects hierarchical data with path-based organization:
@@ -3,7 +3,7 @@
3
3
  import Node from './Node.svelte';
4
4
  import { type LTreeNode } from '../ltree/ltree-node.svelte.js';
5
5
  import { createLTree } from '../ltree/ltree.svelte.js';
6
- import { type Ltree, type InsertArrayResult } from '../ltree/types.js';
6
+ import { type Ltree, type InsertArrayResult, type ContextMenuItem } from '../ltree/types.js';
7
7
  import { setContext, tick } from 'svelte';
8
8
 
9
9
  // Context menu state
@@ -62,12 +62,14 @@
62
62
  indexerBatchSize?: number | null | undefined;
63
63
  indexerTimeout?: number | null | undefined;
64
64
  shouldDisplayDebugInformation?: boolean;
65
+ shouldDisplayContextMenuInDebugMode?: boolean;
65
66
 
66
67
  // EVENTS
67
68
  onNodeClicked?: (node: LTreeNode<T>) => void;
68
69
  onNodeDragStart?: (node: LTreeNode<T>, event: DragEvent) => void;
69
70
  onNodeDragOver?: (node: LTreeNode<T>, event: DragEvent) => void;
70
71
  onNodeDrop?: (node: LTreeNode<T>, draggedNode: LTreeNode<T>, event: DragEvent) => void;
72
+ contextMenuCallback?: (node: LTreeNode<T>) => ContextMenuItem[];
71
73
 
72
74
  // VISUALS
73
75
  bodyClass?: string | null | undefined;
@@ -78,11 +80,13 @@
78
80
  leafIconClass?: string | null | undefined;
79
81
  scrollHighlightTimeout?: number | null | undefined;
80
82
  scrollHighlightClass?: string | null | undefined;
83
+ contextMenuXOffset?: number | null | undefined;
84
+ contextMenuYOffset?: number | null | undefined;
81
85
  }
82
86
 
83
87
  let {
84
88
  treeId,
85
- treePathSeparator,
89
+ treePathSeparator = '.',
86
90
 
87
91
  // MAPPINGS
88
92
  idMember,
@@ -125,12 +129,14 @@
125
129
  indexerBatchSize = 25,
126
130
  indexerTimeout = 50,
127
131
  shouldDisplayDebugInformation = false,
132
+ shouldDisplayContextMenuInDebugMode = false,
128
133
 
129
134
  // EVENTS
130
135
  onNodeClicked,
131
136
  onNodeDragStart,
132
137
  onNodeDragOver,
133
138
  onNodeDrop,
139
+ contextMenuCallback,
134
140
 
135
141
  // VISUALS
136
142
  bodyClass,
@@ -140,7 +146,9 @@
140
146
  selectedNodeClass,
141
147
  dragOverNodeClass,
142
148
  scrollHighlightTimeout = 4000,
143
- scrollHighlightClass = 'ltree-scroll-highlight'
149
+ scrollHighlightClass = 'ltree-scroll-highlight',
150
+ contextMenuXOffset = 8,
151
+ contextMenuYOffset = 0
144
152
  }: Props = $props();
145
153
 
146
154
  export async function expandNodes(nodePath: string) {
@@ -305,20 +313,22 @@
305
313
  }
306
314
 
307
315
  function _onNodeRightClicked(node: LTreeNode<T>, event: MouseEvent) {
308
- if (!contextMenu) {
316
+ if (!contextMenu && !contextMenuCallback) {
309
317
  return;
310
318
  }
311
319
 
312
320
  event.preventDefault();
313
321
  contextMenuNode = node;
314
- contextMenuX = event.clientX;
315
- contextMenuY = event.clientY;
322
+ contextMenuX = event.clientX + contextMenuXOffset;
323
+ contextMenuY = event.clientY + contextMenuYOffset;
316
324
  contextMenuVisible = true;
325
+ isDebugMenuActive = false; // This is a user-triggered menu, not debug menu
317
326
  }
318
327
 
319
328
  function closeContextMenu() {
320
329
  contextMenuVisible = false;
321
330
  contextMenuNode = null;
331
+ isDebugMenuActive = false;
322
332
  }
323
333
 
324
334
  function _onNodeDragStart(node: LTreeNode<T>, event: DragEvent) {
@@ -388,8 +398,8 @@
388
398
  }
389
399
  }
390
400
 
391
- // Add global event listener for document clicks
392
- $effect.root(() => {
401
+ // Add global event listener for document clicks and scroll events
402
+ $effect(() => {
393
403
  if (contextMenuVisible) {
394
404
  const handleGlobalClick = (event: MouseEvent) => {
395
405
  const target = event.target as Element;
@@ -398,15 +408,58 @@
398
408
  }
399
409
  };
400
410
 
411
+ const handleGlobalScroll = (event?: Event) => {
412
+ if (shouldDisplayDebugInformation) {
413
+ console.log('Scroll/wheel event detected, closing context menu', event?.type);
414
+ }
415
+ closeContextMenu();
416
+ };
417
+
418
+ // Add scroll listeners to both window and document to catch all scroll events
401
419
  document.addEventListener('click', handleGlobalClick);
402
420
  document.addEventListener('contextmenu', handleGlobalClick);
421
+ window.addEventListener('scroll', handleGlobalScroll, true);
422
+ document.addEventListener('scroll', handleGlobalScroll, true);
423
+
424
+ // Also listen for wheel events which might not trigger scroll
425
+ window.addEventListener('wheel', handleGlobalScroll, { passive: true });
403
426
 
404
427
  return () => {
405
428
  document.removeEventListener('click', handleGlobalClick);
406
429
  document.removeEventListener('contextmenu', handleGlobalClick);
430
+ window.removeEventListener('scroll', handleGlobalScroll, true);
431
+ document.removeEventListener('scroll', handleGlobalScroll, true);
432
+ window.removeEventListener('wheel', handleGlobalScroll);
407
433
  };
408
434
  }
409
435
  });
436
+
437
+ // Debug context menu - show context menu on second node for styling development
438
+ let isDebugMenuActive = $state(false);
439
+
440
+ $effect(() => {
441
+ if (shouldDisplayContextMenuInDebugMode && (contextMenu || contextMenuCallback) && tree?.tree && tree.tree.length > 1) {
442
+ // Find the second node in the tree
443
+ const secondNode = tree.tree[1];
444
+ if (secondNode) {
445
+ // Position the context menu at a fixed location for easy styling
446
+ contextMenuNode = secondNode;
447
+ contextMenuX = 200; // Fixed position for consistent styling work
448
+ contextMenuY = 100;
449
+ contextMenuVisible = true;
450
+ isDebugMenuActive = true;
451
+
452
+ if (shouldDisplayDebugInformation) {
453
+ console.log('Debug context menu displayed for node:', secondNode.data);
454
+ }
455
+ }
456
+ } else if (!shouldDisplayContextMenuInDebugMode && isDebugMenuActive) {
457
+ // Only hide the context menu if it was opened by debug mode
458
+ contextMenuVisible = false;
459
+ contextMenuNode = null;
460
+ isDebugMenuActive = false;
461
+ }
462
+ });
410
463
  </script>
411
464
 
412
465
  <div>
@@ -471,9 +524,29 @@
471
524
  {@render treeFooter?.()}
472
525
 
473
526
  <!-- Context Menu -->
474
- {#if contextMenuVisible && contextMenu && contextMenuNode}
527
+ {#if contextMenuVisible && contextMenuNode}
475
528
  <div class="ltree-context-menu" style="left: {contextMenuX}px; top: {contextMenuY}px;">
476
- {@render contextMenu(contextMenuNode, closeContextMenu)}
529
+ {#if contextMenuCallback}
530
+ {@const menuItems = contextMenuCallback(contextMenuNode)}
531
+ {#each menuItems as item}
532
+ {#if item.isDivider}
533
+ <div class="ltree-context-menu-divider"></div>
534
+ {:else}
535
+ <div
536
+ class="ltree-context-menu-item"
537
+ class:ltree-context-menu-item-disabled={item.isDisabled}
538
+ onclick={() => !item.isDisabled && item.callback()}
539
+ >
540
+ {#if item.icon}
541
+ <span class="ltree-context-menu-icon">{item.icon}</span>
542
+ {/if}
543
+ {item.title}
544
+ </div>
545
+ {/if}
546
+ {/each}
547
+ {:else if contextMenu}
548
+ {@render contextMenu(contextMenuNode, closeContextMenu)}
549
+ {/if}
477
550
  </div>
478
551
  {/if}
479
552
  </div>
@@ -1,6 +1,6 @@
1
1
  import type { Index, SearchOptions } from 'flexsearch';
2
2
  import { type LTreeNode } from '../ltree/ltree-node.svelte.js';
3
- import { type InsertArrayResult } from '../ltree/types.js';
3
+ import { type InsertArrayResult, type ContextMenuItem } from '../ltree/types.js';
4
4
  declare function $$render<T>(): {
5
5
  props: {
6
6
  trieId?: string | null | undefined;
@@ -38,10 +38,12 @@ declare function $$render<T>(): {
38
38
  indexerBatchSize?: number | null | undefined;
39
39
  indexerTimeout?: number | null | undefined;
40
40
  shouldDisplayDebugInformation?: boolean;
41
+ shouldDisplayContextMenuInDebugMode?: boolean;
41
42
  onNodeClicked?: (node: LTreeNode<T>) => void;
42
43
  onNodeDragStart?: (node: LTreeNode<T>, event: DragEvent) => void;
43
44
  onNodeDragOver?: (node: LTreeNode<T>, event: DragEvent) => void;
44
45
  onNodeDrop?: (node: LTreeNode<T>, draggedNode: LTreeNode<T>, event: DragEvent) => void;
46
+ contextMenuCallback?: (node: LTreeNode<T>) => ContextMenuItem[];
45
47
  bodyClass?: string | null | undefined;
46
48
  selectedNodeClass?: string | null | undefined;
47
49
  dragOverNodeClass?: string | null | undefined;
@@ -50,6 +52,8 @@ declare function $$render<T>(): {
50
52
  leafIconClass?: string | null | undefined;
51
53
  scrollHighlightTimeout?: number | null | undefined;
52
54
  scrollHighlightClass?: string | null | undefined;
55
+ contextMenuXOffset?: number | null | undefined;
56
+ contextMenuYOffset?: number | null | undefined;
53
57
  };
54
58
  exports: {
55
59
  expandNodes: (nodePath: string) => Promise<void>;
@@ -1,6 +1,13 @@
1
1
  import type { SearchOptions } from 'flexsearch';
2
2
  import type { LTreeNode } from './ltree-node.svelte';
3
3
  export type Tuple<T, U> = [T, U];
4
+ export interface ContextMenuItem {
5
+ icon?: string;
6
+ title: string;
7
+ isDisabled?: boolean;
8
+ callback: () => void;
9
+ isDivider?: boolean;
10
+ }
4
11
  export interface InsertArrayResult<T> {
5
12
  successful: number;
6
13
  failed: Array<{
@@ -278,7 +278,8 @@ $body-color: #212529 !default;
278
278
  min-width: 150px;
279
279
 
280
280
  .ltree-context-menu-item {
281
- display: block;
281
+ display: flex;
282
+ align-items: center;
282
283
  padding: 8px 16px;
283
284
  border: none;
284
285
  background: none;
@@ -293,7 +294,7 @@ $body-color: #212529 !default;
293
294
  background-color: var(--ltree-light);
294
295
  }
295
296
 
296
- &:disabled {
297
+ &.ltree-context-menu-item-disabled {
297
298
  opacity: 0.5;
298
299
  cursor: not-allowed;
299
300
  }
@@ -307,6 +308,19 @@ $body-color: #212529 !default;
307
308
  }
308
309
  }
309
310
 
311
+ .ltree-context-menu-icon {
312
+ margin-right: 8px;
313
+ font-size: 12px;
314
+ width: 16px;
315
+ text-align: center;
316
+ }
317
+
318
+ .ltree-context-menu-divider {
319
+ height: 1px;
320
+ background-color: var(--ltree-border);
321
+ margin: 4px 0;
322
+ }
323
+
310
324
  .ltree-context-menu-separator {
311
325
  height: 1px;
312
326
  background-color: var(--ltree-border);
package/dist/styles.css CHANGED
@@ -210,7 +210,8 @@
210
210
  min-width: 150px;
211
211
  }
212
212
  .ltree-context-menu .ltree-context-menu-item {
213
- display: block;
213
+ display: flex;
214
+ align-items: center;
214
215
  padding: 8px 16px;
215
216
  border: none;
216
217
  background: none;
@@ -224,7 +225,7 @@
224
225
  .ltree-context-menu .ltree-context-menu-item:hover {
225
226
  background-color: var(--ltree-light);
226
227
  }
227
- .ltree-context-menu .ltree-context-menu-item:disabled {
228
+ .ltree-context-menu .ltree-context-menu-item.ltree-context-menu-item-disabled {
228
229
  opacity: 0.5;
229
230
  cursor: not-allowed;
230
231
  }
@@ -234,6 +235,17 @@
234
235
  .ltree-context-menu .ltree-context-menu-item.danger:hover {
235
236
  background-color: rgba(var(--ltree-danger-rgb), 0.1);
236
237
  }
238
+ .ltree-context-menu .ltree-context-menu-icon {
239
+ margin-right: 8px;
240
+ font-size: 12px;
241
+ width: 16px;
242
+ text-align: center;
243
+ }
244
+ .ltree-context-menu .ltree-context-menu-divider {
245
+ height: 1px;
246
+ background-color: var(--ltree-border);
247
+ margin: 4px 0;
248
+ }
237
249
  .ltree-context-menu .ltree-context-menu-separator {
238
250
  height: 1px;
239
251
  background-color: var(--ltree-border);
@@ -1 +1 @@
1
- {"version":3,"sourceRoot":"","sources":["../src/lib/styles/main.scss"],"names":[],"mappings":";AAmCA;EACC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAID;EACC,aA5CA;;AA+CA;EACC;EACA,OAlCqB;EAmCrB;EACA;;;AAIF;EACC,aAxDA;EAyDA,WAvDqB;;AAyDrB;EACC;EACA;;AAGD;EACC;EACA;EACA,SAhE0B;EAiE1B,eAhEgC;EAiEhC;EACA;EACA;;AAEA;EACC,kBArEkB;;AAyEpB;EACC;;AAGD;EACC,OA7EuB;EA8EvB;EACA;EACA,cA7E8B;EA8E9B,WAhF2B;EAiF3B,OAhFuB;EAiFvB;EACA;;AAEA;EACC;;AAIF;EACC,cAxF4B;EAyF5B,WAxFyB;;AA2F1B;EACC,aA3F4B;EA4F5B,cA3F6B;;AA8F9B;EACC,WA9FyB;EA+FzB,OA9FqB;;AAiGtB;EACC,YAjGyB;;;AAsG3B;EACC;;;AAGD;EACC;;;AAGD;EACC;;;AAID;EACC;;;AAGD;EACC;;;AAGD;EACC;;;AAGD;EACC;;;AAGD;EACC;;;AAGD;EACC;;;AAID;EACC;EACA;;;AAGD;EACC;EACA;EACA;EACA;;;AAGD;EACC;;AAEA;EACC;EACA;EACA;EACA;;AAGD;EACC;EACA;EACA;EACA;;;AAKF;EACC;EACA;EACA;;;AAGD;EACC;EACA;EACA;;;AAGD;EACC;IAKC;;EAED;IACC;;EAED;IACC;;;AAKF;EACC;;AAEA;EACC;;;AAIF;EACC;EACA;EACA,YACC;;;AAKD;EACC;EACA;EACA;;AAEA;EACC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAIF;EACC;EACA;;AAGD;EACC;EACA;;;AAKF;EACC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACC;;AAGD;EACC;EACA;;AAGD;EACC;;AAEA;EACC;;AAKH;EACC;EACA;EACA;;;AAKF;EACC,aAxTA;EAyTA;EACA;EACA;EACA;EACA;EACA;;AAGC;EACC;EACA;EACA;EACA;;AAEA;EACC;;AAIF;EACC;EACA;;AAIF;EACC;EACA;EACA;;AAEA;EACC;EACA;EACA;EACA;EACA;EACA;EACA;;;AAMH;EACC;EACA;EACA;;;AAGD;EACC;;AACA;EACC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EAEA;;AAED;EACC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EAEA;;;AAKF;EAEC;EACA;EACA;EAGA","file":"styles.css"}
1
+ {"version":3,"sourceRoot":"","sources":["../src/lib/styles/main.scss"],"names":[],"mappings":";AAmCA;EACC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAID;EACC,aA5CA;;AA+CA;EACC;EACA,OAlCqB;EAmCrB;EACA;;;AAIF;EACC,aAxDA;EAyDA,WAvDqB;;AAyDrB;EACC;EACA;;AAGD;EACC;EACA;EACA,SAhE0B;EAiE1B,eAhEgC;EAiEhC;EACA;EACA;;AAEA;EACC,kBArEkB;;AAyEpB;EACC;;AAGD;EACC,OA7EuB;EA8EvB;EACA;EACA,cA7E8B;EA8E9B,WAhF2B;EAiF3B,OAhFuB;EAiFvB;EACA;;AAEA;EACC;;AAIF;EACC,cAxF4B;EAyF5B,WAxFyB;;AA2F1B;EACC,aA3F4B;EA4F5B,cA3F6B;;AA8F9B;EACC,WA9FyB;EA+FzB,OA9FqB;;AAiGtB;EACC,YAjGyB;;;AAsG3B;EACC;;;AAGD;EACC;;;AAGD;EACC;;;AAID;EACC;;;AAGD;EACC;;;AAGD;EACC;;;AAGD;EACC;;;AAGD;EACC;;;AAGD;EACC;;;AAID;EACC;EACA;;;AAGD;EACC;EACA;EACA;EACA;;;AAGD;EACC;;AAEA;EACC;EACA;EACA;EACA;;AAGD;EACC;EACA;EACA;EACA;;;AAKF;EACC;EACA;EACA;;;AAGD;EACC;EACA;EACA;;;AAGD;EACC;IAKC;;EAED;IACC;;EAED;IACC;;;AAKF;EACC;;AAEA;EACC;;;AAIF;EACC;EACA;EACA,YACC;;;AAKD;EACC;EACA;EACA;;AAEA;EACC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAIF;EACC;EACA;;AAGD;EACC;EACA;;;AAKF;EACC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACC;;AAGD;EACC;EACA;;AAGD;EACC;;AAEA;EACC;;AAKH;EACC;EACA;EACA;EACA;;AAGD;EACC;EACA;EACA;;AAGD;EACC;EACA;EACA;;;AAKF;EACC,aAtUA;EAuUA;EACA;EACA;EACA;EACA;EACA;;AAGC;EACC;EACA;EACA;EACA;;AAEA;EACC;;AAIF;EACC;EACA;;AAIF;EACC;EACA;EACA;;AAEA;EACC;EACA;EACA;EACA;EACA;EACA;EACA;;;AAMH;EACC;EACA;EACA;;;AAGD;EACC;;AACA;EACC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EAEA;;AAED;EACC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EAEA;;;AAKF;EAEC;EACA;EACA;EAGA","file":"styles.css"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@keenmate/svelte-treeview",
3
- "version": "4.1.0",
3
+ "version": "4.2.0",
4
4
  "scripts": {
5
5
  "dev": "vite dev --port 17777",
6
6
  "build": "vite build && npm run prepack",
@@ -78,6 +78,7 @@
78
78
  "drag-drop",
79
79
  "search",
80
80
  "flexsearch",
81
+ "context-menu",
81
82
  "component",
82
83
  "ui"
83
84
  ],