@brftech/filex-core 0.5.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{ArchiveViewer-DKW-HyXT.js → ArchiveViewer-EGgNqLPE.js} +2 -2
- package/dist/{ArchiveViewer-DKW-HyXT.js.map → ArchiveViewer-EGgNqLPE.js.map} +1 -1
- package/dist/{CsvViewer-D2HmP2yr.js → CsvViewer-BvriJ42M.js} +2 -2
- package/dist/{CsvViewer-D2HmP2yr.js.map → CsvViewer-BvriJ42M.js.map} +1 -1
- package/dist/{DrawioViewer-DPNvOFCs.js → DrawioViewer-B_bSPsWX.js} +2 -2
- package/dist/{DrawioViewer-DPNvOFCs.js.map → DrawioViewer-B_bSPsWX.js.map} +1 -1
- package/dist/{EpubViewer-ByqjNuNL.js → EpubViewer-hl68h4gG.js} +2 -2
- package/dist/{EpubViewer-ByqjNuNL.js.map → EpubViewer-hl68h4gG.js.map} +1 -1
- package/dist/{IpynbViewer-2iONhbuJ.js → IpynbViewer-lhwOjXK7.js} +2 -2
- package/dist/{IpynbViewer-2iONhbuJ.js.map → IpynbViewer-lhwOjXK7.js.map} +1 -1
- package/dist/{MermaidViewer-CmiU7hIT.js → MermaidViewer-H2Z6AYXg.js} +2 -2
- package/dist/{MermaidViewer-CmiU7hIT.js.map → MermaidViewer-H2Z6AYXg.js.map} +1 -1
- package/dist/{PsdViewer-Inhl2yN9.js → PsdViewer-Bsk-11yH.js} +2 -2
- package/dist/{PsdViewer-Inhl2yN9.js.map → PsdViewer-Bsk-11yH.js.map} +1 -1
- package/dist/{TiffViewer-C2AFFEze.js → TiffViewer-D-j9vycG.js} +2 -2
- package/dist/{TiffViewer-C2AFFEze.js.map → TiffViewer-D-j9vycG.js.map} +1 -1
- package/dist/{Viewer3D-YdW14q_n.js → Viewer3D-Bcr70rTe.js} +2 -2
- package/dist/{Viewer3D-YdW14q_n.js.map → Viewer3D-Bcr70rTe.js.map} +1 -1
- package/dist/filex-core.js +42 -39
- package/dist/filex-core.umd.cjs +59 -58
- package/dist/filex-core.umd.cjs.map +1 -1
- package/dist/index-C_ZSnk_I.js +11109 -0
- package/dist/index-C_ZSnk_I.js.map +1 -0
- package/dist/index.d.ts +234 -1
- package/dist/style.css +1 -1
- package/package.json +1 -1
- package/src/FileExplorer.vue +367 -14
- package/src/components/CommandPalette.vue +12 -1
- package/src/components/GalleryView.vue +214 -0
- package/src/components/GridView.vue +1 -0
- package/src/components/InspectorPanel.vue +170 -0
- package/src/components/ListView.vue +1 -0
- package/src/components/SecondaryPane.vue +411 -0
- package/src/components/TabBar.vue +174 -0
- package/src/components/Toolbar.vue +23 -5
- package/src/composables/useFileApi.ts +53 -0
- package/src/composables/useKeyboardShortcuts.ts +19 -0
- package/src/composables/useTabs.ts +222 -0
- package/src/index.ts +6 -0
- package/src/locales/en.ts +33 -0
- package/src/locales/tr.ts +33 -0
- package/src/styles/base.css +538 -0
- package/src/types/FileNode.ts +1 -1
- package/dist/index-eARevpz0.js +0 -9952
- package/dist/index-eARevpz0.js.map +0 -1
|
@@ -106,6 +106,23 @@ export interface UserSearchResponse {
|
|
|
106
106
|
users: UserSuggestion[];
|
|
107
107
|
}
|
|
108
108
|
|
|
109
|
+
/* === calisma:d3 — node comments (inspector panel) === */
|
|
110
|
+
|
|
111
|
+
/** Mirrors backend `model.NodeComment` (GET /api/files/comments?node_id=…). */
|
|
112
|
+
export interface NodeComment {
|
|
113
|
+
id: number;
|
|
114
|
+
node_id: number;
|
|
115
|
+
user_id: number;
|
|
116
|
+
body: string;
|
|
117
|
+
created_at: string;
|
|
118
|
+
updated_at?: string;
|
|
119
|
+
/** Joined author display name (email fallback), filled by the backend. */
|
|
120
|
+
author_name?: string;
|
|
121
|
+
/** Whether the CURRENT caller may delete this row (author or admin). */
|
|
122
|
+
can_delete?: boolean;
|
|
123
|
+
}
|
|
124
|
+
/* === /calisma:d3 === */
|
|
125
|
+
|
|
109
126
|
export interface InviteResponse {
|
|
110
127
|
mode: 'granted' | 'user_created' | 'shared';
|
|
111
128
|
user_id?: number;
|
|
@@ -741,6 +758,38 @@ export function useFileApi(config: ExplorerConfig) {
|
|
|
741
758
|
}
|
|
742
759
|
/* === /koru:k1 === */
|
|
743
760
|
|
|
761
|
+
/* === calisma:d3 — node comments (inspector panel) ===
|
|
762
|
+
* Same manager-URL derivation trick as versions/permissions so embedded
|
|
763
|
+
* proxies forwarding the whole /api/files/* subtree keep working.
|
|
764
|
+
* GET /api/files/comments?node_id=N → {comments, node_id}
|
|
765
|
+
* POST /api/files/comments → {node_id, body}
|
|
766
|
+
* DELETE /api/files/comments/{id} → {ok}
|
|
767
|
+
*/
|
|
768
|
+
function commentsUrl(sub = ''): string {
|
|
769
|
+
const base = endpoints.manager.replace(/\/manager(\?.*)?$/, '/comments');
|
|
770
|
+
return base + sub;
|
|
771
|
+
}
|
|
772
|
+
async function listComments(nodeId: number): Promise<NodeComment[]> {
|
|
773
|
+
const data = await jsonFetch<{ comments?: NodeComment[] | null }>(
|
|
774
|
+
commentsUrl() + '?node_id=' + encodeURIComponent(String(nodeId)),
|
|
775
|
+
);
|
|
776
|
+
return Array.isArray(data?.comments) ? data.comments : [];
|
|
777
|
+
}
|
|
778
|
+
async function addComment(nodeId: number, body: string): Promise<NodeComment> {
|
|
779
|
+
const data = await jsonFetch<{ comment: NodeComment }>(commentsUrl(), {
|
|
780
|
+
method: 'POST',
|
|
781
|
+
headers: { 'Content-Type': 'application/json' },
|
|
782
|
+
body: JSON.stringify({ node_id: nodeId, body }),
|
|
783
|
+
});
|
|
784
|
+
return data.comment;
|
|
785
|
+
}
|
|
786
|
+
async function deleteComment(id: number): Promise<void> {
|
|
787
|
+
await jsonFetch(commentsUrl('/' + encodeURIComponent(String(id))), {
|
|
788
|
+
method: 'DELETE',
|
|
789
|
+
});
|
|
790
|
+
}
|
|
791
|
+
/* === /calisma:d3 === */
|
|
792
|
+
|
|
744
793
|
// Mint a short-lived WebSocket auth ticket for the realtime layer. Derived
|
|
745
794
|
// from the manager URL (so it flows through the same host proxy) and uses the
|
|
746
795
|
// same auth/creds as every other call. Returns null on any failure (a backend
|
|
@@ -790,6 +839,10 @@ export function useFileApi(config: ExplorerConfig) {
|
|
|
790
839
|
listVersions,
|
|
791
840
|
restoreVersion,
|
|
792
841
|
snapshotVersion,
|
|
842
|
+
// Node comments (calisma:d3 inspector)
|
|
843
|
+
listComments,
|
|
844
|
+
addComment,
|
|
845
|
+
deleteComment,
|
|
793
846
|
// Permissions (RBAC panel)
|
|
794
847
|
listPermissions,
|
|
795
848
|
resolveEmail,
|
|
@@ -38,6 +38,12 @@ export interface ShortcutHandlers {
|
|
|
38
38
|
onShowHelp?: () => void; // ? (Shift+/ on most layouts)
|
|
39
39
|
onToggleInspector?: () => void; // i (koru:k1 details panel)
|
|
40
40
|
onQuickLook?: () => void; // Space (wiring:c2 quick-look overlay)
|
|
41
|
+
/* wiring:d1 — tab strip actions */
|
|
42
|
+
onTabNew?: () => void; // Ctrl+T
|
|
43
|
+
onTabClose?: () => void; // Ctrl+W
|
|
44
|
+
onTabNext?: () => void; // Ctrl+Tab
|
|
45
|
+
onTabPrev?: () => void; // Ctrl+Shift+Tab
|
|
46
|
+
/* /wiring:d1 */
|
|
41
47
|
hasSelection?: () => boolean; // disambiguates Backspace
|
|
42
48
|
}
|
|
43
49
|
|
|
@@ -87,6 +93,14 @@ export const SHORTCUT_ACTIONS: ShortcutActionDef[] = [
|
|
|
87
93
|
{ id: 'cut', defaultCombo: 'Ctrl+X', labelKey: 'shortcuts.cut', groupKey: 'shortcuts.group.file' },
|
|
88
94
|
{ id: 'copy', defaultCombo: 'Ctrl+C', labelKey: 'shortcuts.copy', groupKey: 'shortcuts.group.file' },
|
|
89
95
|
{ id: 'paste', defaultCombo: 'Ctrl+V', labelKey: 'shortcuts.paste', groupKey: 'shortcuts.group.file' },
|
|
96
|
+
/* wiring:d1 — tabs. Note: browsers reserve Ctrl+T/W/Tab in normal pages
|
|
97
|
+
* (preventDefault can't stop them there); they work in webcomponent/PWA/
|
|
98
|
+
* kiosk contexts and stay remappable through the settings modal. */
|
|
99
|
+
{ id: 'tab-new', defaultCombo: 'Ctrl+T', labelKey: 'shortcuts.tab_new', groupKey: 'shortcuts.group.tabs' },
|
|
100
|
+
{ id: 'tab-close', defaultCombo: 'Ctrl+W', labelKey: 'shortcuts.tab_close', groupKey: 'shortcuts.group.tabs' },
|
|
101
|
+
{ id: 'tab-next', defaultCombo: 'Ctrl+Tab', labelKey: 'shortcuts.tab_next', groupKey: 'shortcuts.group.tabs' },
|
|
102
|
+
{ id: 'tab-prev', defaultCombo: 'Ctrl+Shift+Tab', labelKey: 'shortcuts.tab_prev', groupKey: 'shortcuts.group.tabs' },
|
|
103
|
+
/* /wiring:d1 */
|
|
90
104
|
];
|
|
91
105
|
|
|
92
106
|
/** action id → ShortcutHandlers callback name. */
|
|
@@ -105,6 +119,11 @@ const HANDLER_KEY: Record<string, keyof ShortcutHandlers> = {
|
|
|
105
119
|
cut: 'onCut',
|
|
106
120
|
copy: 'onCopy',
|
|
107
121
|
paste: 'onPaste',
|
|
122
|
+
/* wiring:d1 */
|
|
123
|
+
'tab-new': 'onTabNew',
|
|
124
|
+
'tab-close': 'onTabClose',
|
|
125
|
+
'tab-next': 'onTabNext',
|
|
126
|
+
'tab-prev': 'onTabPrev',
|
|
108
127
|
};
|
|
109
128
|
|
|
110
129
|
// --------------------------------------------------------------------
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* useTabs — wiring:d1 sekmeler (çalışma alanı tab şeridi).
|
|
3
|
+
*
|
|
4
|
+
* A LAYER ABOVE FileExplorer's location state, never a replacement for
|
|
5
|
+
* it: each tab is a location snapshot `{ id, path, viewMode, split }`.
|
|
6
|
+
* The composable performs no fetching and owns no navigation — the host
|
|
7
|
+
* activates a tab by running its EXISTING `load(path)` pipeline and
|
|
8
|
+
* reports navigations back through `syncActive()`, which keeps the
|
|
9
|
+
* active snapshot glued to wherever the user actually is.
|
|
10
|
+
*
|
|
11
|
+
* `path` is stored in the SAME form as FileExplorer's `currentPath`
|
|
12
|
+
* (virtual `<storage>/<rel>` in multi-storage mode, bare relative path
|
|
13
|
+
* in single-storage mode) — i.e. the exact string `load(path)` accepts.
|
|
14
|
+
* Storing the wire form (`adapter://rel`) instead would break the
|
|
15
|
+
* rootPath-floor clamp inside load() (the floor is compared in user-path
|
|
16
|
+
* form), so the user-path form is deliberate.
|
|
17
|
+
*
|
|
18
|
+
* Persistence: localStorage under a host-supplied key (the host derives
|
|
19
|
+
* it from the pathPersist scope: disabled when `pathPersist: 'none'`,
|
|
20
|
+
* suffixed with the rootPath confine so embedded instances with
|
|
21
|
+
* different confines never clobber each other). Schema:
|
|
22
|
+
*
|
|
23
|
+
* { "v": 1, "active": "<id>",
|
|
24
|
+
* "tabs": [ { "id", "path", "viewMode", "split": {"path"}|null } ] }
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
import { computed, ref, watch, type Ref } from 'vue';
|
|
28
|
+
import type { ViewMode } from '../types/FileNode';
|
|
29
|
+
|
|
30
|
+
/** Per-tab split state — the secondary pane's own location. */
|
|
31
|
+
export interface TabSplit {
|
|
32
|
+
path: string;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface TabState {
|
|
36
|
+
id: string;
|
|
37
|
+
/** Location snapshot in `currentPath` form (see module docs). */
|
|
38
|
+
path: string;
|
|
39
|
+
viewMode: ViewMode;
|
|
40
|
+
split: TabSplit | null;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export interface UseTabsOptions {
|
|
44
|
+
/** localStorage key; null disables persistence entirely. */
|
|
45
|
+
storageKey: string | null;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function makeId(): string {
|
|
49
|
+
try {
|
|
50
|
+
return crypto.randomUUID();
|
|
51
|
+
} catch {
|
|
52
|
+
return `t${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export function useTabs(opts: UseTabsOptions) {
|
|
57
|
+
const tabs: Ref<TabState[]> = ref([]);
|
|
58
|
+
const activeId = ref<string>('');
|
|
59
|
+
|
|
60
|
+
const activeTab = computed<TabState | null>(
|
|
61
|
+
() => tabs.value.find((t) => t.id === activeId.value) ?? null,
|
|
62
|
+
);
|
|
63
|
+
const activeIndex = computed(() => tabs.value.findIndex((t) => t.id === activeId.value));
|
|
64
|
+
const hasMultiple = computed(() => tabs.value.length > 1);
|
|
65
|
+
|
|
66
|
+
// ------------------------------------------------------------------
|
|
67
|
+
// Persistence
|
|
68
|
+
// ------------------------------------------------------------------
|
|
69
|
+
|
|
70
|
+
/** Restore from storage. Returns true when at least one tab loaded. */
|
|
71
|
+
function restore(): boolean {
|
|
72
|
+
if (!opts.storageKey) return false;
|
|
73
|
+
try {
|
|
74
|
+
const raw = localStorage.getItem(opts.storageKey);
|
|
75
|
+
if (!raw) return false;
|
|
76
|
+
const parsed = JSON.parse(raw) as { v?: unknown; active?: unknown; tabs?: unknown };
|
|
77
|
+
if (!parsed || !Array.isArray(parsed.tabs) || parsed.tabs.length === 0) return false;
|
|
78
|
+
const clean: TabState[] = [];
|
|
79
|
+
for (const t of parsed.tabs as Array<Record<string, unknown>>) {
|
|
80
|
+
if (!t || typeof t.path !== 'string') continue;
|
|
81
|
+
// ViewMode is validated loosely on purpose: future modes (e.g. the
|
|
82
|
+
// gallery wave) must survive a round-trip through an older schema.
|
|
83
|
+
const vm =
|
|
84
|
+
typeof t.viewMode === 'string' && t.viewMode ? (t.viewMode as ViewMode) : 'list';
|
|
85
|
+
const rawSplit = t.split as { path?: unknown } | null | undefined;
|
|
86
|
+
const split =
|
|
87
|
+
rawSplit && typeof rawSplit === 'object' && typeof rawSplit.path === 'string'
|
|
88
|
+
? { path: rawSplit.path }
|
|
89
|
+
: null;
|
|
90
|
+
clean.push({
|
|
91
|
+
id: typeof t.id === 'string' && t.id ? t.id : makeId(),
|
|
92
|
+
path: t.path,
|
|
93
|
+
viewMode: vm,
|
|
94
|
+
split,
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
if (clean.length === 0) return false;
|
|
98
|
+
tabs.value = clean;
|
|
99
|
+
activeId.value = clean.some((t) => t.id === parsed.active)
|
|
100
|
+
? String(parsed.active)
|
|
101
|
+
: clean[0].id;
|
|
102
|
+
return true;
|
|
103
|
+
} catch {
|
|
104
|
+
return false;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function persist(): void {
|
|
109
|
+
if (!opts.storageKey) return;
|
|
110
|
+
try {
|
|
111
|
+
localStorage.setItem(
|
|
112
|
+
opts.storageKey,
|
|
113
|
+
JSON.stringify({ v: 1, active: activeId.value, tabs: tabs.value }),
|
|
114
|
+
);
|
|
115
|
+
} catch {
|
|
116
|
+
/* private mode / quota */
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
watch([tabs, activeId], persist, { deep: true });
|
|
121
|
+
|
|
122
|
+
// ------------------------------------------------------------------
|
|
123
|
+
// Mutations
|
|
124
|
+
// ------------------------------------------------------------------
|
|
125
|
+
|
|
126
|
+
/** Create the first tab (no-op once any tab exists). */
|
|
127
|
+
function seed(path: string, viewMode: ViewMode): void {
|
|
128
|
+
if (tabs.value.length > 0) return;
|
|
129
|
+
const t: TabState = { id: makeId(), path, viewMode, split: null };
|
|
130
|
+
tabs.value = [t];
|
|
131
|
+
activeId.value = t.id;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/** Update the ACTIVE tab's snapshot (navigation / view-mode change). */
|
|
135
|
+
function syncActive(patch: Partial<Pick<TabState, 'path' | 'viewMode'>>): void {
|
|
136
|
+
const t = activeTab.value;
|
|
137
|
+
if (!t) return;
|
|
138
|
+
if (patch.path !== undefined) t.path = patch.path;
|
|
139
|
+
if (patch.viewMode !== undefined) t.viewMode = patch.viewMode;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/** Open a new tab right after the active one (browser convention). */
|
|
143
|
+
function openTab(
|
|
144
|
+
path: string,
|
|
145
|
+
o: { viewMode: ViewMode; background?: boolean; split?: TabSplit | null },
|
|
146
|
+
): TabState {
|
|
147
|
+
const t: TabState = { id: makeId(), path, viewMode: o.viewMode, split: o.split ?? null };
|
|
148
|
+
const idx = activeIndex.value;
|
|
149
|
+
tabs.value.splice(idx === -1 ? tabs.value.length : idx + 1, 0, t);
|
|
150
|
+
if (!o.background) activeId.value = t.id;
|
|
151
|
+
return t;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Close a tab. The last remaining tab never closes. Returns the tab
|
|
156
|
+
* the host must ACTIVATE (right neighbour, else left) when the active
|
|
157
|
+
* one was closed; null when the visible location is unchanged.
|
|
158
|
+
*/
|
|
159
|
+
function closeTab(id: string): TabState | null {
|
|
160
|
+
if (tabs.value.length <= 1) return null;
|
|
161
|
+
const idx = tabs.value.findIndex((t) => t.id === id);
|
|
162
|
+
if (idx === -1) return null;
|
|
163
|
+
const wasActive = tabs.value[idx].id === activeId.value;
|
|
164
|
+
tabs.value.splice(idx, 1);
|
|
165
|
+
if (!wasActive) return null;
|
|
166
|
+
const next = tabs.value[Math.min(idx, tabs.value.length - 1)];
|
|
167
|
+
activeId.value = next.id;
|
|
168
|
+
return next;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/** Make a tab active. Returns it when the active tab actually changed. */
|
|
172
|
+
function activate(id: string): TabState | null {
|
|
173
|
+
const t = tabs.value.find((x) => x.id === id);
|
|
174
|
+
if (!t || t.id === activeId.value) return null;
|
|
175
|
+
activeId.value = t.id;
|
|
176
|
+
return t;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/** Cycle: +1 = next, -1 = previous (wraps). */
|
|
180
|
+
function step(delta: number): TabState | null {
|
|
181
|
+
if (tabs.value.length < 2) return null;
|
|
182
|
+
const idx = activeIndex.value === -1 ? 0 : activeIndex.value;
|
|
183
|
+
const next = tabs.value[(idx + delta + tabs.value.length) % tabs.value.length];
|
|
184
|
+
return activate(next.id);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/** Drag-sort support: move the tab at `from` to position `to`. */
|
|
188
|
+
function move(from: number, to: number): void {
|
|
189
|
+
if (from === to) return;
|
|
190
|
+
if (from < 0 || to < 0 || from >= tabs.value.length || to >= tabs.value.length) return;
|
|
191
|
+
const list = [...tabs.value];
|
|
192
|
+
const [t] = list.splice(from, 1);
|
|
193
|
+
list.splice(to, 0, t);
|
|
194
|
+
tabs.value = list;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/** Set (or clear with null) the ACTIVE tab's split state. */
|
|
198
|
+
function setSplit(split: TabSplit | null): void {
|
|
199
|
+
const t = activeTab.value;
|
|
200
|
+
if (!t) return;
|
|
201
|
+
t.split = split;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
return {
|
|
205
|
+
tabs,
|
|
206
|
+
activeId,
|
|
207
|
+
activeTab,
|
|
208
|
+
activeIndex,
|
|
209
|
+
hasMultiple,
|
|
210
|
+
restore,
|
|
211
|
+
seed,
|
|
212
|
+
syncActive,
|
|
213
|
+
openTab,
|
|
214
|
+
closeTab,
|
|
215
|
+
activate,
|
|
216
|
+
step,
|
|
217
|
+
move,
|
|
218
|
+
setSplit,
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
export type TabsApi = ReturnType<typeof useTabs>;
|
package/src/index.ts
CHANGED
|
@@ -127,3 +127,9 @@ export type {
|
|
|
127
127
|
OperationsStore,
|
|
128
128
|
} from './composables/useOperations';
|
|
129
129
|
export { default as OperationsCenter } from './components/OperationsCenter.vue';
|
|
130
|
+
/* wiring:d1 — sekmeler + split panel */
|
|
131
|
+
export { useTabs } from './composables/useTabs';
|
|
132
|
+
export type { TabState, TabSplit, TabsApi } from './composables/useTabs';
|
|
133
|
+
export { default as TabBar } from './components/TabBar.vue';
|
|
134
|
+
export { default as SecondaryPane } from './components/SecondaryPane.vue';
|
|
135
|
+
/* /wiring:d1 */
|
package/src/locales/en.ts
CHANGED
|
@@ -332,4 +332,37 @@ export const en: Record<string, string> = {
|
|
|
332
332
|
'toolbar.view_label': 'View',
|
|
333
333
|
'list.aria': 'File list',
|
|
334
334
|
'grid.aria': 'File grid',
|
|
335
|
+
|
|
336
|
+
/* === wiring:d1 — tabs + split pane === */
|
|
337
|
+
'tabs.strip': 'Tabs',
|
|
338
|
+
'tabs.new': 'New tab',
|
|
339
|
+
'tabs.close': 'Close tab',
|
|
340
|
+
'tabs.split': 'Split view',
|
|
341
|
+
'tabs.split_off': 'Close split',
|
|
342
|
+
'ctx.open_new_tab': 'Open in new tab',
|
|
343
|
+
'shortcuts.group.tabs': 'Tabs',
|
|
344
|
+
'shortcuts.tab_new': 'New tab',
|
|
345
|
+
'shortcuts.tab_close': 'Close tab',
|
|
346
|
+
'shortcuts.tab_next': 'Next tab',
|
|
347
|
+
'shortcuts.tab_prev': 'Previous tab',
|
|
348
|
+
'cmd.tab_new': 'Open a new tab',
|
|
349
|
+
'cmd.split_toggle': 'Toggle split view',
|
|
350
|
+
'split.pane': 'Secondary pane',
|
|
351
|
+
'split.close': 'Close the side pane',
|
|
352
|
+
'split.error': 'Could not load the listing',
|
|
353
|
+
'split.retry': 'Retry',
|
|
354
|
+
'split.copy_queued': 'Copy queued',
|
|
355
|
+
'split.cross_copy': 'Different storages — copy queued instead',
|
|
356
|
+
'split.cross_failed': 'Cross-storage copy is not supported by this server',
|
|
357
|
+
/* === /wiring:d1 === */
|
|
358
|
+
/* wiring:d2 — gallery view */
|
|
359
|
+
'toolbar.view.gallery': 'Gallery',
|
|
360
|
+
'gallery.aria': 'File gallery',
|
|
361
|
+
/* /wiring:d2 */
|
|
362
|
+
/* wiring:d3 — inspector node comments */
|
|
363
|
+
'inspector.section.comments': 'Comments',
|
|
364
|
+
'inspector.comments.empty': 'No comments yet.',
|
|
365
|
+
'inspector.comments.placeholder': 'Write a comment…',
|
|
366
|
+
'inspector.comments.send': 'Send',
|
|
367
|
+
'inspector.comments.delete': 'Delete comment',
|
|
335
368
|
};
|
package/src/locales/tr.ts
CHANGED
|
@@ -332,4 +332,37 @@ export const tr: Record<string, string> = {
|
|
|
332
332
|
'toolbar.view_label': 'Görünüm',
|
|
333
333
|
'list.aria': 'Dosya listesi',
|
|
334
334
|
'grid.aria': 'Dosya ızgarası',
|
|
335
|
+
|
|
336
|
+
/* === wiring:d1 — sekmeler + split panel === */
|
|
337
|
+
'tabs.strip': 'Sekmeler',
|
|
338
|
+
'tabs.new': 'Yeni sekme',
|
|
339
|
+
'tabs.close': 'Sekmeyi kapat',
|
|
340
|
+
'tabs.split': 'Görünümü böl',
|
|
341
|
+
'tabs.split_off': 'Bölmeyi kapat',
|
|
342
|
+
'ctx.open_new_tab': 'Yeni sekmede aç',
|
|
343
|
+
'shortcuts.group.tabs': 'Sekmeler',
|
|
344
|
+
'shortcuts.tab_new': 'Yeni sekme',
|
|
345
|
+
'shortcuts.tab_close': 'Sekmeyi kapat',
|
|
346
|
+
'shortcuts.tab_next': 'Sonraki sekme',
|
|
347
|
+
'shortcuts.tab_prev': 'Önceki sekme',
|
|
348
|
+
'cmd.tab_new': 'Yeni sekme aç',
|
|
349
|
+
'cmd.split_toggle': 'Görünümü böl / birleştir',
|
|
350
|
+
'split.pane': 'İkincil panel',
|
|
351
|
+
'split.close': 'Yan paneli kapat',
|
|
352
|
+
'split.error': 'Liste yüklenemedi',
|
|
353
|
+
'split.retry': 'Yeniden dene',
|
|
354
|
+
'split.copy_queued': 'Kopyalama kuyruğa alındı',
|
|
355
|
+
'split.cross_copy': 'Depolar farklı — kopyalama kuyruğa alındı',
|
|
356
|
+
'split.cross_failed': 'Depolar arası kopyalama bu sunucuda desteklenmiyor',
|
|
357
|
+
/* === /wiring:d1 === */
|
|
358
|
+
/* wiring:d2 — galeri görünümü */
|
|
359
|
+
'toolbar.view.gallery': 'Galeri',
|
|
360
|
+
'gallery.aria': 'Dosya galerisi',
|
|
361
|
+
/* /wiring:d2 */
|
|
362
|
+
/* wiring:d3 — Yorumlar (inspector node comments) */
|
|
363
|
+
'inspector.section.comments': 'Yorumlar',
|
|
364
|
+
'inspector.comments.empty': 'Henüz yorum yok.',
|
|
365
|
+
'inspector.comments.placeholder': 'Yorum yaz…',
|
|
366
|
+
'inspector.comments.send': 'Gönder',
|
|
367
|
+
'inspector.comments.delete': 'Yorumu sil',
|
|
335
368
|
};
|