@tutti-os/workspace-file-manager 0.0.12 → 0.0.14

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.d.ts CHANGED
@@ -1,7 +1,7 @@
1
- import { y as WorkspaceFileOpenWithApplication, b as WorkspaceFileEntry, w as WorkspaceFileManagerSession } from './fileKinds-CMKjSrBx.js';
2
- export { C as CreateWorkspaceFileManagerSessionInput, W as WorkspaceFileActivationTarget, a as WorkspaceFileDirectoryListing, c as WorkspaceFileEntryKind, d as WorkspaceFileImportConflict, e as WorkspaceFileImportSummary, f as WorkspaceFileImportSummaryReason, g as WorkspaceFileImportSummaryReasonCount, h as WorkspaceFileManagerCapabilities, i as WorkspaceFileManagerFileActivationRequest, j as WorkspaceFileManagerHost, k as WorkspaceFileManagerHostActionMessage, l as WorkspaceFileManagerHostActionMessageStatus, m as WorkspaceFileManagerHostActionResult, n as WorkspaceFileManagerHostExportResult, o as WorkspaceFileManagerHostFallbackAction, p as WorkspaceFileManagerHostFallbackActionKind, q as WorkspaceFileManagerHostFileActivationResult, r as WorkspaceFileManagerHostImportConflict, s as WorkspaceFileManagerHostImportResult, t as WorkspaceFileManagerMutationErrorMessage, u as WorkspaceFileManagerPersistedState, v as WorkspaceFileManagerService, x as WorkspaceFileManagerState, z as WorkspaceFilePreviewKind, A as WorkspaceFilePreviewState, B as WorkspaceFileSearchEntry, D as WorkspaceFileSearchResult, E as classifyWorkspaceFilePreviewKind, F as createWorkspaceFileManagerService, G as resolveWorkspaceFileActivationTarget } from './fileKinds-CMKjSrBx.js';
3
- import { a as WorkspaceFileManagerI18nRuntime } from './index-CppyxTLd.js';
4
- export { W as WorkspaceFileManagerI18nKey, c as createWorkspaceFileManagerI18nRuntime, w as workspaceFileManagerI18nNamespace, b as workspaceFileManagerI18nResources } from './index-CppyxTLd.js';
1
+ import { y as WorkspaceFileOpenWithApplication, b as WorkspaceFileEntry, w as WorkspaceFileManagerSession } from './fileKinds-DxnVJkSm.js';
2
+ export { C as CreateWorkspaceFileManagerSessionInput, W as WorkspaceFileActivationTarget, a as WorkspaceFileDirectoryListing, c as WorkspaceFileEntryKind, d as WorkspaceFileImportConflict, e as WorkspaceFileImportSummary, f as WorkspaceFileImportSummaryReason, g as WorkspaceFileImportSummaryReasonCount, h as WorkspaceFileManagerCapabilities, i as WorkspaceFileManagerFileActivationRequest, j as WorkspaceFileManagerHost, k as WorkspaceFileManagerHostActionMessage, l as WorkspaceFileManagerHostActionMessageStatus, m as WorkspaceFileManagerHostActionResult, n as WorkspaceFileManagerHostExportResult, o as WorkspaceFileManagerHostFallbackAction, p as WorkspaceFileManagerHostFallbackActionKind, q as WorkspaceFileManagerHostFileActivationResult, r as WorkspaceFileManagerHostImportConflict, s as WorkspaceFileManagerHostImportResult, t as WorkspaceFileManagerMutationErrorMessage, u as WorkspaceFileManagerPersistedState, v as WorkspaceFileManagerService, x as WorkspaceFileManagerState, z as WorkspaceFilePreviewKind, A as WorkspaceFilePreviewState, B as WorkspaceFileSearchEntry, D as WorkspaceFileSearchResult, E as classifyWorkspaceFilePreviewKind, F as createWorkspaceFileManagerService, G as resolveWorkspaceFileActivationTarget } from './fileKinds-DxnVJkSm.js';
3
+ import { a as WorkspaceFileManagerI18nRuntime } from './index-BMBoznj4.js';
4
+ export { W as WorkspaceFileManagerI18nKey, c as createWorkspaceFileManagerI18nRuntime, w as workspaceFileManagerI18nNamespace, b as workspaceFileManagerI18nResources } from './index-BMBoznj4.js';
5
5
  import { ReactElement } from 'react';
