@huyooo/file-explorer-frontend-vue 0.4.18 → 0.4.19

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.js CHANGED
@@ -1,6 +1,6 @@
1
- import { defineComponent as q, computed as F, createElementBlock as h, openBlock as a, normalizeClass as B, createVNode as N, unref as O, withModifiers as R, Fragment as G, renderList as J, createElementVNode as s, createBlock as H, createCommentVNode as j, withKeys as ce, toDisplayString as z, createTextVNode as se, ref as D, renderSlot as Z, watch as ee, nextTick as fe, onUnmounted as ne, Teleport as ie, normalizeStyle as de, onMounted as ve, withDirectives as te, vModelText as we, vModelSelect as ye, vModelRadio as ke, vModelDynamic as xe, vModelCheckbox as $e } from "vue";
2
- import { Icon as T } from "@iconify/vue";
3
- const d = {
1
+ import { defineComponent, computed, createElementBlock, openBlock, normalizeClass, createVNode, unref, withModifiers, Fragment, renderList, createElementVNode, createBlock, createCommentVNode, withKeys, toDisplayString, createTextVNode, ref, renderSlot, watch, nextTick, onUnmounted, Teleport, normalizeStyle, onMounted, withDirectives, vModelText, vModelSelect, vModelRadio, vModelDynamic, vModelCheckbox } from "vue";
2
+ import { Icon } from "@iconify/vue";
3
+ const FileType = {
4
4
  FOLDER: "folder",
5
5
  FILE: "file",
6
6
  IMAGE: "image",
@@ -13,7 +13,8 @@ const d = {
13
13
  ARCHIVE: "archive",
14
14
  APPLICATION: "application",
15
15
  UNKNOWN: "unknown"
16
- }, me = /* @__PURE__ */ new Set([
16
+ };
17
+ const KNOWN_TYPES$1 = /* @__PURE__ */ new Set([
17
18
  "3d",
18
19
  "actionscript",
19
20
  "ada",
@@ -329,191 +330,193 @@ const d = {
329
330
  "yarn",
330
331
  "zig",
331
332
  "zip"
332
- ]), ge = {
333
+ ]);
334
+ const EXT_MAP = {
333
335
  // JavaScript/TypeScript
334
- js: "javascript",
335
- mjs: "javascript",
336
- cjs: "javascript",
337
- jsx: "react",
338
- ts: "typescript",
339
- mts: "typescript",
340
- cts: "typescript",
341
- tsx: "react-ts",
336
+ "js": "javascript",
337
+ "mjs": "javascript",
338
+ "cjs": "javascript",
339
+ "jsx": "react",
340
+ "ts": "typescript",
341
+ "mts": "typescript",
342
+ "cts": "typescript",
343
+ "tsx": "react-ts",
342
344
  // 前端框架
343
- vue: "vue",
344
- svelte: "svelte",
345
- astro: "astro",
345
+ "vue": "vue",
346
+ "svelte": "svelte",
347
+ "astro": "astro",
346
348
  // 后端语言
347
- py: "python",
348
- pyw: "python",
349
- pyi: "python",
350
- pyc: "python",
351
- java: "java",
352
- class: "javaclass",
353
- jar: "jar",
354
- c: "c",
355
- h: "h",
356
- cpp: "cpp",
357
- cc: "cpp",
358
- cxx: "cpp",
359
- hpp: "hpp",
360
- hh: "hpp",
361
- hxx: "hpp",
362
- cs: "csharp",
363
- csx: "csharp",
364
- go: "go",
365
- rs: "rust",
366
- php: "php",
367
- phtml: "php",
368
- rb: "ruby",
369
- rake: "ruby",
370
- swift: "swift",
371
- kt: "kotlin",
372
- kts: "kotlin",
373
- scala: "scala",
374
- dart: "dart",
375
- lua: "lua",
376
- luau: "luau",
377
- r: "r",
378
- rdata: "r",
379
- rds: "r",
380
- pl: "perl",
381
- pm: "perl",
382
- sh: "command",
383
- bash: "command",
384
- zsh: "command",
385
- fish: "command",
386
- ps1: "powershell",
387
- psm1: "powershell",
388
- psd1: "powershell",
389
- bat: "command",
390
- cmd: "command",
349
+ "py": "python",
350
+ "pyw": "python",
351
+ "pyi": "python",
352
+ "pyc": "python",
353
+ "java": "java",
354
+ "class": "javaclass",
355
+ "jar": "jar",
356
+ "c": "c",
357
+ "h": "h",
358
+ "cpp": "cpp",
359
+ "cc": "cpp",
360
+ "cxx": "cpp",
361
+ "hpp": "hpp",
362
+ "hh": "hpp",
363
+ "hxx": "hpp",
364
+ "cs": "csharp",
365
+ "csx": "csharp",
366
+ "go": "go",
367
+ "rs": "rust",
368
+ "php": "php",
369
+ "phtml": "php",
370
+ "rb": "ruby",
371
+ "rake": "ruby",
372
+ "swift": "swift",
373
+ "kt": "kotlin",
374
+ "kts": "kotlin",
375
+ "scala": "scala",
376
+ "dart": "dart",
377
+ "lua": "lua",
378
+ "luau": "luau",
379
+ "r": "r",
380
+ "rdata": "r",
381
+ "rds": "r",
382
+ "pl": "perl",
383
+ "pm": "perl",
384
+ "sh": "command",
385
+ "bash": "command",
386
+ "zsh": "command",
387
+ "fish": "command",
388
+ "ps1": "powershell",
389
+ "psm1": "powershell",
390
+ "psd1": "powershell",
391
+ "bat": "command",
392
+ "cmd": "command",
391
393
  // 样式
392
- css: "css",
393
- scss: "sass",
394
- sass: "sass",
395
- less: "less",
396
- styl: "stylus",
394
+ "css": "css",
395
+ "scss": "sass",
396
+ "sass": "sass",
397
+ "less": "less",
398
+ "styl": "stylus",
397
399
  // 标记/配置
398
- html: "html",
399
- htm: "html",
400
- xhtml: "html",
401
- xml: "xml",
402
- xsl: "xml",
403
- xslt: "xml",
404
- json: "json",
405
- jsonc: "json",
406
- json5: "json",
407
- yaml: "yaml",
408
- yml: "yaml",
409
- toml: "toml",
410
- ini: "settings",
411
- conf: "settings",
412
- config: "settings",
400
+ "html": "html",
401
+ "htm": "html",
402
+ "xhtml": "html",
403
+ "xml": "xml",
404
+ "xsl": "xml",
405
+ "xslt": "xml",
406
+ "json": "json",
407
+ "jsonc": "json",
408
+ "json5": "json",
409
+ "yaml": "yaml",
410
+ "yml": "yaml",
411
+ "toml": "toml",
412
+ "ini": "settings",
413
+ "conf": "settings",
414
+ "config": "settings",
413
415
  // 文档
414
- md: "markdown",
415
- markdown: "markdown",
416
- mdx: "mdx",
417
- txt: "document",
418
- pdf: "pdf",
419
- doc: "word",
420
- docx: "word",
421
- dot: "word",
422
- dotx: "word",
423
- odt: "word",
424
- xls: "table",
425
- xlsx: "table",
426
- xlsm: "table",
427
- ods: "table",
428
- csv: "table",
429
- ppt: "powerpoint",
430
- pptx: "powerpoint",
431
- odp: "powerpoint",
416
+ "md": "markdown",
417
+ "markdown": "markdown",
418
+ "mdx": "mdx",
419
+ "txt": "document",
420
+ "pdf": "pdf",
421
+ "doc": "word",
422
+ "docx": "word",
423
+ "dot": "word",
424
+ "dotx": "word",
425
+ "odt": "word",
426
+ "xls": "table",
427
+ "xlsx": "table",
428
+ "xlsm": "table",
429
+ "ods": "table",
430
+ "csv": "table",
431
+ "ppt": "powerpoint",
432
+ "pptx": "powerpoint",
433
+ "odp": "powerpoint",
432
434
  // 图片
433
- jpg: "image",
434
- jpeg: "image",
435
- png: "image",
436
- gif: "image",
437
- webp: "image",
438
- ico: "image",
439
- bmp: "image",
440
- tiff: "image",
441
- tif: "image",
442
- heic: "image",
443
- heif: "image",
444
- svg: "svg",
445
- psd: "adobe-photoshop",
446
- ai: "adobe-illustrator",
447
- sketch: "sketch",
448
- fig: "figma",
449
- figma: "figma",
435
+ "jpg": "image",
436
+ "jpeg": "image",
437
+ "png": "image",
438
+ "gif": "image",
439
+ "webp": "image",
440
+ "ico": "image",
441
+ "bmp": "image",
442
+ "tiff": "image",
443
+ "tif": "image",
444
+ "heic": "image",
445
+ "heif": "image",
446
+ "svg": "svg",
447
+ "psd": "adobe-photoshop",
448
+ "ai": "adobe-illustrator",
449
+ "sketch": "sketch",
450
+ "fig": "figma",
451
+ "figma": "figma",
450
452
  // 视频/音频
451
- mp4: "video",
452
- mov: "video",
453
- avi: "video",
454
- mkv: "video",
455
- webm: "video",
456
- flv: "video",
457
- wmv: "video",
458
- m4v: "video",
453
+ "mp4": "video",
454
+ "mov": "video",
455
+ "avi": "video",
456
+ "mkv": "video",
457
+ "webm": "video",
458
+ "flv": "video",
459
+ "wmv": "video",
460
+ "m4v": "video",
459
461
  "3gp": "video",
460
- mpeg: "video",
461
- mpg: "video",
462
- mp3: "audio",
463
- wav: "audio",
464
- flac: "audio",
465
- aac: "audio",
466
- ogg: "audio",
467
- wma: "audio",
468
- m4a: "audio",
469
- aiff: "audio",
462
+ "mpeg": "video",
463
+ "mpg": "video",
464
+ "mp3": "audio",
465
+ "wav": "audio",
466
+ "flac": "audio",
467
+ "aac": "audio",
468
+ "ogg": "audio",
469
+ "wma": "audio",
470
+ "m4a": "audio",
471
+ "aiff": "audio",
470
472
  // 压缩
471
- zip: "zip",
472
- rar: "zip",
473
+ "zip": "zip",
474
+ "rar": "zip",
473
475
  "7z": "zip",
474
- tar: "zip",
475
- gz: "zip",
476
- bz2: "zip",
477
- xz: "zip",
478
- tgz: "zip",
479
- tbz2: "zip",
476
+ "tar": "zip",
477
+ "gz": "zip",
478
+ "bz2": "zip",
479
+ "xz": "zip",
480
+ "tgz": "zip",
481
+ "tbz2": "zip",
480
482
  // 数据库
481
- sql: "database",
482
- db: "database",
483
- sqlite: "database",
484
- sqlite3: "database",
485
- prisma: "prisma",
483
+ "sql": "database",
484
+ "db": "database",
485
+ "sqlite": "database",
486
+ "sqlite3": "database",
487
+ "prisma": "prisma",
486
488
  // 其他
487
- log: "log",
488
- lock: "lock",
489
- env: "settings",
490
- graphql: "graphql",
491
- gql: "graphql",
492
- proto: "proto",
493
- wasm: "webassembly",
494
- zig: "zig",
495
- nim: "nim",
496
- nix: "nix",
497
- hcl: "hcl",
498
- tf: "terraform",
499
- sol: "solidity",
500
- ex: "elixir",
501
- exs: "elixir",
502
- erl: "erlang",
503
- hrl: "erlang",
504
- hs: "haskell",
505
- lhs: "haskell",
506
- ml: "ocaml",
507
- mli: "ocaml",
508
- clj: "clojure",
509
- cljs: "clojure",
510
- cljc: "clojure",
511
- lisp: "lisp",
512
- lsp: "lisp",
513
- el: "lisp",
514
- vim: "vim",
515
- dockerfile: "docker"
516
- }, pe = {
489
+ "log": "log",
490
+ "lock": "lock",
491
+ "env": "settings",
492
+ "graphql": "graphql",
493
+ "gql": "graphql",
494
+ "proto": "proto",
495
+ "wasm": "webassembly",
496
+ "zig": "zig",
497
+ "nim": "nim",
498
+ "nix": "nix",
499
+ "hcl": "hcl",
500
+ "tf": "terraform",
501
+ "sol": "solidity",
502
+ "ex": "elixir",
503
+ "exs": "elixir",
504
+ "erl": "erlang",
505
+ "hrl": "erlang",
506
+ "hs": "haskell",
507
+ "lhs": "haskell",
508
+ "ml": "ocaml",
509
+ "mli": "ocaml",
510
+ "clj": "clojure",
511
+ "cljs": "clojure",
512
+ "cljc": "clojure",
513
+ "lisp": "lisp",
514
+ "lsp": "lisp",
515
+ "el": "lisp",
516
+ "vim": "vim",
517
+ "dockerfile": "docker"
518
+ };
519
+ const SPECIAL_FILES = {
517
520
  // Git
518
521
  ".gitignore": "git",
519
522
  ".gitattributes": "git",
@@ -538,7 +541,7 @@ const d = {
538
541
  "bunfig.toml": "bun",
539
542
  // Python
540
543
  "requirements.txt": "python",
541
- pipfile: "python",
544
+ "pipfile": "python",
542
545
  "pipfile.lock": "python",
543
546
  "pyproject.toml": "python",
544
547
  "poetry.lock": "python",
@@ -554,17 +557,17 @@ const d = {
554
557
  "composer.json": "php",
555
558
  "composer.lock": "php",
556
559
  // Ruby
557
- gemfile: "gemfile",
560
+ "gemfile": "gemfile",
558
561
  "gemfile.lock": "gemfile",
559
- rakefile: "ruby",
562
+ "rakefile": "ruby",
560
563
  // Docker
561
- dockerfile: "docker",
564
+ "dockerfile": "docker",
562
565
  "docker-compose.yml": "docker",
563
566
  "docker-compose.yaml": "docker",
564
567
  ".dockerignore": "docker",
565
568
  // 构建工具
566
- makefile: "makefile",
567
- gnumakefile: "makefile",
569
+ "makefile": "makefile",
570
+ "gnumakefile": "makefile",
568
571
  "cmakelists.txt": "cmake",
569
572
  "build.gradle": "gradle",
570
573
  "build.gradle.kts": "gradle",
@@ -632,19 +635,19 @@ const d = {
632
635
  "vercel.json": "vercel",
633
636
  "netlify.toml": "netlify",
634
637
  // 其他
635
- license: "license",
638
+ "license": "license",
636
639
  "license.md": "license",
637
640
  "license.txt": "license",
638
- readme: "readme",
641
+ "readme": "readme",
639
642
  "readme.md": "readme",
640
643
  "readme.txt": "readme",
641
- changelog: "changelog",
644
+ "changelog": "changelog",
642
645
  "changelog.md": "changelog",
643
646
  ".npmrc": "npm",
644
647
  ".npmignore": "npm",
645
648
  "robots.txt": "robots",
646
649
  ".htaccess": "nginx",
647
- vagrantfile: "vagrant",
650
+ "vagrantfile": "vagrant",
648
651
  ".stylelintrc": "stylelint",
649
652
  ".stylelintrc.json": "stylelint",
650
653
  "nodemon.json": "nodemon",
@@ -654,62 +657,73 @@ const d = {
654
657
  "deno.json": "deno",
655
658
  "deno.jsonc": "deno"
656
659
  };
657
- function he(e, g) {
658
- const t = e.toLowerCase();
659
- if (pe[t]) {
660
- const i = pe[t];
661
- if (me.has(i))
662
- return `material-icon-theme:${i}`;
660
+ function getFileTypeIcon(fileName, fallbackType) {
661
+ const lowerName = fileName.toLowerCase();
662
+ if (SPECIAL_FILES[lowerName]) {
663
+ const type = SPECIAL_FILES[lowerName];
664
+ if (KNOWN_TYPES$1.has(type)) {
665
+ return `material-icon-theme:${type}`;
666
+ }
663
667
  }
664
- if (t === "dockerfile" || t.startsWith("dockerfile."))
668
+ if (lowerName === "dockerfile" || lowerName.startsWith("dockerfile.")) {
665
669
  return "material-icon-theme:docker";
666
- if (t === ".env" || t.startsWith(".env."))
670
+ }
671
+ if (lowerName === ".env" || lowerName.startsWith(".env.")) {
667
672
  return "material-icon-theme:settings";
668
- const r = e.lastIndexOf("."), l = r > 0 ? e.substring(r + 1).toLowerCase() : "";
669
- if (l === "ts" || l === "js") {
670
- const i = e.substring(0, r).toLowerCase();
671
- if (i.endsWith(".d"))
673
+ }
674
+ const lastDotIndex = fileName.lastIndexOf(".");
675
+ const ext = lastDotIndex > 0 ? fileName.substring(lastDotIndex + 1).toLowerCase() : "";
676
+ if (ext === "ts" || ext === "js") {
677
+ const baseName = fileName.substring(0, lastDotIndex).toLowerCase();
678
+ if (baseName.endsWith(".d")) {
672
679
  return "material-icon-theme:typescript-def";
673
- if (i.endsWith(".test") || i.endsWith(".spec"))
674
- return l === "ts" ? "material-icon-theme:test-ts" : "material-icon-theme:test-js";
680
+ }
681
+ if (baseName.endsWith(".test") || baseName.endsWith(".spec")) {
682
+ return ext === "ts" ? "material-icon-theme:test-ts" : "material-icon-theme:test-js";
683
+ }
675
684
  }
676
- if (l === "jsx" || l === "tsx") {
677
- const i = e.substring(0, r).toLowerCase();
678
- if (i.endsWith(".test") || i.endsWith(".spec"))
679
- return l === "tsx" ? "material-icon-theme:test-ts" : "material-icon-theme:test-jsx";
685
+ if (ext === "jsx" || ext === "tsx") {
686
+ const baseName = fileName.substring(0, lastDotIndex).toLowerCase();
687
+ if (baseName.endsWith(".test") || baseName.endsWith(".spec")) {
688
+ return ext === "tsx" ? "material-icon-theme:test-ts" : "material-icon-theme:test-jsx";
689
+ }
690
+ }
691
+ if (ext && EXT_MAP[ext]) {
692
+ const type = EXT_MAP[ext];
693
+ if (KNOWN_TYPES$1.has(type)) {
694
+ return `material-icon-theme:${type}`;
695
+ }
680
696
  }
681
- if (l && ge[l]) {
682
- const i = ge[l];
683
- if (me.has(i))
684
- return `material-icon-theme:${i}`;
697
+ if (fallbackType) {
698
+ return getFallbackIcon(fallbackType);
685
699
  }
686
- return g ? Ce(g) : "material-icon-theme:document";
700
+ return "material-icon-theme:document";
687
701
  }
688
- function Ce(e) {
689
- switch (e) {
690
- case d.IMAGE:
702
+ function getFallbackIcon(type) {
703
+ switch (type) {
704
+ case FileType.IMAGE:
691
705
  return "material-icon-theme:image";
692
- case d.VIDEO:
706
+ case FileType.VIDEO:
693
707
  return "material-icon-theme:video";
694
- case d.MUSIC:
708
+ case FileType.MUSIC:
695
709
  return "material-icon-theme:audio";
696
- case d.CODE:
710
+ case FileType.CODE:
697
711
  return "material-icon-theme:javascript";
698
- case d.TEXT:
712
+ case FileType.TEXT:
699
713
  return "material-icon-theme:document";
700
- case d.DOCUMENT:
714
+ case FileType.DOCUMENT:
701
715
  return "material-icon-theme:word";
702
- case d.PDF:
716
+ case FileType.PDF:
703
717
  return "material-icon-theme:pdf";
704
- case d.ARCHIVE:
718
+ case FileType.ARCHIVE:
705
719
  return "material-icon-theme:zip";
706
- case d.APPLICATION:
720
+ case FileType.APPLICATION:
707
721
  return "material-icon-theme:exe";
708
722
  default:
709
723
  return "material-icon-theme:document";
710
724
  }
711
725
  }
712
- const Ie = /* @__PURE__ */ new Set([
726
+ const KNOWN_TYPES = /* @__PURE__ */ new Set([
713
727
  "admin",
714
728
  "android",
715
729
  "angular",
@@ -965,114 +979,115 @@ const Ie = /* @__PURE__ */ new Set([
965
979
  "wordpress",
966
980
  "yarn",
967
981
  "zeabur"
968
- ]), Ee = {
982
+ ]);
983
+ const ALIASES = {
969
984
  // 复数/变体
970
- tests: "test",
971
- __tests__: "test",
972
- __test__: "test",
973
- spec: "test",
974
- specs: "test",
975
- script: "scripts",
976
- configs: "config",
977
- configuration: "config",
978
- configurations: "config",
979
- route: "routes",
980
- routing: "routes",
981
- stories: "storybook",
982
- story: "storybook",
983
- templates: "template",
984
- themes: "theme",
985
- videos: "video",
986
- imgs: "images",
987
- img: "images",
988
- image: "images",
989
- fonts: "font",
990
- styles: "css",
991
- style: "css",
992
- styling: "css",
993
- stylesheets: "css",
994
- view: "views",
995
- pages: "views",
996
- page: "views",
997
- layouts: "layout",
998
- models: "database",
999
- model: "database",
1000
- modules: "lib",
1001
- module: "lib",
1002
- mods: "lib",
1003
- plugins: "plugin",
1004
- addons: "plugin",
1005
- extensions: "plugin",
1006
- middlewares: "middleware",
1007
- helpers: "helper",
1008
- utilities: "utils",
1009
- util: "utils",
1010
- tool: "tools",
1011
- tooling: "tools",
1012
- resources: "resource",
1013
- res: "resource",
1014
- assets: "resource",
1015
- asset: "resource",
1016
- hooks: "hook",
1017
- composables: "hook",
1018
- mocks: "mock",
1019
- __mocks__: "mock",
1020
- fixtures: "mock",
1021
- __fixtures__: "mock",
1022
- logs: "log",
1023
- uploads: "upload",
1024
- function: "functions",
1025
- func: "functions",
1026
- fns: "functions",
1027
- services: "server",
1028
- service: "server",
1029
- component: "components",
1030
- comp: "components",
1031
- comps: "components",
1032
- controllers: "controller",
985
+ "tests": "test",
986
+ "__tests__": "test",
987
+ "__test__": "test",
988
+ "spec": "test",
989
+ "specs": "test",
990
+ "script": "scripts",
991
+ "configs": "config",
992
+ "configuration": "config",
993
+ "configurations": "config",
994
+ "route": "routes",
995
+ "routing": "routes",
996
+ "stories": "storybook",
997
+ "story": "storybook",
998
+ "templates": "template",
999
+ "themes": "theme",
1000
+ "videos": "video",
1001
+ "imgs": "images",
1002
+ "img": "images",
1003
+ "image": "images",
1004
+ "fonts": "font",
1005
+ "styles": "css",
1006
+ "style": "css",
1007
+ "styling": "css",
1008
+ "stylesheets": "css",
1009
+ "view": "views",
1010
+ "pages": "views",
1011
+ "page": "views",
1012
+ "layouts": "layout",
1013
+ "models": "database",
1014
+ "model": "database",
1015
+ "modules": "lib",
1016
+ "module": "lib",
1017
+ "mods": "lib",
1018
+ "plugins": "plugin",
1019
+ "addons": "plugin",
1020
+ "extensions": "plugin",
1021
+ "middlewares": "middleware",
1022
+ "helpers": "helper",
1023
+ "utilities": "utils",
1024
+ "util": "utils",
1025
+ "tool": "tools",
1026
+ "tooling": "tools",
1027
+ "resources": "resource",
1028
+ "res": "resource",
1029
+ "assets": "resource",
1030
+ "asset": "resource",
1031
+ "hooks": "hook",
1032
+ "composables": "hook",
1033
+ "mocks": "mock",
1034
+ "__mocks__": "mock",
1035
+ "fixtures": "mock",
1036
+ "__fixtures__": "mock",
1037
+ "logs": "log",
1038
+ "uploads": "upload",
1039
+ "function": "functions",
1040
+ "func": "functions",
1041
+ "fns": "functions",
1042
+ "services": "server",
1043
+ "service": "server",
1044
+ "component": "components",
1045
+ "comp": "components",
1046
+ "comps": "components",
1047
+ "controllers": "controller",
1033
1048
  // 常见变体
1034
- source: "src",
1035
- sources: "src",
1036
- distribution: "dist",
1037
- build: "dist",
1038
- builds: "dist",
1039
- out: "dist",
1040
- output: "dist",
1041
- documentation: "docs",
1042
- doc: "docs",
1043
- document: "docs",
1044
- documents: "docs",
1045
- static: "public",
1046
- statics: "public",
1047
- publics: "public",
1048
- libs: "lib",
1049
- library: "lib",
1050
- vendor: "lib",
1051
- vendors: "lib",
1052
- bin: "scripts",
1053
- binaries: "scripts",
1054
- tmp: "temp",
1055
- temporary: "temp",
1056
- cache: "temp",
1057
- caches: "temp",
1049
+ "source": "src",
1050
+ "sources": "src",
1051
+ "distribution": "dist",
1052
+ "build": "dist",
1053
+ "builds": "dist",
1054
+ "out": "dist",
1055
+ "output": "dist",
1056
+ "documentation": "docs",
1057
+ "doc": "docs",
1058
+ "document": "docs",
1059
+ "documents": "docs",
1060
+ "static": "public",
1061
+ "statics": "public",
1062
+ "publics": "public",
1063
+ "libs": "lib",
1064
+ "library": "lib",
1065
+ "vendor": "lib",
1066
+ "vendors": "lib",
1067
+ "bin": "scripts",
1068
+ "binaries": "scripts",
1069
+ "tmp": "temp",
1070
+ "temporary": "temp",
1071
+ "cache": "temp",
1072
+ "caches": "temp",
1058
1073
  ".cache": "temp",
1059
1074
  ".turbo": "temp",
1060
- types: "typescript",
1075
+ "types": "typescript",
1061
1076
  "@types": "typescript",
1062
- typings: "typescript",
1063
- dts: "typescript",
1064
- locales: "i18n",
1065
- locale: "i18n",
1066
- lang: "i18n",
1067
- languages: "i18n",
1068
- translations: "i18n",
1069
- db: "database",
1070
- databases: "database",
1071
- sql: "database",
1072
- queries: "database",
1073
- migration: "migrations",
1074
- seeds: "seeders",
1075
- seed: "seeders",
1077
+ "typings": "typescript",
1078
+ "dts": "typescript",
1079
+ "locales": "i18n",
1080
+ "locale": "i18n",
1081
+ "lang": "i18n",
1082
+ "languages": "i18n",
1083
+ "translations": "i18n",
1084
+ "db": "database",
1085
+ "databases": "database",
1086
+ "sql": "database",
1087
+ "queries": "database",
1088
+ "migration": "migrations",
1089
+ "seeds": "seeders",
1090
+ "seed": "seeders",
1076
1091
  // 技术栈
1077
1092
  ".vscode": "vscode",
1078
1093
  ".github": "github",
@@ -1080,48 +1095,51 @@ const Ie = /* @__PURE__ */ new Set([
1080
1095
  ".circleci": "circleci",
1081
1096
  ".husky": "husky",
1082
1097
  ".docker": "docker",
1083
- node_modules: "node",
1084
- scss: "sass",
1085
- renderer: "client",
1086
- frontend: "client",
1087
- web: "client",
1088
- webapp: "client",
1089
- website: "client",
1090
- backend: "server",
1091
- main: "server",
1092
- preload: "scripts",
1098
+ "node_modules": "node",
1099
+ "scss": "sass",
1100
+ "renderer": "client",
1101
+ "frontend": "client",
1102
+ "web": "client",
1103
+ "webapp": "client",
1104
+ "website": "client",
1105
+ "backend": "server",
1106
+ "main": "server",
1107
+ "preload": "scripts",
1093
1108
  ".idea": "intellij",
1094
1109
  ".git": "git",
1095
- k8s: "kubernetes",
1096
- kube: "kubernetes",
1097
- mongo: "database",
1098
- mongodb: "database",
1099
- mysql: "database",
1100
- postgres: "database",
1101
- api: "api",
1102
- apis: "api",
1103
- interfaces: "interface",
1104
- notebook: "jupyter",
1105
- notebooks: "jupyter",
1106
- ipynb: "jupyter",
1107
- notification: "messages",
1108
- notifications: "messages",
1109
- env: "environment",
1110
- envs: "environment",
1111
- redux: "redux-reducer",
1112
- store: "store",
1113
- stores: "store",
1114
- electron: "desktop",
1115
- tauri: "src-tauri"
1110
+ "k8s": "kubernetes",
1111
+ "kube": "kubernetes",
1112
+ "mongo": "database",
1113
+ "mongodb": "database",
1114
+ "mysql": "database",
1115
+ "postgres": "database",
1116
+ "api": "api",
1117
+ "apis": "api",
1118
+ "interfaces": "interface",
1119
+ "notebook": "jupyter",
1120
+ "notebooks": "jupyter",
1121
+ "ipynb": "jupyter",
1122
+ "notification": "messages",
1123
+ "notifications": "messages",
1124
+ "env": "environment",
1125
+ "envs": "environment",
1126
+ "redux": "redux-reducer",
1127
+ "store": "store",
1128
+ "stores": "store",
1129
+ "electron": "desktop",
1130
+ "tauri": "src-tauri"
1116
1131
  };
1117
- function Me(e) {
1118
- const g = (e || "").trim();
1119
- if (!g) return;
1120
- const t = g.replace(/[\\/]+$/, "").toLowerCase(), r = Ee[t] ?? t;
1121
- if (Ie.has(r))
1122
- return `material-icon-theme:folder-${r}`;
1132
+ function getFolderTypeIcon(folderName) {
1133
+ const name = (folderName || "").trim();
1134
+ if (!name) return void 0;
1135
+ const lower = name.replace(/[\\/]+$/, "").toLowerCase();
1136
+ const standardName = ALIASES[lower] ?? lower;
1137
+ if (KNOWN_TYPES.has(standardName)) {
1138
+ return `material-icon-theme:folder-${standardName}`;
1139
+ }
1140
+ return void 0;
1123
1141
  }
1124
- const je = /* @__PURE__ */ q({
1142
+ const _sfc_main$d = /* @__PURE__ */ defineComponent({
1125
1143
  __name: "FileIcon",
1126
1144
  props: {
1127
1145
  type: {},
@@ -1129,83 +1147,106 @@ const je = /* @__PURE__ */ q({
1129
1147
  className: { default: "" },
1130
1148
  size: { default: 24 }
1131
1149
  },
1132
- setup(e) {
1133
- const g = e, t = F(() => {
1134
- if (g.type === d.FOLDER)
1135
- return (g.name ? Me(g.name) : void 0) ?? "ic:round-folder";
1136
- if (g.name)
1137
- return he(g.name, g.type);
1138
- switch (g.type) {
1139
- case d.IMAGE:
1150
+ setup(__props) {
1151
+ const props = __props;
1152
+ const iconName = computed(() => {
1153
+ if (props.type === FileType.FOLDER) {
1154
+ const folderIcon = props.name ? getFolderTypeIcon(props.name) : void 0;
1155
+ return folderIcon ?? "ic:round-folder";
1156
+ }
1157
+ if (props.name) {
1158
+ return getFileTypeIcon(props.name, props.type);
1159
+ }
1160
+ switch (props.type) {
1161
+ case FileType.IMAGE:
1140
1162
  return "material-icon-theme:image";
1141
- case d.TEXT:
1163
+ case FileType.TEXT:
1142
1164
  return "material-icon-theme:document";
1143
- case d.CODE:
1165
+ case FileType.CODE:
1144
1166
  return "material-icon-theme:javascript";
1145
- case d.MUSIC:
1167
+ case FileType.MUSIC:
1146
1168
  return "material-icon-theme:audio";
1147
- case d.VIDEO:
1169
+ case FileType.VIDEO:
1148
1170
  return "material-icon-theme:video";
1149
- case d.PDF:
1171
+ case FileType.PDF:
1150
1172
  return "material-icon-theme:pdf";
1151
- case d.DOCUMENT:
1173
+ case FileType.DOCUMENT:
1152
1174
  return "material-icon-theme:word";
1153
- case d.APPLICATION:
1175
+ case FileType.APPLICATION:
1154
1176
  return "material-icon-theme:exe";
1155
- case d.ARCHIVE:
1177
+ case FileType.ARCHIVE:
1156
1178
  return "material-icon-theme:zip";
1157
1179
  default:
1158
1180
  return "material-icon-theme:document";
1159
1181
  }
1160
- }), r = F(() => {
1161
- const l = "file-icon";
1162
- switch (g.type) {
1163
- case d.FOLDER:
1164
- return `${l} file-icon--folder`;
1165
- case d.IMAGE:
1166
- return `${l} file-icon--image`;
1167
- case d.TEXT:
1168
- return `${l} file-icon--text`;
1169
- case d.CODE:
1170
- return `${l} file-icon--code`;
1171
- case d.MUSIC:
1172
- return `${l} file-icon--music`;
1173
- case d.VIDEO:
1174
- return `${l} file-icon--video`;
1175
- case d.PDF:
1176
- case d.DOCUMENT:
1177
- return `${l} file-icon--pdf`;
1178
- case d.APPLICATION:
1179
- return `${l} file-icon--application`;
1180
- case d.ARCHIVE:
1181
- return `${l} file-icon--archive`;
1182
+ });
1183
+ const iconClass = computed(() => {
1184
+ const base = "file-icon";
1185
+ switch (props.type) {
1186
+ case FileType.FOLDER:
1187
+ return `${base} file-icon--folder`;
1188
+ case FileType.IMAGE:
1189
+ return `${base} file-icon--image`;
1190
+ case FileType.TEXT:
1191
+ return `${base} file-icon--text`;
1192
+ case FileType.CODE:
1193
+ return `${base} file-icon--code`;
1194
+ case FileType.MUSIC:
1195
+ return `${base} file-icon--music`;
1196
+ case FileType.VIDEO:
1197
+ return `${base} file-icon--video`;
1198
+ case FileType.PDF:
1199
+ case FileType.DOCUMENT:
1200
+ return `${base} file-icon--pdf`;
1201
+ case FileType.APPLICATION:
1202
+ return `${base} file-icon--application`;
1203
+ case FileType.ARCHIVE:
1204
+ return `${base} file-icon--archive`;
1182
1205
  default:
1183
- return `${l} file-icon--default`;
1206
+ return `${base} file-icon--default`;
1184
1207
  }
1185
1208
  });
1186
- return (l, i) => (a(), h("div", {
1187
- class: B(e.className)
1188
- }, [
1189
- N(O(T), {
1190
- icon: t.value,
1191
- width: e.size,
1192
- height: e.size,
1193
- class: B(r.value)
1194
- }, null, 8, ["icon", "width", "height", "class"])
1195
- ], 2));
1209
+ return (_ctx, _cache) => {
1210
+ return openBlock(), createElementBlock("div", {
1211
+ class: normalizeClass(__props.className)
1212
+ }, [
1213
+ createVNode(unref(Icon), {
1214
+ icon: iconName.value,
1215
+ width: __props.size,
1216
+ height: __props.size,
1217
+ class: normalizeClass(iconClass.value)
1218
+ }, null, 8, ["icon", "width", "height", "class"])
1219
+ ], 2);
1220
+ };
1196
1221
  }
1197
- }), K = (e, g) => {
1198
- const t = e.__vccOpts || e;
1199
- for (const [r, l] of g)
1200
- t[r] = l;
1201
- return t;
1202
- }, be = /* @__PURE__ */ K(je, [["__scopeId", "data-v-5777367f"]]), De = ["draggable", "onDragstart", "onDragover", "onDrop", "onClick", "onDblclick", "onContextmenu"], ze = { class: "file-grid-item-icon" }, Se = ["src", "alt"], Oe = {
1222
+ });
1223
+ const _export_sfc = (sfc, props) => {
1224
+ const target = sfc.__vccOpts || sfc;
1225
+ for (const [key, val] of props) {
1226
+ target[key] = val;
1227
+ }
1228
+ return target;
1229
+ };
1230
+ const FileIcon = /* @__PURE__ */ _export_sfc(_sfc_main$d, [["__scopeId", "data-v-5777367f"]]);
1231
+ const _hoisted_1$c = ["draggable", "onDragstart", "onDragover", "onDrop", "onClick", "onDblclick", "onContextmenu"];
1232
+ const _hoisted_2$b = { class: "file-grid-item-icon" };
1233
+ const _hoisted_3$8 = ["src", "alt"];
1234
+ const _hoisted_4$8 = {
1203
1235
  key: 0,
1204
1236
  class: "file-grid-item-thumbnail file-grid-item-thumbnail--video"
1205
- }, Le = ["src", "alt", "onError"], Te = ["src", "alt", "onError"], Ae = { class: "file-grid-item-name-wrapper" }, Ne = ["value", "onBlur"], Pe = ["onClick", "title"], Ue = { class: "file-grid-item-name-base" }, Fe = { class: "file-grid-item-name-ext" }, We = {
1237
+ };
1238
+ const _hoisted_5$7 = ["src", "alt", "onError"];
1239
+ const _hoisted_6$6 = ["src", "alt", "onError"];
1240
+ const _hoisted_7$6 = { class: "file-grid-item-name-wrapper" };
1241
+ const _hoisted_8$5 = ["value", "onBlur"];
1242
+ const _hoisted_9$5 = ["onClick", "title"];
1243
+ const _hoisted_10$3 = { class: "file-grid-item-name-base" };
1244
+ const _hoisted_11$3 = { class: "file-grid-item-name-ext" };
1245
+ const _hoisted_12$3 = {
1206
1246
  key: 1,
1207
1247
  class: "file-grid-item-name-base file-grid-item-name-base--two-lines"
1208
- }, Re = /* @__PURE__ */ q({
1248
+ };
1249
+ const _sfc_main$c = /* @__PURE__ */ defineComponent({
1209
1250
  __name: "FileGrid",
1210
1251
  props: {
1211
1252
  items: {},
@@ -1215,138 +1256,188 @@ const je = /* @__PURE__ */ q({
1215
1256
  getAppIconUrl: { type: Function }
1216
1257
  },
1217
1258
  emits: ["select", "open", "contextMenu", "contextMenuEmpty", "nameClick", "rename", "renameCancel", "dragStart", "dragOver", "dragLeave", "drop", "thumbnailError"],
1218
- setup(e, { emit: g }) {
1219
- function t(n, C) {
1220
- if (C)
1221
- return { baseName: n, ext: "" };
1222
- const c = n.lastIndexOf(".");
1223
- return c <= 0 ? { baseName: n, ext: "" } : {
1224
- baseName: n.substring(0, c),
1225
- ext: n.substring(c)
1259
+ setup(__props, { emit: __emit }) {
1260
+ function splitFileName(name, isFolder) {
1261
+ if (isFolder) {
1262
+ return { baseName: name, ext: "" };
1263
+ }
1264
+ const lastDot = name.lastIndexOf(".");
1265
+ if (lastDot <= 0) {
1266
+ return { baseName: name, ext: "" };
1267
+ }
1268
+ return {
1269
+ baseName: name.substring(0, lastDot),
1270
+ ext: name.substring(lastDot)
1226
1271
  };
1227
1272
  }
1228
- const r = /* @__PURE__ */ new Map();
1229
- function l(n) {
1230
- const C = `${n.id}-${n.name}`;
1231
- return r.has(C) || r.set(C, t(n.name, n.type === d.FOLDER)), r.get(C);
1273
+ const fileNameCache = /* @__PURE__ */ new Map();
1274
+ function getFileNameParts(item) {
1275
+ const key = `${item.id}-${item.name}`;
1276
+ if (!fileNameCache.has(key)) {
1277
+ fileNameCache.set(key, splitFileName(item.name, item.type === FileType.FOLDER));
1278
+ }
1279
+ return fileNameCache.get(key);
1232
1280
  }
1233
- const i = e, w = g, I = (n) => {
1234
- n.target.closest(".file-grid-item") || w("contextMenuEmpty", n);
1235
- }, m = (n) => {
1236
- var C;
1237
- return n.type === d.APPLICATION && ((C = i.getAppIconUrl) != null && C.call(i, n)) ? !0 : n.type === d.IMAGE || n.type === d.VIDEO ? !!n.thumbnailUrl : !1;
1238
- }, v = (n, C) => {
1239
- const y = C.target.value.trim();
1240
- y && y !== n.name ? w("rename", n, y) : w("renameCancel", n);
1241
- }, b = (n) => {
1242
- n.target.blur();
1243
- }, u = (n) => {
1244
- const C = n.target, c = i.items.find((y) => y.id === i.editingId);
1245
- c && (C.value = c.name), C.blur();
1246
- };
1247
- return (n, C) => (a(), h("div", {
1248
- class: "file-grid",
1249
- onContextmenu: R(I, ["prevent"])
1250
- }, [
1251
- (a(!0), h(G, null, J(e.items, (c) => {
1252
- var y;
1253
- return a(), h("div", {
1254
- key: c.id,
1255
- draggable: e.editingId !== c.id,
1256
- onDragstart: (M) => n.$emit("dragStart", M, c),
1257
- onDragover: R((M) => n.$emit("dragOver", M, c), ["prevent"]),
1258
- onDragleave: C[0] || (C[0] = (M) => n.$emit("dragLeave", M)),
1259
- onDrop: R((M) => n.$emit("drop", M, c), ["prevent"]),
1260
- onClick: R((M) => n.$emit("select", c, M), ["stop"]),
1261
- onDblclick: R((M) => n.$emit("open", c), ["stop"]),
1262
- onContextmenu: R((M) => n.$emit("contextMenu", c, M), ["prevent", "stop"]),
1263
- class: B([
1264
- "file-grid-item",
1265
- e.selectedIds.has(c.id) && e.editingId !== c.id ? "file-grid-item--selected" : e.dragOverId === c.id ? "file-grid-item--drag-over" : "file-grid-item--normal"
1266
- ])
1267
- }, [
1268
- s("div", ze, [
1269
- c.type === O(d).APPLICATION && ((y = e.getAppIconUrl) != null && y.call(e, c)) ? (a(), h("img", {
1270
- key: 0,
1271
- src: e.getAppIconUrl(c),
1272
- alt: c.name,
1273
- class: B([
1274
- "file-grid-item-thumbnail file-grid-item-thumbnail--application",
1275
- e.selectedIds.has(c.id) && e.editingId !== c.id ? "file-grid-item-thumbnail--selected" : ""
1276
- ])
1277
- }, null, 10, Se)) : m(c) ? (a(), h(G, { key: 1 }, [
1278
- c.type === O(d).VIDEO && c.thumbnailUrl ? (a(), h("div", Oe, [
1279
- s("img", {
1280
- src: c.thumbnailUrl,
1281
+ const props = __props;
1282
+ const emit = __emit;
1283
+ const handleEmptyContextMenu = (e) => {
1284
+ const target = e.target;
1285
+ if (!target.closest(".file-grid-item")) {
1286
+ emit("contextMenuEmpty", e);
1287
+ }
1288
+ };
1289
+ const hasThumbnail = (item) => {
1290
+ var _a;
1291
+ if (item.type === FileType.APPLICATION && ((_a = props.getAppIconUrl) == null ? void 0 : _a.call(props, item))) {
1292
+ return true;
1293
+ }
1294
+ if (item.type === FileType.IMAGE) {
1295
+ return !!item.thumbnailUrl;
1296
+ }
1297
+ if (item.type === FileType.VIDEO) {
1298
+ return !!item.thumbnailUrl;
1299
+ }
1300
+ return false;
1301
+ };
1302
+ const handleRename = (item, e) => {
1303
+ const input = e.target;
1304
+ const newName = input.value.trim();
1305
+ if (newName && newName !== item.name) {
1306
+ emit("rename", item, newName);
1307
+ } else {
1308
+ emit("renameCancel", item);
1309
+ }
1310
+ };
1311
+ const handleEnterKey = (e) => {
1312
+ e.target.blur();
1313
+ };
1314
+ const handleEscapeKey = (e) => {
1315
+ const input = e.target;
1316
+ const item = props.items.find((i) => i.id === props.editingId);
1317
+ if (item) {
1318
+ input.value = item.name;
1319
+ }
1320
+ input.blur();
1321
+ };
1322
+ return (_ctx, _cache) => {
1323
+ return openBlock(), createElementBlock("div", {
1324
+ class: "file-grid",
1325
+ onContextmenu: withModifiers(handleEmptyContextMenu, ["prevent"])
1326
+ }, [
1327
+ (openBlock(true), createElementBlock(Fragment, null, renderList(__props.items, (item) => {
1328
+ var _a;
1329
+ return openBlock(), createElementBlock("div", {
1330
+ key: item.id,
1331
+ draggable: __props.editingId !== item.id,
1332
+ onDragstart: ($event) => _ctx.$emit("dragStart", $event, item),
1333
+ onDragover: withModifiers(($event) => _ctx.$emit("dragOver", $event, item), ["prevent"]),
1334
+ onDragleave: _cache[0] || (_cache[0] = ($event) => _ctx.$emit("dragLeave", $event)),
1335
+ onDrop: withModifiers(($event) => _ctx.$emit("drop", $event, item), ["prevent"]),
1336
+ onClick: withModifiers(($event) => _ctx.$emit("select", item, $event), ["stop"]),
1337
+ onDblclick: withModifiers(($event) => _ctx.$emit("open", item), ["stop"]),
1338
+ onContextmenu: withModifiers(($event) => _ctx.$emit("contextMenu", item, $event), ["prevent", "stop"]),
1339
+ class: normalizeClass([
1340
+ "file-grid-item",
1341
+ __props.selectedIds.has(item.id) && __props.editingId !== item.id ? "file-grid-item--selected" : __props.dragOverId === item.id ? "file-grid-item--drag-over" : "file-grid-item--normal"
1342
+ ])
1343
+ }, [
1344
+ createElementVNode("div", _hoisted_2$b, [
1345
+ item.type === unref(FileType).APPLICATION && ((_a = __props.getAppIconUrl) == null ? void 0 : _a.call(__props, item)) ? (openBlock(), createElementBlock("img", {
1346
+ key: 0,
1347
+ src: __props.getAppIconUrl(item),
1348
+ alt: item.name,
1349
+ class: normalizeClass([
1350
+ "file-grid-item-thumbnail file-grid-item-thumbnail--application",
1351
+ __props.selectedIds.has(item.id) && __props.editingId !== item.id ? "file-grid-item-thumbnail--selected" : ""
1352
+ ])
1353
+ }, null, 10, _hoisted_3$8)) : hasThumbnail(item) ? (openBlock(), createElementBlock(Fragment, { key: 1 }, [
1354
+ item.type === unref(FileType).VIDEO && item.thumbnailUrl ? (openBlock(), createElementBlock("div", _hoisted_4$8, [
1355
+ createElementVNode("img", {
1356
+ src: item.thumbnailUrl,
1357
+ class: "file-grid-item-thumbnail",
1358
+ alt: item.name,
1359
+ onError: ($event) => _ctx.$emit("thumbnailError", item, $event)
1360
+ }, null, 40, _hoisted_5$7),
1361
+ _cache[1] || (_cache[1] = createElementVNode("div", { class: "file-grid-item-video-play" }, [
1362
+ createElementVNode("div", { class: "file-grid-item-video-play-icon" })
1363
+ ], -1))
1364
+ ])) : item.thumbnailUrl ? (openBlock(), createElementBlock("img", {
1365
+ key: 1,
1366
+ src: item.thumbnailUrl,
1367
+ alt: item.name,
1281
1368
  class: "file-grid-item-thumbnail",
1282
- alt: c.name,
1283
- onError: (M) => n.$emit("thumbnailError", c, M)
1284
- }, null, 40, Le),
1285
- C[1] || (C[1] = s("div", { class: "file-grid-item-video-play" }, [
1286
- s("div", { class: "file-grid-item-video-play-icon" })
1287
- ], -1))
1288
- ])) : c.thumbnailUrl ? (a(), h("img", {
1369
+ onError: ($event) => _ctx.$emit("thumbnailError", item, $event)
1370
+ }, null, 40, _hoisted_6$6)) : createCommentVNode("", true)
1371
+ ], 64)) : (openBlock(), createBlock(FileIcon, {
1372
+ key: 2,
1373
+ type: item.type,
1374
+ name: item.name,
1375
+ size: 48
1376
+ }, null, 8, ["type", "name"]))
1377
+ ]),
1378
+ createElementVNode("div", _hoisted_7$6, [
1379
+ __props.editingId === item.id ? (openBlock(), createElementBlock("input", {
1380
+ key: 0,
1381
+ type: "text",
1382
+ class: "file-grid-item-rename-input",
1383
+ value: item.name,
1384
+ onBlur: ($event) => handleRename(item, $event),
1385
+ onKeydown: [
1386
+ withKeys(handleEnterKey, ["enter"]),
1387
+ withKeys(handleEscapeKey, ["escape"])
1388
+ ],
1389
+ ref_for: true,
1390
+ ref: "renameInput",
1391
+ autofocus: ""
1392
+ }, null, 40, _hoisted_8$5)) : (openBlock(), createElementBlock("span", {
1289
1393
  key: 1,
1290
- src: c.thumbnailUrl,
1291
- alt: c.name,
1292
- class: "file-grid-item-thumbnail",
1293
- onError: (M) => n.$emit("thumbnailError", c, M)
1294
- }, null, 40, Te)) : j("", !0)
1295
- ], 64)) : (a(), H(be, {
1296
- key: 2,
1297
- type: c.type,
1298
- name: c.name,
1299
- size: 48
1300
- }, null, 8, ["type", "name"]))
1301
- ]),
1302
- s("div", Ae, [
1303
- e.editingId === c.id ? (a(), h("input", {
1304
- key: 0,
1305
- type: "text",
1306
- class: "file-grid-item-rename-input",
1307
- value: c.name,
1308
- onBlur: (M) => v(c, M),
1309
- onKeydown: [
1310
- ce(b, ["enter"]),
1311
- ce(u, ["escape"])
1312
- ],
1313
- ref_for: !0,
1314
- ref: "renameInput",
1315
- autofocus: ""
1316
- }, null, 40, Ne)) : (a(), h("span", {
1317
- key: 1,
1318
- onClick: R((M) => n.$emit("nameClick", c, M), ["stop"]),
1319
- class: B([
1320
- "file-grid-item-name",
1321
- e.selectedIds.has(c.id) ? "file-grid-item-name--selected" : ""
1322
- ]),
1323
- title: c.name
1324
- }, [
1325
- l(c).ext ? (a(), h(G, { key: 0 }, [
1326
- s("span", Ue, z(l(c).baseName), 1),
1327
- s("span", Fe, z(l(c).ext), 1)
1328
- ], 64)) : (a(), h("span", We, z(c.name), 1))
1329
- ], 10, Pe))
1330
- ])
1331
- ], 42, De);
1332
- }), 128))
1333
- ], 32));
1394
+ onClick: withModifiers(($event) => _ctx.$emit("nameClick", item, $event), ["stop"]),
1395
+ class: normalizeClass([
1396
+ "file-grid-item-name",
1397
+ __props.selectedIds.has(item.id) ? "file-grid-item-name--selected" : ""
1398
+ ]),
1399
+ title: item.name
1400
+ }, [
1401
+ getFileNameParts(item).ext ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [
1402
+ createElementVNode("span", _hoisted_10$3, toDisplayString(getFileNameParts(item).baseName), 1),
1403
+ createElementVNode("span", _hoisted_11$3, toDisplayString(getFileNameParts(item).ext), 1)
1404
+ ], 64)) : (openBlock(), createElementBlock("span", _hoisted_12$3, toDisplayString(item.name), 1))
1405
+ ], 10, _hoisted_9$5))
1406
+ ])
1407
+ ], 42, _hoisted_1$c);
1408
+ }), 128))
1409
+ ], 32);
1410
+ };
1334
1411
  }
1335
- }), Be = /* @__PURE__ */ K(Re, [["__scopeId", "data-v-7303a333"]]), He = { class: "sort-indicator" }, Ve = /* @__PURE__ */ q({
1412
+ });
1413
+ const FileGrid = /* @__PURE__ */ _export_sfc(_sfc_main$c, [["__scopeId", "data-v-7303a333"]]);
1414
+ const _hoisted_1$b = { class: "sort-indicator" };
1415
+ const _sfc_main$b = /* @__PURE__ */ defineComponent({
1336
1416
  __name: "SortIndicator",
1337
1417
  props: {
1338
1418
  direction: {}
1339
1419
  },
1340
- setup(e) {
1341
- return (g, t) => (a(), h("span", He, [
1342
- N(O(T), {
1343
- icon: e.direction === "asc" ? "lucide:chevron-up" : "lucide:chevron-down",
1344
- width: 12,
1345
- height: 12
1346
- }, null, 8, ["icon"])
1347
- ]));
1420
+ setup(__props) {
1421
+ return (_ctx, _cache) => {
1422
+ return openBlock(), createElementBlock("span", _hoisted_1$b, [
1423
+ createVNode(unref(Icon), {
1424
+ icon: __props.direction === "asc" ? "lucide:chevron-up" : "lucide:chevron-down",
1425
+ width: 12,
1426
+ height: 12
1427
+ }, null, 8, ["icon"])
1428
+ ]);
1429
+ };
1348
1430
  }
1349
- }), ae = /* @__PURE__ */ K(Ve, [["__scopeId", "data-v-06e188ee"]]), _e = { class: "file-list-table" }, Ge = { class: "file-list-header" }, qe = { class: "file-list-body" }, Ke = ["draggable", "onDragstart", "onDragover", "onDrop", "onClick", "onDblclick", "onContextmenu"], Xe = { class: "file-list-cell file-list-cell--name" }, Ye = ["value", "onBlur"], Je = ["onClick"], Qe = /* @__PURE__ */ q({
1431
+ });
1432
+ const SortIndicator = /* @__PURE__ */ _export_sfc(_sfc_main$b, [["__scopeId", "data-v-06e188ee"]]);
1433
+ const _hoisted_1$a = { class: "file-list-table" };
1434
+ const _hoisted_2$a = { class: "file-list-header" };
1435
+ const _hoisted_3$7 = { class: "file-list-body" };
1436
+ const _hoisted_4$7 = ["draggable", "onDragstart", "onDragover", "onDrop", "onClick", "onDblclick", "onContextmenu"];
1437
+ const _hoisted_5$6 = { class: "file-list-cell file-list-cell--name" };
1438
+ const _hoisted_6$5 = ["value", "onBlur"];
1439
+ const _hoisted_7$5 = ["onClick"];
1440
+ const _sfc_main$a = /* @__PURE__ */ defineComponent({
1350
1441
  __name: "FileList",
1351
1442
  props: {
1352
1443
  items: {},
@@ -1356,489 +1447,653 @@ const je = /* @__PURE__ */ q({
1356
1447
  dragOverId: {}
1357
1448
  },
1358
1449
  emits: ["select", "open", "contextMenu", "contextMenuEmpty", "nameClick", "rename", "renameCancel", "sort", "dragStart", "dragOver", "dragLeave", "drop"],
1359
- setup(e, { emit: g }) {
1360
- const t = e, r = g, l = (v) => {
1361
- v.target.closest("tr") || r("contextMenuEmpty", v);
1362
- }, i = (v) => ({
1363
- [d.FOLDER]: "文件夹",
1364
- [d.FILE]: "文件",
1365
- [d.IMAGE]: "图片",
1366
- [d.VIDEO]: "视频",
1367
- [d.MUSIC]: "音频",
1368
- [d.DOCUMENT]: "文档",
1369
- [d.CODE]: "代码",
1370
- [d.TEXT]: "文本",
1371
- [d.PDF]: "PDF",
1372
- [d.ARCHIVE]: "压缩包",
1373
- [d.APPLICATION]: "应用程序",
1374
- [d.UNKNOWN]: "未知"
1375
- })[v] || v, w = (v, b) => {
1376
- const n = b.target.value.trim();
1377
- n && n !== v.name ? r("rename", v, n) : r("renameCancel", v);
1378
- }, I = (v) => {
1379
- v.target.blur();
1380
- }, m = (v) => {
1381
- const b = v.target, u = t.items.find((n) => n.id === t.editingId);
1382
- u && (b.value = u.name), b.blur();
1383
- };
1384
- return (v, b) => {
1385
- var u, n, C, c;
1386
- return a(), h("div", {
1450
+ setup(__props, { emit: __emit }) {
1451
+ const props = __props;
1452
+ const emit = __emit;
1453
+ const handleEmptyContextMenu = (e) => {
1454
+ const target = e.target;
1455
+ if (!target.closest("tr")) {
1456
+ emit("contextMenuEmpty", e);
1457
+ }
1458
+ };
1459
+ const getTypeLabel = (type) => {
1460
+ const labels = {
1461
+ [FileType.FOLDER]: "文件夹",
1462
+ [FileType.FILE]: "文件",
1463
+ [FileType.IMAGE]: "图片",
1464
+ [FileType.VIDEO]: "视频",
1465
+ [FileType.MUSIC]: "音频",
1466
+ [FileType.DOCUMENT]: "文档",
1467
+ [FileType.CODE]: "代码",
1468
+ [FileType.TEXT]: "文本",
1469
+ [FileType.PDF]: "PDF",
1470
+ [FileType.ARCHIVE]: "压缩包",
1471
+ [FileType.APPLICATION]: "应用程序",
1472
+ [FileType.UNKNOWN]: "未知"
1473
+ };
1474
+ return labels[type] || type;
1475
+ };
1476
+ const handleRename = (item, e) => {
1477
+ const input = e.target;
1478
+ const newName = input.value.trim();
1479
+ if (newName && newName !== item.name) {
1480
+ emit("rename", item, newName);
1481
+ } else {
1482
+ emit("renameCancel", item);
1483
+ }
1484
+ };
1485
+ const handleEnterKey = (e) => {
1486
+ e.target.blur();
1487
+ };
1488
+ const handleEscapeKey = (e) => {
1489
+ const input = e.target;
1490
+ const item = props.items.find((i) => i.id === props.editingId);
1491
+ if (item) {
1492
+ input.value = item.name;
1493
+ }
1494
+ input.blur();
1495
+ };
1496
+ return (_ctx, _cache) => {
1497
+ var _a, _b, _c, _d;
1498
+ return openBlock(), createElementBlock("div", {
1387
1499
  class: "file-list",
1388
- onContextmenu: R(l, ["prevent"])
1500
+ onContextmenu: withModifiers(handleEmptyContextMenu, ["prevent"])
1389
1501
  }, [
1390
- s("table", _e, [
1391
- s("thead", Ge, [
1392
- s("tr", null, [
1393
- s("th", {
1502
+ createElementVNode("table", _hoisted_1$a, [
1503
+ createElementVNode("thead", _hoisted_2$a, [
1504
+ createElementVNode("tr", null, [
1505
+ createElementVNode("th", {
1394
1506
  class: "file-list-header-cell file-list-header-cell--name",
1395
- onClick: b[0] || (b[0] = (y) => v.$emit("sort", "name"))
1507
+ onClick: _cache[0] || (_cache[0] = ($event) => _ctx.$emit("sort", "name"))
1396
1508
  }, [
1397
- b[5] || (b[5] = se(" 名称 ", -1)),
1398
- ((u = e.sortConfig) == null ? void 0 : u.field) === "name" ? (a(), H(ae, {
1509
+ _cache[5] || (_cache[5] = createTextVNode(" 名称 ", -1)),
1510
+ ((_a = __props.sortConfig) == null ? void 0 : _a.field) === "name" ? (openBlock(), createBlock(SortIndicator, {
1399
1511
  key: 0,
1400
- direction: e.sortConfig.direction
1401
- }, null, 8, ["direction"])) : j("", !0)
1512
+ direction: __props.sortConfig.direction
1513
+ }, null, 8, ["direction"])) : createCommentVNode("", true)
1402
1514
  ]),
1403
- s("th", {
1515
+ createElementVNode("th", {
1404
1516
  class: "file-list-header-cell",
1405
- onClick: b[1] || (b[1] = (y) => v.$emit("sort", "dateModified"))
1517
+ onClick: _cache[1] || (_cache[1] = ($event) => _ctx.$emit("sort", "dateModified"))
1406
1518
  }, [
1407
- b[6] || (b[6] = se(" 修改日期 ", -1)),
1408
- ((n = e.sortConfig) == null ? void 0 : n.field) === "dateModified" ? (a(), H(ae, {
1519
+ _cache[6] || (_cache[6] = createTextVNode(" 修改日期 ", -1)),
1520
+ ((_b = __props.sortConfig) == null ? void 0 : _b.field) === "dateModified" ? (openBlock(), createBlock(SortIndicator, {
1409
1521
  key: 0,
1410
- direction: e.sortConfig.direction
1411
- }, null, 8, ["direction"])) : j("", !0)
1522
+ direction: __props.sortConfig.direction
1523
+ }, null, 8, ["direction"])) : createCommentVNode("", true)
1412
1524
  ]),
1413
- s("th", {
1525
+ createElementVNode("th", {
1414
1526
  class: "file-list-header-cell",
1415
- onClick: b[2] || (b[2] = (y) => v.$emit("sort", "size"))
1527
+ onClick: _cache[2] || (_cache[2] = ($event) => _ctx.$emit("sort", "size"))
1416
1528
  }, [
1417
- b[7] || (b[7] = se(" 大小 ", -1)),
1418
- ((C = e.sortConfig) == null ? void 0 : C.field) === "size" ? (a(), H(ae, {
1529
+ _cache[7] || (_cache[7] = createTextVNode(" 大小 ", -1)),
1530
+ ((_c = __props.sortConfig) == null ? void 0 : _c.field) === "size" ? (openBlock(), createBlock(SortIndicator, {
1419
1531
  key: 0,
1420
- direction: e.sortConfig.direction
1421
- }, null, 8, ["direction"])) : j("", !0)
1532
+ direction: __props.sortConfig.direction
1533
+ }, null, 8, ["direction"])) : createCommentVNode("", true)
1422
1534
  ]),
1423
- s("th", {
1535
+ createElementVNode("th", {
1424
1536
  class: "file-list-header-cell",
1425
- onClick: b[3] || (b[3] = (y) => v.$emit("sort", "type"))
1537
+ onClick: _cache[3] || (_cache[3] = ($event) => _ctx.$emit("sort", "type"))
1426
1538
  }, [
1427
- b[8] || (b[8] = se(" 类型 ", -1)),
1428
- ((c = e.sortConfig) == null ? void 0 : c.field) === "type" ? (a(), H(ae, {
1539
+ _cache[8] || (_cache[8] = createTextVNode(" 类型 ", -1)),
1540
+ ((_d = __props.sortConfig) == null ? void 0 : _d.field) === "type" ? (openBlock(), createBlock(SortIndicator, {
1429
1541
  key: 0,
1430
- direction: e.sortConfig.direction
1431
- }, null, 8, ["direction"])) : j("", !0)
1542
+ direction: __props.sortConfig.direction
1543
+ }, null, 8, ["direction"])) : createCommentVNode("", true)
1432
1544
  ])
1433
1545
  ])
1434
1546
  ]),
1435
- s("tbody", qe, [
1436
- (a(!0), h(G, null, J(e.items, (y, M) => (a(), h("tr", {
1437
- key: y.id,
1438
- draggable: e.editingId !== y.id,
1439
- onDragstart: (S) => v.$emit("dragStart", S, y),
1440
- onDragover: R((S) => v.$emit("dragOver", S, y), ["prevent"]),
1441
- onDragleave: b[4] || (b[4] = (S) => v.$emit("dragLeave", S)),
1442
- onDrop: R((S) => v.$emit("drop", S, y), ["prevent"]),
1443
- onClick: R((S) => v.$emit("select", y, S), ["stop"]),
1444
- onDblclick: R((S) => v.$emit("open", y), ["stop"]),
1445
- onContextmenu: R((S) => v.$emit("contextMenu", y, S), ["prevent", "stop"]),
1446
- class: B([
1447
- "file-list-row",
1448
- e.selectedIds.has(y.id) ? "file-list-row--selected" : e.dragOverId === y.id ? "file-list-row--drag-over" : M % 2 === 0 ? "file-list-row--even" : "file-list-row--odd"
1449
- ])
1450
- }, [
1451
- s("td", Xe, [
1452
- N(be, {
1453
- type: y.type,
1454
- name: y.name,
1455
- size: 16
1456
- }, null, 8, ["type", "name"]),
1457
- e.editingId === y.id ? (a(), h("input", {
1458
- key: 0,
1459
- type: "text",
1460
- class: "file-list-rename-input",
1461
- value: y.name,
1462
- onBlur: (S) => w(y, S),
1463
- onKeydown: [
1464
- ce(I, ["enter"]),
1465
- ce(m, ["escape"])
1466
- ],
1467
- autofocus: ""
1468
- }, null, 40, Ye)) : (a(), h("span", {
1469
- key: 1,
1470
- onClick: R((S) => v.$emit("nameClick", y, S), ["stop"]),
1471
- class: B([
1472
- "file-list-name",
1473
- e.selectedIds.has(y.id) ? "file-list-name--selected" : ""
1474
- ])
1475
- }, z(y.name), 11, Je))
1476
- ]),
1477
- s("td", {
1478
- class: B(["file-list-cell", e.selectedIds.has(y.id) ? "file-list-cell--selected" : ""])
1479
- }, z(y.dateModified || "--"), 3),
1480
- s("td", {
1481
- class: B(["file-list-cell file-list-cell--size", e.selectedIds.has(y.id) ? "file-list-cell--selected" : ""])
1482
- }, z(y.size || "--"), 3),
1483
- s("td", {
1484
- class: B(["file-list-cell", e.selectedIds.has(y.id) ? "file-list-cell--selected" : ""])
1485
- }, z(i(y.type)), 3)
1486
- ], 42, Ke))), 128))
1547
+ createElementVNode("tbody", _hoisted_3$7, [
1548
+ (openBlock(true), createElementBlock(Fragment, null, renderList(__props.items, (item, index) => {
1549
+ return openBlock(), createElementBlock("tr", {
1550
+ key: item.id,
1551
+ draggable: __props.editingId !== item.id,
1552
+ onDragstart: ($event) => _ctx.$emit("dragStart", $event, item),
1553
+ onDragover: withModifiers(($event) => _ctx.$emit("dragOver", $event, item), ["prevent"]),
1554
+ onDragleave: _cache[4] || (_cache[4] = ($event) => _ctx.$emit("dragLeave", $event)),
1555
+ onDrop: withModifiers(($event) => _ctx.$emit("drop", $event, item), ["prevent"]),
1556
+ onClick: withModifiers(($event) => _ctx.$emit("select", item, $event), ["stop"]),
1557
+ onDblclick: withModifiers(($event) => _ctx.$emit("open", item), ["stop"]),
1558
+ onContextmenu: withModifiers(($event) => _ctx.$emit("contextMenu", item, $event), ["prevent", "stop"]),
1559
+ class: normalizeClass([
1560
+ "file-list-row",
1561
+ __props.selectedIds.has(item.id) ? "file-list-row--selected" : __props.dragOverId === item.id ? "file-list-row--drag-over" : index % 2 === 0 ? "file-list-row--even" : "file-list-row--odd"
1562
+ ])
1563
+ }, [
1564
+ createElementVNode("td", _hoisted_5$6, [
1565
+ createVNode(FileIcon, {
1566
+ type: item.type,
1567
+ name: item.name,
1568
+ size: 16
1569
+ }, null, 8, ["type", "name"]),
1570
+ __props.editingId === item.id ? (openBlock(), createElementBlock("input", {
1571
+ key: 0,
1572
+ type: "text",
1573
+ class: "file-list-rename-input",
1574
+ value: item.name,
1575
+ onBlur: ($event) => handleRename(item, $event),
1576
+ onKeydown: [
1577
+ withKeys(handleEnterKey, ["enter"]),
1578
+ withKeys(handleEscapeKey, ["escape"])
1579
+ ],
1580
+ autofocus: ""
1581
+ }, null, 40, _hoisted_6$5)) : (openBlock(), createElementBlock("span", {
1582
+ key: 1,
1583
+ onClick: withModifiers(($event) => _ctx.$emit("nameClick", item, $event), ["stop"]),
1584
+ class: normalizeClass([
1585
+ "file-list-name",
1586
+ __props.selectedIds.has(item.id) ? "file-list-name--selected" : ""
1587
+ ])
1588
+ }, toDisplayString(item.name), 11, _hoisted_7$5))
1589
+ ]),
1590
+ createElementVNode("td", {
1591
+ class: normalizeClass(["file-list-cell", __props.selectedIds.has(item.id) ? "file-list-cell--selected" : ""])
1592
+ }, toDisplayString(item.dateModified || "--"), 3),
1593
+ createElementVNode("td", {
1594
+ class: normalizeClass(["file-list-cell file-list-cell--size", __props.selectedIds.has(item.id) ? "file-list-cell--selected" : ""])
1595
+ }, toDisplayString(item.size || "--"), 3),
1596
+ createElementVNode("td", {
1597
+ class: normalizeClass(["file-list-cell", __props.selectedIds.has(item.id) ? "file-list-cell--selected" : ""])
1598
+ }, toDisplayString(getTypeLabel(item.type)), 3)
1599
+ ], 42, _hoisted_4$7);
1600
+ }), 128))
1487
1601
  ])
1488
1602
  ])
1489
1603
  ], 32);
1490
1604
  };
1491
1605
  }
1492
- }), Ze = /* @__PURE__ */ K(Qe, [["__scopeId", "data-v-0635c948"]]), et = {
1606
+ });
1607
+ const FileList = /* @__PURE__ */ _export_sfc(_sfc_main$a, [["__scopeId", "data-v-0635c948"]]);
1608
+ const _hoisted_1$9 = {
1493
1609
  key: 0,
1494
1610
  class: "file-list-view-loading"
1495
- }, tt = {
1611
+ };
1612
+ const _hoisted_2$9 = {
1496
1613
  key: 1,
1497
1614
  class: "file-list-view-empty"
1498
- }, st = /* @__PURE__ */ q({
1615
+ };
1616
+ const _sfc_main$9 = /* @__PURE__ */ defineComponent({
1499
1617
  __name: "FileListView",
1500
1618
  props: {
1501
1619
  items: {},
1502
1620
  viewMode: { default: "grid" },
1503
- loading: { type: Boolean, default: !1 },
1621
+ loading: { type: Boolean, default: false },
1504
1622
  adapter: {},
1505
1623
  currentPath: {},
1506
1624
  getAppIconUrl: {}
1507
1625
  },
1508
1626
  emits: ["open", "selection-change", "context-menu", "context-menu-empty", "rename", "sort-change", "move"],
1509
- setup(e, { expose: g, emit: t }) {
1510
- const r = e, l = t, i = D(/* @__PURE__ */ new Set()), w = D(null), I = D(null), m = D({ field: "name", direction: "asc" }), v = F(
1511
- () => r.items.filter((k) => i.value.has(k.id))
1512
- ), b = (k, E) => {
1513
- if (E.metaKey || E.ctrlKey) {
1514
- const P = new Set(i.value);
1515
- P.has(k.id) ? P.delete(k.id) : P.add(k.id), i.value = P;
1516
- } else if (E.shiftKey && i.value.size > 0) {
1517
- const P = Array.from(i.value).pop(), _ = r.items.findIndex((Q) => Q.id === P), X = r.items.findIndex((Q) => Q.id === k.id), oe = Math.min(_, X), le = Math.max(_, X), ue = /* @__PURE__ */ new Set();
1518
- for (let Q = oe; Q <= le; Q++)
1519
- ue.add(r.items[Q].id);
1520
- i.value = ue;
1521
- } else
1522
- i.value = /* @__PURE__ */ new Set([k.id]);
1523
- l("selection-change", i.value, v.value);
1524
- }, u = (k) => {
1525
- k.target === k.currentTarget && n();
1526
- }, n = () => {
1527
- i.value = /* @__PURE__ */ new Set(), l("selection-change", i.value, []);
1528
- }, C = (k) => {
1529
- l("open", k);
1530
- }, c = (k, E) => {
1531
- i.value.has(k.id) || (i.value = /* @__PURE__ */ new Set([k.id]), l("selection-change", i.value, [k])), l("context-menu", E, k);
1532
- }, y = (k) => {
1533
- const E = k.target;
1534
- !E.closest(".file-grid-item") && !E.closest(".file-list-row") && (n(), l("context-menu-empty", k));
1535
- }, M = (k) => {
1536
- n(), l("context-menu-empty", k);
1537
- }, S = (k, E) => {
1538
- i.value.has(k.id) && i.value.size === 1 && setTimeout(() => {
1539
- i.value.has(k.id) && (w.value = k.id);
1540
- }, 500);
1541
- }, L = (k, E) => {
1542
- E && E !== k.name && l("rename", k, E), w.value = null;
1543
- }, $ = () => {
1544
- w.value = null;
1545
- }, f = (k) => {
1546
- m.value.field === k ? m.value.direction = m.value.direction === "asc" ? "desc" : "asc" : (m.value.field = k, m.value.direction = "asc"), l("sort-change", { ...m.value });
1547
- }, A = (k, E) => {
1548
- var P;
1549
- i.value.has(E.id) || (i.value = /* @__PURE__ */ new Set([E.id]), l("selection-change", i.value, [E])), (P = k.dataTransfer) == null || P.setData("text/plain", JSON.stringify([...i.value]));
1550
- }, U = (k, E) => {
1551
- E.type === d.FOLDER && !i.value.has(E.id) && (I.value = E.id);
1552
- }, o = () => {
1553
- I.value = null;
1554
- }, x = (k, E) => {
1555
- var _;
1556
- if (I.value = null, E.type !== d.FOLDER) return;
1557
- const P = (_ = k.dataTransfer) == null ? void 0 : _.getData("text/plain");
1558
- if (P)
1559
- try {
1560
- const X = JSON.parse(P);
1561
- if (X.includes(E.id)) return;
1562
- l("move", X, E.id), n();
1563
- } catch (X) {
1564
- console.error("拖拽解析失败:", X);
1627
+ setup(__props, { expose: __expose, emit: __emit }) {
1628
+ const props = __props;
1629
+ const emit = __emit;
1630
+ const selectedIds = ref(/* @__PURE__ */ new Set());
1631
+ const editingId = ref(null);
1632
+ const dragOverId = ref(null);
1633
+ const sortConfig = ref({ field: "name", direction: "asc" });
1634
+ const selectedItems = computed(
1635
+ () => props.items.filter((item) => selectedIds.value.has(item.id))
1636
+ );
1637
+ const handleSelect = (item, e) => {
1638
+ if (e.metaKey || e.ctrlKey) {
1639
+ const newSet = new Set(selectedIds.value);
1640
+ if (newSet.has(item.id)) {
1641
+ newSet.delete(item.id);
1642
+ } else {
1643
+ newSet.add(item.id);
1565
1644
  }
1645
+ selectedIds.value = newSet;
1646
+ } else if (e.shiftKey && selectedIds.value.size > 0) {
1647
+ const lastId = Array.from(selectedIds.value).pop();
1648
+ const lastIndex = props.items.findIndex((i) => i.id === lastId);
1649
+ const currentIndex = props.items.findIndex((i) => i.id === item.id);
1650
+ const start = Math.min(lastIndex, currentIndex);
1651
+ const end = Math.max(lastIndex, currentIndex);
1652
+ const newSet = /* @__PURE__ */ new Set();
1653
+ for (let i = start; i <= end; i++) {
1654
+ newSet.add(props.items[i].id);
1655
+ }
1656
+ selectedIds.value = newSet;
1657
+ } else {
1658
+ selectedIds.value = /* @__PURE__ */ new Set([item.id]);
1659
+ }
1660
+ emit("selection-change", selectedIds.value, selectedItems.value);
1661
+ };
1662
+ const handleEmptyClick = (e) => {
1663
+ if (e.target === e.currentTarget) {
1664
+ clearSelection();
1665
+ }
1666
+ };
1667
+ const clearSelection = () => {
1668
+ selectedIds.value = /* @__PURE__ */ new Set();
1669
+ emit("selection-change", selectedIds.value, []);
1670
+ };
1671
+ const handleOpen = (item) => {
1672
+ emit("open", item);
1673
+ };
1674
+ const handleContextMenu = (item, e) => {
1675
+ if (!selectedIds.value.has(item.id)) {
1676
+ selectedIds.value = /* @__PURE__ */ new Set([item.id]);
1677
+ emit("selection-change", selectedIds.value, [item]);
1678
+ }
1679
+ emit("context-menu", e, item);
1680
+ };
1681
+ const handleEmptyContextMenu = (e) => {
1682
+ const target = e.target;
1683
+ if (!target.closest(".file-grid-item") && !target.closest(".file-list-row")) {
1684
+ clearSelection();
1685
+ emit("context-menu-empty", e);
1686
+ }
1687
+ };
1688
+ const handleEmptyContextMenuFromChild = (e) => {
1689
+ clearSelection();
1690
+ emit("context-menu-empty", e);
1691
+ };
1692
+ const handleNameClick = (item, e) => {
1693
+ if (selectedIds.value.has(item.id) && selectedIds.value.size === 1) {
1694
+ setTimeout(() => {
1695
+ if (selectedIds.value.has(item.id)) {
1696
+ editingId.value = item.id;
1697
+ }
1698
+ }, 500);
1699
+ }
1700
+ };
1701
+ const handleRename = (item, newName) => {
1702
+ if (newName && newName !== item.name) {
1703
+ emit("rename", item, newName);
1704
+ }
1705
+ editingId.value = null;
1706
+ };
1707
+ const handleRenameCancel = () => {
1708
+ editingId.value = null;
1709
+ };
1710
+ const handleSort = (field) => {
1711
+ if (sortConfig.value.field === field) {
1712
+ sortConfig.value.direction = sortConfig.value.direction === "asc" ? "desc" : "asc";
1713
+ } else {
1714
+ sortConfig.value.field = field;
1715
+ sortConfig.value.direction = "asc";
1716
+ }
1717
+ emit("sort-change", { ...sortConfig.value });
1718
+ };
1719
+ const handleDragStart = (e, item) => {
1720
+ var _a;
1721
+ if (!selectedIds.value.has(item.id)) {
1722
+ selectedIds.value = /* @__PURE__ */ new Set([item.id]);
1723
+ emit("selection-change", selectedIds.value, [item]);
1724
+ }
1725
+ (_a = e.dataTransfer) == null ? void 0 : _a.setData("text/plain", JSON.stringify([...selectedIds.value]));
1726
+ };
1727
+ const handleDragOver = (e, item) => {
1728
+ if (item.type === FileType.FOLDER && !selectedIds.value.has(item.id)) {
1729
+ dragOverId.value = item.id;
1730
+ }
1731
+ };
1732
+ const handleDragLeave = () => {
1733
+ dragOverId.value = null;
1734
+ };
1735
+ const handleDrop = (e, targetItem) => {
1736
+ var _a;
1737
+ dragOverId.value = null;
1738
+ if (targetItem.type !== FileType.FOLDER) return;
1739
+ const data = (_a = e.dataTransfer) == null ? void 0 : _a.getData("text/plain");
1740
+ if (!data) return;
1741
+ try {
1742
+ const draggedIds = JSON.parse(data);
1743
+ if (draggedIds.includes(targetItem.id)) return;
1744
+ emit("move", draggedIds, targetItem.id);
1745
+ clearSelection();
1746
+ } catch (error) {
1747
+ console.error("拖拽解析失败:", error);
1748
+ }
1749
+ };
1750
+ const startRename = (id) => {
1751
+ editingId.value = id;
1752
+ };
1753
+ const selectAll = () => {
1754
+ selectedIds.value = new Set(props.items.map((i) => i.id));
1755
+ emit("selection-change", selectedIds.value, props.items);
1756
+ };
1757
+ __expose({
1758
+ clearSelection,
1759
+ startRename,
1760
+ selectAll,
1761
+ selectedIds,
1762
+ selectedItems
1763
+ });
1764
+ return (_ctx, _cache) => {
1765
+ return openBlock(), createElementBlock("div", {
1766
+ class: "file-list-view",
1767
+ onClick: handleEmptyClick,
1768
+ onContextmenu: withModifiers(handleEmptyContextMenu, ["prevent"])
1769
+ }, [
1770
+ __props.loading ? (openBlock(), createElementBlock("div", _hoisted_1$9, [..._cache[0] || (_cache[0] = [
1771
+ createElementVNode("div", { class: "file-list-view-spinner" }, null, -1),
1772
+ createElementVNode("p", null, "加载中...", -1)
1773
+ ])])) : __props.items.length === 0 ? (openBlock(), createElementBlock("div", _hoisted_2$9, [
1774
+ createVNode(unref(Icon), {
1775
+ icon: "lucide:folder-open",
1776
+ width: "64",
1777
+ height: "64",
1778
+ class: "file-list-view-empty-icon"
1779
+ }),
1780
+ _cache[1] || (_cache[1] = createElementVNode("p", null, "文件夹为空", -1))
1781
+ ])) : __props.viewMode === "grid" ? (openBlock(), createBlock(FileGrid, {
1782
+ key: 2,
1783
+ items: __props.items,
1784
+ "selected-ids": selectedIds.value,
1785
+ "editing-id": editingId.value,
1786
+ "drag-over-id": dragOverId.value,
1787
+ "get-app-icon-url": __props.getAppIconUrl,
1788
+ onSelect: handleSelect,
1789
+ onOpen: handleOpen,
1790
+ onContextMenu: handleContextMenu,
1791
+ onContextMenuEmpty: handleEmptyContextMenuFromChild,
1792
+ onNameClick: handleNameClick,
1793
+ onRename: handleRename,
1794
+ onRenameCancel: handleRenameCancel,
1795
+ onDragStart: handleDragStart,
1796
+ onDragOver: handleDragOver,
1797
+ onDragLeave: handleDragLeave,
1798
+ onDrop: handleDrop
1799
+ }, null, 8, ["items", "selected-ids", "editing-id", "drag-over-id", "get-app-icon-url"])) : (openBlock(), createBlock(FileList, {
1800
+ key: 3,
1801
+ items: __props.items,
1802
+ "selected-ids": selectedIds.value,
1803
+ "editing-id": editingId.value,
1804
+ "drag-over-id": dragOverId.value,
1805
+ "sort-config": sortConfig.value,
1806
+ onSelect: handleSelect,
1807
+ onOpen: handleOpen,
1808
+ onContextMenu: handleContextMenu,
1809
+ onContextMenuEmpty: handleEmptyContextMenuFromChild,
1810
+ onNameClick: handleNameClick,
1811
+ onRename: handleRename,
1812
+ onRenameCancel: handleRenameCancel,
1813
+ onSort: handleSort,
1814
+ onDragStart: handleDragStart,
1815
+ onDragOver: handleDragOver,
1816
+ onDragLeave: handleDragLeave,
1817
+ onDrop: handleDrop
1818
+ }, null, 8, ["items", "selected-ids", "editing-id", "drag-over-id", "sort-config"]))
1819
+ ], 32);
1566
1820
  };
1567
- return g({
1568
- clearSelection: n,
1569
- startRename: (k) => {
1570
- w.value = k;
1571
- },
1572
- selectAll: () => {
1573
- i.value = new Set(r.items.map((k) => k.id)), l("selection-change", i.value, r.items);
1574
- },
1575
- selectedIds: i,
1576
- selectedItems: v
1577
- }), (k, E) => (a(), h("div", {
1578
- class: "file-list-view",
1579
- onClick: u,
1580
- onContextmenu: R(y, ["prevent"])
1581
- }, [
1582
- e.loading ? (a(), h("div", et, [...E[0] || (E[0] = [
1583
- s("div", { class: "file-list-view-spinner" }, null, -1),
1584
- s("p", null, "加载中...", -1)
1585
- ])])) : e.items.length === 0 ? (a(), h("div", tt, [
1586
- N(O(T), {
1587
- icon: "lucide:folder-open",
1588
- width: "64",
1589
- height: "64",
1590
- class: "file-list-view-empty-icon"
1591
- }),
1592
- E[1] || (E[1] = s("p", null, "文件夹为空", -1))
1593
- ])) : e.viewMode === "grid" ? (a(), H(Be, {
1594
- key: 2,
1595
- items: e.items,
1596
- "selected-ids": i.value,
1597
- "editing-id": w.value,
1598
- "drag-over-id": I.value,
1599
- "get-app-icon-url": e.getAppIconUrl,
1600
- onSelect: b,
1601
- onOpen: C,
1602
- onContextMenu: c,
1603
- onContextMenuEmpty: M,
1604
- onNameClick: S,
1605
- onRename: L,
1606
- onRenameCancel: $,
1607
- onDragStart: A,
1608
- onDragOver: U,
1609
- onDragLeave: o,
1610
- onDrop: x
1611
- }, null, 8, ["items", "selected-ids", "editing-id", "drag-over-id", "get-app-icon-url"])) : (a(), H(Ze, {
1612
- key: 3,
1613
- items: e.items,
1614
- "selected-ids": i.value,
1615
- "editing-id": w.value,
1616
- "drag-over-id": I.value,
1617
- "sort-config": m.value,
1618
- onSelect: b,
1619
- onOpen: C,
1620
- onContextMenu: c,
1621
- onContextMenuEmpty: M,
1622
- onNameClick: S,
1623
- onRename: L,
1624
- onRenameCancel: $,
1625
- onSort: f,
1626
- onDragStart: A,
1627
- onDragOver: U,
1628
- onDragLeave: o,
1629
- onDrop: x
1630
- }, null, 8, ["items", "selected-ids", "editing-id", "drag-over-id", "sort-config"]))
1631
- ], 32));
1632
1821
  }
1633
- }), tn = /* @__PURE__ */ K(st, [["__scopeId", "data-v-8a3b7e12"]]), nt = { class: "file-sidebar" }, it = { class: "file-sidebar-section-title" }, ot = { class: "file-sidebar-list" }, lt = ["onClick"], at = /* @__PURE__ */ q({
1822
+ });
1823
+ const FileListView = /* @__PURE__ */ _export_sfc(_sfc_main$9, [["__scopeId", "data-v-8a3b7e12"]]);
1824
+ const _hoisted_1$8 = { class: "file-sidebar" };
1825
+ const _hoisted_2$8 = { class: "file-sidebar-section-title" };
1826
+ const _hoisted_3$6 = { class: "file-sidebar-list" };
1827
+ const _hoisted_4$6 = ["onClick"];
1828
+ const _sfc_main$8 = /* @__PURE__ */ defineComponent({
1634
1829
  __name: "FileSidebar",
1635
1830
  props: {
1636
1831
  sections: {},
1637
1832
  activeId: {}
1638
1833
  },
1639
1834
  emits: ["navigate"],
1640
- setup(e, { emit: g }) {
1641
- const t = g, r = (i) => i ? i.includes(":") ? i : `lucide:${i.toLowerCase()}` : "mdi:folder", l = (i) => {
1642
- t("navigate", i);
1643
- };
1644
- return (i, w) => (a(), h("div", nt, [
1645
- (a(!0), h(G, null, J(e.sections, (I) => (a(), h("div", {
1646
- key: I.id,
1647
- class: "file-sidebar-section"
1648
- }, [
1649
- s("div", it, z(I.title), 1),
1650
- s("ul", ot, [
1651
- (a(!0), h(G, null, J(I.items, (m) => (a(), h("li", {
1652
- key: m.id,
1653
- onClick: (v) => l(m),
1654
- class: B([
1655
- "file-sidebar-item",
1656
- e.activeId === m.id ? "file-sidebar-item--active" : ""
1657
- ])
1835
+ setup(__props, { emit: __emit }) {
1836
+ const emit = __emit;
1837
+ const getIconName = (iconName) => {
1838
+ if (!iconName) return "mdi:folder";
1839
+ if (iconName.includes(":")) return iconName;
1840
+ return `lucide:${iconName.toLowerCase()}`;
1841
+ };
1842
+ const handleNavigate = (item) => {
1843
+ emit("navigate", item);
1844
+ };
1845
+ return (_ctx, _cache) => {
1846
+ return openBlock(), createElementBlock("div", _hoisted_1$8, [
1847
+ (openBlock(true), createElementBlock(Fragment, null, renderList(__props.sections, (section) => {
1848
+ return openBlock(), createElementBlock("div", {
1849
+ key: section.id,
1850
+ class: "file-sidebar-section"
1658
1851
  }, [
1659
- N(O(T), {
1660
- icon: r(m.icon),
1661
- width: 18,
1662
- height: 18,
1663
- class: B(e.activeId === m.id ? "file-sidebar-item-icon--active" : "file-sidebar-item-icon")
1664
- }, null, 8, ["icon", "class"]),
1665
- s("span", null, z(m.label), 1)
1666
- ], 10, lt))), 128))
1667
- ])
1668
- ]))), 128))
1669
- ]));
1852
+ createElementVNode("div", _hoisted_2$8, toDisplayString(section.title), 1),
1853
+ createElementVNode("ul", _hoisted_3$6, [
1854
+ (openBlock(true), createElementBlock(Fragment, null, renderList(section.items, (item) => {
1855
+ return openBlock(), createElementBlock("li", {
1856
+ key: item.id,
1857
+ onClick: ($event) => handleNavigate(item),
1858
+ class: normalizeClass([
1859
+ "file-sidebar-item",
1860
+ __props.activeId === item.id ? "file-sidebar-item--active" : ""
1861
+ ])
1862
+ }, [
1863
+ createVNode(unref(Icon), {
1864
+ icon: getIconName(item.icon),
1865
+ width: 18,
1866
+ height: 18,
1867
+ class: normalizeClass(__props.activeId === item.id ? "file-sidebar-item-icon--active" : "file-sidebar-item-icon")
1868
+ }, null, 8, ["icon", "class"]),
1869
+ createElementVNode("span", null, toDisplayString(item.label), 1)
1870
+ ], 10, _hoisted_4$6);
1871
+ }), 128))
1872
+ ])
1873
+ ]);
1874
+ }), 128))
1875
+ ]);
1876
+ };
1670
1877
  }
1671
- }), sn = /* @__PURE__ */ K(at, [["__scopeId", "data-v-11104260"]]), rt = { class: "file-breadcrumb" }, ct = ["onClick"], dt = /* @__PURE__ */ q({
1878
+ });
1879
+ const FileSidebar = /* @__PURE__ */ _export_sfc(_sfc_main$8, [["__scopeId", "data-v-11104260"]]);
1880
+ const _hoisted_1$7 = { class: "file-breadcrumb" };
1881
+ const _hoisted_2$7 = ["onClick"];
1882
+ const _sfc_main$7 = /* @__PURE__ */ defineComponent({
1672
1883
  __name: "Breadcrumb",
1673
1884
  props: {
1674
1885
  items: {}
1675
1886
  },
1676
1887
  emits: ["navigate"],
1677
- setup(e, { emit: g }) {
1678
- const t = e, r = g, l = (i, w) => {
1679
- w < t.items.length - 1 && r("navigate", i, w);
1680
- };
1681
- return (i, w) => (a(), h("div", rt, [
1682
- (a(!0), h(G, null, J(e.items, (I, m) => (a(), h("span", {
1683
- key: I.id,
1684
- class: "file-breadcrumb-item"
1685
- }, [
1686
- s("span", {
1687
- onClick: (v) => l(I, m),
1688
- class: B([
1689
- "file-breadcrumb-link",
1690
- m === e.items.length - 1 ? "file-breadcrumb-link--current" : ""
1691
- ])
1692
- }, z(I.name), 11, ct),
1693
- m < e.items.length - 1 ? (a(), H(O(T), {
1694
- key: 0,
1695
- icon: "lucide:chevron-right",
1696
- width: 14,
1697
- height: 14,
1698
- class: "file-breadcrumb-separator"
1699
- })) : j("", !0)
1700
- ]))), 128))
1701
- ]));
1888
+ setup(__props, { emit: __emit }) {
1889
+ const props = __props;
1890
+ const emit = __emit;
1891
+ const handleClick = (item, index) => {
1892
+ if (index < props.items.length - 1) {
1893
+ emit("navigate", item, index);
1894
+ }
1895
+ };
1896
+ return (_ctx, _cache) => {
1897
+ return openBlock(), createElementBlock("div", _hoisted_1$7, [
1898
+ (openBlock(true), createElementBlock(Fragment, null, renderList(__props.items, (item, index) => {
1899
+ return openBlock(), createElementBlock("span", {
1900
+ key: item.id,
1901
+ class: "file-breadcrumb-item"
1902
+ }, [
1903
+ createElementVNode("span", {
1904
+ onClick: ($event) => handleClick(item, index),
1905
+ class: normalizeClass([
1906
+ "file-breadcrumb-link",
1907
+ index === __props.items.length - 1 ? "file-breadcrumb-link--current" : ""
1908
+ ])
1909
+ }, toDisplayString(item.name), 11, _hoisted_2$7),
1910
+ index < __props.items.length - 1 ? (openBlock(), createBlock(unref(Icon), {
1911
+ key: 0,
1912
+ icon: "lucide:chevron-right",
1913
+ width: 14,
1914
+ height: 14,
1915
+ class: "file-breadcrumb-separator"
1916
+ })) : createCommentVNode("", true)
1917
+ ]);
1918
+ }), 128))
1919
+ ]);
1920
+ };
1702
1921
  }
1703
- }), ut = /* @__PURE__ */ K(dt, [["__scopeId", "data-v-10c3c31a"]]), mt = { class: "file-toolbar-nav" }, gt = ["disabled"], pt = ["disabled"], ft = { class: "file-toolbar-breadcrumb" }, vt = {
1922
+ });
1923
+ const Breadcrumb = /* @__PURE__ */ _export_sfc(_sfc_main$7, [["__scopeId", "data-v-10c3c31a"]]);
1924
+ const _hoisted_1$6 = { class: "file-toolbar-nav" };
1925
+ const _hoisted_2$6 = ["disabled"];
1926
+ const _hoisted_3$5 = ["disabled"];
1927
+ const _hoisted_4$5 = { class: "file-toolbar-breadcrumb" };
1928
+ const _hoisted_5$5 = {
1704
1929
  key: 0,
1705
1930
  class: "file-toolbar-custom"
1706
- }, ht = { class: "file-toolbar-actions" }, bt = {
1931
+ };
1932
+ const _hoisted_6$4 = { class: "file-toolbar-actions" };
1933
+ const _hoisted_7$4 = {
1707
1934
  key: 0,
1708
1935
  class: "file-toolbar-search"
1709
- }, wt = ["value"], yt = {
1936
+ };
1937
+ const _hoisted_8$4 = ["value"];
1938
+ const _hoisted_9$4 = {
1710
1939
  key: 1,
1711
1940
  class: "file-toolbar-view-toggle"
1712
- }, kt = /* @__PURE__ */ q({
1941
+ };
1942
+ const _sfc_main$6 = /* @__PURE__ */ defineComponent({
1713
1943
  __name: "Toolbar",
1714
1944
  props: {
1715
- canGoBack: { type: Boolean, default: !1 },
1716
- canGoForward: { type: Boolean, default: !1 },
1945
+ canGoBack: { type: Boolean, default: false },
1946
+ canGoForward: { type: Boolean, default: false },
1717
1947
  breadcrumbs: { default: () => [] },
1718
1948
  viewMode: { default: "grid" },
1719
1949
  searchQuery: { default: "" },
1720
- showSearch: { type: Boolean, default: !1 },
1721
- showViewToggle: { type: Boolean, default: !0 },
1722
- draggable: { type: Boolean, default: !1 }
1950
+ showSearch: { type: Boolean, default: false },
1951
+ showViewToggle: { type: Boolean, default: true },
1952
+ draggable: { type: Boolean, default: false }
1723
1953
  },
1724
1954
  emits: ["back", "forward", "breadcrumb-navigate", "update:viewMode", "update:searchQuery"],
1725
- setup(e, { emit: g }) {
1726
- const t = g;
1727
- return (r, l) => (a(), h("div", {
1728
- class: B(["file-toolbar", { "file-toolbar--draggable": e.draggable }])
1729
- }, [
1730
- s("div", mt, [
1731
- s("button", {
1732
- class: "file-toolbar-button",
1733
- onClick: l[0] || (l[0] = (i) => t("back")),
1734
- disabled: !e.canGoBack,
1735
- title: "后退"
1736
- }, [
1737
- N(O(T), {
1738
- icon: "lucide:chevron-left",
1739
- width: 18,
1740
- height: 18
1741
- })
1742
- ], 8, gt),
1743
- s("button", {
1744
- class: "file-toolbar-button",
1745
- onClick: l[1] || (l[1] = (i) => t("forward")),
1746
- disabled: !e.canGoForward,
1747
- title: "前进"
1748
- }, [
1749
- N(O(T), {
1750
- icon: "lucide:chevron-right",
1751
- width: 18,
1752
- height: 18
1753
- })
1754
- ], 8, pt)
1755
- ]),
1756
- s("div", ft, [
1757
- Z(r.$slots, "breadcrumb", {}, () => [
1758
- e.breadcrumbs.length > 0 ? (a(), H(ut, {
1759
- key: 0,
1760
- items: e.breadcrumbs,
1761
- onNavigate: l[2] || (l[2] = (i) => t("breadcrumb-navigate", i))
1762
- }, null, 8, ["items"])) : j("", !0)
1763
- ], !0)
1764
- ]),
1765
- r.$slots.default ? (a(), h("div", vt, [
1766
- Z(r.$slots, "default", {}, void 0, !0)
1767
- ])) : j("", !0),
1768
- s("div", ht, [
1769
- e.showSearch ? (a(), h("div", bt, [
1770
- N(O(T), {
1771
- icon: "lucide:search",
1772
- width: 16,
1773
- height: 16,
1774
- class: "file-toolbar-search-icon"
1775
- }),
1776
- s("input", {
1777
- type: "text",
1778
- value: e.searchQuery,
1779
- onInput: l[3] || (l[3] = (i) => t("update:searchQuery", i.target.value)),
1780
- placeholder: "搜索",
1781
- class: "file-toolbar-search-input"
1782
- }, null, 40, wt)
1783
- ])) : j("", !0),
1784
- e.showViewToggle ? (a(), h("div", yt, [
1785
- s("button", {
1786
- onClick: l[4] || (l[4] = (i) => t("update:viewMode", "grid")),
1787
- class: B(["file-toolbar-button", e.viewMode === "grid" ? "file-toolbar-button--active" : ""]),
1788
- title: "网格视图"
1955
+ setup(__props, { emit: __emit }) {
1956
+ const emit = __emit;
1957
+ return (_ctx, _cache) => {
1958
+ return openBlock(), createElementBlock("div", {
1959
+ class: normalizeClass(["file-toolbar", { "file-toolbar--draggable": __props.draggable }])
1960
+ }, [
1961
+ createElementVNode("div", _hoisted_1$6, [
1962
+ createElementVNode("button", {
1963
+ class: "file-toolbar-button",
1964
+ onClick: _cache[0] || (_cache[0] = ($event) => emit("back")),
1965
+ disabled: !__props.canGoBack,
1966
+ title: "后退"
1789
1967
  }, [
1790
- N(O(T), {
1791
- icon: "lucide:layout-grid",
1968
+ createVNode(unref(Icon), {
1969
+ icon: "lucide:chevron-left",
1792
1970
  width: 18,
1793
1971
  height: 18
1794
1972
  })
1795
- ], 2),
1796
- s("button", {
1797
- onClick: l[5] || (l[5] = (i) => t("update:viewMode", "list")),
1798
- class: B(["file-toolbar-button", e.viewMode === "list" ? "file-toolbar-button--active" : ""]),
1799
- title: "列表视图"
1973
+ ], 8, _hoisted_2$6),
1974
+ createElementVNode("button", {
1975
+ class: "file-toolbar-button",
1976
+ onClick: _cache[1] || (_cache[1] = ($event) => emit("forward")),
1977
+ disabled: !__props.canGoForward,
1978
+ title: "前进"
1800
1979
  }, [
1801
- N(O(T), {
1802
- icon: "lucide:list",
1980
+ createVNode(unref(Icon), {
1981
+ icon: "lucide:chevron-right",
1803
1982
  width: 18,
1804
1983
  height: 18
1805
1984
  })
1806
- ], 2)
1807
- ])) : j("", !0),
1808
- Z(r.$slots, "actions", {}, void 0, !0)
1809
- ])
1810
- ], 2));
1985
+ ], 8, _hoisted_3$5)
1986
+ ]),
1987
+ createElementVNode("div", _hoisted_4$5, [
1988
+ renderSlot(_ctx.$slots, "breadcrumb", {}, () => [
1989
+ __props.breadcrumbs.length > 0 ? (openBlock(), createBlock(Breadcrumb, {
1990
+ key: 0,
1991
+ items: __props.breadcrumbs,
1992
+ onNavigate: _cache[2] || (_cache[2] = (item) => emit("breadcrumb-navigate", item))
1993
+ }, null, 8, ["items"])) : createCommentVNode("", true)
1994
+ ], true)
1995
+ ]),
1996
+ _ctx.$slots.default ? (openBlock(), createElementBlock("div", _hoisted_5$5, [
1997
+ renderSlot(_ctx.$slots, "default", {}, void 0, true)
1998
+ ])) : createCommentVNode("", true),
1999
+ createElementVNode("div", _hoisted_6$4, [
2000
+ __props.showSearch ? (openBlock(), createElementBlock("div", _hoisted_7$4, [
2001
+ createVNode(unref(Icon), {
2002
+ icon: "lucide:search",
2003
+ width: 16,
2004
+ height: 16,
2005
+ class: "file-toolbar-search-icon"
2006
+ }),
2007
+ createElementVNode("input", {
2008
+ type: "text",
2009
+ value: __props.searchQuery,
2010
+ onInput: _cache[3] || (_cache[3] = ($event) => emit("update:searchQuery", $event.target.value)),
2011
+ placeholder: "搜索",
2012
+ class: "file-toolbar-search-input"
2013
+ }, null, 40, _hoisted_8$4)
2014
+ ])) : createCommentVNode("", true),
2015
+ __props.showViewToggle ? (openBlock(), createElementBlock("div", _hoisted_9$4, [
2016
+ createElementVNode("button", {
2017
+ onClick: _cache[4] || (_cache[4] = ($event) => emit("update:viewMode", "grid")),
2018
+ class: normalizeClass(["file-toolbar-button", __props.viewMode === "grid" ? "file-toolbar-button--active" : ""]),
2019
+ title: "网格视图"
2020
+ }, [
2021
+ createVNode(unref(Icon), {
2022
+ icon: "lucide:layout-grid",
2023
+ width: 18,
2024
+ height: 18
2025
+ })
2026
+ ], 2),
2027
+ createElementVNode("button", {
2028
+ onClick: _cache[5] || (_cache[5] = ($event) => emit("update:viewMode", "list")),
2029
+ class: normalizeClass(["file-toolbar-button", __props.viewMode === "list" ? "file-toolbar-button--active" : ""]),
2030
+ title: "列表视图"
2031
+ }, [
2032
+ createVNode(unref(Icon), {
2033
+ icon: "lucide:list",
2034
+ width: 18,
2035
+ height: 18
2036
+ })
2037
+ ], 2)
2038
+ ])) : createCommentVNode("", true),
2039
+ renderSlot(_ctx.$slots, "actions", {}, void 0, true)
2040
+ ])
2041
+ ], 2);
2042
+ };
1811
2043
  }
1812
- }), nn = /* @__PURE__ */ K(kt, [["__scopeId", "data-v-d3a92980"]]), xt = { class: "file-status-bar" }, $t = { key: 0 }, Ct = /* @__PURE__ */ q({
2044
+ });
2045
+ const Toolbar = /* @__PURE__ */ _export_sfc(_sfc_main$6, [["__scopeId", "data-v-d3a92980"]]);
2046
+ const _hoisted_1$5 = { class: "file-status-bar" };
2047
+ const _hoisted_2$5 = { key: 0 };
2048
+ const _sfc_main$5 = /* @__PURE__ */ defineComponent({
1813
2049
  __name: "StatusBar",
1814
2050
  props: {
1815
2051
  itemCount: { default: 0 },
1816
2052
  selectedCount: { default: 0 }
1817
2053
  },
1818
- setup(e) {
1819
- return (g, t) => (a(), h("div", xt, [
1820
- Z(g.$slots, "default", {}, () => [
1821
- s("span", null, z(e.itemCount) + " 个项目", 1),
1822
- e.selectedCount > 0 ? (a(), h("span", $t, " • 已选择 " + z(e.selectedCount) + " ", 1)) : j("", !0)
1823
- ], !0)
1824
- ]));
2054
+ setup(__props) {
2055
+ return (_ctx, _cache) => {
2056
+ return openBlock(), createElementBlock("div", _hoisted_1$5, [
2057
+ renderSlot(_ctx.$slots, "default", {}, () => [
2058
+ createElementVNode("span", null, toDisplayString(__props.itemCount) + " 个项目", 1),
2059
+ __props.selectedCount > 0 ? (openBlock(), createElementBlock("span", _hoisted_2$5, " • 已选择 " + toDisplayString(__props.selectedCount) + " 个", 1)) : createCommentVNode("", true)
2060
+ ], true)
2061
+ ]);
2062
+ };
1825
2063
  }
1826
- }), on = /* @__PURE__ */ K(Ct, [["__scopeId", "data-v-f1062f30"]]), It = {
2064
+ });
2065
+ const StatusBar = /* @__PURE__ */ _export_sfc(_sfc_main$5, [["__scopeId", "data-v-f1062f30"]]);
2066
+ const _hoisted_1$4 = {
1827
2067
  key: 0,
1828
2068
  class: "context-menu-container"
1829
- }, Et = {
2069
+ };
2070
+ const _hoisted_2$4 = {
1830
2071
  key: 0,
1831
2072
  class: "context-menu-separator"
1832
- }, Mt = ["onClick", "onMouseenter"], jt = { class: "context-menu-item-label" }, Dt = {
2073
+ };
2074
+ const _hoisted_3$4 = ["onClick", "onMouseenter"];
2075
+ const _hoisted_4$4 = { class: "context-menu-item-label" };
2076
+ const _hoisted_5$4 = {
1833
2077
  key: 2,
1834
2078
  class: "context-menu-item-shortcut"
1835
- }, zt = {
2079
+ };
2080
+ const _hoisted_6$3 = {
1836
2081
  key: 0,
1837
2082
  class: "context-menu-separator"
1838
- }, St = ["onClick"], Ot = { class: "context-menu-item-label" }, Lt = {
2083
+ };
2084
+ const _hoisted_7$3 = ["onClick"];
2085
+ const _hoisted_8$3 = { class: "context-menu-item-label" };
2086
+ const _hoisted_9$3 = {
1839
2087
  key: 2,
1840
2088
  class: "context-menu-item-shortcut"
1841
- }, W = 8, Y = 220, Tt = 32, At = 9, Nt = 8, re = 0, Pt = /* @__PURE__ */ q({
2089
+ };
2090
+ const MARGIN = 8;
2091
+ const MENU_WIDTH = 220;
2092
+ const MENU_ITEM_HEIGHT = 32;
2093
+ const SEPARATOR_HEIGHT = 9;
2094
+ const MENU_PADDING = 8;
2095
+ const SUBMENU_GAP = 0;
2096
+ const _sfc_main$4 = /* @__PURE__ */ defineComponent({
1842
2097
  __name: "ContextMenu",
1843
2098
  props: {
1844
2099
  visible: { type: Boolean },
@@ -1847,387 +2102,683 @@ const je = /* @__PURE__ */ q({
1847
2102
  options: {}
1848
2103
  },
1849
2104
  emits: ["close", "select"],
1850
- setup(e, { emit: g }) {
1851
- const t = e, r = g;
1852
- function l(o) {
1853
- let x = Nt;
1854
- for (const p of o)
1855
- x += p.separator ? At : Tt;
1856
- return x;
2105
+ setup(__props, { emit: __emit }) {
2106
+ const props = __props;
2107
+ const emit = __emit;
2108
+ function estimateMenuHeight(items) {
2109
+ let height = MENU_PADDING;
2110
+ for (const item of items) {
2111
+ height += item.separator ? SEPARATOR_HEIGHT : MENU_ITEM_HEIGHT;
2112
+ }
2113
+ return height;
1857
2114
  }
1858
- function i(o, x, p) {
1859
- const V = window.innerWidth, k = window.innerHeight;
1860
- let E = o, P = x;
1861
- const _ = V - o, X = o;
1862
- _ < Y + W && (X >= Y + W ? E = o - Y : _ > X ? E = V - Y - W : E = W);
1863
- const oe = k - x, le = x;
1864
- return oe < p + W && (le >= p + W ? P = x - p : oe > le ? P = k - p - W : P = W), E = Math.max(W, Math.min(E, V - Y - W)), P = Math.max(W, Math.min(P, k - p - W)), { x: E, y: P };
2115
+ function calculateMenuPosition(clickX, clickY, menuHeight) {
2116
+ const viewportWidth = window.innerWidth;
2117
+ const viewportHeight = window.innerHeight;
2118
+ let adjustedX = clickX;
2119
+ let adjustedY = clickY;
2120
+ const spaceRight = viewportWidth - clickX;
2121
+ const spaceLeft = clickX;
2122
+ if (spaceRight < MENU_WIDTH + MARGIN) {
2123
+ if (spaceLeft >= MENU_WIDTH + MARGIN) {
2124
+ adjustedX = clickX - MENU_WIDTH;
2125
+ } else {
2126
+ if (spaceRight > spaceLeft) {
2127
+ adjustedX = viewportWidth - MENU_WIDTH - MARGIN;
2128
+ } else {
2129
+ adjustedX = MARGIN;
2130
+ }
2131
+ }
2132
+ }
2133
+ const spaceBottom = viewportHeight - clickY;
2134
+ const spaceTop = clickY;
2135
+ if (spaceBottom < menuHeight + MARGIN) {
2136
+ if (spaceTop >= menuHeight + MARGIN) {
2137
+ adjustedY = clickY - menuHeight;
2138
+ } else {
2139
+ if (spaceBottom > spaceTop) {
2140
+ adjustedY = viewportHeight - menuHeight - MARGIN;
2141
+ } else {
2142
+ adjustedY = MARGIN;
2143
+ }
2144
+ }
2145
+ }
2146
+ adjustedX = Math.max(MARGIN, Math.min(adjustedX, viewportWidth - MENU_WIDTH - MARGIN));
2147
+ adjustedY = Math.max(MARGIN, Math.min(adjustedY, viewportHeight - menuHeight - MARGIN));
2148
+ return { x: adjustedX, y: adjustedY };
1865
2149
  }
1866
- function w(o, x) {
1867
- const p = window.innerWidth, V = window.innerHeight, k = p - o.right, E = o.left;
1868
- let P, _;
1869
- return k >= Y + re + W ? P = o.right + re : E >= Y + re + W ? P = o.left - Y - re : k > E ? P = p - Y - W : P = W, _ = o.top, _ + x > V - W && (_ = V - x - W), _ < W && (_ = W), { x: P, y: _ };
2150
+ function calculateSubmenuPosition(parentRect, submenuHeight) {
2151
+ const viewportWidth = window.innerWidth;
2152
+ const viewportHeight = window.innerHeight;
2153
+ const spaceRight = viewportWidth - parentRect.right;
2154
+ const spaceLeft = parentRect.left;
2155
+ let submenuX;
2156
+ let submenuY;
2157
+ if (spaceRight >= MENU_WIDTH + SUBMENU_GAP + MARGIN) {
2158
+ submenuX = parentRect.right + SUBMENU_GAP;
2159
+ } else if (spaceLeft >= MENU_WIDTH + SUBMENU_GAP + MARGIN) {
2160
+ submenuX = parentRect.left - MENU_WIDTH - SUBMENU_GAP;
2161
+ } else {
2162
+ if (spaceRight > spaceLeft) {
2163
+ submenuX = viewportWidth - MENU_WIDTH - MARGIN;
2164
+ } else {
2165
+ submenuX = MARGIN;
2166
+ }
2167
+ }
2168
+ submenuY = parentRect.top;
2169
+ if (submenuY + submenuHeight > viewportHeight - MARGIN) {
2170
+ submenuY = viewportHeight - submenuHeight - MARGIN;
2171
+ }
2172
+ if (submenuY < MARGIN) {
2173
+ submenuY = MARGIN;
2174
+ }
2175
+ return { x: submenuX, y: submenuY };
1870
2176
  }
1871
- const I = D(null), m = D(null), v = D(null), b = D(/* @__PURE__ */ new Map()), u = F(() => {
1872
- const o = l(t.options);
1873
- return i(t.x, t.y, o);
1874
- }), n = F(() => ({
1875
- left: `${u.value.x}px`,
1876
- top: `${u.value.y}px`
1877
- })), C = F(() => v.value ? {
1878
- left: `${v.value.x}px`,
1879
- top: `${v.value.y}px`
1880
- } : {}), c = F(() => m.value ? t.options.find((o) => o.id === m.value && o.children && o.children.length > 0) : null), y = (o, x) => {
1881
- x && x instanceof HTMLElement ? b.value.set(o, x) : b.value.delete(o);
1882
- }, M = (o) => o.children && o.children.length > 0;
1883
- ee(m, (o) => {
1884
- if (!o || !c.value) {
1885
- v.value = null;
2177
+ const menuRef = ref(null);
2178
+ const hoveredItemId = ref(null);
2179
+ const submenuPosition = ref(null);
2180
+ const itemRefs = ref(/* @__PURE__ */ new Map());
2181
+ const position = computed(() => {
2182
+ const estimatedHeight = estimateMenuHeight(props.options);
2183
+ return calculateMenuPosition(props.x, props.y, estimatedHeight);
2184
+ });
2185
+ const menuStyle = computed(() => ({
2186
+ left: `${position.value.x}px`,
2187
+ top: `${position.value.y}px`
2188
+ }));
2189
+ const submenuStyle = computed(() => {
2190
+ if (!submenuPosition.value) return {};
2191
+ return {
2192
+ left: `${submenuPosition.value.x}px`,
2193
+ top: `${submenuPosition.value.y}px`
2194
+ };
2195
+ });
2196
+ const hoveredItem = computed(() => {
2197
+ if (!hoveredItemId.value) return null;
2198
+ return props.options.find((opt) => opt.id === hoveredItemId.value && opt.children && opt.children.length > 0);
2199
+ });
2200
+ const setItemRef = (id, el) => {
2201
+ if (el && el instanceof HTMLElement) {
2202
+ itemRefs.value.set(id, el);
2203
+ } else {
2204
+ itemRefs.value.delete(id);
2205
+ }
2206
+ };
2207
+ const hasChildren = (option) => {
2208
+ return option.children && option.children.length > 0;
2209
+ };
2210
+ watch(hoveredItemId, (newId) => {
2211
+ if (!newId || !hoveredItem.value) {
2212
+ submenuPosition.value = null;
1886
2213
  return;
1887
2214
  }
1888
- fe(() => {
1889
- var k;
1890
- const x = b.value.get(o);
1891
- if (!x || !((k = c.value) != null && k.children)) {
1892
- v.value = null;
2215
+ nextTick(() => {
2216
+ var _a;
2217
+ const itemEl = itemRefs.value.get(newId);
2218
+ if (!itemEl || !((_a = hoveredItem.value) == null ? void 0 : _a.children)) {
2219
+ submenuPosition.value = null;
1893
2220
  return;
1894
2221
  }
1895
- const p = x.getBoundingClientRect(), V = l(c.value.children);
1896
- v.value = w(p, V);
2222
+ const rect = itemEl.getBoundingClientRect();
2223
+ const submenuHeight = estimateMenuHeight(hoveredItem.value.children);
2224
+ submenuPosition.value = calculateSubmenuPosition(rect, submenuHeight);
1897
2225
  });
1898
- }), ee(() => t.visible, (o) => {
1899
- o || (m.value = null, v.value = null);
1900
2226
  });
1901
- const S = (o) => {
1902
- const x = o.target, p = document.querySelector(".context-menu-container");
1903
- p && p.contains(x) || r("close");
1904
- }, L = (o) => {
1905
- o.key === "Escape" && r("close");
1906
- };
1907
- ee(() => t.visible, (o) => {
1908
- o ? (document.addEventListener("mousedown", S), document.addEventListener("keydown", L)) : (document.removeEventListener("mousedown", S), document.removeEventListener("keydown", L));
1909
- }, { immediate: !0 }), ne(() => {
1910
- document.removeEventListener("mousedown", S), document.removeEventListener("keydown", L);
2227
+ watch(() => props.visible, (visible) => {
2228
+ if (!visible) {
2229
+ hoveredItemId.value = null;
2230
+ submenuPosition.value = null;
2231
+ }
1911
2232
  });
1912
- const $ = (o) => {
1913
- o.disabled || o.children && o.children.length > 0 || (o.action && o.action(), r("select", o), r("close"));
1914
- }, f = (o) => {
1915
- o.children && o.children.length > 0 ? m.value = o.id : m.value = null;
1916
- }, A = () => {
1917
- }, U = () => {
1918
- m.value = null;
1919
- };
1920
- return (o, x) => (a(), H(ie, { to: "body" }, [
1921
- e.visible ? (a(), h("div", It, [
1922
- s("div", {
1923
- ref_key: "menuRef",
1924
- ref: I,
1925
- class: "context-menu",
1926
- style: de(n.value)
1927
- }, [
1928
- (a(!0), h(G, null, J(e.options, (p, V) => (a(), h(G, {
1929
- key: p.id || V
2233
+ const handleClickOutside = (e) => {
2234
+ const target = e.target;
2235
+ const menuContainer = document.querySelector(".context-menu-container");
2236
+ if (menuContainer && menuContainer.contains(target)) {
2237
+ return;
2238
+ }
2239
+ emit("close");
2240
+ };
2241
+ const handleEscape = (e) => {
2242
+ if (e.key === "Escape") {
2243
+ emit("close");
2244
+ }
2245
+ };
2246
+ watch(() => props.visible, (visible) => {
2247
+ if (visible) {
2248
+ document.addEventListener("mousedown", handleClickOutside);
2249
+ document.addEventListener("keydown", handleEscape);
2250
+ } else {
2251
+ document.removeEventListener("mousedown", handleClickOutside);
2252
+ document.removeEventListener("keydown", handleEscape);
2253
+ }
2254
+ }, { immediate: true });
2255
+ onUnmounted(() => {
2256
+ document.removeEventListener("mousedown", handleClickOutside);
2257
+ document.removeEventListener("keydown", handleEscape);
2258
+ });
2259
+ const handleOptionClick = (option) => {
2260
+ if (option.disabled) return;
2261
+ if (option.children && option.children.length > 0) {
2262
+ return;
2263
+ }
2264
+ if (option.action) {
2265
+ option.action();
2266
+ }
2267
+ emit("select", option);
2268
+ emit("close");
2269
+ };
2270
+ const handleItemMouseEnter = (option) => {
2271
+ if (option.children && option.children.length > 0) {
2272
+ hoveredItemId.value = option.id;
2273
+ } else {
2274
+ hoveredItemId.value = null;
2275
+ }
2276
+ };
2277
+ const keepSubmenuOpen = () => {
2278
+ };
2279
+ const closeSubmenu = () => {
2280
+ hoveredItemId.value = null;
2281
+ };
2282
+ return (_ctx, _cache) => {
2283
+ return openBlock(), createBlock(Teleport, { to: "body" }, [
2284
+ __props.visible ? (openBlock(), createElementBlock("div", _hoisted_1$4, [
2285
+ createElementVNode("div", {
2286
+ ref_key: "menuRef",
2287
+ ref: menuRef,
2288
+ class: "context-menu",
2289
+ style: normalizeStyle(menuStyle.value)
1930
2290
  }, [
1931
- p.separator ? (a(), h("div", Et)) : (a(), h("div", {
1932
- key: 1,
1933
- ref_for: !0,
1934
- ref: (k) => y(p.id, k),
1935
- class: B([
1936
- "context-menu-item",
1937
- p.disabled ? "context-menu-item--disabled" : "",
1938
- p.danger ? "context-menu-item--danger" : "",
1939
- M(p) ? "context-menu-item--has-children" : "",
1940
- m.value === p.id ? "context-menu-item--active" : ""
1941
- ]),
1942
- onClick: (k) => $(p),
1943
- onMouseenter: (k) => f(p)
1944
- }, [
1945
- p.icon ? (a(), H(O(T), {
1946
- key: 0,
1947
- icon: p.icon,
1948
- width: "16",
1949
- height: "16",
1950
- class: "context-menu-item-icon"
1951
- }, null, 8, ["icon"])) : j("", !0),
1952
- s("span", jt, z(p.label), 1),
1953
- p.checked ? (a(), H(O(T), {
1954
- key: 1,
1955
- icon: "lucide:check",
1956
- width: "14",
1957
- height: "14",
1958
- class: "context-menu-item-check"
1959
- })) : j("", !0),
1960
- p.shortcut && !M(p) ? (a(), h("span", Dt, z(p.shortcut), 1)) : j("", !0),
1961
- M(p) ? (a(), H(O(T), {
1962
- key: 3,
1963
- icon: "lucide:chevron-right",
1964
- width: "14",
1965
- height: "14",
1966
- class: "context-menu-item-arrow"
1967
- })) : j("", !0)
1968
- ], 42, Mt))
1969
- ], 64))), 128))
1970
- ], 4),
1971
- c.value && v.value ? (a(), h("div", {
1972
- key: 0,
1973
- class: "context-menu context-menu-submenu",
1974
- style: de(C.value),
1975
- onMouseenter: A,
1976
- onMouseleave: U
1977
- }, [
1978
- (a(!0), h(G, null, J(c.value.children, (p, V) => (a(), h(G, {
1979
- key: p.id || V
2291
+ (openBlock(true), createElementBlock(Fragment, null, renderList(__props.options, (option, index) => {
2292
+ return openBlock(), createElementBlock(Fragment, {
2293
+ key: option.id || index
2294
+ }, [
2295
+ option.separator ? (openBlock(), createElementBlock("div", _hoisted_2$4)) : (openBlock(), createElementBlock("div", {
2296
+ key: 1,
2297
+ ref_for: true,
2298
+ ref: (el) => setItemRef(option.id, el),
2299
+ class: normalizeClass([
2300
+ "context-menu-item",
2301
+ option.disabled ? "context-menu-item--disabled" : "",
2302
+ option.danger ? "context-menu-item--danger" : "",
2303
+ hasChildren(option) ? "context-menu-item--has-children" : "",
2304
+ hoveredItemId.value === option.id ? "context-menu-item--active" : ""
2305
+ ]),
2306
+ onClick: ($event) => handleOptionClick(option),
2307
+ onMouseenter: ($event) => handleItemMouseEnter(option)
2308
+ }, [
2309
+ option.icon ? (openBlock(), createBlock(unref(Icon), {
2310
+ key: 0,
2311
+ icon: option.icon,
2312
+ width: "16",
2313
+ height: "16",
2314
+ class: "context-menu-item-icon"
2315
+ }, null, 8, ["icon"])) : createCommentVNode("", true),
2316
+ createElementVNode("span", _hoisted_4$4, toDisplayString(option.label), 1),
2317
+ option.checked ? (openBlock(), createBlock(unref(Icon), {
2318
+ key: 1,
2319
+ icon: "lucide:check",
2320
+ width: "14",
2321
+ height: "14",
2322
+ class: "context-menu-item-check"
2323
+ })) : createCommentVNode("", true),
2324
+ option.shortcut && !hasChildren(option) ? (openBlock(), createElementBlock("span", _hoisted_5$4, toDisplayString(option.shortcut), 1)) : createCommentVNode("", true),
2325
+ hasChildren(option) ? (openBlock(), createBlock(unref(Icon), {
2326
+ key: 3,
2327
+ icon: "lucide:chevron-right",
2328
+ width: "14",
2329
+ height: "14",
2330
+ class: "context-menu-item-arrow"
2331
+ })) : createCommentVNode("", true)
2332
+ ], 42, _hoisted_3$4))
2333
+ ], 64);
2334
+ }), 128))
2335
+ ], 4),
2336
+ hoveredItem.value && submenuPosition.value ? (openBlock(), createElementBlock("div", {
2337
+ key: 0,
2338
+ class: "context-menu context-menu-submenu",
2339
+ style: normalizeStyle(submenuStyle.value),
2340
+ onMouseenter: keepSubmenuOpen,
2341
+ onMouseleave: closeSubmenu
1980
2342
  }, [
1981
- p.separator ? (a(), h("div", zt)) : (a(), h("div", {
1982
- key: 1,
1983
- class: B([
1984
- "context-menu-item",
1985
- p.disabled ? "context-menu-item--disabled" : "",
1986
- p.danger ? "context-menu-item--danger" : ""
1987
- ]),
1988
- onClick: (k) => $(p)
1989
- }, [
1990
- p.icon ? (a(), H(O(T), {
1991
- key: 0,
1992
- icon: p.icon,
1993
- width: "16",
1994
- height: "16",
1995
- class: "context-menu-item-icon"
1996
- }, null, 8, ["icon"])) : j("", !0),
1997
- s("span", Ot, z(p.label), 1),
1998
- p.checked ? (a(), H(O(T), {
1999
- key: 1,
2000
- icon: "lucide:check",
2001
- width: "14",
2002
- height: "14",
2003
- class: "context-menu-item-check"
2004
- })) : j("", !0),
2005
- p.shortcut ? (a(), h("span", Lt, z(p.shortcut), 1)) : j("", !0)
2006
- ], 10, St))
2007
- ], 64))), 128))
2008
- ], 36)) : j("", !0)
2009
- ])) : j("", !0)
2010
- ]));
2343
+ (openBlock(true), createElementBlock(Fragment, null, renderList(hoveredItem.value.children, (child, childIndex) => {
2344
+ return openBlock(), createElementBlock(Fragment, {
2345
+ key: child.id || childIndex
2346
+ }, [
2347
+ child.separator ? (openBlock(), createElementBlock("div", _hoisted_6$3)) : (openBlock(), createElementBlock("div", {
2348
+ key: 1,
2349
+ class: normalizeClass([
2350
+ "context-menu-item",
2351
+ child.disabled ? "context-menu-item--disabled" : "",
2352
+ child.danger ? "context-menu-item--danger" : ""
2353
+ ]),
2354
+ onClick: ($event) => handleOptionClick(child)
2355
+ }, [
2356
+ child.icon ? (openBlock(), createBlock(unref(Icon), {
2357
+ key: 0,
2358
+ icon: child.icon,
2359
+ width: "16",
2360
+ height: "16",
2361
+ class: "context-menu-item-icon"
2362
+ }, null, 8, ["icon"])) : createCommentVNode("", true),
2363
+ createElementVNode("span", _hoisted_8$3, toDisplayString(child.label), 1),
2364
+ child.checked ? (openBlock(), createBlock(unref(Icon), {
2365
+ key: 1,
2366
+ icon: "lucide:check",
2367
+ width: "14",
2368
+ height: "14",
2369
+ class: "context-menu-item-check"
2370
+ })) : createCommentVNode("", true),
2371
+ child.shortcut ? (openBlock(), createElementBlock("span", _hoisted_9$3, toDisplayString(child.shortcut), 1)) : createCommentVNode("", true)
2372
+ ], 10, _hoisted_7$3))
2373
+ ], 64);
2374
+ }), 128))
2375
+ ], 36)) : createCommentVNode("", true)
2376
+ ])) : createCommentVNode("", true)
2377
+ ]);
2378
+ };
2011
2379
  }
2012
- }), ln = /* @__PURE__ */ K(Pt, [["__scopeId", "data-v-bce7298d"]]);
2013
- function Ut() {
2014
- const e = D({ x: 0, y: 0 }), g = D(!1), t = (i) => {
2015
- g.value && (e.value = {
2016
- x: e.value.x + i.movementX,
2017
- y: e.value.y + i.movementY
2018
- });
2019
- }, r = () => {
2020
- g.value = !1;
2021
- }, l = (i) => {
2022
- const w = i.target;
2023
- w.closest(".draggable-area") && !w.closest("button") && (i.preventDefault(), g.value = !0);
2380
+ });
2381
+ const ContextMenu = /* @__PURE__ */ _export_sfc(_sfc_main$4, [["__scopeId", "data-v-bce7298d"]]);
2382
+ function useWindowDrag() {
2383
+ const position = ref({ x: 0, y: 0 });
2384
+ const isDragging = ref(false);
2385
+ const handleMouseMove = (e) => {
2386
+ if (!isDragging.value) return;
2387
+ position.value = {
2388
+ x: position.value.x + e.movementX,
2389
+ y: position.value.y + e.movementY
2390
+ };
2024
2391
  };
2025
- return ee(g, (i) => {
2026
- i ? (window.addEventListener("mousemove", t), window.addEventListener("mouseup", r)) : (window.removeEventListener("mousemove", t), window.removeEventListener("mouseup", r));
2027
- }), ne(() => {
2028
- window.removeEventListener("mousemove", t), window.removeEventListener("mouseup", r);
2029
- }), {
2030
- position: e,
2031
- isDragging: g,
2032
- startDrag: l
2392
+ const handleMouseUp = () => {
2393
+ isDragging.value = false;
2394
+ };
2395
+ const startDrag = (e) => {
2396
+ const target = e.target;
2397
+ if (target.closest(".draggable-area") && !target.closest("button")) {
2398
+ e.preventDefault();
2399
+ isDragging.value = true;
2400
+ }
2401
+ };
2402
+ watch(isDragging, (dragging) => {
2403
+ if (dragging) {
2404
+ window.addEventListener("mousemove", handleMouseMove);
2405
+ window.addEventListener("mouseup", handleMouseUp);
2406
+ } else {
2407
+ window.removeEventListener("mousemove", handleMouseMove);
2408
+ window.removeEventListener("mouseup", handleMouseUp);
2409
+ }
2410
+ });
2411
+ onUnmounted(() => {
2412
+ window.removeEventListener("mousemove", handleMouseMove);
2413
+ window.removeEventListener("mouseup", handleMouseUp);
2414
+ });
2415
+ return {
2416
+ position,
2417
+ isDragging,
2418
+ startDrag
2033
2419
  };
2034
2420
  }
2035
- function Ft(e, g, t, r, l, i) {
2036
- const w = D(e), I = D(g), m = D(!1), v = D(null), b = D(0), u = D(0), n = D(0), C = D(0), c = (L) => {
2037
- if (!m.value || !v.value) return;
2038
- const $ = L.clientX - b.value, f = L.clientY - u.value;
2039
- let A = n.value, U = C.value;
2040
- const o = v.value;
2041
- o.includes("e") ? A = Math.min(Math.max(n.value + $, t), l) : o.includes("w") && (A = Math.min(Math.max(n.value - $, t), l)), o.includes("s") ? U = Math.min(Math.max(C.value + f, r), i) : o.includes("n") && (U = Math.min(Math.max(C.value - f, r), i)), w.value = A, I.value = U;
2042
- }, y = () => {
2043
- m.value = !1, v.value = null;
2044
- }, M = (L, $, f, A) => {
2045
- L.preventDefault(), L.stopPropagation(), m.value = !0, v.value = $, b.value = L.clientX, u.value = L.clientY, n.value = f, C.value = A;
2046
- }, S = (L) => ({
2047
- n: "n-resize",
2048
- s: "s-resize",
2049
- e: "e-resize",
2050
- w: "w-resize",
2051
- ne: "ne-resize",
2052
- nw: "nw-resize",
2053
- se: "se-resize",
2054
- sw: "sw-resize"
2055
- })[L];
2056
- return ee(m, (L) => {
2057
- L ? (window.addEventListener("mousemove", c), window.addEventListener("mouseup", y), document.body.style.cursor = S(v.value || "se"), document.body.style.userSelect = "none") : (window.removeEventListener("mousemove", c), window.removeEventListener("mouseup", y), document.body.style.cursor = "", document.body.style.userSelect = "");
2058
- }), ne(() => {
2059
- window.removeEventListener("mousemove", c), window.removeEventListener("mouseup", y), document.body.style.cursor = "", document.body.style.userSelect = "";
2060
- }), {
2061
- width: w,
2062
- height: I,
2063
- isResizing: m,
2064
- startResize: M
2421
+ function useWindowResize(initialWidth, initialHeight, minWidth, minHeight, maxWidth, maxHeight) {
2422
+ const width = ref(initialWidth);
2423
+ const height = ref(initialHeight);
2424
+ const isResizing = ref(false);
2425
+ const resizeDirection = ref(null);
2426
+ const startX = ref(0);
2427
+ const startY = ref(0);
2428
+ const startWidth = ref(0);
2429
+ const startHeight = ref(0);
2430
+ const handleMouseMove = (e) => {
2431
+ if (!isResizing.value || !resizeDirection.value) return;
2432
+ const deltaX = e.clientX - startX.value;
2433
+ const deltaY = e.clientY - startY.value;
2434
+ let newWidth = startWidth.value;
2435
+ let newHeight = startHeight.value;
2436
+ const direction = resizeDirection.value;
2437
+ if (direction.includes("e")) {
2438
+ newWidth = Math.min(Math.max(startWidth.value + deltaX, minWidth), maxWidth);
2439
+ } else if (direction.includes("w")) {
2440
+ newWidth = Math.min(Math.max(startWidth.value - deltaX, minWidth), maxWidth);
2441
+ }
2442
+ if (direction.includes("s")) {
2443
+ newHeight = Math.min(Math.max(startHeight.value + deltaY, minHeight), maxHeight);
2444
+ } else if (direction.includes("n")) {
2445
+ newHeight = Math.min(Math.max(startHeight.value - deltaY, minHeight), maxHeight);
2446
+ }
2447
+ width.value = newWidth;
2448
+ height.value = newHeight;
2449
+ };
2450
+ const handleMouseUp = () => {
2451
+ isResizing.value = false;
2452
+ resizeDirection.value = null;
2453
+ };
2454
+ const startResize = (e, direction, currentWidth, currentHeight) => {
2455
+ e.preventDefault();
2456
+ e.stopPropagation();
2457
+ isResizing.value = true;
2458
+ resizeDirection.value = direction;
2459
+ startX.value = e.clientX;
2460
+ startY.value = e.clientY;
2461
+ startWidth.value = currentWidth;
2462
+ startHeight.value = currentHeight;
2463
+ };
2464
+ const getCursorForDirection = (direction) => {
2465
+ const cursors = {
2466
+ n: "n-resize",
2467
+ s: "s-resize",
2468
+ e: "e-resize",
2469
+ w: "w-resize",
2470
+ ne: "ne-resize",
2471
+ nw: "nw-resize",
2472
+ se: "se-resize",
2473
+ sw: "sw-resize"
2474
+ };
2475
+ return cursors[direction];
2476
+ };
2477
+ watch(isResizing, (resizing) => {
2478
+ if (resizing) {
2479
+ window.addEventListener("mousemove", handleMouseMove);
2480
+ window.addEventListener("mouseup", handleMouseUp);
2481
+ document.body.style.cursor = getCursorForDirection(resizeDirection.value || "se");
2482
+ document.body.style.userSelect = "none";
2483
+ } else {
2484
+ window.removeEventListener("mousemove", handleMouseMove);
2485
+ window.removeEventListener("mouseup", handleMouseUp);
2486
+ document.body.style.cursor = "";
2487
+ document.body.style.userSelect = "";
2488
+ }
2489
+ });
2490
+ onUnmounted(() => {
2491
+ window.removeEventListener("mousemove", handleMouseMove);
2492
+ window.removeEventListener("mouseup", handleMouseUp);
2493
+ document.body.style.cursor = "";
2494
+ document.body.style.userSelect = "";
2495
+ });
2496
+ return {
2497
+ width,
2498
+ height,
2499
+ isResizing,
2500
+ startResize
2065
2501
  };
2066
2502
  }
2067
- const Wt = { class: "window-controls" }, Rt = { class: "window-title-info" }, Bt = { class: "window-title-text" }, Ht = { class: "window-title-actions" }, Vt = { class: "window-content" }, _t = /* @__PURE__ */ q({
2503
+ const _hoisted_1$3 = { class: "window-controls" };
2504
+ const _hoisted_2$3 = { class: "window-title-info" };
2505
+ const _hoisted_3$3 = { class: "window-title-text" };
2506
+ const _hoisted_4$3 = { class: "window-title-actions" };
2507
+ const _hoisted_5$3 = { class: "window-content" };
2508
+ const _sfc_main$3 = /* @__PURE__ */ defineComponent({
2068
2509
  __name: "Window",
2069
2510
  props: {
2070
2511
  title: {},
2071
- showTitleBar: { type: Boolean, default: !0 },
2072
- showMinimize: { type: Boolean, default: !1 },
2073
- showMaximize: { type: Boolean, default: !1 },
2074
- draggable: { type: Boolean, default: !0 },
2075
- resizable: { type: Boolean, default: !0 },
2512
+ showTitleBar: { type: Boolean, default: true },
2513
+ showMinimize: { type: Boolean, default: false },
2514
+ showMaximize: { type: Boolean, default: false },
2515
+ draggable: { type: Boolean, default: true },
2516
+ resizable: { type: Boolean, default: true },
2076
2517
  width: { default: "auto" },
2077
2518
  height: { default: "auto" },
2078
2519
  minWidth: { default: 300 },
2079
2520
  minHeight: { default: 200 },
2080
2521
  maxWidth: { default: "80vw" },
2081
2522
  maxHeight: { default: "80vh" },
2082
- closeOnBackdrop: { type: Boolean, default: !0 },
2083
- fitContent: { type: Boolean, default: !1 }
2523
+ closeOnBackdrop: { type: Boolean, default: true },
2524
+ fitContent: { type: Boolean, default: false }
2084
2525
  },
2085
2526
  emits: ["close", "minimize", "maximize"],
2086
- setup(e, { emit: g }) {
2087
- const t = e, r = g, l = D(null), i = t.draggable ? Ut() : null, w = F(() => t.fitContent || t.width === "auto" || t.width === "fit-content" || t.height === "auto" || t.height === "fit-content"), I = () => {
2088
- if (w.value)
2527
+ setup(__props, { emit: __emit }) {
2528
+ const props = __props;
2529
+ const emit = __emit;
2530
+ const windowContainerRef = ref(null);
2531
+ const windowDrag = props.draggable ? useWindowDrag() : null;
2532
+ const isAutoSize = computed(() => {
2533
+ return props.fitContent || props.width === "auto" || props.width === "fit-content" || props.height === "auto" || props.height === "fit-content";
2534
+ });
2535
+ const getInitialSize = () => {
2536
+ if (isAutoSize.value) {
2089
2537
  return { initialWidth: 0, initialHeight: 0 };
2090
- const o = 600, x = 500;
2091
- let p = o, V = x;
2092
- return t.width !== "auto" && t.width !== "fit-content" && (p = typeof t.width == "number" ? t.width : parseInt(t.width)), t.height !== "auto" && t.height !== "fit-content" && (V = typeof t.height == "number" ? t.height : parseInt(t.height)), { initialWidth: p, initialHeight: V };
2093
- }, m = (o, x) => typeof o == "number" ? o : o.endsWith("px") ? parseInt(o) : o.endsWith("vw") ? parseInt(o) / 100 * window.innerWidth : o.endsWith("vh") ? parseInt(o) / 100 * window.innerHeight : x, { initialWidth: v, initialHeight: b } = I(), u = m(t.minWidth, 500), n = m(t.minHeight, 350), C = m(t.maxWidth, window.innerWidth * 0.8), c = m(t.maxHeight, window.innerHeight * 0.8), y = t.resizable ? Ft(v, b, u, n, C, c) : null, M = F(() => {
2094
- const o = {
2538
+ }
2539
+ const defaultWidth = 600;
2540
+ const defaultHeight = 500;
2541
+ let initialWidth2 = defaultWidth;
2542
+ let initialHeight2 = defaultHeight;
2543
+ if (props.width !== "auto" && props.width !== "fit-content") {
2544
+ initialWidth2 = typeof props.width === "number" ? props.width : parseInt(props.width);
2545
+ }
2546
+ if (props.height !== "auto" && props.height !== "fit-content") {
2547
+ initialHeight2 = typeof props.height === "number" ? props.height : parseInt(props.height);
2548
+ }
2549
+ return { initialWidth: initialWidth2, initialHeight: initialHeight2 };
2550
+ };
2551
+ const parseSize = (size, defaultPx) => {
2552
+ if (typeof size === "number") return size;
2553
+ if (size.endsWith("px")) return parseInt(size);
2554
+ if (size.endsWith("vw")) return parseInt(size) / 100 * window.innerWidth;
2555
+ if (size.endsWith("vh")) return parseInt(size) / 100 * window.innerHeight;
2556
+ return defaultPx;
2557
+ };
2558
+ const { initialWidth, initialHeight } = getInitialSize();
2559
+ const minW = parseSize(props.minWidth, 500);
2560
+ const minH = parseSize(props.minHeight, 350);
2561
+ const maxW = parseSize(props.maxWidth, window.innerWidth * 0.8);
2562
+ const maxH = parseSize(props.maxHeight, window.innerHeight * 0.8);
2563
+ const windowResize = props.resizable ? useWindowResize(initialWidth, initialHeight, minW, minH, maxW, maxH) : null;
2564
+ const windowStyle = computed(() => {
2565
+ const baseStyle = {
2095
2566
  left: "50%",
2096
2567
  top: "50%"
2097
2568
  };
2098
- let x = "-50%", p = "-50%";
2099
- return t.draggable && i && (x = `calc(-50% + ${i.position.value.x}px)`, p = `calc(-50% + ${i.position.value.y}px)`), o.transform = `translate(${x}, ${p})`, o.transformOrigin = "center center", w.value ? t.resizable && y && y.width.value > 0 && (o.width = `${y.width.value}px`, o.height = `${y.height.value}px`) : t.resizable && y ? (o.width = `${y.width.value}px`, o.height = `${y.height.value}px`) : (t.width !== "auto" && t.width !== "fit-content" && (o.width = typeof t.width == "number" ? `${t.width}px` : t.width), t.height !== "auto" && t.height !== "fit-content" && (o.height = typeof t.height == "number" ? `${t.height}px` : t.height)), t.minWidth && (o.minWidth = typeof t.minWidth == "number" ? `${t.minWidth}px` : t.minWidth), t.minHeight && (o.minHeight = typeof t.minHeight == "number" ? `${t.minHeight}px` : t.minHeight), t.maxWidth && (o.maxWidth = typeof t.maxWidth == "number" ? `${t.maxWidth}px` : t.maxWidth), t.maxHeight && (o.maxHeight = typeof t.maxHeight == "number" ? `${t.maxHeight}px` : t.maxHeight), o;
2100
- }), S = (o) => {
2101
- t.closeOnBackdrop && o.target === o.currentTarget && r("close");
2102
- }, L = (o) => {
2103
- t.draggable && i && i.startDrag(o);
2104
- }, $ = () => {
2105
- r("close");
2106
- }, f = () => {
2107
- r("minimize");
2108
- }, A = () => {
2109
- r("maximize");
2110
- }, U = (o, x) => {
2111
- if (!t.resizable || !y || !l.value) return;
2112
- const p = l.value.getBoundingClientRect(), V = p.width, k = p.height;
2113
- y.startResize(o, x, V, k);
2114
- };
2115
- return ve(() => {
2116
- const o = (x) => {
2117
- x.key === "Escape" && (x.preventDefault(), r("close"));
2569
+ let translateX = "-50%";
2570
+ let translateY = "-50%";
2571
+ if (props.draggable && windowDrag) {
2572
+ translateX = `calc(-50% + ${windowDrag.position.value.x}px)`;
2573
+ translateY = `calc(-50% + ${windowDrag.position.value.y}px)`;
2574
+ }
2575
+ baseStyle.transform = `translate(${translateX}, ${translateY})`;
2576
+ baseStyle.transformOrigin = "center center";
2577
+ if (isAutoSize.value) {
2578
+ if (props.resizable && windowResize && windowResize.width.value > 0) {
2579
+ baseStyle.width = `${windowResize.width.value}px`;
2580
+ baseStyle.height = `${windowResize.height.value}px`;
2581
+ }
2582
+ } else {
2583
+ if (props.resizable && windowResize) {
2584
+ baseStyle.width = `${windowResize.width.value}px`;
2585
+ baseStyle.height = `${windowResize.height.value}px`;
2586
+ } else {
2587
+ if (props.width !== "auto" && props.width !== "fit-content") {
2588
+ baseStyle.width = typeof props.width === "number" ? `${props.width}px` : props.width;
2589
+ }
2590
+ if (props.height !== "auto" && props.height !== "fit-content") {
2591
+ baseStyle.height = typeof props.height === "number" ? `${props.height}px` : props.height;
2592
+ }
2593
+ }
2594
+ }
2595
+ if (props.minWidth) {
2596
+ baseStyle.minWidth = typeof props.minWidth === "number" ? `${props.minWidth}px` : props.minWidth;
2597
+ }
2598
+ if (props.minHeight) {
2599
+ baseStyle.minHeight = typeof props.minHeight === "number" ? `${props.minHeight}px` : props.minHeight;
2600
+ }
2601
+ if (props.maxWidth) {
2602
+ baseStyle.maxWidth = typeof props.maxWidth === "number" ? `${props.maxWidth}px` : props.maxWidth;
2603
+ }
2604
+ if (props.maxHeight) {
2605
+ baseStyle.maxHeight = typeof props.maxHeight === "number" ? `${props.maxHeight}px` : props.maxHeight;
2606
+ }
2607
+ return baseStyle;
2608
+ });
2609
+ const handleBackdropClick = (e) => {
2610
+ if (props.closeOnBackdrop && e.target === e.currentTarget) {
2611
+ emit("close");
2612
+ }
2613
+ };
2614
+ const handleDragStart = (e) => {
2615
+ if (props.draggable && windowDrag) {
2616
+ windowDrag.startDrag(e);
2617
+ }
2618
+ };
2619
+ const handleClose = () => {
2620
+ emit("close");
2621
+ };
2622
+ const handleMinimize = () => {
2623
+ emit("minimize");
2624
+ };
2625
+ const handleMaximize = () => {
2626
+ emit("maximize");
2627
+ };
2628
+ const handleResizeStart = (e, direction) => {
2629
+ if (!props.resizable || !windowResize || !windowContainerRef.value) return;
2630
+ const rect = windowContainerRef.value.getBoundingClientRect();
2631
+ const currentWidth = rect.width;
2632
+ const currentHeight = rect.height;
2633
+ windowResize.startResize(e, direction, currentWidth, currentHeight);
2634
+ };
2635
+ onMounted(() => {
2636
+ const handleEsc = (e) => {
2637
+ if (e.key === "Escape") {
2638
+ e.preventDefault();
2639
+ emit("close");
2640
+ }
2118
2641
  };
2119
- window.addEventListener("keydown", o), ne(() => {
2120
- window.removeEventListener("keydown", o);
2642
+ window.addEventListener("keydown", handleEsc);
2643
+ onUnmounted(() => {
2644
+ window.removeEventListener("keydown", handleEsc);
2121
2645
  });
2122
- }), (o, x) => (a(), H(ie, { to: "body" }, [
2123
- s("div", {
2124
- class: "window-overlay",
2125
- onClick: S
2126
- }, [
2127
- s("div", {
2128
- ref_key: "windowContainerRef",
2129
- ref: l,
2130
- class: "window-container",
2131
- style: de(M.value),
2132
- onClick: x[8] || (x[8] = R(() => {
2133
- }, ["stop"]))
2646
+ });
2647
+ return (_ctx, _cache) => {
2648
+ return openBlock(), createBlock(Teleport, { to: "body" }, [
2649
+ createElementVNode("div", {
2650
+ class: "window-overlay",
2651
+ onClick: handleBackdropClick
2134
2652
  }, [
2135
- e.showTitleBar ? (a(), h("div", {
2136
- key: 0,
2137
- class: "window-title-bar draggable-area",
2138
- onMousedown: L
2653
+ createElementVNode("div", {
2654
+ ref_key: "windowContainerRef",
2655
+ ref: windowContainerRef,
2656
+ class: "window-container",
2657
+ style: normalizeStyle(windowStyle.value),
2658
+ onClick: _cache[8] || (_cache[8] = withModifiers(() => {
2659
+ }, ["stop"]))
2139
2660
  }, [
2140
- s("div", Wt, [
2141
- s("button", {
2142
- onClick: R($, ["stop"]),
2143
- class: "window-control-button window-control-button--close"
2144
- }, [
2145
- N(O(T), {
2146
- icon: "lucide:x",
2147
- width: "7",
2148
- height: "7",
2149
- class: "window-control-icon"
2150
- })
2661
+ __props.showTitleBar ? (openBlock(), createElementBlock("div", {
2662
+ key: 0,
2663
+ class: "window-title-bar draggable-area",
2664
+ onMousedown: handleDragStart
2665
+ }, [
2666
+ createElementVNode("div", _hoisted_1$3, [
2667
+ createElementVNode("button", {
2668
+ onClick: withModifiers(handleClose, ["stop"]),
2669
+ class: "window-control-button window-control-button--close"
2670
+ }, [
2671
+ createVNode(unref(Icon), {
2672
+ icon: "lucide:x",
2673
+ width: "7",
2674
+ height: "7",
2675
+ class: "window-control-icon"
2676
+ })
2677
+ ]),
2678
+ __props.showMinimize ? (openBlock(), createElementBlock("button", {
2679
+ key: 0,
2680
+ onClick: withModifiers(handleMinimize, ["stop"]),
2681
+ class: "window-control-button window-control-button--minimize"
2682
+ }, [
2683
+ createVNode(unref(Icon), {
2684
+ icon: "lucide:minus",
2685
+ width: "7",
2686
+ height: "7",
2687
+ class: "window-control-icon"
2688
+ })
2689
+ ])) : createCommentVNode("", true),
2690
+ __props.showMaximize ? (openBlock(), createElementBlock("button", {
2691
+ key: 1,
2692
+ onClick: withModifiers(handleMaximize, ["stop"]),
2693
+ class: "window-control-button window-control-button--maximize"
2694
+ }, [
2695
+ createVNode(unref(Icon), {
2696
+ icon: "lucide:maximize-2",
2697
+ width: "7",
2698
+ height: "7",
2699
+ class: "window-control-icon"
2700
+ })
2701
+ ])) : createCommentVNode("", true)
2151
2702
  ]),
2152
- e.showMinimize ? (a(), h("button", {
2153
- key: 0,
2154
- onClick: R(f, ["stop"]),
2155
- class: "window-control-button window-control-button--minimize"
2156
- }, [
2157
- N(O(T), {
2158
- icon: "lucide:minus",
2159
- width: "7",
2160
- height: "7",
2161
- class: "window-control-icon"
2162
- })
2163
- ])) : j("", !0),
2164
- e.showMaximize ? (a(), h("button", {
2165
- key: 1,
2166
- onClick: R(A, ["stop"]),
2167
- class: "window-control-button window-control-button--maximize"
2168
- }, [
2169
- N(O(T), {
2170
- icon: "lucide:maximize-2",
2171
- width: "7",
2172
- height: "7",
2173
- class: "window-control-icon"
2174
- })
2175
- ])) : j("", !0)
2176
- ]),
2177
- s("div", Rt, [
2178
- Z(o.$slots, "title", {}, () => [
2179
- s("span", Bt, z(e.title), 1)
2180
- ], !0)
2703
+ createElementVNode("div", _hoisted_2$3, [
2704
+ renderSlot(_ctx.$slots, "title", {}, () => [
2705
+ createElementVNode("span", _hoisted_3$3, toDisplayString(__props.title), 1)
2706
+ ], true)
2707
+ ]),
2708
+ createElementVNode("div", _hoisted_4$3, [
2709
+ renderSlot(_ctx.$slots, "actions", {}, void 0, true)
2710
+ ])
2711
+ ], 32)) : createCommentVNode("", true),
2712
+ createElementVNode("div", _hoisted_5$3, [
2713
+ renderSlot(_ctx.$slots, "default", {}, void 0, true)
2181
2714
  ]),
2182
- s("div", Ht, [
2183
- Z(o.$slots, "actions", {}, void 0, !0)
2184
- ])
2185
- ], 32)) : j("", !0),
2186
- s("div", Vt, [
2187
- Z(o.$slots, "default", {}, void 0, !0)
2188
- ]),
2189
- e.resizable ? (a(), h(G, { key: 1 }, [
2190
- s("div", {
2191
- class: "window-resize-handle window-resize-handle--n",
2192
- onMousedown: x[0] || (x[0] = (p) => U(p, "n"))
2193
- }, null, 32),
2194
- s("div", {
2195
- class: "window-resize-handle window-resize-handle--s",
2196
- onMousedown: x[1] || (x[1] = (p) => U(p, "s"))
2197
- }, null, 32),
2198
- s("div", {
2199
- class: "window-resize-handle window-resize-handle--e",
2200
- onMousedown: x[2] || (x[2] = (p) => U(p, "e"))
2201
- }, null, 32),
2202
- s("div", {
2203
- class: "window-resize-handle window-resize-handle--w",
2204
- onMousedown: x[3] || (x[3] = (p) => U(p, "w"))
2205
- }, null, 32),
2206
- s("div", {
2207
- class: "window-resize-handle window-resize-handle--ne",
2208
- onMousedown: x[4] || (x[4] = (p) => U(p, "ne"))
2209
- }, null, 32),
2210
- s("div", {
2211
- class: "window-resize-handle window-resize-handle--nw",
2212
- onMousedown: x[5] || (x[5] = (p) => U(p, "nw"))
2213
- }, null, 32),
2214
- s("div", {
2215
- class: "window-resize-handle window-resize-handle--se",
2216
- onMousedown: x[6] || (x[6] = (p) => U(p, "se"))
2217
- }, null, 32),
2218
- s("div", {
2219
- class: "window-resize-handle window-resize-handle--sw",
2220
- onMousedown: x[7] || (x[7] = (p) => U(p, "sw"))
2221
- }, null, 32)
2222
- ], 64)) : j("", !0)
2223
- ], 4)
2224
- ])
2225
- ]));
2715
+ __props.resizable ? (openBlock(), createElementBlock(Fragment, { key: 1 }, [
2716
+ createElementVNode("div", {
2717
+ class: "window-resize-handle window-resize-handle--n",
2718
+ onMousedown: _cache[0] || (_cache[0] = (e) => handleResizeStart(e, "n"))
2719
+ }, null, 32),
2720
+ createElementVNode("div", {
2721
+ class: "window-resize-handle window-resize-handle--s",
2722
+ onMousedown: _cache[1] || (_cache[1] = (e) => handleResizeStart(e, "s"))
2723
+ }, null, 32),
2724
+ createElementVNode("div", {
2725
+ class: "window-resize-handle window-resize-handle--e",
2726
+ onMousedown: _cache[2] || (_cache[2] = (e) => handleResizeStart(e, "e"))
2727
+ }, null, 32),
2728
+ createElementVNode("div", {
2729
+ class: "window-resize-handle window-resize-handle--w",
2730
+ onMousedown: _cache[3] || (_cache[3] = (e) => handleResizeStart(e, "w"))
2731
+ }, null, 32),
2732
+ createElementVNode("div", {
2733
+ class: "window-resize-handle window-resize-handle--ne",
2734
+ onMousedown: _cache[4] || (_cache[4] = (e) => handleResizeStart(e, "ne"))
2735
+ }, null, 32),
2736
+ createElementVNode("div", {
2737
+ class: "window-resize-handle window-resize-handle--nw",
2738
+ onMousedown: _cache[5] || (_cache[5] = (e) => handleResizeStart(e, "nw"))
2739
+ }, null, 32),
2740
+ createElementVNode("div", {
2741
+ class: "window-resize-handle window-resize-handle--se",
2742
+ onMousedown: _cache[6] || (_cache[6] = (e) => handleResizeStart(e, "se"))
2743
+ }, null, 32),
2744
+ createElementVNode("div", {
2745
+ class: "window-resize-handle window-resize-handle--sw",
2746
+ onMousedown: _cache[7] || (_cache[7] = (e) => handleResizeStart(e, "sw"))
2747
+ }, null, 32)
2748
+ ], 64)) : createCommentVNode("", true)
2749
+ ], 4)
2750
+ ])
2751
+ ]);
2752
+ };
2226
2753
  }
2227
- }), an = /* @__PURE__ */ K(_t, [["__scopeId", "data-v-19502782"]]), Gt = { class: "compress-dialog-header" }, qt = { class: "compress-dialog-title" }, Kt = { class: "compress-dialog-content" }, Xt = { class: "compress-dialog-info" }, Yt = { class: "compress-dialog-field" }, Jt = { class: "compress-dialog-input-group" }, Qt = { class: "compress-dialog-ext" }, Zt = { class: "compress-dialog-field" }, es = ["value"], ts = { class: "compress-dialog-field" }, ss = { class: "compress-dialog-levels" }, ns = ["value"], is = { class: "compress-dialog-level-label" }, os = { class: "compress-dialog-level-desc" }, ls = {
2754
+ });
2755
+ const Window = /* @__PURE__ */ _export_sfc(_sfc_main$3, [["__scopeId", "data-v-19502782"]]);
2756
+ const _hoisted_1$2 = { class: "compress-dialog-header" };
2757
+ const _hoisted_2$2 = { class: "compress-dialog-title" };
2758
+ const _hoisted_3$2 = { class: "compress-dialog-content" };
2759
+ const _hoisted_4$2 = { class: "compress-dialog-info" };
2760
+ const _hoisted_5$2 = { class: "compress-dialog-field" };
2761
+ const _hoisted_6$2 = { class: "compress-dialog-input-group" };
2762
+ const _hoisted_7$2 = { class: "compress-dialog-ext" };
2763
+ const _hoisted_8$2 = { class: "compress-dialog-field" };
2764
+ const _hoisted_9$2 = ["value"];
2765
+ const _hoisted_10$2 = { class: "compress-dialog-field" };
2766
+ const _hoisted_11$2 = { class: "compress-dialog-levels" };
2767
+ const _hoisted_12$2 = ["value"];
2768
+ const _hoisted_13$2 = { class: "compress-dialog-level-label" };
2769
+ const _hoisted_14$2 = { class: "compress-dialog-level-desc" };
2770
+ const _hoisted_15$2 = {
2228
2771
  key: 0,
2229
2772
  class: "compress-dialog-field"
2230
- }, as = { class: "compress-dialog-input-group" }, rs = ["type"], cs = { class: "compress-dialog-field compress-dialog-checkbox" }, ds = { class: "compress-dialog-preview" }, us = { class: "compress-dialog-preview-path" }, ms = { class: "compress-dialog-footer" }, gs = ["disabled"], ps = /* @__PURE__ */ q({
2773
+ };
2774
+ const _hoisted_16$1 = { class: "compress-dialog-input-group" };
2775
+ const _hoisted_17$1 = ["type"];
2776
+ const _hoisted_18$1 = { class: "compress-dialog-field compress-dialog-checkbox" };
2777
+ const _hoisted_19$1 = { class: "compress-dialog-preview" };
2778
+ const _hoisted_20$1 = { class: "compress-dialog-preview-path" };
2779
+ const _hoisted_21$1 = { class: "compress-dialog-footer" };
2780
+ const _hoisted_22 = ["disabled"];
2781
+ const _sfc_main$2 = /* @__PURE__ */ defineComponent({
2231
2782
  __name: "CompressDialog",
2232
2783
  props: {
2233
2784
  visible: { type: Boolean },
@@ -2235,193 +2786,256 @@ const Wt = { class: "window-controls" }, Rt = { class: "window-title-info" }, Bt
2235
2786
  outputDir: {}
2236
2787
  },
2237
2788
  emits: ["confirm", "cancel"],
2238
- setup(e, { emit: g }) {
2239
- const t = e, r = g, l = [
2789
+ setup(__props, { emit: __emit }) {
2790
+ const props = __props;
2791
+ const emit = __emit;
2792
+ const FORMAT_OPTIONS = [
2240
2793
  { value: "zip", label: "ZIP", ext: ".zip" },
2241
2794
  { value: "tgz", label: "TAR.GZ (gzip)", ext: ".tar.gz" },
2242
2795
  { value: "tarbz2", label: "TAR.BZ2 (bzip2)", ext: ".tar.bz2" },
2243
2796
  { value: "tar", label: "TAR (无压缩)", ext: ".tar" }
2244
- ], i = [
2797
+ ];
2798
+ const LEVEL_OPTIONS = [
2245
2799
  { value: "fast", label: "快速", desc: "压缩速度快,文件较大" },
2246
2800
  { value: "normal", label: "标准", desc: "平衡速度和大小" },
2247
2801
  { value: "best", label: "最佳", desc: "文件最小,速度较慢" }
2248
- ], w = D("zip"), I = D("normal"), m = D(""), v = D(!1), b = D(""), u = D(!1), n = F(() => t.filePaths.length === 0 ? "archive" : t.filePaths.length === 1 ? (t.filePaths[0].split("/").pop() || "archive").replace(/\.[^.]+$/, "") : "压缩文件"), C = F(() => t.filePaths.length === 1 ? t.filePaths[0].split("/").pop() : `${t.filePaths.length} 个项目`), c = F(() => {
2249
- var L;
2250
- return ((L = l.find(($) => $.value === w.value)) == null ? void 0 : L.ext) || ".zip";
2251
- }), y = F(() => `${t.outputDir}/${m.value}${c.value}`), M = F(() => !1);
2252
- ee(() => t.visible, (L) => {
2253
- L && (m.value = n.value, w.value = "zip", I.value = "normal", v.value = !1, b.value = "");
2802
+ ];
2803
+ const format = ref("zip");
2804
+ const level = ref("normal");
2805
+ const outputName = ref("");
2806
+ const deleteSource = ref(false);
2807
+ const password = ref("");
2808
+ const showPassword = ref(false);
2809
+ const defaultOutputName = computed(() => {
2810
+ if (props.filePaths.length === 0) return "archive";
2811
+ if (props.filePaths.length === 1) {
2812
+ const name = props.filePaths[0].split("/").pop() || "archive";
2813
+ return name.replace(/\.[^.]+$/, "");
2814
+ }
2815
+ return "压缩文件";
2816
+ });
2817
+ const fileDisplayName = computed(() => {
2818
+ if (props.filePaths.length === 1) {
2819
+ return props.filePaths[0].split("/").pop();
2820
+ }
2821
+ return `${props.filePaths.length} 个项目`;
2822
+ });
2823
+ const currentExt = computed(() => {
2824
+ var _a;
2825
+ return ((_a = FORMAT_OPTIONS.find((f) => f.value === format.value)) == null ? void 0 : _a.ext) || ".zip";
2826
+ });
2827
+ const fullOutputPath = computed(() => {
2828
+ return `${props.outputDir}/${outputName.value}${currentExt.value}`;
2829
+ });
2830
+ const supportsPassword = computed(() => {
2831
+ return false;
2832
+ });
2833
+ watch(() => props.visible, (visible) => {
2834
+ if (visible) {
2835
+ outputName.value = defaultOutputName.value;
2836
+ format.value = "zip";
2837
+ level.value = "normal";
2838
+ deleteSource.value = false;
2839
+ password.value = "";
2840
+ }
2254
2841
  });
2255
- const S = () => {
2256
- r("confirm", {
2257
- format: w.value,
2258
- level: I.value,
2259
- outputName: m.value + c.value,
2260
- deleteSource: v.value
2842
+ const handleConfirm = () => {
2843
+ emit("confirm", {
2844
+ format: format.value,
2845
+ level: level.value,
2846
+ outputName: outputName.value + currentExt.value,
2847
+ deleteSource: deleteSource.value
2261
2848
  });
2262
2849
  };
2263
- return (L, $) => (a(), H(ie, { to: "body" }, [
2264
- e.visible ? (a(), h("div", {
2265
- key: 0,
2266
- class: "compress-dialog-overlay",
2267
- onClick: $[9] || ($[9] = (f) => r("cancel"))
2268
- }, [
2269
- s("div", {
2270
- class: "compress-dialog",
2271
- onClick: $[8] || ($[8] = R(() => {
2272
- }, ["stop"]))
2850
+ return (_ctx, _cache) => {
2851
+ return openBlock(), createBlock(Teleport, { to: "body" }, [
2852
+ __props.visible ? (openBlock(), createElementBlock("div", {
2853
+ key: 0,
2854
+ class: "compress-dialog-overlay",
2855
+ onClick: _cache[9] || (_cache[9] = ($event) => emit("cancel"))
2273
2856
  }, [
2274
- s("div", Gt, [
2275
- s("div", qt, [
2276
- N(O(T), {
2277
- icon: "lucide:archive",
2278
- width: "20",
2279
- height: "20"
2280
- }),
2281
- $[10] || ($[10] = s("span", null, "压缩文件", -1))
2282
- ]),
2283
- s("button", {
2284
- class: "compress-dialog-close",
2285
- onClick: $[0] || ($[0] = (f) => r("cancel"))
2286
- }, [
2287
- N(O(T), {
2288
- icon: "lucide:x",
2289
- width: "18",
2290
- height: "18"
2291
- })
2292
- ])
2293
- ]),
2294
- s("div", Kt, [
2295
- s("div", Xt, [
2296
- N(O(T), {
2297
- icon: "lucide:file-archive",
2298
- width: "16",
2299
- height: "16"
2300
- }),
2301
- s("span", null, z(C.value), 1)
2302
- ]),
2303
- s("div", Yt, [
2304
- $[11] || ($[11] = s("label", null, "文件名", -1)),
2305
- s("div", Jt, [
2306
- te(s("input", {
2307
- type: "text",
2308
- "onUpdate:modelValue": $[1] || ($[1] = (f) => m.value = f),
2309
- placeholder: "输入文件名"
2310
- }, null, 512), [
2311
- [we, m.value]
2312
- ]),
2313
- s("span", Qt, z(c.value), 1)
2314
- ])
2315
- ]),
2316
- s("div", Zt, [
2317
- $[12] || ($[12] = s("label", null, "压缩格式", -1)),
2318
- te(s("select", {
2319
- "onUpdate:modelValue": $[2] || ($[2] = (f) => w.value = f)
2857
+ createElementVNode("div", {
2858
+ class: "compress-dialog",
2859
+ onClick: _cache[8] || (_cache[8] = withModifiers(() => {
2860
+ }, ["stop"]))
2861
+ }, [
2862
+ createElementVNode("div", _hoisted_1$2, [
2863
+ createElementVNode("div", _hoisted_2$2, [
2864
+ createVNode(unref(Icon), {
2865
+ icon: "lucide:archive",
2866
+ width: "20",
2867
+ height: "20"
2868
+ }),
2869
+ _cache[10] || (_cache[10] = createElementVNode("span", null, "压缩文件", -1))
2870
+ ]),
2871
+ createElementVNode("button", {
2872
+ class: "compress-dialog-close",
2873
+ onClick: _cache[0] || (_cache[0] = ($event) => emit("cancel"))
2320
2874
  }, [
2321
- (a(), h(G, null, J(l, (f) => s("option", {
2322
- key: f.value,
2323
- value: f.value
2324
- }, z(f.label), 9, es)), 64))
2325
- ], 512), [
2326
- [ye, w.value]
2875
+ createVNode(unref(Icon), {
2876
+ icon: "lucide:x",
2877
+ width: "18",
2878
+ height: "18"
2879
+ })
2327
2880
  ])
2328
2881
  ]),
2329
- s("div", ts, [
2330
- $[13] || ($[13] = s("label", null, "压缩级别", -1)),
2331
- s("div", ss, [
2332
- (a(), h(G, null, J(i, (f) => s("label", {
2333
- key: f.value,
2334
- class: "compress-dialog-level"
2882
+ createElementVNode("div", _hoisted_3$2, [
2883
+ createElementVNode("div", _hoisted_4$2, [
2884
+ createVNode(unref(Icon), {
2885
+ icon: "lucide:file-archive",
2886
+ width: "16",
2887
+ height: "16"
2888
+ }),
2889
+ createElementVNode("span", null, toDisplayString(fileDisplayName.value), 1)
2890
+ ]),
2891
+ createElementVNode("div", _hoisted_5$2, [
2892
+ _cache[11] || (_cache[11] = createElementVNode("label", null, "文件名", -1)),
2893
+ createElementVNode("div", _hoisted_6$2, [
2894
+ withDirectives(createElementVNode("input", {
2895
+ type: "text",
2896
+ "onUpdate:modelValue": _cache[1] || (_cache[1] = ($event) => outputName.value = $event),
2897
+ placeholder: "输入文件名"
2898
+ }, null, 512), [
2899
+ [vModelText, outputName.value]
2900
+ ]),
2901
+ createElementVNode("span", _hoisted_7$2, toDisplayString(currentExt.value), 1)
2902
+ ])
2903
+ ]),
2904
+ createElementVNode("div", _hoisted_8$2, [
2905
+ _cache[12] || (_cache[12] = createElementVNode("label", null, "压缩格式", -1)),
2906
+ withDirectives(createElementVNode("select", {
2907
+ "onUpdate:modelValue": _cache[2] || (_cache[2] = ($event) => format.value = $event)
2335
2908
  }, [
2336
- te(s("input", {
2337
- type: "radio",
2338
- name: "level",
2339
- value: f.value,
2340
- "onUpdate:modelValue": $[3] || ($[3] = (A) => I.value = A)
2341
- }, null, 8, ns), [
2342
- [ke, I.value]
2909
+ (openBlock(), createElementBlock(Fragment, null, renderList(FORMAT_OPTIONS, (opt) => {
2910
+ return createElementVNode("option", {
2911
+ key: opt.value,
2912
+ value: opt.value
2913
+ }, toDisplayString(opt.label), 9, _hoisted_9$2);
2914
+ }), 64))
2915
+ ], 512), [
2916
+ [vModelSelect, format.value]
2917
+ ])
2918
+ ]),
2919
+ createElementVNode("div", _hoisted_10$2, [
2920
+ _cache[13] || (_cache[13] = createElementVNode("label", null, "压缩级别", -1)),
2921
+ createElementVNode("div", _hoisted_11$2, [
2922
+ (openBlock(), createElementBlock(Fragment, null, renderList(LEVEL_OPTIONS, (opt) => {
2923
+ return createElementVNode("label", {
2924
+ key: opt.value,
2925
+ class: "compress-dialog-level"
2926
+ }, [
2927
+ withDirectives(createElementVNode("input", {
2928
+ type: "radio",
2929
+ name: "level",
2930
+ value: opt.value,
2931
+ "onUpdate:modelValue": _cache[3] || (_cache[3] = ($event) => level.value = $event)
2932
+ }, null, 8, _hoisted_12$2), [
2933
+ [vModelRadio, level.value]
2934
+ ]),
2935
+ createElementVNode("span", _hoisted_13$2, toDisplayString(opt.label), 1),
2936
+ createElementVNode("span", _hoisted_14$2, toDisplayString(opt.desc), 1)
2937
+ ]);
2938
+ }), 64))
2939
+ ])
2940
+ ]),
2941
+ supportsPassword.value ? (openBlock(), createElementBlock("div", _hoisted_15$2, [
2942
+ _cache[14] || (_cache[14] = createElementVNode("label", null, "密码保护(可选)", -1)),
2943
+ createElementVNode("div", _hoisted_16$1, [
2944
+ withDirectives(createElementVNode("input", {
2945
+ type: showPassword.value ? "text" : "password",
2946
+ "onUpdate:modelValue": _cache[4] || (_cache[4] = ($event) => password.value = $event),
2947
+ placeholder: "设置密码"
2948
+ }, null, 8, _hoisted_17$1), [
2949
+ [vModelDynamic, password.value]
2343
2950
  ]),
2344
- s("span", is, z(f.label), 1),
2345
- s("span", os, z(f.desc), 1)
2346
- ])), 64))
2347
- ])
2348
- ]),
2349
- M.value ? (a(), h("div", ls, [
2350
- $[14] || ($[14] = s("label", null, "密码保护(可选)", -1)),
2351
- s("div", as, [
2352
- te(s("input", {
2353
- type: u.value ? "text" : "password",
2354
- "onUpdate:modelValue": $[4] || ($[4] = (f) => b.value = f),
2355
- placeholder: "设置密码"
2356
- }, null, 8, rs), [
2357
- [xe, b.value]
2358
- ]),
2359
- s("button", {
2360
- type: "button",
2361
- class: "compress-dialog-toggle-password",
2362
- onClick: $[5] || ($[5] = (f) => u.value = !u.value)
2363
- }, z(u.value ? "隐藏" : "显示"), 1)
2364
- ])
2365
- ])) : j("", !0),
2366
- s("div", cs, [
2367
- s("label", null, [
2368
- te(s("input", {
2369
- type: "checkbox",
2370
- "onUpdate:modelValue": $[6] || ($[6] = (f) => v.value = f)
2371
- }, null, 512), [
2372
- [$e, v.value]
2373
- ]),
2374
- $[15] || ($[15] = s("span", null, "压缩后删除源文件", -1))
2951
+ createElementVNode("button", {
2952
+ type: "button",
2953
+ class: "compress-dialog-toggle-password",
2954
+ onClick: _cache[5] || (_cache[5] = ($event) => showPassword.value = !showPassword.value)
2955
+ }, toDisplayString(showPassword.value ? "隐藏" : "显示"), 1)
2956
+ ])
2957
+ ])) : createCommentVNode("", true),
2958
+ createElementVNode("div", _hoisted_18$1, [
2959
+ createElementVNode("label", null, [
2960
+ withDirectives(createElementVNode("input", {
2961
+ type: "checkbox",
2962
+ "onUpdate:modelValue": _cache[6] || (_cache[6] = ($event) => deleteSource.value = $event)
2963
+ }, null, 512), [
2964
+ [vModelCheckbox, deleteSource.value]
2965
+ ]),
2966
+ _cache[15] || (_cache[15] = createElementVNode("span", null, "压缩后删除源文件", -1))
2967
+ ])
2968
+ ]),
2969
+ createElementVNode("div", _hoisted_19$1, [
2970
+ _cache[16] || (_cache[16] = createElementVNode("span", { class: "compress-dialog-preview-label" }, "输出位置:", -1)),
2971
+ createElementVNode("span", _hoisted_20$1, toDisplayString(fullOutputPath.value), 1)
2375
2972
  ])
2376
2973
  ]),
2377
- s("div", ds, [
2378
- $[16] || ($[16] = s("span", { class: "compress-dialog-preview-label" }, "输出位置:", -1)),
2379
- s("span", us, z(y.value), 1)
2974
+ createElementVNode("div", _hoisted_21$1, [
2975
+ createElementVNode("button", {
2976
+ class: "compress-dialog-btn compress-dialog-btn-cancel",
2977
+ onClick: _cache[7] || (_cache[7] = ($event) => emit("cancel"))
2978
+ }, " 取消 "),
2979
+ createElementVNode("button", {
2980
+ class: "compress-dialog-btn compress-dialog-btn-confirm",
2981
+ onClick: handleConfirm,
2982
+ disabled: !outputName.value.trim()
2983
+ }, " 压缩 ", 8, _hoisted_22)
2380
2984
  ])
2381
- ]),
2382
- s("div", ms, [
2383
- s("button", {
2384
- class: "compress-dialog-btn compress-dialog-btn-cancel",
2385
- onClick: $[7] || ($[7] = (f) => r("cancel"))
2386
- }, " 取消 "),
2387
- s("button", {
2388
- class: "compress-dialog-btn compress-dialog-btn-confirm",
2389
- onClick: S,
2390
- disabled: !m.value.trim()
2391
- }, " 压缩 ", 8, gs)
2392
2985
  ])
2393
- ])
2394
- ])) : j("", !0)
2395
- ]));
2986
+ ])) : createCommentVNode("", true)
2987
+ ]);
2988
+ };
2396
2989
  }
2397
- }), rn = /* @__PURE__ */ K(ps, [["__scopeId", "data-v-1800ac01"]]), fs = {
2990
+ });
2991
+ const CompressDialog = /* @__PURE__ */ _export_sfc(_sfc_main$2, [["__scopeId", "data-v-1800ac01"]]);
2992
+ const _hoisted_1$1 = {
2398
2993
  key: 0,
2399
2994
  class: "progress-dialog-overlay"
2400
- }, vs = { class: "progress-dialog" }, hs = { class: "progress-dialog-header" }, bs = { class: "progress-dialog-title" }, ws = { class: "progress-dialog-content" }, ys = { class: "progress-dialog-status" }, ks = {
2995
+ };
2996
+ const _hoisted_2$1 = { class: "progress-dialog" };
2997
+ const _hoisted_3$1 = { class: "progress-dialog-header" };
2998
+ const _hoisted_4$1 = { class: "progress-dialog-title" };
2999
+ const _hoisted_5$1 = { class: "progress-dialog-content" };
3000
+ const _hoisted_6$1 = { class: "progress-dialog-status" };
3001
+ const _hoisted_7$1 = {
2401
3002
  key: 0,
2402
3003
  class: "progress-dialog-bar-container"
2403
- }, xs = { class: "progress-dialog-bar" }, $s = { class: "progress-dialog-percent" }, Cs = {
3004
+ };
3005
+ const _hoisted_8$1 = { class: "progress-dialog-bar" };
3006
+ const _hoisted_9$1 = { class: "progress-dialog-percent" };
3007
+ const _hoisted_10$1 = {
2404
3008
  key: 1,
2405
3009
  class: "progress-dialog-current-file"
2406
- }, Is = {
3010
+ };
3011
+ const _hoisted_11$1 = {
2407
3012
  key: 2,
2408
3013
  class: "progress-dialog-count"
2409
- }, Es = {
3014
+ };
3015
+ const _hoisted_12$1 = {
2410
3016
  key: 3,
2411
3017
  class: "progress-dialog-error"
2412
- }, Ms = {
3018
+ };
3019
+ const _hoisted_13$1 = {
2413
3020
  key: 4,
2414
3021
  class: "progress-dialog-output"
2415
- }, js = { class: "progress-dialog-output-path" }, Ds = { class: "progress-dialog-footer" }, zs = /* @__PURE__ */ q({
3022
+ };
3023
+ const _hoisted_14$1 = { class: "progress-dialog-output-path" };
3024
+ const _hoisted_15$1 = { class: "progress-dialog-footer" };
3025
+ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
2416
3026
  __name: "ProgressDialog",
2417
3027
  props: {
2418
3028
  visible: { type: Boolean },
2419
3029
  progress: {}
2420
3030
  },
2421
3031
  emits: ["cancel", "close", "openFolder"],
2422
- setup(e, { emit: g }) {
2423
- const t = e, r = g, l = F(() => t.progress.type === "compress" ? "压缩文件" : "解压文件"), i = F(() => t.progress.status === "success" || t.progress.status === "error"), w = F(() => {
2424
- switch (t.progress.status) {
3032
+ setup(__props, { emit: __emit }) {
3033
+ const props = __props;
3034
+ const emit = __emit;
3035
+ const title = computed(() => props.progress.type === "compress" ? "压缩文件" : "解压文件");
3036
+ const isCompleted = computed(() => props.progress.status === "success" || props.progress.status === "error");
3037
+ const statusIconName = computed(() => {
3038
+ switch (props.progress.status) {
2425
3039
  case "processing":
2426
3040
  return "lucide:loader-2";
2427
3041
  case "success":
@@ -2431,8 +3045,9 @@ const Wt = { class: "window-controls" }, Rt = { class: "window-title-info" }, Bt
2431
3045
  default:
2432
3046
  return "lucide:archive";
2433
3047
  }
2434
- }), I = F(() => {
2435
- switch (t.progress.status) {
3048
+ });
3049
+ const statusIconClass = computed(() => {
3050
+ switch (props.progress.status) {
2436
3051
  case "processing":
2437
3052
  return "progress-dialog-icon-spin";
2438
3053
  case "success":
@@ -2442,483 +3057,650 @@ const Wt = { class: "window-controls" }, Rt = { class: "window-title-info" }, Bt
2442
3057
  default:
2443
3058
  return "";
2444
3059
  }
2445
- }), m = F(() => {
2446
- switch (t.progress.status) {
3060
+ });
3061
+ const statusText = computed(() => {
3062
+ switch (props.progress.status) {
2447
3063
  case "pending":
2448
3064
  return "准备中...";
2449
3065
  case "processing":
2450
- return t.progress.type === "compress" ? "正在压缩..." : "正在解压...";
3066
+ return props.progress.type === "compress" ? "正在压缩..." : "正在解压...";
2451
3067
  case "success":
2452
- return t.progress.type === "compress" ? "压缩完成" : "解压完成";
3068
+ return props.progress.type === "compress" ? "压缩完成" : "解压完成";
2453
3069
  case "error":
2454
3070
  return "操作失败";
2455
3071
  default:
2456
3072
  return "";
2457
3073
  }
2458
- }), v = () => {
2459
- i.value ? r("close") : r("cancel");
2460
- };
2461
- return (b, u) => (a(), H(ie, { to: "body" }, [
2462
- e.visible ? (a(), h("div", fs, [
2463
- s("div", vs, [
2464
- s("div", hs, [
2465
- s("div", bs, [
2466
- N(O(T), {
2467
- icon: w.value,
2468
- width: "24",
2469
- height: "24",
2470
- class: B(I.value)
2471
- }, null, 8, ["icon", "class"]),
2472
- s("span", null, z(l.value), 1)
2473
- ]),
2474
- i.value ? (a(), h("button", {
2475
- key: 0,
2476
- class: "progress-dialog-close",
2477
- onClick: v
2478
- }, [
2479
- N(O(T), {
2480
- icon: "lucide:x",
2481
- width: "18",
2482
- height: "18"
2483
- })
2484
- ])) : j("", !0)
2485
- ]),
2486
- s("div", ws, [
2487
- s("div", ys, z(m.value), 1),
2488
- e.progress.status === "processing" ? (a(), h("div", ks, [
2489
- s("div", xs, [
2490
- s("div", {
2491
- class: "progress-dialog-bar-fill",
2492
- style: de({ width: `${e.progress.percent}%` })
2493
- }, null, 4)
3074
+ });
3075
+ const handleClose = () => {
3076
+ if (isCompleted.value) {
3077
+ emit("close");
3078
+ } else {
3079
+ emit("cancel");
3080
+ }
3081
+ };
3082
+ return (_ctx, _cache) => {
3083
+ return openBlock(), createBlock(Teleport, { to: "body" }, [
3084
+ __props.visible ? (openBlock(), createElementBlock("div", _hoisted_1$1, [
3085
+ createElementVNode("div", _hoisted_2$1, [
3086
+ createElementVNode("div", _hoisted_3$1, [
3087
+ createElementVNode("div", _hoisted_4$1, [
3088
+ createVNode(unref(Icon), {
3089
+ icon: statusIconName.value,
3090
+ width: "24",
3091
+ height: "24",
3092
+ class: normalizeClass(statusIconClass.value)
3093
+ }, null, 8, ["icon", "class"]),
3094
+ createElementVNode("span", null, toDisplayString(title.value), 1)
2494
3095
  ]),
2495
- s("span", $s, z(e.progress.percent) + "%", 1)
2496
- ])) : j("", !0),
2497
- e.progress.currentFile && e.progress.status === "processing" ? (a(), h("div", Cs, z(e.progress.currentFile), 1)) : j("", !0),
2498
- e.progress.totalCount && e.progress.totalCount > 0 && e.progress.status === "processing" ? (a(), h("div", Is, z(e.progress.processedCount || 0) + " / " + z(e.progress.totalCount) + " 个文件 ", 1)) : j("", !0),
2499
- e.progress.error ? (a(), h("div", Es, z(e.progress.error), 1)) : j("", !0),
2500
- e.progress.status === "success" && e.progress.outputPath ? (a(), h("div", Ms, [
2501
- u[2] || (u[2] = s("span", { class: "progress-dialog-output-label" }, "输出位置:", -1)),
2502
- s("span", js, z(e.progress.outputPath), 1)
2503
- ])) : j("", !0)
2504
- ]),
2505
- s("div", Ds, [
2506
- e.progress.status === "processing" ? (a(), h("button", {
2507
- key: 0,
2508
- class: "progress-dialog-btn progress-dialog-btn-cancel",
2509
- onClick: u[0] || (u[0] = (n) => r("cancel"))
2510
- }, " 取消 ")) : j("", !0),
2511
- e.progress.status === "success" && e.progress.outputPath ? (a(), h("button", {
2512
- key: 1,
2513
- class: "progress-dialog-btn progress-dialog-btn-folder",
2514
- onClick: u[1] || (u[1] = (n) => r("openFolder", e.progress.outputPath))
2515
- }, [
2516
- N(O(T), {
2517
- icon: "lucide:folder-open",
2518
- width: "16",
2519
- height: "16"
2520
- }),
2521
- u[3] || (u[3] = se(" 打开文件夹 ", -1))
2522
- ])) : j("", !0),
2523
- i.value ? (a(), h("button", {
2524
- key: 2,
2525
- class: "progress-dialog-btn progress-dialog-btn-close",
2526
- onClick: v
2527
- }, " 关闭 ")) : j("", !0)
3096
+ isCompleted.value ? (openBlock(), createElementBlock("button", {
3097
+ key: 0,
3098
+ class: "progress-dialog-close",
3099
+ onClick: handleClose
3100
+ }, [
3101
+ createVNode(unref(Icon), {
3102
+ icon: "lucide:x",
3103
+ width: "18",
3104
+ height: "18"
3105
+ })
3106
+ ])) : createCommentVNode("", true)
3107
+ ]),
3108
+ createElementVNode("div", _hoisted_5$1, [
3109
+ createElementVNode("div", _hoisted_6$1, toDisplayString(statusText.value), 1),
3110
+ __props.progress.status === "processing" ? (openBlock(), createElementBlock("div", _hoisted_7$1, [
3111
+ createElementVNode("div", _hoisted_8$1, [
3112
+ createElementVNode("div", {
3113
+ class: "progress-dialog-bar-fill",
3114
+ style: normalizeStyle({ width: `${__props.progress.percent}%` })
3115
+ }, null, 4)
3116
+ ]),
3117
+ createElementVNode("span", _hoisted_9$1, toDisplayString(__props.progress.percent) + "%", 1)
3118
+ ])) : createCommentVNode("", true),
3119
+ __props.progress.currentFile && __props.progress.status === "processing" ? (openBlock(), createElementBlock("div", _hoisted_10$1, toDisplayString(__props.progress.currentFile), 1)) : createCommentVNode("", true),
3120
+ __props.progress.totalCount && __props.progress.totalCount > 0 && __props.progress.status === "processing" ? (openBlock(), createElementBlock("div", _hoisted_11$1, toDisplayString(__props.progress.processedCount || 0) + " / " + toDisplayString(__props.progress.totalCount) + " 个文件 ", 1)) : createCommentVNode("", true),
3121
+ __props.progress.error ? (openBlock(), createElementBlock("div", _hoisted_12$1, toDisplayString(__props.progress.error), 1)) : createCommentVNode("", true),
3122
+ __props.progress.status === "success" && __props.progress.outputPath ? (openBlock(), createElementBlock("div", _hoisted_13$1, [
3123
+ _cache[2] || (_cache[2] = createElementVNode("span", { class: "progress-dialog-output-label" }, "输出位置:", -1)),
3124
+ createElementVNode("span", _hoisted_14$1, toDisplayString(__props.progress.outputPath), 1)
3125
+ ])) : createCommentVNode("", true)
3126
+ ]),
3127
+ createElementVNode("div", _hoisted_15$1, [
3128
+ __props.progress.status === "processing" ? (openBlock(), createElementBlock("button", {
3129
+ key: 0,
3130
+ class: "progress-dialog-btn progress-dialog-btn-cancel",
3131
+ onClick: _cache[0] || (_cache[0] = ($event) => emit("cancel"))
3132
+ }, " 取消 ")) : createCommentVNode("", true),
3133
+ __props.progress.status === "success" && __props.progress.outputPath ? (openBlock(), createElementBlock("button", {
3134
+ key: 1,
3135
+ class: "progress-dialog-btn progress-dialog-btn-folder",
3136
+ onClick: _cache[1] || (_cache[1] = ($event) => emit("openFolder", __props.progress.outputPath))
3137
+ }, [
3138
+ createVNode(unref(Icon), {
3139
+ icon: "lucide:folder-open",
3140
+ width: "16",
3141
+ height: "16"
3142
+ }),
3143
+ _cache[3] || (_cache[3] = createTextVNode(" 打开文件夹 ", -1))
3144
+ ])) : createCommentVNode("", true),
3145
+ isCompleted.value ? (openBlock(), createElementBlock("button", {
3146
+ key: 2,
3147
+ class: "progress-dialog-btn progress-dialog-btn-close",
3148
+ onClick: handleClose
3149
+ }, " 关闭 ")) : createCommentVNode("", true)
3150
+ ])
2528
3151
  ])
2529
- ])
2530
- ])) : j("", !0)
2531
- ]));
3152
+ ])) : createCommentVNode("", true)
3153
+ ]);
3154
+ };
2532
3155
  }
2533
- }), cn = /* @__PURE__ */ K(zs, [["__scopeId", "data-v-e07b95ae"]]), Ss = { class: "file-info-dialog" }, Os = { class: "file-info-dialog-header" }, Ls = { class: "file-info-dialog-title" }, Ts = ["title"], As = { class: "file-info-dialog-content" }, Ns = { class: "file-info-row" }, Ps = { class: "file-info-label" }, Us = { class: "file-info-value" }, Fs = {
3156
+ });
3157
+ const ProgressDialog = /* @__PURE__ */ _export_sfc(_sfc_main$1, [["__scopeId", "data-v-e07b95ae"]]);
3158
+ const _hoisted_1 = { class: "file-info-dialog" };
3159
+ const _hoisted_2 = { class: "file-info-dialog-header" };
3160
+ const _hoisted_3 = { class: "file-info-dialog-title" };
3161
+ const _hoisted_4 = ["title"];
3162
+ const _hoisted_5 = { class: "file-info-dialog-content" };
3163
+ const _hoisted_6 = { class: "file-info-row" };
3164
+ const _hoisted_7 = { class: "file-info-label" };
3165
+ const _hoisted_8 = { class: "file-info-value" };
3166
+ const _hoisted_9 = {
2534
3167
  key: 0,
2535
3168
  class: "file-info-row"
2536
- }, Ws = { class: "file-info-label" }, Rs = { class: "file-info-value" }, Bs = { class: "file-info-row" }, Hs = { class: "file-info-label" }, Vs = ["title"], _s = { class: "file-info-row" }, Gs = { class: "file-info-label" }, qs = ["title"], Ks = {
3169
+ };
3170
+ const _hoisted_10 = { class: "file-info-label" };
3171
+ const _hoisted_11 = { class: "file-info-value" };
3172
+ const _hoisted_12 = { class: "file-info-row" };
3173
+ const _hoisted_13 = { class: "file-info-label" };
3174
+ const _hoisted_14 = ["title"];
3175
+ const _hoisted_15 = { class: "file-info-row" };
3176
+ const _hoisted_16 = { class: "file-info-label" };
3177
+ const _hoisted_17 = ["title"];
3178
+ const _hoisted_18 = {
2537
3179
  key: 1,
2538
3180
  class: "file-info-row"
2539
- }, Xs = { class: "file-info-label" }, Ys = { class: "file-info-value" }, Js = { class: "file-info-dialog-footer" }, Qs = /* @__PURE__ */ q({
3181
+ };
3182
+ const _hoisted_19 = { class: "file-info-label" };
3183
+ const _hoisted_20 = { class: "file-info-value" };
3184
+ const _hoisted_21 = { class: "file-info-dialog-footer" };
3185
+ const _sfc_main = /* @__PURE__ */ defineComponent({
2540
3186
  __name: "FileInfoDialog",
2541
3187
  props: {
2542
3188
  visible: { type: Boolean },
2543
3189
  item: {}
2544
3190
  },
2545
3191
  emits: ["close"],
2546
- setup(e, { emit: g }) {
2547
- const t = e, r = g;
2548
- function l(u, n) {
2549
- if (u === d.FOLDER)
3192
+ setup(__props, { emit: __emit }) {
3193
+ const props = __props;
3194
+ const emit = __emit;
3195
+ function getFileIcon(type, name) {
3196
+ if (type === FileType.FOLDER) {
2550
3197
  return "ic:round-folder";
2551
- if (n)
2552
- return he(n, u);
2553
- switch (u) {
2554
- case d.IMAGE:
3198
+ }
3199
+ if (name) {
3200
+ return getFileTypeIcon(name, type);
3201
+ }
3202
+ switch (type) {
3203
+ case FileType.IMAGE:
2555
3204
  return "material-icon-theme:image";
2556
- case d.VIDEO:
3205
+ case FileType.VIDEO:
2557
3206
  return "material-icon-theme:video";
2558
- case d.MUSIC:
3207
+ case FileType.MUSIC:
2559
3208
  return "material-icon-theme:audio";
2560
- case d.DOCUMENT:
3209
+ case FileType.DOCUMENT:
2561
3210
  return "material-icon-theme:word";
2562
- case d.CODE:
3211
+ case FileType.CODE:
2563
3212
  return "material-icon-theme:javascript";
2564
- case d.ARCHIVE:
3213
+ case FileType.ARCHIVE:
2565
3214
  return "material-icon-theme:zip";
2566
3215
  default:
2567
3216
  return "material-icon-theme:document";
2568
3217
  }
2569
3218
  }
2570
- function i(u) {
2571
- switch (u) {
2572
- case d.FOLDER:
3219
+ function getIconClass(type) {
3220
+ switch (type) {
3221
+ case FileType.FOLDER:
2573
3222
  return "file-info-icon--folder";
2574
- case d.IMAGE:
3223
+ case FileType.IMAGE:
2575
3224
  return "file-info-icon--image";
2576
- case d.VIDEO:
3225
+ case FileType.VIDEO:
2577
3226
  return "file-info-icon--video";
2578
- case d.MUSIC:
3227
+ case FileType.MUSIC:
2579
3228
  return "file-info-icon--music";
2580
- case d.DOCUMENT:
3229
+ case FileType.DOCUMENT:
2581
3230
  return "file-info-icon--document";
2582
- case d.CODE:
3231
+ case FileType.CODE:
2583
3232
  return "file-info-icon--code";
2584
- case d.ARCHIVE:
3233
+ case FileType.ARCHIVE:
2585
3234
  return "file-info-icon--archive";
2586
3235
  default:
2587
3236
  return "file-info-icon--file";
2588
3237
  }
2589
3238
  }
2590
- function w(u, n) {
2591
- switch (u) {
2592
- case d.FOLDER:
3239
+ function getFileTypeName(type, ext) {
3240
+ switch (type) {
3241
+ case FileType.FOLDER:
2593
3242
  return "文件夹";
2594
- case d.IMAGE:
2595
- return `图片${n ? ` (${n.toUpperCase()})` : ""}`;
2596
- case d.VIDEO:
2597
- return `视频${n ? ` (${n.toUpperCase()})` : ""}`;
2598
- case d.MUSIC:
2599
- return `音频${n ? ` (${n.toUpperCase()})` : ""}`;
2600
- case d.DOCUMENT:
2601
- return `文档${n ? ` (${n.toUpperCase()})` : ""}`;
2602
- case d.CODE:
2603
- return `代码文件${n ? ` (${n.toUpperCase()})` : ""}`;
2604
- case d.ARCHIVE:
2605
- return `压缩包${n ? ` (${n.toUpperCase()})` : ""}`;
3243
+ case FileType.IMAGE:
3244
+ return `图片${ext ? ` (${ext.toUpperCase()})` : ""}`;
3245
+ case FileType.VIDEO:
3246
+ return `视频${ext ? ` (${ext.toUpperCase()})` : ""}`;
3247
+ case FileType.MUSIC:
3248
+ return `音频${ext ? ` (${ext.toUpperCase()})` : ""}`;
3249
+ case FileType.DOCUMENT:
3250
+ return `文档${ext ? ` (${ext.toUpperCase()})` : ""}`;
3251
+ case FileType.CODE:
3252
+ return `代码文件${ext ? ` (${ext.toUpperCase()})` : ""}`;
3253
+ case FileType.ARCHIVE:
3254
+ return `压缩包${ext ? ` (${ext.toUpperCase()})` : ""}`;
2606
3255
  default:
2607
- return n ? `${n.toUpperCase()} 文件` : "文件";
3256
+ return ext ? `${ext.toUpperCase()} 文件` : "文件";
2608
3257
  }
2609
3258
  }
2610
- const I = F(() => {
2611
- if (!t.item) return;
2612
- const u = t.item.name.lastIndexOf(".");
2613
- if (!(u === -1 || u === 0))
2614
- return t.item.name.substring(u + 1).toLowerCase();
2615
- }), m = F(() => {
2616
- if (!t.item) return "";
2617
- const u = t.item.id.lastIndexOf("/");
2618
- return u === -1 ? t.item.id : t.item.id.substring(0, u) || "/";
3259
+ const extension = computed(() => {
3260
+ if (!props.item) return void 0;
3261
+ const lastDot = props.item.name.lastIndexOf(".");
3262
+ if (lastDot === -1 || lastDot === 0) return void 0;
3263
+ return props.item.name.substring(lastDot + 1).toLowerCase();
3264
+ });
3265
+ const directory = computed(() => {
3266
+ if (!props.item) return "";
3267
+ const lastSlash = props.item.id.lastIndexOf("/");
3268
+ if (lastSlash === -1) return props.item.id;
3269
+ return props.item.id.substring(0, lastSlash) || "/";
2619
3270
  });
2620
- function v(u) {
2621
- u.target === u.currentTarget && r("close");
3271
+ function handleBackdropClick(e) {
3272
+ if (e.target === e.currentTarget) {
3273
+ emit("close");
3274
+ }
2622
3275
  }
2623
- function b(u) {
2624
- u.key === "Escape" && t.visible && r("close");
3276
+ function handleKeyDown(e) {
3277
+ if (e.key === "Escape" && props.visible) {
3278
+ emit("close");
3279
+ }
2625
3280
  }
2626
- return ve(() => {
2627
- document.addEventListener("keydown", b);
2628
- }), ne(() => {
2629
- document.removeEventListener("keydown", b);
2630
- }), (u, n) => (a(), H(ie, { to: "body" }, [
2631
- e.visible && e.item ? (a(), h("div", {
2632
- key: 0,
2633
- class: "file-info-dialog-overlay",
2634
- onClick: v
2635
- }, [
2636
- s("div", Ss, [
2637
- s("div", Os, [
2638
- s("div", Ls, [
2639
- N(O(T), {
2640
- icon: l(e.item.type, e.item.name),
2641
- width: "48",
2642
- height: "48",
2643
- class: B(["file-info-icon", i(e.item.type)])
2644
- }, null, 8, ["icon", "class"]),
2645
- s("span", {
2646
- class: "file-info-dialog-name",
2647
- title: e.item.name
2648
- }, z(e.item.name), 9, Ts)
2649
- ]),
2650
- s("button", {
2651
- class: "file-info-dialog-close",
2652
- onClick: n[0] || (n[0] = (C) => r("close"))
2653
- }, [
2654
- N(O(T), {
2655
- icon: "lucide:x",
2656
- width: "18",
2657
- height: "18"
2658
- })
2659
- ])
2660
- ]),
2661
- s("div", As, [
2662
- s("div", Ns, [
2663
- s("div", Ps, [
2664
- N(O(T), {
2665
- icon: "lucide:file",
2666
- width: "14",
2667
- height: "14"
2668
- }),
2669
- n[2] || (n[2] = s("span", null, "类型", -1))
3281
+ onMounted(() => {
3282
+ document.addEventListener("keydown", handleKeyDown);
3283
+ });
3284
+ onUnmounted(() => {
3285
+ document.removeEventListener("keydown", handleKeyDown);
3286
+ });
3287
+ return (_ctx, _cache) => {
3288
+ return openBlock(), createBlock(Teleport, { to: "body" }, [
3289
+ __props.visible && __props.item ? (openBlock(), createElementBlock("div", {
3290
+ key: 0,
3291
+ class: "file-info-dialog-overlay",
3292
+ onClick: handleBackdropClick
3293
+ }, [
3294
+ createElementVNode("div", _hoisted_1, [
3295
+ createElementVNode("div", _hoisted_2, [
3296
+ createElementVNode("div", _hoisted_3, [
3297
+ createVNode(unref(Icon), {
3298
+ icon: getFileIcon(__props.item.type, __props.item.name),
3299
+ width: "48",
3300
+ height: "48",
3301
+ class: normalizeClass(["file-info-icon", getIconClass(__props.item.type)])
3302
+ }, null, 8, ["icon", "class"]),
3303
+ createElementVNode("span", {
3304
+ class: "file-info-dialog-name",
3305
+ title: __props.item.name
3306
+ }, toDisplayString(__props.item.name), 9, _hoisted_4)
2670
3307
  ]),
2671
- s("div", Us, z(w(e.item.type, I.value)), 1)
3308
+ createElementVNode("button", {
3309
+ class: "file-info-dialog-close",
3310
+ onClick: _cache[0] || (_cache[0] = ($event) => emit("close"))
3311
+ }, [
3312
+ createVNode(unref(Icon), {
3313
+ icon: "lucide:x",
3314
+ width: "18",
3315
+ height: "18"
3316
+ })
3317
+ ])
2672
3318
  ]),
2673
- e.item.type !== O(d).FOLDER && e.item.size ? (a(), h("div", Fs, [
2674
- s("div", Ws, [
2675
- N(O(T), {
2676
- icon: "lucide:hard-drive",
2677
- width: "14",
2678
- height: "14"
2679
- }),
2680
- n[3] || (n[3] = s("span", null, "大小", -1))
3319
+ createElementVNode("div", _hoisted_5, [
3320
+ createElementVNode("div", _hoisted_6, [
3321
+ createElementVNode("div", _hoisted_7, [
3322
+ createVNode(unref(Icon), {
3323
+ icon: "lucide:file",
3324
+ width: "14",
3325
+ height: "14"
3326
+ }),
3327
+ _cache[2] || (_cache[2] = createElementVNode("span", null, "类型", -1))
3328
+ ]),
3329
+ createElementVNode("div", _hoisted_8, toDisplayString(getFileTypeName(__props.item.type, extension.value)), 1)
2681
3330
  ]),
2682
- s("div", Rs, z(e.item.size), 1)
2683
- ])) : j("", !0),
2684
- s("div", Bs, [
2685
- s("div", Hs, [
2686
- N(O(T), {
2687
- icon: "lucide:map-pin",
2688
- width: "14",
2689
- height: "14"
2690
- }),
2691
- n[4] || (n[4] = s("span", null, "位置", -1))
3331
+ __props.item.type !== unref(FileType).FOLDER && __props.item.size ? (openBlock(), createElementBlock("div", _hoisted_9, [
3332
+ createElementVNode("div", _hoisted_10, [
3333
+ createVNode(unref(Icon), {
3334
+ icon: "lucide:hard-drive",
3335
+ width: "14",
3336
+ height: "14"
3337
+ }),
3338
+ _cache[3] || (_cache[3] = createElementVNode("span", null, "大小", -1))
3339
+ ]),
3340
+ createElementVNode("div", _hoisted_11, toDisplayString(__props.item.size), 1)
3341
+ ])) : createCommentVNode("", true),
3342
+ createElementVNode("div", _hoisted_12, [
3343
+ createElementVNode("div", _hoisted_13, [
3344
+ createVNode(unref(Icon), {
3345
+ icon: "lucide:map-pin",
3346
+ width: "14",
3347
+ height: "14"
3348
+ }),
3349
+ _cache[4] || (_cache[4] = createElementVNode("span", null, "位置", -1))
3350
+ ]),
3351
+ createElementVNode("div", {
3352
+ class: "file-info-value file-info-value--path",
3353
+ title: directory.value
3354
+ }, toDisplayString(directory.value), 9, _hoisted_14)
2692
3355
  ]),
2693
- s("div", {
2694
- class: "file-info-value file-info-value--path",
2695
- title: m.value
2696
- }, z(m.value), 9, Vs)
2697
- ]),
2698
- s("div", _s, [
2699
- s("div", Gs, [
2700
- N(O(T), {
2701
- icon: "lucide:map-pin",
2702
- width: "14",
2703
- height: "14"
2704
- }),
2705
- n[5] || (n[5] = s("span", null, "完整路径", -1))
3356
+ createElementVNode("div", _hoisted_15, [
3357
+ createElementVNode("div", _hoisted_16, [
3358
+ createVNode(unref(Icon), {
3359
+ icon: "lucide:map-pin",
3360
+ width: "14",
3361
+ height: "14"
3362
+ }),
3363
+ _cache[5] || (_cache[5] = createElementVNode("span", null, "完整路径", -1))
3364
+ ]),
3365
+ createElementVNode("div", {
3366
+ class: "file-info-value file-info-value--path",
3367
+ title: __props.item.id
3368
+ }, toDisplayString(__props.item.id), 9, _hoisted_17)
2706
3369
  ]),
2707
- s("div", {
2708
- class: "file-info-value file-info-value--path",
2709
- title: e.item.id
2710
- }, z(e.item.id), 9, qs)
3370
+ __props.item.dateModified ? (openBlock(), createElementBlock("div", _hoisted_18, [
3371
+ createElementVNode("div", _hoisted_19, [
3372
+ createVNode(unref(Icon), {
3373
+ icon: "lucide:clock",
3374
+ width: "14",
3375
+ height: "14"
3376
+ }),
3377
+ _cache[6] || (_cache[6] = createElementVNode("span", null, "修改时间", -1))
3378
+ ]),
3379
+ createElementVNode("div", _hoisted_20, toDisplayString(__props.item.dateModified), 1)
3380
+ ])) : createCommentVNode("", true)
2711
3381
  ]),
2712
- e.item.dateModified ? (a(), h("div", Ks, [
2713
- s("div", Xs, [
2714
- N(O(T), {
2715
- icon: "lucide:clock",
2716
- width: "14",
2717
- height: "14"
2718
- }),
2719
- n[6] || (n[6] = s("span", null, "修改时间", -1))
2720
- ]),
2721
- s("div", Ys, z(e.item.dateModified), 1)
2722
- ])) : j("", !0)
2723
- ]),
2724
- s("div", Js, [
2725
- s("button", {
2726
- class: "file-info-dialog-btn",
2727
- onClick: n[1] || (n[1] = (C) => r("close"))
2728
- }, " 关闭 ")
3382
+ createElementVNode("div", _hoisted_21, [
3383
+ createElementVNode("button", {
3384
+ class: "file-info-dialog-btn",
3385
+ onClick: _cache[1] || (_cache[1] = ($event) => emit("close"))
3386
+ }, " 关闭 ")
3387
+ ])
2729
3388
  ])
2730
- ])
2731
- ])) : j("", !0)
2732
- ]));
3389
+ ])) : createCommentVNode("", true)
3390
+ ]);
3391
+ };
2733
3392
  }
2734
- }), dn = /* @__PURE__ */ K(Qs, [["__scopeId", "data-v-f8297fdd"]]);
2735
- function un() {
2736
- const e = D(/* @__PURE__ */ new Set()), g = D(null), t = D(null), r = () => {
2737
- e.value = /* @__PURE__ */ new Set(), g.value = null;
3393
+ });
3394
+ const FileInfoDialog = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-f8297fdd"]]);
3395
+ function useSelection() {
3396
+ const selectedIds = ref(/* @__PURE__ */ new Set());
3397
+ const lastSelectedId = ref(null);
3398
+ const editingId = ref(null);
3399
+ const clearSelection = () => {
3400
+ selectedIds.value = /* @__PURE__ */ new Set();
3401
+ lastSelectedId.value = null;
2738
3402
  };
2739
- return {
2740
- selectedIds: e,
2741
- lastSelectedId: g,
2742
- editingId: t,
2743
- clearSelection: r,
2744
- selectItem: (m, v, b = !1, u = !1) => {
2745
- if (!m) {
2746
- r();
2747
- return;
2748
- }
2749
- if (u && g.value) {
2750
- const n = v.findIndex((c) => c.id === g.value), C = v.findIndex((c) => c.id === m);
2751
- if (n !== -1 && C !== -1) {
2752
- const c = Math.min(n, C), y = Math.max(n, C), M = new Set(b ? e.value : []);
2753
- for (let S = c; S <= y; S++) {
2754
- const L = v[S];
2755
- L && M.add(L.id);
3403
+ const selectItem = (id, items, multi = false, range = false) => {
3404
+ if (!id) {
3405
+ clearSelection();
3406
+ return;
3407
+ }
3408
+ if (range && lastSelectedId.value) {
3409
+ const indexA = items.findIndex((i) => i.id === lastSelectedId.value);
3410
+ const indexB = items.findIndex((i) => i.id === id);
3411
+ if (indexA !== -1 && indexB !== -1) {
3412
+ const start = Math.min(indexA, indexB);
3413
+ const end = Math.max(indexA, indexB);
3414
+ const newSet = new Set(multi ? selectedIds.value : []);
3415
+ for (let i = start; i <= end; i++) {
3416
+ const item = items[i];
3417
+ if (item) {
3418
+ newSet.add(item.id);
2756
3419
  }
2757
- e.value = M;
2758
- return;
2759
3420
  }
2760
- }
2761
- if (b) {
2762
- const n = new Set(e.value);
2763
- n.has(m) ? n.delete(m) : n.add(m), g.value = m, e.value = n;
3421
+ selectedIds.value = newSet;
2764
3422
  return;
2765
3423
  }
2766
- g.value = m, e.value = /* @__PURE__ */ new Set([m]);
2767
- },
2768
- selectAll: (m) => {
2769
- e.value = new Set(m.map((v) => v.id));
2770
- },
2771
- setEditing: (m) => {
2772
- t.value = m;
2773
- },
2774
- isSelected: (m) => e.value.has(m)
3424
+ }
3425
+ if (multi) {
3426
+ const newSet = new Set(selectedIds.value);
3427
+ if (newSet.has(id)) {
3428
+ newSet.delete(id);
3429
+ } else {
3430
+ newSet.add(id);
3431
+ }
3432
+ lastSelectedId.value = id;
3433
+ selectedIds.value = newSet;
3434
+ return;
3435
+ }
3436
+ lastSelectedId.value = id;
3437
+ selectedIds.value = /* @__PURE__ */ new Set([id]);
3438
+ };
3439
+ const selectAll = (items) => {
3440
+ selectedIds.value = new Set(items.map((i) => i.id));
3441
+ };
3442
+ const setEditing = (id) => {
3443
+ editingId.value = id;
3444
+ };
3445
+ const isSelected = (id) => {
3446
+ return selectedIds.value.has(id);
2775
3447
  };
2776
- }
2777
- function mn(e, g, t) {
2778
- const r = D(null), l = D(!1);
2779
3448
  return {
2780
- dragOverId: r,
2781
- isDragging: l,
2782
- handleDragStart: (b, u) => {
2783
- if (!b.dataTransfer) return;
2784
- const n = e();
2785
- n.has(u) || g(u, !1, !1);
2786
- const C = n.has(u) ? n : /* @__PURE__ */ new Set([u]);
2787
- b.dataTransfer.setData("text/plain", JSON.stringify([...C])), b.dataTransfer.effectAllowed = "move", l.value = !0;
2788
- },
2789
- handleDragOver: (b, u) => {
2790
- l.value && u.type === d.FOLDER && (e().has(u.id) || (b.preventDefault(), r.value = u.id));
2791
- },
2792
- handleDragLeave: () => {
2793
- r.value = null;
2794
- },
2795
- handleDrop: (b, u) => {
2796
- if (r.value = null, l.value = !1, !b.dataTransfer || u.type !== d.FOLDER) return;
2797
- const n = b.dataTransfer.getData("text/plain");
2798
- if (n)
2799
- try {
2800
- const C = JSON.parse(n), c = new Set(C);
2801
- if (c.has(u.id)) return;
2802
- t(u.id, c);
2803
- } catch {
2804
- }
2805
- },
2806
- handleDragEnd: () => {
2807
- r.value = null, l.value = !1;
2808
- }
3449
+ selectedIds,
3450
+ lastSelectedId,
3451
+ editingId,
3452
+ clearSelection,
3453
+ selectItem,
3454
+ selectAll,
3455
+ setEditing,
3456
+ isSelected
2809
3457
  };
2810
3458
  }
2811
- function gn(e, g) {
2812
- const t = D(!1), r = D(0), l = D(0), i = D(0), w = D(!1), I = D(1), m = D(1), v = D(!1), b = e === d.MUSIC, u = () => {
2813
- const f = g();
2814
- if (f) {
2815
- const A = f.currentTime, U = f.duration;
2816
- l.value = A, U && !isNaN(U) && (i.value = U, r.value = A / U * 100);
3459
+ function useDragAndDrop(getSelectedIds, onSelect, onMove) {
3460
+ const dragOverId = ref(null);
3461
+ const isDragging = ref(false);
3462
+ const handleDragStart = (e, itemId) => {
3463
+ if (!e.dataTransfer) return;
3464
+ const selectedIds = getSelectedIds();
3465
+ if (!selectedIds.has(itemId)) {
3466
+ onSelect(itemId, false, false);
3467
+ }
3468
+ const draggedIds = selectedIds.has(itemId) ? selectedIds : /* @__PURE__ */ new Set([itemId]);
3469
+ e.dataTransfer.setData("text/plain", JSON.stringify([...draggedIds]));
3470
+ e.dataTransfer.effectAllowed = "move";
3471
+ isDragging.value = true;
3472
+ };
3473
+ const handleDragOver = (e, item) => {
3474
+ if (!isDragging.value) return;
3475
+ if (item.type === FileType.FOLDER) {
3476
+ const selectedIds = getSelectedIds();
3477
+ if (!selectedIds.has(item.id)) {
3478
+ e.preventDefault();
3479
+ dragOverId.value = item.id;
3480
+ }
3481
+ }
3482
+ };
3483
+ const handleDragLeave = () => {
3484
+ dragOverId.value = null;
3485
+ };
3486
+ const handleDrop = (e, targetItem) => {
3487
+ dragOverId.value = null;
3488
+ isDragging.value = false;
3489
+ if (!e.dataTransfer || targetItem.type !== FileType.FOLDER) return;
3490
+ const data = e.dataTransfer.getData("text/plain");
3491
+ if (!data) return;
3492
+ try {
3493
+ const draggedIds = JSON.parse(data);
3494
+ const itemIds = new Set(draggedIds);
3495
+ if (itemIds.has(targetItem.id)) return;
3496
+ onMove(targetItem.id, itemIds);
3497
+ } catch {
2817
3498
  }
2818
3499
  };
3500
+ const handleDragEnd = () => {
3501
+ dragOverId.value = null;
3502
+ isDragging.value = false;
3503
+ };
2819
3504
  return {
2820
- isPlaying: t,
2821
- progress: r,
2822
- currentTime: l,
2823
- duration: i,
2824
- isMuted: w,
2825
- volume: I,
2826
- showControls: v,
2827
- isAudio: b,
2828
- togglePlay: () => {
2829
- const f = g();
2830
- f && (t.value ? (f.pause(), t.value = !1) : (f.play(), t.value = !0));
2831
- },
2832
- toggleMute: () => {
2833
- const f = g();
2834
- if (f)
2835
- if (w.value) {
2836
- const A = m.value || 1;
2837
- f.volume = A, f.muted = !1, I.value = A, w.value = !1;
2838
- } else
2839
- m.value = I.value, f.volume = 0, f.muted = !0, I.value = 0, w.value = !0;
2840
- },
2841
- handleVolumeChange: (f) => {
2842
- I.value = f;
2843
- const A = g();
2844
- A && (A.volume = f, f === 0 ? (w.value = !0, A.muted = !0) : (w.value = !1, A.muted = !1));
2845
- },
2846
- seekTo: (f) => {
2847
- const A = g();
2848
- A && i.value && (A.currentTime = f, l.value = f, r.value = f / i.value * 100);
2849
- },
2850
- formatTime: (f) => {
2851
- if (isNaN(f)) return "0:00";
2852
- const A = Math.floor(f / 60), U = Math.floor(f % 60);
2853
- return `${A}:${U.toString().padStart(2, "0")}`;
2854
- },
2855
- autoPlay: () => {
2856
- fe(() => {
2857
- const f = g();
2858
- (e === d.VIDEO || b) && f && (f.volume = I.value, f.play().catch(() => {
2859
- }), t.value = !0);
3505
+ dragOverId,
3506
+ isDragging,
3507
+ handleDragStart,
3508
+ handleDragOver,
3509
+ handleDragLeave,
3510
+ handleDrop,
3511
+ handleDragEnd
3512
+ };
3513
+ }
3514
+ function useMediaPlayer(mediaType, mediaRef) {
3515
+ const isPlaying = ref(false);
3516
+ const progress = ref(0);
3517
+ const currentTime = ref(0);
3518
+ const duration = ref(0);
3519
+ const isMuted = ref(false);
3520
+ const volume = ref(1);
3521
+ const lastVolume = ref(1);
3522
+ const showControls = ref(false);
3523
+ const isAudio = mediaType === FileType.MUSIC;
3524
+ const updateProgress = () => {
3525
+ const media = mediaRef();
3526
+ if (media) {
3527
+ const curr = media.currentTime;
3528
+ const dur = media.duration;
3529
+ currentTime.value = curr;
3530
+ if (dur && !isNaN(dur)) {
3531
+ duration.value = dur;
3532
+ progress.value = curr / dur * 100;
3533
+ }
3534
+ }
3535
+ };
3536
+ const togglePlay = () => {
3537
+ const media = mediaRef();
3538
+ if (media) {
3539
+ if (isPlaying.value) {
3540
+ media.pause();
3541
+ isPlaying.value = false;
3542
+ } else {
3543
+ media.play();
3544
+ isPlaying.value = true;
3545
+ }
3546
+ }
3547
+ };
3548
+ const toggleMute = () => {
3549
+ const media = mediaRef();
3550
+ if (media) {
3551
+ if (isMuted.value) {
3552
+ const volToRestore = lastVolume.value || 1;
3553
+ media.volume = volToRestore;
3554
+ media.muted = false;
3555
+ volume.value = volToRestore;
3556
+ isMuted.value = false;
3557
+ } else {
3558
+ lastVolume.value = volume.value;
3559
+ media.volume = 0;
3560
+ media.muted = true;
3561
+ volume.value = 0;
3562
+ isMuted.value = true;
3563
+ }
3564
+ }
3565
+ };
3566
+ const handleVolumeChange = (val) => {
3567
+ volume.value = val;
3568
+ const media = mediaRef();
3569
+ if (media) {
3570
+ media.volume = val;
3571
+ if (val === 0) {
3572
+ isMuted.value = true;
3573
+ media.muted = true;
3574
+ } else {
3575
+ isMuted.value = false;
3576
+ media.muted = false;
3577
+ }
3578
+ }
3579
+ };
3580
+ const seekTo = (time) => {
3581
+ const media = mediaRef();
3582
+ if (media && duration.value) {
3583
+ media.currentTime = time;
3584
+ currentTime.value = time;
3585
+ progress.value = time / duration.value * 100;
3586
+ }
3587
+ };
3588
+ const formatTime = (time) => {
3589
+ if (isNaN(time)) return "0:00";
3590
+ const minutes = Math.floor(time / 60);
3591
+ const seconds = Math.floor(time % 60);
3592
+ return `${minutes}:${seconds.toString().padStart(2, "0")}`;
3593
+ };
3594
+ const autoPlay = () => {
3595
+ nextTick(() => {
3596
+ const media = mediaRef();
3597
+ if ((mediaType === FileType.VIDEO || isAudio) && media) {
3598
+ media.volume = volume.value;
3599
+ media.play().catch(() => {
3600
+ });
3601
+ isPlaying.value = true;
3602
+ }
3603
+ });
3604
+ };
3605
+ const setupMediaListeners = () => {
3606
+ const media = mediaRef();
3607
+ if (media) {
3608
+ media.addEventListener("timeupdate", updateProgress);
3609
+ media.addEventListener("loadedmetadata", updateProgress);
3610
+ media.addEventListener("ended", () => {
3611
+ isPlaying.value = false;
2860
3612
  });
2861
- },
2862
- setupMediaListeners: () => {
2863
- const f = g();
2864
- f && (f.addEventListener("timeupdate", u), f.addEventListener("loadedmetadata", u), f.addEventListener("ended", () => {
2865
- t.value = !1;
2866
- }));
2867
- },
2868
- cleanupMediaListeners: () => {
2869
- const f = g();
2870
- f && (f.removeEventListener("timeupdate", u), f.removeEventListener("loadedmetadata", u));
2871
- },
2872
- updateProgress: u
3613
+ }
3614
+ };
3615
+ const cleanupMediaListeners = () => {
3616
+ const media = mediaRef();
3617
+ if (media) {
3618
+ media.removeEventListener("timeupdate", updateProgress);
3619
+ media.removeEventListener("loadedmetadata", updateProgress);
3620
+ }
3621
+ };
3622
+ return {
3623
+ isPlaying,
3624
+ progress,
3625
+ currentTime,
3626
+ duration,
3627
+ isMuted,
3628
+ volume,
3629
+ showControls,
3630
+ isAudio,
3631
+ togglePlay,
3632
+ toggleMute,
3633
+ handleVolumeChange,
3634
+ seekTo,
3635
+ formatTime,
3636
+ autoPlay,
3637
+ setupMediaListeners,
3638
+ cleanupMediaListeners,
3639
+ updateProgress
2873
3640
  };
2874
3641
  }
2875
- function pn(e) {
2876
- const g = /* @__PURE__ */ new Map(), t = D(/* @__PURE__ */ new Map()), r = async (i) => {
2877
- if (!(i.type !== d.APPLICATION || !i.id)) {
2878
- if (g.has(i.id)) {
2879
- const w = g.get(i.id);
2880
- w && t.value.set(i.id, w);
2881
- return;
3642
+ function useApplicationIcon(items) {
3643
+ const appIconCache = /* @__PURE__ */ new Map();
3644
+ const appIconUrls = ref(/* @__PURE__ */ new Map());
3645
+ const loadApplicationIcon = async (item) => {
3646
+ if (item.type !== FileType.APPLICATION || !item.id) return;
3647
+ if (appIconCache.has(item.id)) {
3648
+ const cachedUrl = appIconCache.get(item.id);
3649
+ if (cachedUrl) {
3650
+ appIconUrls.value.set(item.id, cachedUrl);
2882
3651
  }
2883
- if (!t.value.has(i.id) && typeof window.fileExplorerAPI < "u" && window.fileExplorerAPI.getApplicationIcon)
2884
- try {
2885
- const w = await window.fileExplorerAPI.getApplicationIcon(i.id);
2886
- w && (g.set(i.id, w), t.value.set(i.id, w));
2887
- } catch (w) {
2888
- console.error(`Failed to load application icon for ${i.name}:`, w);
3652
+ return;
3653
+ }
3654
+ if (appIconUrls.value.has(item.id)) {
3655
+ return;
3656
+ }
3657
+ if (typeof window.fileExplorerAPI !== "undefined" && window.fileExplorerAPI.getApplicationIcon) {
3658
+ try {
3659
+ const iconUrl = await window.fileExplorerAPI.getApplicationIcon(item.id);
3660
+ if (iconUrl) {
3661
+ appIconCache.set(item.id, iconUrl);
3662
+ appIconUrls.value.set(item.id, iconUrl);
2889
3663
  }
3664
+ } catch (error) {
3665
+ console.error(`Failed to load application icon for ${item.name}:`, error);
3666
+ }
2890
3667
  }
2891
3668
  };
2892
- return ee(e, (i) => {
2893
- i.forEach((w) => {
2894
- w.type === d.APPLICATION && !t.value.has(w.id) && r(w);
3669
+ watch(items, (newItems) => {
3670
+ newItems.forEach((item) => {
3671
+ if (item.type === FileType.APPLICATION && !appIconUrls.value.has(item.id)) {
3672
+ loadApplicationIcon(item);
3673
+ }
2895
3674
  });
2896
- }, { immediate: !0, deep: !0 }), {
2897
- getAppIconUrl: (i) => t.value.get(i.id),
2898
- loadApplicationIcon: r
3675
+ }, { immediate: true, deep: true });
3676
+ const getAppIconUrl = (item) => {
3677
+ return appIconUrls.value.get(item.id);
3678
+ };
3679
+ return {
3680
+ getAppIconUrl,
3681
+ loadApplicationIcon
2899
3682
  };
2900
3683
  }
2901
3684
  export {
2902
- ut as Breadcrumb,
2903
- rn as CompressDialog,
2904
- ln as ContextMenu,
2905
- Be as FileGrid,
2906
- be as FileIcon,
2907
- dn as FileInfoDialog,
2908
- Ze as FileList,
2909
- tn as FileListView,
2910
- sn as FileSidebar,
2911
- d as FileType,
2912
- cn as ProgressDialog,
2913
- ae as SortIndicator,
2914
- on as StatusBar,
2915
- nn as Toolbar,
2916
- an as Window,
2917
- pn as useApplicationIcon,
2918
- mn as useDragAndDrop,
2919
- gn as useMediaPlayer,
2920
- un as useSelection,
2921
- Ut as useWindowDrag,
2922
- Ft as useWindowResize
3685
+ Breadcrumb,
3686
+ CompressDialog,
3687
+ ContextMenu,
3688
+ FileGrid,
3689
+ FileIcon,
3690
+ FileInfoDialog,
3691
+ FileList,
3692
+ FileListView,
3693
+ FileSidebar,
3694
+ FileType,
3695
+ ProgressDialog,
3696
+ SortIndicator,
3697
+ StatusBar,
3698
+ Toolbar,
3699
+ Window,
3700
+ useApplicationIcon,
3701
+ useDragAndDrop,
3702
+ useMediaPlayer,
3703
+ useSelection,
3704
+ useWindowDrag,
3705
+ useWindowResize
2923
3706
  };
2924
- //# sourceMappingURL=index.js.map