@lijian-ui/dsh-file-manager 0.2.3 → 0.2.4

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.
Files changed (96) hide show
  1. package/LICENSE +38 -38
  2. package/README.i18n.yaml +6 -6
  3. package/README.md +66 -66
  4. package/README.zh.md +66 -66
  5. package/cordis.patch.yml +13 -13
  6. package/lib/client.js +27305 -270
  7. package/lib/client.js.map +1 -1
  8. package/lib/index.js +474 -42
  9. package/lib/tsconfig.client.tsbuildinfo +1 -1
  10. package/lib/tsconfig.host.tsbuildinfo +1 -1
  11. package/lib/types/client/file-source.d.ts +10 -0
  12. package/lib/types/client/file-source.d.ts.map +1 -1
  13. package/lib/types/client/fileType.d.ts +19 -4
  14. package/lib/types/client/fileType.d.ts.map +1 -1
  15. package/lib/types/client/index.d.ts.map +1 -1
  16. package/lib/types/client/locales.d.ts +3 -0
  17. package/lib/types/client/locales.d.ts.map +1 -1
  18. package/lib/types/client/mount.d.ts +1 -1
  19. package/lib/types/client/mount.d.ts.map +1 -1
  20. package/lib/types/client/preview/PreviewPanel.d.ts +2 -1
  21. package/lib/types/client/preview/PreviewPanel.d.ts.map +1 -1
  22. package/lib/types/client/preview/PreviewToolbar.d.ts +3 -1
  23. package/lib/types/client/preview/PreviewToolbar.d.ts.map +1 -1
  24. package/lib/types/client/preview/content.d.ts +3 -1
  25. package/lib/types/client/preview/content.d.ts.map +1 -1
  26. package/lib/types/client/preview/office.d.ts +23 -0
  27. package/lib/types/client/preview/office.d.ts.map +1 -0
  28. package/lib/types/client/reference.d.ts +17 -0
  29. package/lib/types/client/reference.d.ts.map +1 -1
  30. package/lib/types/client/store.d.ts.map +1 -1
  31. package/lib/types/host/fs-service.d.ts.map +1 -1
  32. package/lib/types/host/office-preview.d.ts +13 -0
  33. package/lib/types/host/office-preview.d.ts.map +1 -0
  34. package/lib/types/host/routes.d.ts.map +1 -1
  35. package/lib/types/index.d.ts.map +1 -1
  36. package/package.json +19 -4
  37. package/src/client/FileManagerSettingsCard.tsx +117 -117
  38. package/src/client/PluginSettingsCard.tsx +337 -337
  39. package/src/client/chat/file-ref.ts +144 -144
  40. package/src/client/chat/mermaid-chat.tsx +102 -102
  41. package/src/client/chat/placeholder-hint.tsx +46 -46
  42. package/src/client/components/ExplorerPanel.tsx +534 -534
  43. package/src/client/components/FileIcon.tsx +46 -46
  44. package/src/client/components/ScmPanel.tsx +480 -480
  45. package/src/client/components/a11y.ts +20 -20
  46. package/src/client/components/icons.tsx +274 -274
  47. package/src/client/components/overlay.tsx +225 -225
  48. package/src/client/drag/DragFileInlay.tsx +89 -89
  49. package/src/client/drag/file-drag.ts +67 -67
  50. package/src/client/drag.ts +154 -154
  51. package/src/client/file-source.ts +34 -0
  52. package/src/client/fileType.ts +32 -5
  53. package/src/client/hooks/useResizableSplit.ts +91 -91
  54. package/src/client/hooks/useStore.ts +15 -15
  55. package/src/client/index.ts +42 -3
  56. package/src/client/layout.ts +523 -523
  57. package/src/client/locales.ts +6 -0
  58. package/src/client/maximize.ts +34 -34
  59. package/src/client/mount.tsx +2 -1
  60. package/src/client/persist.ts +194 -194
  61. package/src/client/picker/FilePickerModal.tsx +526 -526
  62. package/src/client/picker/file-picker.ts +86 -86
  63. package/src/client/preview/PreviewPanel.tsx +7 -1
  64. package/src/client/preview/PreviewTabs.tsx +159 -159
  65. package/src/client/preview/PreviewToolbar.tsx +3 -2
  66. package/src/client/preview/content.tsx +7 -2
  67. package/src/client/preview/markdown.ts +351 -351
  68. package/src/client/preview/mermaid.ts +274 -274
  69. package/src/client/preview/office.tsx +321 -0
  70. package/src/client/reference.ts +49 -0
  71. package/src/client/settings-card.module.css +316 -316
  72. package/src/client/settings-form.ts +451 -451
  73. package/src/client/store.ts +17 -12
  74. package/src/client/styles/drag.module.css +30 -30
  75. package/src/client/styles/explorer.module.css +371 -371
  76. package/src/client/styles/picker.module.css +344 -344
  77. package/src/client/styles/preview.module.css +3 -1
  78. package/src/client/styles/scm.module.css +380 -380
  79. package/src/client/styles/tokens.module.css +376 -371
  80. package/src/core/types.ts +162 -162
  81. package/src/host/fs-service.ts +7 -1
  82. package/src/host/gate.ts +73 -73
  83. package/src/host/git-runner.ts +116 -116
  84. package/src/host/git-service.ts +395 -395
  85. package/src/host/loopback.ts +63 -63
  86. package/src/host/office-preview.ts +399 -0
  87. package/src/host/poll-guard.ts +109 -109
  88. package/src/host/routes.ts +72 -1
  89. package/src/index.ts +3 -1
  90. package/src/mount-once.ts +48 -48
  91. package/lib/types/client/chat/AttachedFilesDock.d.ts +0 -51
  92. package/lib/types/client/chat/AttachedFilesDock.d.ts.map +0 -1
  93. package/lib/types/client/floating.d.ts +0 -27
  94. package/lib/types/client/floating.d.ts.map +0 -1
  95. package/lib/types/client/mention.d.ts +0 -44
  96. package/lib/types/client/mention.d.ts.map +0 -1