6
6
  import { TuttiDateLocale } from '@tutti-os/ui-system/date-format';
7
7
  export { decodeWorkspaceTextFile, isWorkspaceTextFileTooLarge, looksLikeBinaryText, resolveWorkspaceFileExtension, resolveWorkspaceImageMimeType, workspaceFilePreviewMaxBytes, workspaceFileTextMaxBytes } from '@tutti-os/workspace-file-preview';
package/dist/index.js CHANGED
@@ -10,23 +10,28 @@ import {
10
10
  isWorkspaceTextFileTooLarge,
11
11
  looksLikeBinaryText,
12
12
  normalizeWorkspaceFilePath,
13
+ readWorkspaceFileManagerArrangeMode,
13
14
  resolveWorkspaceFileActivationTarget,
15
+ resolveWorkspaceFileEntryArrangeDateMs,
14
16
  resolveWorkspaceFileEntryIconCacheKey,
15
17
  resolveWorkspaceFileExtension,
16
18
  resolveWorkspaceFileVisualKind,
17
19
  resolveWorkspaceImageMimeType,
18
20
  shouldResolveWorkspaceFileEntryIcon,
21
+ shouldUseWorkspaceFileArchiveIcon,
19
22
  shouldUseWorkspaceFileExtensionDocumentIcon,
23
+ sortWorkspaceFileEntriesForArrangeMode,
20
24
  splitWorkspaceFileName,
21
25
  workspaceFilePreviewMaxBytes,
22
- workspaceFileTextMaxBytes
23
- } from "./chunk-CSFEGRX7.js";
26
+ workspaceFileTextMaxBytes,
27
+ writeWorkspaceFileManagerArrangeMode
28
+ } from "./chunk-5C34NYLK.js";
24
29
  import {
25
30
  createWorkspaceFileManagerI18nRuntime,
26
31
  resolveRevealInFolderLabel,
27
32
  workspaceFileManagerI18nNamespace,
28
33
  workspaceFileManagerI18nResources
29
- } from "./chunk-L6SAJEFE.js";
34
+ } from "./chunk-MDBT2GS5.js";
30
35
 
31
36
  // src/ui/WorkspaceFileManager.tsx
32
37
  import { useEffect as useEffect5, useMemo as useMemo2, useRef as useRef5, useState as useState7 } from "react";
