momoi-explorer 0.8.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/dist/index.cjs ADDED
@@ -0,0 +1,690 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var src_exports = {};
22
+ __export(src_exports, {
23
+ ExplorerCommands: () => ExplorerCommands,
24
+ coalesceEvents: () => coalesceEvents,
25
+ computeSelection: () => computeSelection,
26
+ createEventProcessor: () => createEventProcessor,
27
+ createFileTree: () => createFileTree,
28
+ defaultExplorerKeybindings: () => defaultExplorerKeybindings,
29
+ defaultFilter: () => defaultFilter,
30
+ defaultSort: () => defaultSort,
31
+ findMatchingPaths: () => findMatchingPaths,
32
+ flattenTree: () => flattenTree,
33
+ fuzzyFind: () => fuzzyFind,
34
+ fuzzyMatch: () => fuzzyMatch
35
+ });
36
+ module.exports = __toCommonJS(src_exports);
37
+
38
+ // src/core/event-processor.ts
39
+ var DEFAULT_DEBOUNCE_MS = 75;
40
+ var DEFAULT_THROTTLE_CHUNK_SIZE = 500;
41
+ var DEFAULT_THROTTLE_DELAY_MS = 200;
42
+ function coalesceEvents(raw) {
43
+ const expanded = [];
44
+ for (const event of raw) {
45
+ if (event.type === "rename" && event.newPath) {
46
+ expanded.push({ type: "delete", path: event.path, isDirectory: event.isDirectory });
47
+ expanded.push({ type: "create", path: event.newPath, isDirectory: event.isDirectory });
48
+ } else {
49
+ expanded.push({ type: event.type, path: event.path, isDirectory: event.isDirectory });
50
+ }
51
+ }
52
+ const byPath = /* @__PURE__ */ new Map();
53
+ for (const event of expanded) {
54
+ const existing = byPath.get(event.path);
55
+ if (!existing) {
56
+ byPath.set(event.path, event);
57
+ continue;
58
+ }
59
+ if (existing.type === "delete" && event.type === "create") {
60
+ byPath.set(event.path, { type: "modify", path: event.path, isDirectory: event.isDirectory });
61
+ continue;
62
+ }
63
+ if (existing.type === "create" && event.type === "modify") {
64
+ continue;
65
+ }
66
+ if (existing.type === "create" && event.type === "delete") {
67
+ byPath.delete(event.path);
68
+ continue;
69
+ }
70
+ byPath.set(event.path, event);
71
+ }
72
+ const result = Array.from(byPath.values());
73
+ const deletedDirs = /* @__PURE__ */ new Set();
74
+ for (const event of result) {
75
+ if (event.type === "delete" && event.isDirectory) {
76
+ deletedDirs.add(event.path);
77
+ }
78
+ }
79
+ if (deletedDirs.size === 0) return result;
80
+ return result.filter((event) => {
81
+ if (event.type !== "delete") return true;
82
+ for (const dir of deletedDirs) {
83
+ if (event.path !== dir && event.path.startsWith(dir + "/")) {
84
+ return false;
85
+ }
86
+ }
87
+ return true;
88
+ });
89
+ }
90
+ function createEventProcessor(callback, options = {}) {
91
+ const debounceMs = options.debounceMs ?? DEFAULT_DEBOUNCE_MS;
92
+ const shouldCoalesce = options.coalesce ?? true;
93
+ const throttleChunkSize = options.throttle?.maxChunkSize ?? DEFAULT_THROTTLE_CHUNK_SIZE;
94
+ const throttleDelayMs = options.throttle?.delayMs ?? DEFAULT_THROTTLE_DELAY_MS;
95
+ let buffer = [];
96
+ let debounceTimer = null;
97
+ let throttleTimer = null;
98
+ let destroyed = false;
99
+ function processBuffer() {
100
+ if (destroyed || buffer.length === 0) return;
101
+ const raw = buffer;
102
+ buffer = [];
103
+ const events = shouldCoalesce ? coalesceEvents(raw) : raw.map((e) => ({
104
+ type: e.type === "rename" ? "modify" : e.type,
105
+ path: e.type === "rename" && e.newPath ? e.newPath : e.path,
106
+ isDirectory: e.isDirectory
107
+ }));
108
+ if (events.length === 0) return;
109
+ if (events.length <= throttleChunkSize) {
110
+ callback(events);
111
+ return;
112
+ }
113
+ let offset = 0;
114
+ function emitChunk() {
115
+ if (destroyed || offset >= events.length) return;
116
+ const chunk = events.slice(offset, offset + throttleChunkSize);
117
+ offset += throttleChunkSize;
118
+ callback(chunk);
119
+ if (offset < events.length) {
120
+ throttleTimer = setTimeout(emitChunk, throttleDelayMs);
121
+ }
122
+ }
123
+ emitChunk();
124
+ }
125
+ return {
126
+ push(events) {
127
+ if (destroyed) return;
128
+ buffer.push(...events);
129
+ if (debounceTimer !== null) {
130
+ clearTimeout(debounceTimer);
131
+ }
132
+ debounceTimer = setTimeout(processBuffer, debounceMs);
133
+ },
134
+ flush() {
135
+ if (debounceTimer !== null) {
136
+ clearTimeout(debounceTimer);
137
+ debounceTimer = null;
138
+ }
139
+ processBuffer();
140
+ },
141
+ destroy() {
142
+ destroyed = true;
143
+ if (debounceTimer !== null) clearTimeout(debounceTimer);
144
+ if (throttleTimer !== null) clearTimeout(throttleTimer);
145
+ buffer = [];
146
+ }
147
+ };
148
+ }
149
+
150
+ // src/core/flatten.ts
151
+ function flattenTree(nodes, expandedPaths, matchingPaths) {
152
+ const result = [];
153
+ function walk(children, depth) {
154
+ for (const node of children) {
155
+ if (matchingPaths && !matchingPaths.has(node.path)) continue;
156
+ result.push({ node, depth });
157
+ if (node.isDirectory && node.children) {
158
+ if (matchingPaths || expandedPaths.has(node.path)) {
159
+ walk(node.children, depth + 1);
160
+ }
161
+ }
162
+ }
163
+ }
164
+ walk(nodes, 0);
165
+ return result;
166
+ }
167
+
168
+ // src/core/selection.ts
169
+ function computeSelection(currentSelected, anchorPath, targetPath, mode, flatList) {
170
+ switch (mode) {
171
+ case "replace":
172
+ return {
173
+ selectedPaths: /* @__PURE__ */ new Set([targetPath]),
174
+ anchorPath: targetPath
175
+ };
176
+ case "toggle": {
177
+ const next = new Set(currentSelected);
178
+ if (next.has(targetPath)) {
179
+ next.delete(targetPath);
180
+ } else {
181
+ next.add(targetPath);
182
+ }
183
+ return {
184
+ selectedPaths: next,
185
+ anchorPath: targetPath
186
+ };
187
+ }
188
+ case "range": {
189
+ if (!anchorPath) {
190
+ return {
191
+ selectedPaths: /* @__PURE__ */ new Set([targetPath]),
192
+ anchorPath: targetPath
193
+ };
194
+ }
195
+ const paths = flatList.map((f) => f.node.path);
196
+ const anchorIdx = paths.indexOf(anchorPath);
197
+ const targetIdx = paths.indexOf(targetPath);
198
+ if (anchorIdx === -1 || targetIdx === -1) {
199
+ return {
200
+ selectedPaths: /* @__PURE__ */ new Set([targetPath]),
201
+ anchorPath: targetPath
202
+ };
203
+ }
204
+ const start = Math.min(anchorIdx, targetIdx);
205
+ const end = Math.max(anchorIdx, targetIdx);
206
+ const rangePaths = new Set(paths.slice(start, end + 1));
207
+ return {
208
+ selectedPaths: rangePaths,
209
+ anchorPath
210
+ // range選択ではanchorは変えない
211
+ };
212
+ }
213
+ }
214
+ }
215
+
216
+ // src/core/sort.ts
217
+ function defaultSort(a, b) {
218
+ if (a.isDirectory !== b.isDirectory) {
219
+ return a.isDirectory ? -1 : 1;
220
+ }
221
+ return a.name.localeCompare(b.name, void 0, { sensitivity: "base" });
222
+ }
223
+
224
+ // src/core/filter.ts
225
+ function defaultFilter(_entry) {
226
+ return true;
227
+ }
228
+
229
+ // src/core/search.ts
230
+ function fuzzyMatch(query, target) {
231
+ const q = query.toLowerCase();
232
+ const t = target.toLowerCase();
233
+ if (q.length === 0) return { match: true, score: 0 };
234
+ if (q.length > t.length) return { match: false, score: 0 };
235
+ if (t === q) return { match: true, score: 100 };
236
+ if (t.startsWith(q)) return { match: true, score: 90 };
237
+ if (t.includes(q)) return { match: true, score: 80 };
238
+ let qi = 0;
239
+ let score = 0;
240
+ let lastMatchIndex = -2;
241
+ for (let ti = 0; ti < t.length && qi < q.length; ti++) {
242
+ if (t[ti] === q[qi]) {
243
+ qi++;
244
+ if (ti === lastMatchIndex + 1) {
245
+ score += 5;
246
+ }
247
+ if (ti === 0 || "/\\-_.".includes(t[ti - 1])) {
248
+ score += 10;
249
+ }
250
+ score += 1;
251
+ lastMatchIndex = ti;
252
+ }
253
+ }
254
+ if (qi < q.length) return { match: false, score: 0 };
255
+ return { match: true, score };
256
+ }
257
+ function findMatchingPaths(nodes, query) {
258
+ const matching = /* @__PURE__ */ new Set();
259
+ function walk(node, ancestors) {
260
+ const nameMatch = fuzzyMatch(query, node.name).match;
261
+ let childMatch = false;
262
+ if (node.children) {
263
+ for (const child of node.children) {
264
+ if (walk(child, [...ancestors, node.path])) {
265
+ childMatch = true;
266
+ }
267
+ }
268
+ }
269
+ if (nameMatch || childMatch) {
270
+ matching.add(node.path);
271
+ for (const a of ancestors) {
272
+ matching.add(a);
273
+ }
274
+ return true;
275
+ }
276
+ return false;
277
+ }
278
+ for (const node of nodes) {
279
+ walk(node, []);
280
+ }
281
+ return matching;
282
+ }
283
+ function fuzzyFind(files, query, maxResults = 50) {
284
+ if (!query) return [];
285
+ const scored = [];
286
+ for (const entry of files) {
287
+ const nameResult = fuzzyMatch(query, entry.name);
288
+ const pathResult = fuzzyMatch(query, entry.path);
289
+ const bestScore = Math.max(nameResult.score, pathResult.score * 0.5);
290
+ if (nameResult.match || pathResult.match) {
291
+ scored.push({ entry, score: bestScore });
292
+ }
293
+ }
294
+ scored.sort((a, b) => b.score - a.score);
295
+ return scored.slice(0, maxResults).map((s) => s.entry);
296
+ }
297
+
298
+ // src/core/tree.ts
299
+ function toTreeNode(entry, depth) {
300
+ return {
301
+ ...entry,
302
+ depth,
303
+ children: entry.isDirectory ? void 0 : void 0,
304
+ childrenLoaded: false
305
+ };
306
+ }
307
+ function findNode(nodes, path) {
308
+ for (const node of nodes) {
309
+ if (node.path === path) return node;
310
+ if (node.children) {
311
+ const found = findNode(node.children, path);
312
+ if (found) return found;
313
+ }
314
+ }
315
+ return void 0;
316
+ }
317
+ function dirname(path) {
318
+ const sep = path.includes("\\") ? "\\" : "/";
319
+ const idx = path.lastIndexOf(sep);
320
+ return idx === -1 ? "" : path.slice(0, idx);
321
+ }
322
+ function createFileTree(options) {
323
+ const { adapter, rootPath, onEvent } = options;
324
+ let sortFn = options.sort ?? defaultSort;
325
+ let filterFn = options.filter ?? defaultFilter;
326
+ let state = {
327
+ rootPath,
328
+ rootNodes: [],
329
+ expandedPaths: /* @__PURE__ */ new Set(),
330
+ selectedPaths: /* @__PURE__ */ new Set(),
331
+ anchorPath: null,
332
+ renamingPath: null,
333
+ creatingState: null,
334
+ searchQuery: null,
335
+ flatList: []
336
+ };
337
+ const listeners = /* @__PURE__ */ new Set();
338
+ let expandingPaths = /* @__PURE__ */ new Set();
339
+ function emit(event) {
340
+ onEvent?.(event);
341
+ }
342
+ function notify() {
343
+ const matchingPaths = state.searchQuery ? findMatchingPaths(state.rootNodes, state.searchQuery) : null;
344
+ state = { ...state, flatList: flattenTree(state.rootNodes, state.expandedPaths, matchingPaths) };
345
+ for (const listener of listeners) {
346
+ listener(state);
347
+ }
348
+ }
349
+ async function loadChildren(node) {
350
+ const entries = await adapter.readDir(node.path);
351
+ const filtered = entries.filter(filterFn);
352
+ filtered.sort(sortFn);
353
+ const oldChildMap = node.children ? new Map(node.children.map((c) => [c.path, c])) : /* @__PURE__ */ new Map();
354
+ node.children = filtered.map((e) => {
355
+ const existing = oldChildMap.get(e.path);
356
+ if (existing && existing.childrenLoaded) {
357
+ return { ...toTreeNode(e, node.depth + 1), children: existing.children, childrenLoaded: true };
358
+ }
359
+ return toTreeNode(e, node.depth + 1);
360
+ });
361
+ node.childrenLoaded = true;
362
+ }
363
+ async function refreshParent(parentPath) {
364
+ const parentNode = findNode(state.rootNodes, parentPath);
365
+ if (parentNode) {
366
+ await loadChildren(parentNode);
367
+ state.expandedPaths = new Set(state.expandedPaths);
368
+ state.expandedPaths.add(parentPath);
369
+ } else if (parentPath === rootPath) {
370
+ const entries = await adapter.readDir(rootPath);
371
+ const filtered = entries.filter(filterFn);
372
+ filtered.sort(sortFn);
373
+ const oldNodeMap = new Map(state.rootNodes.map((n) => [n.path, n]));
374
+ state.rootNodes = filtered.map((e) => {
375
+ const existing = oldNodeMap.get(e.path);
376
+ if (existing && existing.childrenLoaded) {
377
+ return { ...toTreeNode(e, 0), children: existing.children, childrenLoaded: true };
378
+ }
379
+ return toTreeNode(e, 0);
380
+ });
381
+ }
382
+ }
383
+ function sortNodes(nodes) {
384
+ nodes.sort(sortFn);
385
+ for (const node of nodes) {
386
+ if (node.children) {
387
+ sortNodes(node.children);
388
+ }
389
+ }
390
+ }
391
+ function filterNodes(nodes) {
392
+ return nodes.filter((node) => {
393
+ if (!filterFn(node)) return false;
394
+ if (node.children) {
395
+ node.children = filterNodes(node.children);
396
+ }
397
+ return true;
398
+ });
399
+ }
400
+ let unwatchFn = null;
401
+ let eventProcessor = null;
402
+ function handleWatchEvents(events) {
403
+ emit({ type: "external-change", changes: events });
404
+ const dirsToRefresh = /* @__PURE__ */ new Set();
405
+ for (const event of events) {
406
+ const parent = dirname(event.path);
407
+ if (parent === rootPath || state.expandedPaths.has(parent)) {
408
+ dirsToRefresh.add(parent);
409
+ }
410
+ if (event.isDirectory && state.expandedPaths.has(event.path)) {
411
+ dirsToRefresh.add(event.path);
412
+ }
413
+ }
414
+ for (const dir of dirsToRefresh) {
415
+ refreshParent(dir).then(() => notify()).catch(() => {
416
+ });
417
+ }
418
+ }
419
+ function startWatching() {
420
+ if (!adapter.watch) return;
421
+ eventProcessor = createEventProcessor(handleWatchEvents, options.watchOptions);
422
+ unwatchFn = adapter.watch(rootPath, (events) => {
423
+ eventProcessor.push(events);
424
+ });
425
+ }
426
+ function stopWatching() {
427
+ if (unwatchFn) {
428
+ unwatchFn();
429
+ unwatchFn = null;
430
+ }
431
+ if (eventProcessor) {
432
+ eventProcessor.destroy();
433
+ eventProcessor = null;
434
+ }
435
+ }
436
+ const controller = {
437
+ getState() {
438
+ return state;
439
+ },
440
+ subscribe(listener) {
441
+ listeners.add(listener);
442
+ return () => listeners.delete(listener);
443
+ },
444
+ async loadRoot() {
445
+ const entries = await adapter.readDir(rootPath);
446
+ const filtered = entries.filter(filterFn);
447
+ filtered.sort(sortFn);
448
+ state.rootNodes = filtered.map((e) => toTreeNode(e, 0));
449
+ notify();
450
+ startWatching();
451
+ },
452
+ async expand(path) {
453
+ if (expandingPaths.has(path)) return;
454
+ expandingPaths.add(path);
455
+ try {
456
+ const node = findNode(state.rootNodes, path);
457
+ if (!node || !node.isDirectory) return;
458
+ if (!node.childrenLoaded) {
459
+ await loadChildren(node);
460
+ }
461
+ state.expandedPaths = new Set(state.expandedPaths);
462
+ state.expandedPaths.add(path);
463
+ notify();
464
+ emit({ type: "expand", path });
465
+ } finally {
466
+ expandingPaths.delete(path);
467
+ }
468
+ },
469
+ collapse(path) {
470
+ const sep = path.includes("\\") ? "\\" : "/";
471
+ const prefix = path + sep;
472
+ state.expandedPaths = new Set(state.expandedPaths);
473
+ state.expandedPaths.delete(path);
474
+ for (const p of state.expandedPaths) {
475
+ if (p.startsWith(prefix)) {
476
+ state.expandedPaths.delete(p);
477
+ }
478
+ }
479
+ notify();
480
+ emit({ type: "collapse", path });
481
+ },
482
+ async toggleExpand(path) {
483
+ if (expandingPaths.has(path)) return;
484
+ if (state.expandedPaths.has(path)) {
485
+ controller.collapse(path);
486
+ } else {
487
+ await controller.expand(path);
488
+ }
489
+ },
490
+ async expandTo(path) {
491
+ const parts = [];
492
+ let current = path;
493
+ while (current !== rootPath && current !== "") {
494
+ const parent = dirname(current);
495
+ if (parent === current) break;
496
+ parts.unshift(parent);
497
+ current = parent;
498
+ }
499
+ for (const ancestorPath of parts) {
500
+ if (ancestorPath === rootPath) continue;
501
+ if (!state.expandedPaths.has(ancestorPath)) {
502
+ await controller.expand(ancestorPath);
503
+ }
504
+ }
505
+ },
506
+ select(path, mode = "replace") {
507
+ const result = computeSelection(
508
+ state.selectedPaths,
509
+ state.anchorPath,
510
+ path,
511
+ mode,
512
+ state.flatList
513
+ );
514
+ state.selectedPaths = result.selectedPaths;
515
+ state.anchorPath = result.anchorPath;
516
+ notify();
517
+ emit({ type: "select", paths: Array.from(result.selectedPaths) });
518
+ },
519
+ selectAll() {
520
+ state.selectedPaths = new Set(state.flatList.map((f) => f.node.path));
521
+ notify();
522
+ emit({ type: "select", paths: Array.from(state.selectedPaths) });
523
+ },
524
+ clearSelection() {
525
+ state.selectedPaths = /* @__PURE__ */ new Set();
526
+ state.anchorPath = null;
527
+ notify();
528
+ emit({ type: "select", paths: [] });
529
+ },
530
+ startRename(path) {
531
+ state.renamingPath = path;
532
+ notify();
533
+ },
534
+ async commitRename(newName) {
535
+ if (!state.renamingPath || !adapter.rename) return;
536
+ const oldPath = state.renamingPath;
537
+ const parent = dirname(oldPath);
538
+ const sep = oldPath.includes("\\") ? "\\" : "/";
539
+ const newPath = parent + sep + newName;
540
+ await adapter.rename(oldPath, newPath);
541
+ state.renamingPath = null;
542
+ if (parent === rootPath) {
543
+ await controller.loadRoot();
544
+ } else {
545
+ const parentNode = findNode(state.rootNodes, parent);
546
+ if (parentNode) {
547
+ await loadChildren(parentNode);
548
+ }
549
+ }
550
+ notify();
551
+ emit({ type: "rename", oldPath, newPath });
552
+ },
553
+ cancelRename() {
554
+ state.renamingPath = null;
555
+ notify();
556
+ },
557
+ async startCreate(parentPath, isDirectory, insertAfterPath) {
558
+ if (parentPath !== rootPath && !state.expandedPaths.has(parentPath)) {
559
+ await controller.expand(parentPath);
560
+ }
561
+ state.creatingState = { parentPath, isDirectory, insertAfterPath };
562
+ notify();
563
+ },
564
+ async commitCreate(name) {
565
+ if (!state.creatingState) return;
566
+ const { parentPath, isDirectory } = state.creatingState;
567
+ state.creatingState = null;
568
+ if (isDirectory) {
569
+ await controller.createDir(parentPath, name);
570
+ } else {
571
+ await controller.createFile(parentPath, name);
572
+ }
573
+ },
574
+ cancelCreate() {
575
+ state.creatingState = null;
576
+ notify();
577
+ },
578
+ async createFile(parentPath, name) {
579
+ if (!adapter.createFile) return;
580
+ await adapter.createFile(parentPath, name);
581
+ await refreshParent(parentPath);
582
+ notify();
583
+ emit({ type: "create", parentPath, name, isDirectory: false });
584
+ },
585
+ async createDir(parentPath, name) {
586
+ if (!adapter.createDir) return;
587
+ await adapter.createDir(parentPath, name);
588
+ await refreshParent(parentPath);
589
+ notify();
590
+ emit({ type: "create", parentPath, name, isDirectory: true });
591
+ },
592
+ async deleteSelected() {
593
+ if (!adapter.delete || state.selectedPaths.size === 0) return;
594
+ const paths = Array.from(state.selectedPaths);
595
+ await adapter.delete(paths);
596
+ state.selectedPaths = /* @__PURE__ */ new Set();
597
+ state.anchorPath = null;
598
+ const parentDirs = new Set(paths.map(dirname));
599
+ for (const dir of parentDirs) {
600
+ await refreshParent(dir);
601
+ }
602
+ notify();
603
+ emit({ type: "delete", paths });
604
+ },
605
+ async refresh(path) {
606
+ if (!path || path === rootPath) {
607
+ await refreshParent(rootPath);
608
+ } else {
609
+ const node = findNode(state.rootNodes, path);
610
+ if (node && node.isDirectory) {
611
+ await loadChildren(node);
612
+ }
613
+ }
614
+ notify();
615
+ emit({ type: "refresh", path });
616
+ },
617
+ setSearchQuery(query) {
618
+ state.searchQuery = query && query.trim() ? query.trim() : null;
619
+ notify();
620
+ },
621
+ async collectAllFiles() {
622
+ const result = [];
623
+ async function walk(dirPath) {
624
+ const entries = await adapter.readDir(dirPath);
625
+ for (const entry of entries) {
626
+ if (!filterFn(entry)) continue;
627
+ result.push(entry);
628
+ if (entry.isDirectory) {
629
+ await walk(entry.path);
630
+ }
631
+ }
632
+ }
633
+ await walk(rootPath);
634
+ return result;
635
+ },
636
+ setFilter(fn) {
637
+ filterFn = fn ?? defaultFilter;
638
+ state.rootNodes = filterNodes(state.rootNodes);
639
+ notify();
640
+ },
641
+ setSort(fn) {
642
+ sortFn = fn ?? defaultSort;
643
+ sortNodes(state.rootNodes);
644
+ notify();
645
+ },
646
+ destroy() {
647
+ stopWatching();
648
+ listeners.clear();
649
+ }
650
+ };
651
+ return controller;
652
+ }
653
+
654
+ // src/core/keybindings.ts
655
+ var ExplorerCommands = {
656
+ DELETE: "explorer.delete",
657
+ RENAME: "explorer.rename",
658
+ NEW_FILE: "explorer.newFile",
659
+ NEW_FOLDER: "explorer.newFolder",
660
+ REFRESH: "explorer.refresh",
661
+ COLLAPSE_ALL: "explorer.collapseAll",
662
+ SELECT_ALL: "explorer.selectAll",
663
+ COPY_PATH: "explorer.copyPath"
664
+ };
665
+ var defaultExplorerKeybindings = [
666
+ { key: "Delete", command: ExplorerCommands.DELETE, when: "explorerFocus" },
667
+ { key: "F2", command: ExplorerCommands.RENAME, when: "explorerFocus" },
668
+ { key: "Ctrl+N", command: ExplorerCommands.NEW_FILE, when: "explorerFocus" },
669
+ { key: "Ctrl+Shift+N", command: ExplorerCommands.NEW_FOLDER, when: "explorerFocus" },
670
+ { key: "Ctrl+R", command: ExplorerCommands.REFRESH, when: "explorerFocus" },
671
+ { key: "Ctrl+Shift+E", command: ExplorerCommands.COLLAPSE_ALL, when: "explorerFocus" },
672
+ { key: "Ctrl+A", command: ExplorerCommands.SELECT_ALL, when: "explorerFocus" },
673
+ { key: "Ctrl+Shift+C", command: ExplorerCommands.COPY_PATH, when: "explorerFocus" }
674
+ ];
675
+ // Annotate the CommonJS export names for ESM import in node:
676
+ 0 && (module.exports = {
677
+ ExplorerCommands,
678
+ coalesceEvents,
679
+ computeSelection,
680
+ createEventProcessor,
681
+ createFileTree,
682
+ defaultExplorerKeybindings,
683
+ defaultFilter,
684
+ defaultSort,
685
+ findMatchingPaths,
686
+ flattenTree,
687
+ fuzzyFind,
688
+ fuzzyMatch
689
+ });
690
+ //# sourceMappingURL=index.cjs.map