@@ -1,371 +1,376 @@
1
- /**
2
- * The panel design system: FileManager's tokens, scoped to the plugin's own
3
- * root elements so they never leak into the shell. The `--aion-*` names are
4
- * kept as an alias layer that forwards to the official `--dsw-*` token system
5
- * — dark-mode adaptation is handled by `--dsw-*` itself, so no per-theme
6
- * override block is needed.
7
- *
8
- * Scoped to BODY, not :root: since the official theme rc.2 the `--dsw-*`
9
- * semantic tokens live on `body` (not html), so an alias defined at :root
10
- * would substitute var() against an undefined name and compute to the
11
- * guaranteed-invalid value (""), killing every background that consumes it.
12
- * On body the dsw tokens resolve and the aliases inherit to all visible
13
- * elements — including the DOM-created chrome (panel columns, drag handles,
14
- * the '@' picker portal) appended outside any React subtree.
15
- */
16
- :global(body) {
17
- --aion-bg-base: var(--dsw-alias-bg-base);
18
- --aion-bg-1: var(--dsw-alias-bg-layer-1);
19
- --aion-bg-2: var(--dsw-alias-bg-layer-2);
20
- --aion-bg-3: var(--dsw-alias-bg-layer-3);
21
- --aion-bg-4: var(--dsw-alias-label-dimmed);
22
- --aion-bg-hover: var(--dsw-alias-interactive-bg-hover);
23
- --aion-bg-active: var(--dsw-alias-interactive-bg-active);
24
- --aion-text-primary: var(--dsw-alias-label-primary);
25
- --aion-text-secondary: var(--dsw-alias-label-secondary);
26
- --aion-text-tertiary: var(--dsw-alias-label-tertiary);
27
- --aion-text-disabled: var(--dsw-alias-label-dimmed);
28
- --aion-primary: var(--dsw-alias-state-business-primary);
29
- --aion-success: var(--dsw-alias-state-success-primary);
30
- --aion-warning: var(--dsw-alias-state-warn-primary);
31
- --aion-danger: var(--dsw-alias-state-error-primary);
32
- --aion-brand: var(--dsw-alias-brand-primary);
33
- --aion-aou-2: var(--dsw-alias-bg-layer-2);
34
- --aion-aou-6: var(--dsw-alias-brand-primary);
35
- --aion-fill-2: var(--dsw-alias-interactive-bg-hover);
36
- --aion-fill-3: var(--dsw-alias-interactive-bg-hover-solid);
37
- --aion-border-base: var(--dsw-alias-border-l2);
38
- --aion-overlay-shadow: var(--dsw-shadow-lv2);
39
- /* 官方字体 token;mono 用本地栈 —— 当前主题版本尚无 --dsw-alias-font-family-mono */
40
- --aion-font-sans: var(--dsw-font-family);
41
- --aion-font-mono: ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace;
42
- }
43
-
44
-
45
- /* Shared base for every plugin-owned surface. */
46
- :global(.filemgr-root) {
47
- font-family: var(--aion-font-sans);
48
- font-size: 13px;
49
- color: var(--aion-text-primary);
50
- background-color: var(--aion-bg-1);
51
- }
52
-
53
- :global(.filemgr-root *),
54
- :global(.filemgr-root *::before),
55
- :global(.filemgr-root *::after) {
56
- box-sizing: border-box;
57
- }
58
-
59
- /* Thin scrollbars matching the shell look. */
60
- :global(.filemgr-root ::-webkit-scrollbar) {
61
- width: 8px;
62
- height: 8px;
63
- }
64
- :global(.filemgr-root ::-webkit-scrollbar-thumb) {
65
- background: var(--aion-bg-3);
66
- border-radius: 4px;
67
- }
68
- :global(.filemgr-root ::-webkit-scrollbar-thumb:hover) {
69
- background: var(--aion-bg-4);
70
- }
71
- :global(.filemgr-root ::-webkit-scrollbar-track) {
72
- background: transparent;
73
- }
74
-
75
- /* prefers-reduced-motion: kill every panel animation globally. */
76
- @media (prefers-reduced-motion: reduce) {
77
- :global(.filemgr-root *),
78
- :global(.filemgr-root *::before),
79
- :global(.filemgr-root *::after) {
80
- animation: none !important;
81
- transition: none !important;
82
- }
83
- }
84
-
85
- /* ── frame-level chrome (created by the layout controller) ──────────────── */
86
-
87
- /* The shell frame's grid transition must not animate panel width changes. */
88
- :global([data-dsh-frame][data-filemgr-instant]) {
89
- transition: none !important;
90
- }
91
-
92
- /* Panel columns are plain grid items; overflow hidden so width 0 clips.
93
- z-index 30 lifts the columns above the shell.overlay slot layer (the core
94
- AppFrame renders it as ::global(.overlayLayer) at z-index 20, inset:0 over
95
- the whole frame). Right-edge overlay plugins would otherwise paint on top of
96
- the Explorer / Preview columns' content (issue #195). Kept below dialogs
97
- (1000+) so modals/toasts still stack above the panels. Matches the tab-bar
98
- z-index 30 convention (issues #169 / #87), so the three stay consistent.
99
- Full-screen drawer overlays (e.g. the biaoqingbao emoji manager) must
100
- therefore render at the ROOT stacking context (portal to document.body,
101
- z in (100, 1000)) to cover the panels AND the frame chrome (drag handles
102
- and the floating expand button stack at 30/100 — they overlap the column
103
- tracks, so lowering them below the columns would bury them under the
104
- opaque panels and kill drag/click hit-testing, issue #234 follow-up). */
105
- :global(.filemgr-preview-col),
106
- :global(.filemgr-explorer-col) {
107
- min-width: 0;
108
- overflow: hidden;
109
- display: flex;
110
- flex-direction: column;
111
- background-color: var(--aion-bg-1);
112
- z-index: 30;
113
- }
114
-
115
- :global(.filemgr-preview-col) {
116
- /* 1px left border only — no outer margins (FileManager contract). */
117
- border-left: 1px solid var(--aion-bg-3);
118
- }
119
-
120
- /* Maximized narrow-screen overlay (issue #315): on viewports below the
121
- breakpoint the maximized column leaves the grid and covers the whole
122
- window (mobile-friendly full-screen mode). The layout controller toggles
123
- this class; removing it restores the normal grid position. Above the
124
- columns/chrome (60) and below dialogs (1000+). */
125
- :global(.filemgr-preview-col.filemgr-maximized),
126
- :global(.filemgr-explorer-col.filemgr-maximized) {
127
- position: fixed !important;
128
- inset: 0;
129
- z-index: 60;
130
- }
131
-
132
- :global(.filemgr-explorer-col) {
133
- border-left: 1px solid var(--aion-bg-3);
134
- }
135
-
136
- /* Preview region enter animation (0.25s, translateX(20px) + fade). */
137
- :global(.filemgr-preview-col.filemgr-preview-enter) {
138
- animation: filemgr-preview-enter 0.25s cubic-bezier(0.4, 0, 0.2, 1);
139
- }
140
-
141
- @keyframes filemgr-preview-enter {
142
- from {
143
- transform: translateX(20px);
144
- opacity: 0;
145
- }
146
- to {
147
- transform: translateX(0);
148
- opacity: 1;
149
- }
150
- }
151
-
152
- /* Drag handles: invisible, col-resize cursor only (like DSH native sidebar). */
153
- :global(.filemgr-explorer-handle),
154
- :global(.filemgr-preview-handle) {
155
- touch-action: none;
156
- cursor: col-resize;
157
- }
158
-
159
-
160
- /* The collapse chevron inside the explorer tab bar (top-right). It rides
161
- the explorer column's stacking context (the column stacks at z 30), so
162
- its own z-index only orders it against tab-bar siblings; full-screen
163
- overlay drawers must render at the ROOT stacking context (z 100~1000)
164
- to cover it (issue #234). */
165
- :global(.filemgr-collapse-chevron) {
166
- position: absolute;
167
- /* In desktop wrappers with the Window Controls Overlay, the native
168
- window buttons occupy the top-right corner of the webview; shift the
169
- chevron below that strip. Browsers report 0px, so layout is
170
- unchanged there (issue #169). */
171
- top: calc(6px + env(titlebar-area-height, 0px));
172
- right: 8px;
173
- z-index: 30;
174
- width: 24px;
175
- height: 24px;
176
- display: flex;
177
- align-items: center;
178
- justify-content: center;
179
- border: none;
180
- border-radius: 4px;
181
- background: transparent;
182
- color: var(--aion-text-secondary);
183
- cursor: pointer;
184
- transition: background-color 0.15s cubic-bezier(0.4, 0, 0.2, 1);
185
- }
186
- :global(.filemgr-collapse-chevron:hover) {
187
- background-color: var(--aion-bg-3);
188
- color: var(--aion-text-primary);
189
- }
190
- :global(.filemgr-collapse-chevron:active) {
191
- background-color: var(--aion-bg-active);
192
- }
193
- :global(.filemgr-collapse-chevron:focus-visible) {
194
- outline: 2px solid var(--aion-primary);
195
- outline-offset: 2px;
196
- }
197
-
198
- /* Confirm dialog backdrop + card. */
199
- :global(.filemgr-overlay) {
200
- position: fixed;
201
- inset: 0;
202
- z-index: 1000;
203
- display: flex;
204
- align-items: center;
205
- justify-content: center;
206
- background: var(--dsw-alias-bg-mask-1);
207
- }
208
- :global(.filemgr-dialog) {
209
- width: 400px;
210
- max-width: calc(100vw - 48px);
211
- border-radius: 16px;
212
- background: var(--aion-bg-base);
213
- box-shadow: var(--aion-overlay-shadow);
214
- overflow: hidden;
215
- font-family: var(--aion-font-sans);
216
- }
217
- :global(.filemgr-dialog-title) {
218
- font-size: 14px;
219
- font-weight: 600;
220
- color: var(--aion-text-primary);
221
- padding: 16px 20px 8px;
222
- }
223
- :global(.filemgr-dialog-body) {
224
- font-size: 13px;
225
- color: var(--aion-text-secondary);
226
- padding: 0 20px;
227
- line-height: 1.6;
228
- }
229
- :global(.filemgr-dialog-actions) {
230
- display: flex;
231
- justify-content: flex-end;
232
- gap: 8px;
233
- padding: 16px 20px 20px;
234
- }
235
- :global(.filemgr-btn) {
236
- height: 28px;
237
- padding: 0 14px;
238
- border: 1px solid var(--aion-bg-3);
239
- border-radius: 4px;
240
- background: var(--aion-bg-base);
241
- color: var(--aion-text-primary);
242
- font-size: 13px;
243
- cursor: pointer;
244
- transition: background-color 0.15s cubic-bezier(0.4, 0, 0.2, 1);
245
- }
246
- :global(.filemgr-btn:hover) {
247
- background: var(--aion-bg-hover);
248
- }
249
- :global(.filemgr-btn:active) {
250
- background: var(--aion-bg-active);
251
- }
252
- :global(.filemgr-btn:focus-visible) {
253
- outline: 2px solid var(--aion-primary);
254
- outline-offset: 2px;
255
- }
256
- :global(.filemgr-btn-primary) {
257
- background: var(--dsw-alias-button-primary-fill);
258
- border-color: var(--dsw-alias-button-primary-fill);
259
- color: var(--dsw-alias-label-primary-foreground);
260
- }
261
- :global(.filemgr-btn-primary:hover) {
262
- background: var(--dsw-alias-button-primary-hover);
263
- border-color: var(--dsw-alias-button-primary-hover);
264
- }
265
- :global(.filemgr-btn-primary:active) {
266
- background: var(--dsw-alias-button-primary-hover);
267
- border-color: var(--dsw-alias-button-primary-hover);
268
- }
269
- :global(.filemgr-btn-danger) {
270
- background: var(--aion-danger);
271
- border-color: var(--aion-danger);
272
- color: var(--dsw-alias-label-primary-foreground);
273
- }
274
- :global(.filemgr-btn-danger:hover) {
275
- background: color-mix(in srgb, var(--aion-danger) 88%, black);
276
- border-color: color-mix(in srgb, var(--aion-danger) 88%, black);
277
- }
278
- :global(.filemgr-btn-danger:active) {
279
- background: color-mix(in srgb, var(--aion-danger) 78%, black);
280
- border-color: color-mix(in srgb, var(--aion-danger) 78%, black);
281
- }
282
-
283
- /* Context menu (tab right-click / tree right-click). */
284
- :global(.filemgr-menu) {
285
- position: fixed;
286
- z-index: 1100;
287
- min-width: 160px;
288
- padding: 4px;
289
- border-radius: 8px;
290
- background: var(--aion-bg-base);
291
- box-shadow: var(--aion-overlay-shadow);
292
- border: 1px solid var(--aion-bg-3);
293
- font-family: var(--aion-font-sans);
294
- }
295
- :global(.filemgr-menu-item) {
296
- display: flex;
297
- align-items: center;
298
- height: 28px;
299
- padding: 0 10px;
300
- border-radius: 4px;
301
- font-size: 13px;
302
- color: var(--aion-text-primary);
303
- cursor: pointer;
304
- white-space: nowrap;
305
- }
306
- :global(.filemgr-menu-item:hover) {
307
- background: var(--aion-fill-2);
308
- }
309
- :global(.filemgr-menu-item:focus-visible) {
310
- outline: 2px solid var(--aion-primary);
311
- outline-offset: -2px;
312
- }
313
- :global(.filemgr-menu-item-disabled) {
314
- color: var(--aion-text-disabled);
315
- cursor: default;
316
- }
317
- :global(.filemgr-menu-item-disabled:hover) {
318
- background: transparent;
319
- }
320
- :global(.filemgr-menu-sep) {
321
- height: 1px;
322
- margin: 4px 8px;
323
- background: var(--aion-bg-3);
324
- }
325
-
326
- /* Prompt dialog text input. */
327
- :global(.filemgr-input) {
328
- width: 100%;
329
- height: 32px;
330
- padding: 0 10px;
331
- border: 1px solid var(--aion-bg-3);
332
- border-radius: 6px;
333
- background: var(--aion-bg-base);
334
- color: var(--aion-text-primary);
335
- font-size: 13px;
336
- font-family: var(--aion-font-sans);
337
- outline: none;
338
- box-sizing: border-box;
339
- }
340
- :global(.filemgr-input:focus) {
341
- border-color: var(--aion-primary);
342
- }
343
-
344
- /* Toast. */
345
- :global(.filemgr-toast) {
346
- position: fixed;
347
- bottom: 32px;
348
- left: 50%;
349
- transform: translateX(-50%);
350
- z-index: 1200;
351
- max-width: 70vw;
352
- padding: 8px 14px;
353
- border-radius: 6px;
354
- background: var(--aion-bg-base);
355
- color: var(--aion-text-primary);
356
- font-size: 13px;
357
- font-family: var(--aion-font-sans);
358
- box-shadow: var(--aion-overlay-shadow);
359
- border: 1px solid var(--aion-bg-3);
360
- animation: filemgr-toast-in 0.2s cubic-bezier(0.4, 0, 0.2, 1);
361
- }
362
- @keyframes filemgr-toast-in {
363
- from {
364
- opacity: 0;
365
- transform: translateX(-50%) translateY(8px);
366
- }
367
- to {
368
- opacity: 1;
369
- transform: translateX(-50%) translateY(0);
370
- }
371
- }
1
+ /**
2
+ * The panel design system: FileManager's tokens, scoped to the plugin's own
3
+ * root elements so they never leak into the shell. The `--aion-*` names are
4
+ * kept as an alias layer that forwards to the official `--dsw-*` token system
5
+ * — dark-mode adaptation is handled by `--dsw-*` itself, so no per-theme
6
+ * override block is needed.
7
+ *
8
+ * Scoped to BODY, not :root: since the official theme rc.2 the `--dsw-*`
9
+ * semantic tokens live on `body` (not html), so an alias defined at :root
10
+ * would substitute var() against an undefined name and compute to the
11
+ * guaranteed-invalid value (""), killing every background that consumes it.
12
+ * On body the dsw tokens resolve and the aliases inherit to all visible
13
+ * elements — including the DOM-created chrome (panel columns, drag handles,
14
+ * the '@' picker portal) appended outside any React subtree.
15
+ */
16
+ :global(body) {
17
+ --aion-bg-base: var(--dsw-alias-bg-base);
18
+ --aion-bg-1: var(--dsw-alias-bg-layer-1);
19
+ --aion-bg-2: var(--dsw-alias-bg-layer-2);
20
+ --aion-bg-3: var(--dsw-alias-bg-layer-3);
21
+ --aion-bg-4: var(--dsw-alias-label-dimmed);
22
+ --aion-bg-hover: var(--dsw-alias-interactive-bg-hover);
23
+ --aion-bg-active: var(--dsw-alias-interactive-bg-active);
24
+ --aion-text-primary: var(--dsw-alias-label-primary);
25
+ --aion-text-secondary: var(--dsw-alias-label-secondary);
26
+ --aion-text-tertiary: var(--dsw-alias-label-tertiary);
27
+ --aion-text-disabled: var(--dsw-alias-label-dimmed);
28
+ --aion-primary: var(--dsw-alias-state-business-primary);
29
+ --aion-success: var(--dsw-alias-state-success-primary);
30
+ --aion-warning: var(--dsw-alias-state-warn-primary);
31
+ --aion-danger: var(--dsw-alias-state-error-primary);
32
+ --aion-brand: var(--dsw-alias-brand-primary);
33
+ --aion-aou-2: var(--dsw-alias-bg-layer-2);
34
+ --aion-aou-6: var(--dsw-alias-brand-primary);
35
+ --aion-fill-2: var(--dsw-alias-interactive-bg-hover);
36
+ --aion-fill-3: var(--dsw-alias-interactive-bg-hover-solid);
37
+ --aion-border-base: var(--dsw-alias-border-l2);
38
+ --aion-overlay-shadow: var(--dsw-shadow-lv2);
39
+ /* 官方字体 token;mono 用本地栈 —— 当前主题版本尚无 --dsw-alias-font-family-mono */
40
+ --aion-font-sans: var(--dsw-font-family);
41
+ --aion-font-mono: ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace;
42
+ }
43
+
44
+
45
+ /* Shared base for every plugin-owned surface. */
46
+ :global(.filemgr-root) {
47
+ font-family: var(--aion-font-sans);
48
+ font-size: 13px;
49
+ color: var(--aion-text-primary);
50
+ background-color: var(--aion-bg-1);
51
+ }
52
+
53
+ :global(.filemgr-root *),
54
+ :global(.filemgr-root *::before),
55
+ :global(.filemgr-root *::after) {
56
+ box-sizing: border-box;
57
+ }
58
+
59
+ /* Thin scrollbars matching the shell look. */
60
+ :global(.filemgr-root ::-webkit-scrollbar) {
61
+ width: 8px;
62
+ height: 8px;
63
+ }
64
+ :global(.filemgr-root ::-webkit-scrollbar-thumb) {
65
+ background: var(--aion-bg-3);
66
+ border-radius: 4px;
67
+ }
68
+ :global(.filemgr-root ::-webkit-scrollbar-thumb:hover) {
69
+ background: var(--aion-bg-4);
70
+ }
71
+ :global(.filemgr-root ::-webkit-scrollbar-track) {
72
+ background: transparent;
73
+ }
74
+
75
+ /* prefers-reduced-motion: kill every panel animation globally. */
76
+ @media (prefers-reduced-motion: reduce) {
77
+ :global(.filemgr-root *),
78
+ :global(.filemgr-root *::before),
79
+ :global(.filemgr-root *::after) {
80
+ animation: none !important;
81
+ transition: none !important;
82
+ }
83
+ }
84
+
85
+ /* ── frame-level chrome (created by the layout controller) ──────────────── */
86
+
87
+ /* The shell frame's grid transition must not animate panel width changes. */
88
+ :global([data-dsh-frame][data-filemgr-instant]) {
89
+ transition: none !important;
90
+ }
91
+
92
+ /* Panel columns are plain grid items; overflow hidden so width 0 clips.
93
+ z-index 30 lifts the columns above the shell.overlay slot layer (the core
94
+ AppFrame renders it as ::global(.overlayLayer) at z-index 20, inset:0 over
95
+ the whole frame). Right-edge overlay plugins would otherwise paint on top of
96
+ the Explorer / Preview columns' content (issue #195). Kept below dialogs
97
+ (1000+) so modals/toasts still stack above the panels. Matches the tab-bar
98
+ z-index 30 convention (issues #169 / #87), so the three stay consistent.
99
+ Full-screen drawer overlays (e.g. the biaoqingbao emoji manager) must
100
+ therefore render at the ROOT stacking context (portal to document.body,
101
+ z in (100, 1000)) to cover the panels AND the frame chrome (drag handles
102
+ and the floating expand button stack at 30/100 — they overlap the column
103
+ tracks, so lowering them below the columns would bury them under the
104
+ opaque panels and kill drag/click hit-testing, issue #234 follow-up). */
105
+ :global(.filemgr-preview-col),
106
+ :global(.filemgr-explorer-col) {
107
+ min-width: 0;
108
+ overflow: hidden;
109
+ display: flex;
110
+ flex-direction: column;
111
+ background-color: var(--aion-bg-1);
112
+ z-index: 30;
113
+ }
114
+
115
+ :global(.filemgr-preview-col) {
116
+ /* 1px left border only — no outer margins (FileManager contract).
117
+ Use the semantic divider color (border-l2), NOT the bg-layer-3
118
+ background hint: bg-layer-3 is nearly indistinguishable from the
119
+ panel's own bg-layer-1 on both light and dark themes, so the
120
+ boundary vs. the shell was not visible. border-l2 is a real
121
+ stroke level with visible contrast in both themes. */
122
+ border-left: 1px solid var(--aion-border-base);
123
+ }
124
+
125
+ /* Maximized narrow-screen overlay (issue #315): on viewports below the
126
+ breakpoint the maximized column leaves the grid and covers the whole
127
+ window (mobile-friendly full-screen mode). The layout controller toggles
128
+ this class; removing it restores the normal grid position. Above the
129
+ columns/chrome (60) and below dialogs (1000+). */
130
+ :global(.filemgr-preview-col.filemgr-maximized),
131
+ :global(.filemgr-explorer-col.filemgr-maximized) {
132
+ position: fixed !important;
133
+ inset: 0;
134
+ z-index: 60;
135
+ }
136
+
137
+ :global(.filemgr-explorer-col) {
138
+ border-left: 1px solid var(--aion-border-base);
139
+ }
140
+
141
+ /* Preview region enter animation (0.25s, translateX(20px) + fade). */
142
+ :global(.filemgr-preview-col.filemgr-preview-enter) {
143
+ animation: filemgr-preview-enter 0.25s cubic-bezier(0.4, 0, 0.2, 1);
144
+ }
145
+
146
+ @keyframes filemgr-preview-enter {
147
+ from {
148
+ transform: translateX(20px);
149
+ opacity: 0;
150
+ }
151
+ to {
152
+ transform: translateX(0);
153
+ opacity: 1;
154
+ }
155
+ }
156
+
157
+ /* Drag handles: invisible, col-resize cursor only (like DSH native sidebar). */
158
+ :global(.filemgr-explorer-handle),
159
+ :global(.filemgr-preview-handle) {
160
+ touch-action: none;
161
+ cursor: col-resize;
162
+ }
163
+
164
+
165
+ /* The collapse chevron inside the explorer tab bar (top-right). It rides
166
+ the explorer column's stacking context (the column stacks at z 30), so
167
+ its own z-index only orders it against tab-bar siblings; full-screen
168
+ overlay drawers must render at the ROOT stacking context (z 100~1000)
169
+ to cover it (issue #234). */
170
+ :global(.filemgr-collapse-chevron) {
171
+ position: absolute;
172
+ /* In desktop wrappers with the Window Controls Overlay, the native
173
+ window buttons occupy the top-right corner of the webview; shift the
174
+ chevron below that strip. Browsers report 0px, so layout is
175
+ unchanged there (issue #169). */
176
+ top: calc(6px + env(titlebar-area-height, 0px));
177
+ right: 8px;
178
+ z-index: 30;
179
+ width: 24px;
180
+ height: 24px;
181
+ display: flex;
182
+ align-items: center;
183
+ justify-content: center;
184
+ border: none;
185
+ border-radius: 4px;
186
+ background: transparent;
187
+ color: var(--aion-text-secondary);
188
+ cursor: pointer;
189
+ transition: background-color 0.15s cubic-bezier(0.4, 0, 0.2, 1);
190
+ }
191
+ :global(.filemgr-collapse-chevron:hover) {
192
+ background-color: var(--aion-bg-3);
193
+ color: var(--aion-text-primary);
194
+ }
195
+ :global(.filemgr-collapse-chevron:active) {
196
+ background-color: var(--aion-bg-active);
197
+ }
198
+ :global(.filemgr-collapse-chevron:focus-visible) {
199
+ outline: 2px solid var(--aion-primary);
200
+ outline-offset: 2px;
201
+ }
202
+
203
+ /* Confirm dialog backdrop + card. */
204
+ :global(.filemgr-overlay) {
205
+ position: fixed;
206
+ inset: 0;
207
+ z-index: 1000;
208
+ display: flex;
209
+ align-items: center;
210
+ justify-content: center;
211
+ background: var(--dsw-alias-bg-mask-1);
212
+ }
213
+ :global(.filemgr-dialog) {
214
+ width: 400px;
215
+ max-width: calc(100vw - 48px);
216
+ border-radius: 16px;
217
+ background: var(--aion-bg-base);
218
+ box-shadow: var(--aion-overlay-shadow);
219
+ overflow: hidden;
220
+ font-family: var(--aion-font-sans);
221
+ }
222
+ :global(.filemgr-dialog-title) {
223
+ font-size: 14px;
224
+ font-weight: 600;
225
+ color: var(--aion-text-primary);
226
+ padding: 16px 20px 8px;
227
+ }
228
+ :global(.filemgr-dialog-body) {
229
+ font-size: 13px;
230
+ color: var(--aion-text-secondary);
231
+ padding: 0 20px;
232
+ line-height: 1.6;
233
+ }
234
+ :global(.filemgr-dialog-actions) {
235
+ display: flex;
236
+ justify-content: flex-end;
237
+ gap: 8px;
238
+ padding: 16px 20px 20px;
239
+ }
240
+ :global(.filemgr-btn) {
241
+ height: 28px;
242
+ padding: 0 14px;
243
+ border: 1px solid var(--aion-bg-3);
244
+ border-radius: 4px;
245
+ background: var(--aion-bg-base);
246
+ color: var(--aion-text-primary);
247
+ font-size: 13px;
248
+ cursor: pointer;
249
+ transition: background-color 0.15s cubic-bezier(0.4, 0, 0.2, 1);
250
+ }
251
+ :global(.filemgr-btn:hover) {
252
+ background: var(--aion-bg-hover);
253
+ }
254
+ :global(.filemgr-btn:active) {
255
+ background: var(--aion-bg-active);
256
+ }
257
+ :global(.filemgr-btn:focus-visible) {
258
+ outline: 2px solid var(--aion-primary);
259
+ outline-offset: 2px;
260
+ }
261
+ :global(.filemgr-btn-primary) {
262
+ background: var(--dsw-alias-button-primary-fill);
263
+ border-color: var(--dsw-alias-button-primary-fill);
264
+ color: var(--dsw-alias-label-primary-foreground);
265
+ }
266
+ :global(.filemgr-btn-primary:hover) {
267
+ background: var(--dsw-alias-button-primary-hover);
268
+ border-color: var(--dsw-alias-button-primary-hover);
269
+ }
270
+ :global(.filemgr-btn-primary:active) {
271
+ background: var(--dsw-alias-button-primary-hover);
272
+ border-color: var(--dsw-alias-button-primary-hover);
273
+ }
274
+ :global(.filemgr-btn-danger) {
275
+ background: var(--aion-danger);
276
+ border-color: var(--aion-danger);
277
+ color: var(--dsw-alias-label-primary-foreground);
278
+ }
279
+ :global(.filemgr-btn-danger:hover) {
280
+ background: color-mix(in srgb, var(--aion-danger) 88%, black);
281
+ border-color: color-mix(in srgb, var(--aion-danger) 88%, black);
282
+ }
283
+ :global(.filemgr-btn-danger:active) {
284
+ background: color-mix(in srgb, var(--aion-danger) 78%, black);
285
+ border-color: color-mix(in srgb, var(--aion-danger) 78%, black);
286
+ }
287
+
288
+ /* Context menu (tab right-click / tree right-click). */
289
+ :global(.filemgr-menu) {
290
+ position: fixed;
291
+ z-index: 1100;
292
+ min-width: 160px;
293
+ padding: 4px;
294
+ border-radius: 8px;
295
+ background: var(--aion-bg-base);
296
+ box-shadow: var(--aion-overlay-shadow);
297
+ border: 1px solid var(--aion-bg-3);
298
+ font-family: var(--aion-font-sans);
299
+ }
300
+ :global(.filemgr-menu-item) {
301
+ display: flex;
302
+ align-items: center;
303
+ height: 28px;
304
+ padding: 0 10px;
305
+ border-radius: 4px;
306
+ font-size: 13px;
307
+ color: var(--aion-text-primary);
308
+ cursor: pointer;
309
+ white-space: nowrap;
310
+ }
311
+ :global(.filemgr-menu-item:hover) {
312
+ background: var(--aion-fill-2);
313
+ }
314
+ :global(.filemgr-menu-item:focus-visible) {
315
+ outline: 2px solid var(--aion-primary);
316
+ outline-offset: -2px;
317
+ }
318
+ :global(.filemgr-menu-item-disabled) {
319
+ color: var(--aion-text-disabled);
320
+ cursor: default;
321
+ }
322
+ :global(.filemgr-menu-item-disabled:hover) {
323
+ background: transparent;
324
+ }
325
+ :global(.filemgr-menu-sep) {
326
+ height: 1px;
327
+ margin: 4px 8px;
328
+ background: var(--aion-bg-3);
329
+ }
330
+
331
+ /* Prompt dialog text input. */
332
+ :global(.filemgr-input) {
333
+ width: 100%;
334
+ height: 32px;
335
+ padding: 0 10px;
336
+ border: 1px solid var(--aion-bg-3);
337
+ border-radius: 6px;
338
+ background: var(--aion-bg-base);
339
+ color: var(--aion-text-primary);
340
+ font-size: 13px;
341
+ font-family: var(--aion-font-sans);
342
+ outline: none;
343
+ box-sizing: border-box;
344
+ }
345
+ :global(.filemgr-input:focus) {
346
+ border-color: var(--aion-primary);
347
+ }
348
+
349
+ /* Toast. */
350
+ :global(.filemgr-toast) {
351
+ position: fixed;
352
+ bottom: 32px;
353
+ left: 50%;
354
+ transform: translateX(-50%);
355
+ z-index: 1200;
356
+ max-width: 70vw;
357
+ padding: 8px 14px;
358
+ border-radius: 6px;
359
+ background: var(--aion-bg-base);
360
+ color: var(--aion-text-primary);
361
+ font-size: 13px;
362
+ font-family: var(--aion-font-sans);
363
+ box-shadow: var(--aion-overlay-shadow);
364
+ border: 1px solid var(--aion-bg-3);
365
+ animation: filemgr-toast-in 0.2s cubic-bezier(0.4, 0, 0.2, 1);
366
+ }
367
+ @keyframes filemgr-toast-in {
368
+ from {
369
+ opacity: 0;
370
+ transform: translateX(-50%) translateY(8px);
371
+ }
372
+ to {
373
+ opacity: 1;
374
+ transform: translateX(-50%) translateY(0);
375
+ }
376
+ }