@@ -900,8 +905,6 @@ function importSummaryReasonCopyKey(reason) {
900
905
  import {
901
906
  FileCodeIcon as FileCodeIcon2,
902
907
  FileTextIcon as FileTextIcon2,
903
- FolderFilledIcon as FolderFilledIcon2,
904
- ImageFileIcon as ImageFileIcon2,
905
908
  LoadingIcon as LoadingIcon2,
906
909
  ScrollArea,
907
910
  VideoFileIcon as VideoFileIcon2,
@@ -924,20 +927,31 @@ import { useLayoutEffect as useLayoutEffect2, useRef as useRef3 } from "react";
924
927
  import {
925
928
  FileCodeIcon,
926
929
  FileTextIcon,
927
- FolderFilledIcon,
928
- ImageFileIcon,
929
930
  LoadingIcon,
930
931
  VideoFileIcon,
931
932
  cn as cn2
932
933
  } from "@tutti-os/ui-system";
933
934
  import { useEffect as useEffect2, useRef as useRef2 } from "react";
934
935
  import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
936
+ var workspaceArchiveFallbackIconUrl = new URL(
937
+ "../assets/workspace-archive-fallback.png",
938
+ import.meta.url
939
+ ).toString();
940
+ var workspaceFolderFallbackIconUrl = new URL(
941
+ "../assets/workspace-folder-fallback.png",
942
+ import.meta.url
943
+ ).toString();
944
+ var workspaceImageFallbackIconUrl = new URL(
945
+ "../assets/workspace-image-fallback.png",
946
+ import.meta.url
947
+ ).toString();
935
948
  function WorkspaceFileEntryIcon({
936
949
  entry,
937
950
  frameClassName,
938
951
  iconClassName = "size-4",
939
952
  iconUrlByCacheKey,
940
953
  isEnteringDirectory = false,
954
+ loadingIconClassName,
941
955
  onViewportLeave,
942
956
  onViewportEnter
943
957
  }) {
@@ -1016,13 +1030,18 @@ function WorkspaceFileEntryIcon({
1016
1030
  frameClassName,
1017
1031
  isEnteringDirectory ? "text-[var(--text-tertiary)]" : entryIconColorClassName(visualKind, isAppBundle)
1018
1032
  ),
1019
- children: isEnteringDirectory ? /* @__PURE__ */ jsx2(LoadingIcon, { className: iconClassName + " animate-spin" }) : iconUrl ? /* @__PURE__ */ jsx2(
1033
+ children: isEnteringDirectory ? /* @__PURE__ */ jsx2(
1034
+ LoadingIcon,
1035
+ {
1036
+ className: cn2(loadingIconClassName ?? iconClassName, "animate-spin")
1037
+ }
1038
+ ) : iconUrl ? /* @__PURE__ */ jsx2(
1020
1039
  "img",
1021
1040
  {
1022
1041
  alt: "",
1023
1042
  className: cn2(
1024
1043
  iconClassName,
1025
- visualKind === "image" ? "rounded-[6px] border border-[var(--border-1)] bg-[var(--transparency-block)] object-contain shadow-sm" : "rounded-[4px] object-contain"
1044
+ visualKind === "image" ? "rounded-[6px] border border-[var(--border-1)] bg-[var(--transparency-block)] object-contain" : "rounded-[4px] object-contain"
1026
1045
  ),
1027
1046
  decoding: "async",
1028
1047
  draggable: false,
@@ -1058,30 +1077,88 @@ function DefaultEntryIcon({
1058
1077
  iconClassName,
1059
1078
  visualKind
1060
1079
  }) {
1080
+ const vectorIconClassName = vectorFallbackIconClassName(iconClassName);
1061
1081
  if (isWorkspaceApplicationBundle(entry)) {
1062
- return /* @__PURE__ */ jsx2(FileTextIcon, { className: iconClassName });
1082
+ return /* @__PURE__ */ jsx2(FileTextIcon, { className: vectorIconClassName });
1083
+ }
1084
+ if (shouldUseWorkspaceFileArchiveIcon(entry)) {
1085
+ return /* @__PURE__ */ jsx2(WorkspaceArchiveFallbackIcon, { className: iconClassName });
1063
1086
  }
1064
1087
  if (shouldUseWorkspaceFileExtensionDocumentIcon(entry)) {
1065
- return /* @__PURE__ */ jsx2(ExtensionDocumentIcon, { entry, iconClassName });
1088
+ return /* @__PURE__ */ jsx2(
1089
+ ExtensionDocumentIcon,
1090
+ {
1091
+ entry,
1092
+ iconClassName: vectorIconClassName
1093
+ }
1094
+ );
1066
1095
  }
1067
1096
  switch (visualKind) {
1068
1097
  case "directory":
1069
- return /* @__PURE__ */ jsx2(FolderFilledIcon, { className: iconClassName });
1098
+ return /* @__PURE__ */ jsx2(WorkspaceFolderFallbackIcon, { className: iconClassName });
1070
1099
  case "image":
1071
- return /* @__PURE__ */ jsx2(ImageFileIcon, { className: iconClassName });
1100
+ return /* @__PURE__ */ jsx2(WorkspaceImageFallbackIcon, { className: iconClassName });
1072
1101
  case "video":
1073
- return /* @__PURE__ */ jsx2(VideoFileIcon, { className: iconClassName });
1102
+ return /* @__PURE__ */ jsx2(VideoFileIcon, { className: vectorIconClassName });
1074
1103
  case "markdown":
1075
1104
  case "document":
1076
- return /* @__PURE__ */ jsx2(FileTextIcon, { className: iconClassName });
1105
+ return /* @__PURE__ */ jsx2(FileTextIcon, { className: vectorIconClassName });
1077
1106
  case "code":
1078
- return /* @__PURE__ */ jsx2(FileCodeIcon, { className: iconClassName });
1107
+ return /* @__PURE__ */ jsx2(FileCodeIcon, { className: vectorIconClassName });
1079
1108
  case "binary":
1080
- return /* @__PURE__ */ jsx2(FileTextIcon, { className: iconClassName });
1109
+ return /* @__PURE__ */ jsx2(FileTextIcon, { className: vectorIconClassName });
1081
1110
  default:
1082
- return /* @__PURE__ */ jsx2(FileTextIcon, { className: iconClassName });
1111
+ return /* @__PURE__ */ jsx2(FileTextIcon, { className: vectorIconClassName });
1083
1112
  }
1084
1113
  }
1114
+ function vectorFallbackIconClassName(iconClassName) {
1115
+ return iconClassName.includes("size-[84px]") ? "size-[64px]" : iconClassName;
1116
+ }
1117
+ function WorkspaceFolderFallbackIcon({
1118
+ className
1119
+ }) {
1120
+ return /* @__PURE__ */ jsx2(
1121
+ "img",
1122
+ {
1123
+ alt: "",
1124
+ "aria-hidden": "true",
1125
+ className: cn2("object-contain", className),
1126
+ decoding: "async",
1127
+ draggable: false,
1128
+ src: workspaceFolderFallbackIconUrl
1129
+ }
1130
+ );
1131
+ }
1132
+ function WorkspaceArchiveFallbackIcon({
1133
+ className
1134
+ }) {
1135
+ return /* @__PURE__ */ jsx2(
1136
+ "img",
1137
+ {
1138
+ alt: "",
1139
+ "aria-hidden": "true",
1140
+ className: cn2("object-contain", className),
1141
+ decoding: "async",
1142
+ draggable: false,
1143
+ src: workspaceArchiveFallbackIconUrl
1144
+ }
1145
+ );
1146
+ }
1147
+ function WorkspaceImageFallbackIcon({
1148
+ className
1149
+ }) {
1150
+ return /* @__PURE__ */ jsx2(
1151
+ "img",
1152
+ {
1153
+ alt: "",
1154
+ "aria-hidden": "true",
1155
+ className: cn2("object-contain", className),
1156
+ decoding: "async",
1157
+ draggable: false,
1158
+ src: workspaceImageFallbackIconUrl
1159
+ }
1160
+ );
1161
+ }
1085
1162
  function ExtensionDocumentIcon({
1086
1163
  entry,
1087
1164
  iconClassName
@@ -1094,8 +1171,8 @@ function ExtensionDocumentIcon({
1094
1171
  "aria-hidden": "true",
1095
1172
  className: cn2("relative inline-block overflow-visible", iconClassName),
1096
1173
  children: [
1097
- /* @__PURE__ */ jsx2("span", { className: "absolute inset-[5%] rounded-[6px] border border-black/10 bg-linear-to-br from-white via-[#f8f8f8] to-[#ececec] shadow-[0_8px_16px_rgba(0,0,0,0.18),inset_0_1px_0_rgba(255,255,255,0.85)]" }),
1098
- /* @__PURE__ */ jsx2("span", { className: "absolute top-[5%] right-[5%] h-[28%] w-[28%] overflow-hidden rounded-tr-[6px]", children: /* @__PURE__ */ jsx2("span", { className: "absolute top-0 right-0 h-full w-full origin-top-right -skew-x-3 rounded-bl-[4px] border-b border-l border-black/10 bg-linear-to-br from-white to-[#d9d9d9] shadow-[-2px_3px_5px_rgba(0,0,0,0.18)]" }) }),
1174
+ /* @__PURE__ */ jsx2("span", { className: "absolute inset-[5%] rounded-[6px] border border-black/10 bg-linear-to-br from-white via-[#f8f8f8] to-[#ececec]" }),
1175
+ /* @__PURE__ */ jsx2("span", { className: "absolute top-[5%] right-[5%] h-[28%] w-[28%] overflow-hidden rounded-tr-[6px]", children: /* @__PURE__ */ jsx2("span", { className: "absolute top-0 right-0 h-full w-full origin-top-right -skew-x-3 rounded-bl-[4px] border-b border-l border-black/10 bg-linear-to-br from-white to-[#d9d9d9]" }) }),
1099
1176
  showExtension ? /* @__PURE__ */ jsx2("span", { className: "absolute right-[12%] bottom-[14%] left-[12%] truncate text-center text-[10px] leading-none font-semibold tracking-wide text-[#7a7a7a]", children: extension }) : null
1100
1177
  ]
1101
1178
  }
@@ -1239,6 +1316,7 @@ function WorkspaceFileManagerIconTile({
1239
1316
  iconClassName: workspaceFileManagerIconGridIconClassName(),
1240
1317
  iconUrlByCacheKey,
1241
1318
  isEnteringDirectory,
1319
+ loadingIconClassName: "size-7",
1242
1320
  onViewportLeave: onEntryIconViewportLeave,
1243
1321
  onViewportEnter: onEntryIconViewportEnter
1244
1322
  }
@@ -1335,7 +1413,7 @@ function IconTileRenameInput({
1335
1413
  "aria-invalid": inlineRenameValidation !== null,
1336
1414
  "aria-label": copy.t("renameLabel"),
1337
1415
  className: cn3(
1338
- "w-full min-w-0 rounded-md border border-transparent bg-[var(--transparency-block)] px-1 py-0.5 text-center text-xs text-[var(--text-primary)] outline-none",
1416
+ "w-full min-w-0 rounded-[4px] border border-transparent bg-[var(--transparency-block)] px-1 py-0.5 text-center text-xs text-[var(--text-primary)] outline-none",
1339
1417
  inlineRenameValidation !== null && "border-[var(--state-danger)]"
1340
1418
  ),
1341
1419
  defaultValue: entry.name,
@@ -1364,124 +1442,6 @@ function IconTileRenameInput({
1364
1442
  ] });
1365
1443
  }
1366
1444
 
1367
- // src/ui/workspaceFileManagerArrangeMode.ts
1368
- var workspaceFileManagerArrangeModeStorageKey = "tutti.workspace-file-manager.arrange-mode";
1369
- var workspaceFileManagerArrangeModes = /* @__PURE__ */ new Set([
1370
- "none",
1371
- "name",
1372
- "kind",
1373
- "application",
1374
- "lastOpened",
1375
- "dateAdded",
1376
- "modified",
1377
- "created",
1378
- "size",
1379
- "tags"
1380
- ]);
1381
- function readWorkspaceFileManagerArrangeMode() {
1382
- if (typeof window === "undefined") {
1383
- return "none";
1384
- }
1385
- const stored = window.localStorage.getItem(
1386
- workspaceFileManagerArrangeModeStorageKey
1387
- );
1388
- return isWorkspaceFileManagerArrangeMode(stored) ? stored : "none";
1389
- }
1390
- function writeWorkspaceFileManagerArrangeMode(arrangeMode) {
1391
- if (typeof window === "undefined") {
1392
- return;
1393
- }
1394
- window.localStorage.setItem(
1395
- workspaceFileManagerArrangeModeStorageKey,
1396
- arrangeMode
1397
- );
1398
- }
1399
- function sortWorkspaceFileEntriesForArrangeMode(entries, arrangeMode) {
1400
- if (arrangeMode === "none") {
1401
- return entries;
1402
- }
1403
- return [...entries].sort((left, right) => {
1404
- switch (arrangeMode) {
1405
- case "name":
1406
- return compareDirectoryFirst(left, right) || compareEntryName(left, right);
1407
- case "kind":
1408
- return compareDirectoryFirst(left, right) || compareText(
1409
- resolveEntryKindGroup(left),
1410
- resolveEntryKindGroup(right)
1411
- ) || compareEntryName(left, right);
1412
- case "application":
1413
- return compareDirectoryFirst(left, right) || compareText(
1414
- resolveEntryApplicationGroup(left),
1415
- resolveEntryApplicationGroup(right)
1416
- ) || compareEntryName(left, right);
1417
- case "lastOpened":
1418
- return compareDateDescending(left, right, "lastOpened") || compareEntryName(left, right);
1419
- case "dateAdded":
1420
- return compareDateDescending(left, right, "dateAdded") || compareEntryName(left, right);
1421
- case "modified":
1422
- return compareDateDescending(left, right, "modified") || compareEntryName(left, right);
1423
- case "created":
1424
- return compareDateDescending(left, right, "created") || compareEntryName(left, right);
1425
- case "size":
1426
- return compareSizeDescending(left, right) || compareEntryName(left, right);
1427
- case "tags":
1428
- return compareDirectoryFirst(left, right) || compareEntryName(left, right);
1429
- }
1430
- });
1431
- }
1432
- function isWorkspaceFileManagerArrangeMode(value) {
1433
- return workspaceFileManagerArrangeModes.has(
1434
- value
1435
- );
1436
- }
1437
- function compareDirectoryFirst(left, right) {
1438
- const leftRank = left.kind === "directory" ? 0 : 1;
1439
- const rightRank = right.kind === "directory" ? 0 : 1;
1440
- return leftRank - rightRank;
1441
- }
1442
- function compareEntryName(left, right) {
1443
- return compareText(left.name, right.name);
1444
- }
1445
- function compareText(left, right) {
1446
- return left.localeCompare(right, void 0, {
1447
- numeric: true,
1448
- sensitivity: "base"
1449
- });
1450
- }
1451
- function resolveWorkspaceFileEntryArrangeDateMs(entry, arrangeMode) {
1452
- switch (arrangeMode) {
1453
- case "lastOpened":
1454
- return entry.lastOpenedMs ?? entry.mtimeMs;
1455
- case "dateAdded":
1456
- case "created":
1457
- return entry.createdTimeMs ?? entry.mtimeMs;
1458
- case "modified":
1459
- default:
1460
- return entry.mtimeMs;
1461
- }
1462
- }
1463
- function compareDateDescending(left, right, arrangeMode) {
1464
- return (resolveWorkspaceFileEntryArrangeDateMs(right, arrangeMode) ?? 0) - (resolveWorkspaceFileEntryArrangeDateMs(left, arrangeMode) ?? 0);
1465
- }
1466
- function compareSizeDescending(left, right) {
1467
- return (right.sizeBytes ?? 0) - (left.sizeBytes ?? 0);
1468
- }
1469
- function resolveEntryKindGroup(entry) {
1470
- if (entry.kind === "directory") {
1471
- return "directory";
1472
- }
1473
- return resolveWorkspaceFileVisualKind(entry);
1474
- }
1475
- function resolveEntryApplicationGroup(entry) {
1476
- if (entry.kind === "directory") {
1477
- return "folder";
1478
- }
1479
- if (entry.name.trim().toLowerCase().endsWith(".app")) {
1480
- return "application";
1481
- }
1482
- return resolveWorkspaceFileExtension(entry.name) || resolveEntryKindGroup(entry);
1483
- }
1484
-
1485
1445
  // src/ui/WorkspaceFileManagerPanels.tsx
1486
1446
  import { Fragment as Fragment2, jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
1487
1447
  var workspaceFileManagerTableGridClassName = "grid-cols-[minmax(0,_1fr)_148px_96px]";
@@ -2393,9 +2353,9 @@ function EntryIcon({
2393
2353
  }) {
2394
2354
  switch (visualKind) {
2395
2355
  case "directory":
2396
- return /* @__PURE__ */ jsx4(FolderFilledIcon2, { className });
2356
+ return /* @__PURE__ */ jsx4(WorkspaceFolderFallbackIcon, { className });
2397
2357
  case "image":
2398
- return /* @__PURE__ */ jsx4(ImageFileIcon2, { className });
2358
+ return /* @__PURE__ */ jsx4(WorkspaceImageFallbackIcon, { className });
2399
2359
  case "video":
2400
2360
  return /* @__PURE__ */ jsx4(VideoFileIcon2, { className });
2401
2361
  case "markdown":
@@ -2638,8 +2598,7 @@ function LayoutModeToggle({
2638
2598
  { label: copy.t("arrangeDateAddedLabel"), mode: "dateAdded" },
2639
2599
  { label: copy.t("modifiedLabel"), mode: "modified" },
2640
2600
  { label: copy.t("arrangeCreatedLabel"), mode: "created" },
2641
- { label: copy.t("sizeLabel"), mode: "size" },
2642
- { label: copy.t("arrangeTagsLabel"), mode: "tags" }
2601
+ { label: copy.t("sizeLabel"), mode: "size" }
2643
2602
  ];
2644
2603
  return /* @__PURE__ */ jsx5(TooltipProvider, { delayDuration: 300, children: /* @__PURE__ */ jsxs5(
2645
2604
  "div",