@anchrd/intel-ui 0.40.0 → 0.42.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/package.json +8 -1
- package/src/app/app-tree/app-tree.tsx +21 -0
- package/src/attachment-viewer/attachment-viewer.tsx +305 -0
- package/src/board/board-assignee/board-assignee.tsx +45 -0
- package/src/board/board-chip/board-chip.tsx +31 -0
- package/src/board/board-crumbs/board-crumbs.ts +56 -0
- package/src/board/board-crumbs/board-crumbs.tsx +108 -0
- package/src/board/board-kanban/board-kanban.tsx +43 -8
- package/src/board/board-open-task/board-open-task.ts +32 -0
- package/src/board/board-panel/board-panel.tsx +17 -37
- package/src/board/board-status/board-status.tsx +60 -0
- package/src/board/board-table/board-table.tsx +207 -101
- package/src/board/board-task/board-task.tsx +144 -195
- package/src/board/board-title-row/board-title-row.tsx +68 -0
- package/src/file-preview/file-preview-view.tsx +342 -0
- package/src/file-preview/file-preview.tsx +28 -0
- package/src/file-preview/pdf-file-preview.tsx +5 -0
- package/src/file-preview/presentation-file-preview.tsx +21 -0
- package/src/file-preview/spreadsheet-file-preview.tsx +5 -0
- package/src/file-preview/word-file-preview.tsx +5 -0
- package/src/i18n/de.json +62 -6
- package/src/i18n/en.json +62 -6
- package/src/i18n/es.json +62 -6
- package/src/nodes/nodes.tsx +26 -52
- package/src/resource-menu/resource-menu.tsx +18 -12
- package/src/title-row/title-row.tsx +33 -6
- package/vite.config.ts +111 -3
|
@@ -0,0 +1,342 @@
|
|
|
1
|
+
import FileViewer, {
|
|
2
|
+
type FileViewerHandle,
|
|
3
|
+
type ViewerOptions,
|
|
4
|
+
type ViewerState,
|
|
5
|
+
} from "@file-viewer/react";
|
|
6
|
+
import {
|
|
7
|
+
ChevronLeft,
|
|
8
|
+
ChevronRight,
|
|
9
|
+
Minus,
|
|
10
|
+
PanelLeft,
|
|
11
|
+
Plus,
|
|
12
|
+
RotateCcw,
|
|
13
|
+
RotateCw,
|
|
14
|
+
Search,
|
|
15
|
+
X,
|
|
16
|
+
} from "lucide-react";
|
|
17
|
+
import { useEffect, useMemo, useRef, useState } from "react";
|
|
18
|
+
import { ActionSlot } from "@/app/action-slot/action-slot.tsx";
|
|
19
|
+
import { useI18n } from "@/i18n/i18n-context.tsx";
|
|
20
|
+
import { useResolvedTheme } from "@/theme/theme-context.tsx";
|
|
21
|
+
|
|
22
|
+
// The PDF renderer exposes no stable Shadow Parts for its navigation internals. These selectors
|
|
23
|
+
// intentionally target the pinned @file-viewer/renderer-pdf 2.3.0 DOM; verify them before upgrades.
|
|
24
|
+
const viewerTheme = `
|
|
25
|
+
:host,.file-viewer-web-shell{
|
|
26
|
+
--file-viewer-render-surface-background:var(--muted);
|
|
27
|
+
--file-viewer-bg:var(--background);--file-viewer-content-bg:var(--muted);
|
|
28
|
+
--file-viewer-text:var(--foreground);--file-viewer-muted:var(--muted-foreground);
|
|
29
|
+
--file-viewer-border:var(--border);--file-viewer-toolbar-bg:var(--background);
|
|
30
|
+
--file-viewer-toolbar-border:var(--border);--file-viewer-group-bg:var(--muted);
|
|
31
|
+
--file-viewer-group-border:var(--border);--file-viewer-button-color:var(--foreground);
|
|
32
|
+
--file-viewer-button-hover-bg:var(--accent);--file-viewer-button-hover-color:var(--accent-foreground);
|
|
33
|
+
--file-viewer-button-disabled-color:var(--muted-foreground);--file-viewer-input-bg:var(--background);
|
|
34
|
+
--file-viewer-input-color:var(--foreground);--file-viewer-focus-ring:var(--ring);
|
|
35
|
+
}
|
|
36
|
+
.pdf-shell,.pdf-wrapper{background:var(--muted)!important;color:var(--foreground)!important}
|
|
37
|
+
.pdf-nav-pane,.pdf-nav-tabs,.pdf-nav-head{background:var(--background)!important;border-color:var(--border)!important}
|
|
38
|
+
.pdf-nav-head{display:none!important}.pdf-nav-tabs{display:flex!important;justify-content:flex-end;padding:6px!important}
|
|
39
|
+
.pdf-nav-tabs button{width:30px;min-width:30px;padding:0;font-size:0;color:var(--muted-foreground)!important}
|
|
40
|
+
.pdf-nav-tabs button svg{width:15px;height:15px;margin:auto;fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}
|
|
41
|
+
.pdf-nav-tabs button:hover,.pdf-nav-tabs button.active{background:var(--accent)!important;border-color:var(--border)!important;color:var(--accent-foreground)!important}
|
|
42
|
+
.pdf-page-list{gap:4px!important;padding:6px!important}.pdf-page-button{display:flex!important;min-height:36px!important;padding:4px!important;border-color:transparent!important;background:transparent!important;color:var(--foreground)!important}
|
|
43
|
+
.pdf-page-button:hover,.pdf-page-button--active{background:var(--accent)!important;border-color:var(--border)!important;box-shadow:none!important}
|
|
44
|
+
.pdf-page-thumb{width:28px!important;height:28px!important;border:0!important;background:transparent!important;color:var(--foreground)!important}
|
|
45
|
+
.pdf-page-label{display:none!important}.pdf-outline-button{color:var(--foreground)!important}.pdf-outline-button:hover{background:var(--accent)!important;border-color:var(--border)!important}
|
|
46
|
+
`;
|
|
47
|
+
|
|
48
|
+
export function FilePreviewView({
|
|
49
|
+
file,
|
|
50
|
+
renderer,
|
|
51
|
+
pdf = false,
|
|
52
|
+
}: {
|
|
53
|
+
file: File;
|
|
54
|
+
renderer: unknown;
|
|
55
|
+
pdf?: boolean;
|
|
56
|
+
}) {
|
|
57
|
+
const theme = useResolvedTheme();
|
|
58
|
+
const i18n = useI18n();
|
|
59
|
+
const viewer = useRef<FileViewerHandle>(null);
|
|
60
|
+
const searchInput = useRef<HTMLInputElement>(null);
|
|
61
|
+
const [state, setState] = useState<ViewerState | null>(null);
|
|
62
|
+
const [searchOpen, setSearchOpen] = useState(false);
|
|
63
|
+
const [query, setQuery] = useState("");
|
|
64
|
+
const options = useMemo<ViewerOptions>(
|
|
65
|
+
() => ({
|
|
66
|
+
renderers: [renderer] as unknown as NonNullable<ViewerOptions["renderers"]>,
|
|
67
|
+
rendererMode: "replace",
|
|
68
|
+
builtinRenderers: "none",
|
|
69
|
+
autoRenderers: false,
|
|
70
|
+
styleIsolation: "shadow",
|
|
71
|
+
theme,
|
|
72
|
+
locale: "auto",
|
|
73
|
+
toolbar: false,
|
|
74
|
+
...(pdf
|
|
75
|
+
? { pdf: { toolbar: false, navigation: true, defaultNavigationVisible: false } }
|
|
76
|
+
: {}),
|
|
77
|
+
ui: { density: "compact", surfaceBackground: "transparent" },
|
|
78
|
+
}),
|
|
79
|
+
[pdf, renderer, theme],
|
|
80
|
+
);
|
|
81
|
+
const viewState = state?.viewState;
|
|
82
|
+
const page = viewState?.page ?? 1;
|
|
83
|
+
const pageCount = viewState?.pageCount ?? 0;
|
|
84
|
+
const scale = state?.zoom?.scale ?? viewState?.scale ?? 1;
|
|
85
|
+
const search = state?.search;
|
|
86
|
+
|
|
87
|
+
useEffect(() => {
|
|
88
|
+
if (!state?.ready) return;
|
|
89
|
+
const root = viewer.current?.getController()?.container.shadowRoot;
|
|
90
|
+
if (!root || root.querySelector("style[data-intel-viewer-theme]")) return;
|
|
91
|
+
const style = document.createElement("style");
|
|
92
|
+
style.dataset.intelViewerTheme = "true";
|
|
93
|
+
style.textContent = viewerTheme;
|
|
94
|
+
root.append(style);
|
|
95
|
+
const labelPages = () => {
|
|
96
|
+
for (const button of root.querySelectorAll<HTMLButtonElement>(".pdf-page-button")) {
|
|
97
|
+
const label = button.querySelector(".pdf-page-label")?.textContent?.trim();
|
|
98
|
+
if (label) button.title = label;
|
|
99
|
+
}
|
|
100
|
+
for (const [index, button] of root
|
|
101
|
+
.querySelectorAll<HTMLButtonElement>(".pdf-nav-tabs button")
|
|
102
|
+
.entries()) {
|
|
103
|
+
if (button.querySelector("[data-intel-navigation-icon]")) continue;
|
|
104
|
+
const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
|
|
105
|
+
svg.dataset.intelNavigationIcon = "true";
|
|
106
|
+
svg.setAttribute("viewBox", "0 0 24 24");
|
|
107
|
+
svg.setAttribute("aria-hidden", "true");
|
|
108
|
+
const paths =
|
|
109
|
+
index === 0
|
|
110
|
+
? ["M8 6h13M8 12h13M8 18h13", "M3 6h.01M3 12h.01M3 18h.01"]
|
|
111
|
+
: ["M4 6h7M9 12h11M13 18h7", "M4 6v12h9M9 6v6M13 12v6"];
|
|
112
|
+
for (const pathData of paths) {
|
|
113
|
+
const path = document.createElementNS("http://www.w3.org/2000/svg", "path");
|
|
114
|
+
path.setAttribute("d", pathData);
|
|
115
|
+
svg.append(path);
|
|
116
|
+
}
|
|
117
|
+
button.prepend(svg);
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
labelPages();
|
|
121
|
+
const observer = new MutationObserver(labelPages);
|
|
122
|
+
observer.observe(root, { childList: true, subtree: true });
|
|
123
|
+
return () => observer.disconnect();
|
|
124
|
+
}, [state?.ready]);
|
|
125
|
+
|
|
126
|
+
useEffect(() => {
|
|
127
|
+
if (searchOpen) searchInput.current?.focus();
|
|
128
|
+
}, [searchOpen]);
|
|
129
|
+
|
|
130
|
+
const applyViewState = (next: Record<string, unknown>) =>
|
|
131
|
+
viewer.current?.applyViewState({ ...viewState, ...next });
|
|
132
|
+
|
|
133
|
+
return (
|
|
134
|
+
<div className="relative h-full min-h-64">
|
|
135
|
+
{pdf ? (
|
|
136
|
+
<ActionSlot name="title-actions">
|
|
137
|
+
<button
|
|
138
|
+
type="button"
|
|
139
|
+
aria-label={i18n.t("attachment.viewer.navigation")}
|
|
140
|
+
aria-pressed={viewState?.navigation?.visible ?? false}
|
|
141
|
+
onClick={() =>
|
|
142
|
+
void applyViewState({
|
|
143
|
+
navigation: {
|
|
144
|
+
...viewState?.navigation,
|
|
145
|
+
visible: !(viewState?.navigation?.visible ?? false),
|
|
146
|
+
},
|
|
147
|
+
})
|
|
148
|
+
}
|
|
149
|
+
className="inline-flex size-8 items-center justify-center rounded-md bg-transparent outline-none hover:bg-muted focus-visible:ring-2 focus-visible:ring-ring aria-pressed:bg-muted"
|
|
150
|
+
>
|
|
151
|
+
<PanelLeft aria-hidden="true" className="size-4" />
|
|
152
|
+
</button>
|
|
153
|
+
</ActionSlot>
|
|
154
|
+
) : null}
|
|
155
|
+
<div className="absolute inset-x-0 top-0 bottom-14 min-h-0">
|
|
156
|
+
<FileViewer
|
|
157
|
+
ref={viewer}
|
|
158
|
+
file={file}
|
|
159
|
+
className="h-full min-h-0"
|
|
160
|
+
options={options}
|
|
161
|
+
onStateChange={setState}
|
|
162
|
+
/>
|
|
163
|
+
</div>
|
|
164
|
+
{state?.ready ? (
|
|
165
|
+
<div
|
|
166
|
+
role="toolbar"
|
|
167
|
+
aria-label={i18n.t("attachment.viewer.controls")}
|
|
168
|
+
className="absolute inset-x-3 bottom-2 z-[5] mx-auto flex min-h-10 w-fit max-w-[calc(100%-1.5rem)] items-center gap-1 rounded-full border bg-background/95 p-1 shadow-lg backdrop-blur"
|
|
169
|
+
>
|
|
170
|
+
<span role="status" aria-live="polite" aria-atomic="true" className="sr-only">
|
|
171
|
+
{search?.query
|
|
172
|
+
? search.total > 0
|
|
173
|
+
? i18n.t("attachment.viewer.searchResults", {
|
|
174
|
+
current: search.currentIndex + 1,
|
|
175
|
+
total: search.total,
|
|
176
|
+
})
|
|
177
|
+
: i18n.t("attachment.viewer.searchNoResults")
|
|
178
|
+
: ""}
|
|
179
|
+
</span>
|
|
180
|
+
{pdf && pageCount > 0 && !searchOpen ? (
|
|
181
|
+
<div className="flex items-center rounded-full bg-muted p-0.5">
|
|
182
|
+
<button
|
|
183
|
+
type="button"
|
|
184
|
+
aria-label={i18n.t("attachment.viewer.previousPage")}
|
|
185
|
+
disabled={page <= 1}
|
|
186
|
+
onClick={() => void applyViewState({ page: page - 1 })}
|
|
187
|
+
className="size-7 rounded-full hover:bg-accent disabled:opacity-40"
|
|
188
|
+
>
|
|
189
|
+
<ChevronLeft aria-hidden="true" className="mx-auto size-3.5" />
|
|
190
|
+
</button>
|
|
191
|
+
<span className="min-w-14 px-1 text-center text-xs tabular-nums">
|
|
192
|
+
{page} / {pageCount}
|
|
193
|
+
</span>
|
|
194
|
+
<button
|
|
195
|
+
type="button"
|
|
196
|
+
aria-label={i18n.t("attachment.viewer.nextPage")}
|
|
197
|
+
disabled={page >= pageCount}
|
|
198
|
+
onClick={() => void applyViewState({ page: page + 1 })}
|
|
199
|
+
className="size-7 rounded-full hover:bg-accent disabled:opacity-40"
|
|
200
|
+
>
|
|
201
|
+
<ChevronRight aria-hidden="true" className="mx-auto size-3.5" />
|
|
202
|
+
</button>
|
|
203
|
+
</div>
|
|
204
|
+
) : null}
|
|
205
|
+
{searchOpen ? (
|
|
206
|
+
<form
|
|
207
|
+
className="flex min-w-0 items-center gap-1"
|
|
208
|
+
onSubmit={(event) => {
|
|
209
|
+
event.preventDefault();
|
|
210
|
+
void viewer.current?.searchDocument(query);
|
|
211
|
+
}}
|
|
212
|
+
>
|
|
213
|
+
<input
|
|
214
|
+
ref={searchInput}
|
|
215
|
+
value={query}
|
|
216
|
+
onChange={(event) => setQuery(event.target.value)}
|
|
217
|
+
placeholder={i18n.t("attachment.viewer.searchPlaceholder")}
|
|
218
|
+
className="h-7 w-28 min-w-0 rounded-full border bg-background px-3 text-xs outline-none focus:ring-2 focus:ring-ring sm:w-40"
|
|
219
|
+
/>
|
|
220
|
+
<button
|
|
221
|
+
type="submit"
|
|
222
|
+
aria-label={i18n.t("attachment.viewer.search")}
|
|
223
|
+
className="grid size-7 place-items-center rounded-full hover:bg-accent"
|
|
224
|
+
>
|
|
225
|
+
<Search aria-hidden="true" className="size-3.5" />
|
|
226
|
+
</button>
|
|
227
|
+
{search && search.total > 0 ? (
|
|
228
|
+
<div className="flex items-center rounded-full bg-muted p-0.5">
|
|
229
|
+
<button
|
|
230
|
+
type="button"
|
|
231
|
+
aria-label={i18n.t("attachment.viewer.previousResult")}
|
|
232
|
+
disabled={search.total <= 1}
|
|
233
|
+
onClick={() => void viewer.current?.previousSearchResult()}
|
|
234
|
+
className="grid size-7 place-items-center rounded-full hover:bg-accent disabled:opacity-40"
|
|
235
|
+
>
|
|
236
|
+
<ChevronLeft aria-hidden="true" className="size-3.5" />
|
|
237
|
+
</button>
|
|
238
|
+
<span
|
|
239
|
+
aria-hidden="true"
|
|
240
|
+
className="min-w-10 px-1 text-center text-xs tabular-nums"
|
|
241
|
+
>
|
|
242
|
+
{search.currentIndex + 1} / {search.total}
|
|
243
|
+
</span>
|
|
244
|
+
<button
|
|
245
|
+
type="button"
|
|
246
|
+
aria-label={i18n.t("attachment.viewer.nextResult")}
|
|
247
|
+
disabled={search.total <= 1}
|
|
248
|
+
onClick={() => void viewer.current?.nextSearchResult()}
|
|
249
|
+
className="grid size-7 place-items-center rounded-full hover:bg-accent disabled:opacity-40"
|
|
250
|
+
>
|
|
251
|
+
<ChevronRight aria-hidden="true" className="size-3.5" />
|
|
252
|
+
</button>
|
|
253
|
+
</div>
|
|
254
|
+
) : null}
|
|
255
|
+
{search?.query && search.total === 0 ? (
|
|
256
|
+
<span aria-hidden="true" className="min-w-10 px-1 text-center text-xs tabular-nums">
|
|
257
|
+
{i18n.t("attachment.viewer.searchNoResults")}
|
|
258
|
+
</span>
|
|
259
|
+
) : null}
|
|
260
|
+
<button
|
|
261
|
+
type="button"
|
|
262
|
+
aria-label={i18n.t("common.close")}
|
|
263
|
+
onClick={() => {
|
|
264
|
+
setSearchOpen(false);
|
|
265
|
+
setQuery("");
|
|
266
|
+
void viewer.current?.clearDocumentSearch();
|
|
267
|
+
}}
|
|
268
|
+
className="grid size-7 place-items-center rounded-full hover:bg-accent"
|
|
269
|
+
>
|
|
270
|
+
<X aria-hidden="true" className="size-3.5" />
|
|
271
|
+
</button>
|
|
272
|
+
</form>
|
|
273
|
+
) : (
|
|
274
|
+
<button
|
|
275
|
+
type="button"
|
|
276
|
+
aria-label={i18n.t("attachment.viewer.search")}
|
|
277
|
+
onClick={() => setSearchOpen(true)}
|
|
278
|
+
className="grid size-8 place-items-center rounded-full hover:bg-accent"
|
|
279
|
+
>
|
|
280
|
+
<Search aria-hidden="true" className="size-4" />
|
|
281
|
+
</button>
|
|
282
|
+
)}
|
|
283
|
+
{!searchOpen ? (
|
|
284
|
+
<div className="flex items-center rounded-full bg-muted p-0.5">
|
|
285
|
+
<button
|
|
286
|
+
type="button"
|
|
287
|
+
aria-label={i18n.t("attachment.viewer.zoomOut")}
|
|
288
|
+
disabled={state.zoom ? !state.zoom.canZoomOut : false}
|
|
289
|
+
onClick={() => void viewer.current?.zoomOut()}
|
|
290
|
+
className="grid size-7 place-items-center rounded-full hover:bg-accent disabled:opacity-40"
|
|
291
|
+
>
|
|
292
|
+
<Minus aria-hidden="true" className="size-3.5" />
|
|
293
|
+
</button>
|
|
294
|
+
<button
|
|
295
|
+
type="button"
|
|
296
|
+
aria-label={i18n.t("attachment.viewer.resetZoom")}
|
|
297
|
+
disabled={state.zoom ? !state.zoom.canReset : false}
|
|
298
|
+
onClick={() => void viewer.current?.resetZoom()}
|
|
299
|
+
className="min-w-12 px-1 text-xs tabular-nums disabled:opacity-40"
|
|
300
|
+
>
|
|
301
|
+
{Math.round(scale * 100)}%
|
|
302
|
+
</button>
|
|
303
|
+
<button
|
|
304
|
+
type="button"
|
|
305
|
+
aria-label={i18n.t("attachment.viewer.zoomIn")}
|
|
306
|
+
disabled={state.zoom ? !state.zoom.canZoomIn : false}
|
|
307
|
+
onClick={() => void viewer.current?.zoomIn()}
|
|
308
|
+
className="grid size-7 place-items-center rounded-full hover:bg-accent disabled:opacity-40"
|
|
309
|
+
>
|
|
310
|
+
<Plus aria-hidden="true" className="size-3.5" />
|
|
311
|
+
</button>
|
|
312
|
+
</div>
|
|
313
|
+
) : null}
|
|
314
|
+
{pdf && !searchOpen ? (
|
|
315
|
+
<div className="hidden items-center sm:flex">
|
|
316
|
+
<button
|
|
317
|
+
type="button"
|
|
318
|
+
aria-label={i18n.t("attachment.viewer.rotateLeft")}
|
|
319
|
+
onClick={() =>
|
|
320
|
+
void applyViewState({ rotation: ((viewState?.rotation ?? 0) - 90 + 360) % 360 })
|
|
321
|
+
}
|
|
322
|
+
className="grid size-8 place-items-center rounded-full hover:bg-accent"
|
|
323
|
+
>
|
|
324
|
+
<RotateCcw aria-hidden="true" className="size-4" />
|
|
325
|
+
</button>
|
|
326
|
+
<button
|
|
327
|
+
type="button"
|
|
328
|
+
aria-label={i18n.t("attachment.viewer.rotateRight")}
|
|
329
|
+
onClick={() =>
|
|
330
|
+
void applyViewState({ rotation: ((viewState?.rotation ?? 0) + 90) % 360 })
|
|
331
|
+
}
|
|
332
|
+
className="grid size-8 place-items-center rounded-full hover:bg-accent"
|
|
333
|
+
>
|
|
334
|
+
<RotateCw aria-hidden="true" className="size-4" />
|
|
335
|
+
</button>
|
|
336
|
+
</div>
|
|
337
|
+
) : null}
|
|
338
|
+
</div>
|
|
339
|
+
) : null}
|
|
340
|
+
</div>
|
|
341
|
+
);
|
|
342
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { lazy, Suspense } from "react";
|
|
2
|
+
import type { AttachmentPreviewKind } from "@/attachment-viewer/attachment-viewer.tsx";
|
|
3
|
+
|
|
4
|
+
const previews = {
|
|
5
|
+
pdf: lazy(async () => ({ default: (await import("./pdf-file-preview.tsx")).PdfFilePreview })),
|
|
6
|
+
presentation: lazy(async () => ({
|
|
7
|
+
default: (await import("./presentation-file-preview.tsx")).PresentationFilePreview,
|
|
8
|
+
})),
|
|
9
|
+
spreadsheet: lazy(async () => ({
|
|
10
|
+
default: (await import("./spreadsheet-file-preview.tsx")).SpreadsheetFilePreview,
|
|
11
|
+
})),
|
|
12
|
+
word: lazy(async () => ({ default: (await import("./word-file-preview.tsx")).WordFilePreview })),
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export function FilePreview({
|
|
16
|
+
file,
|
|
17
|
+
kind,
|
|
18
|
+
}: {
|
|
19
|
+
file: File;
|
|
20
|
+
kind: Exclude<AttachmentPreviewKind, "image" | "unsupported">;
|
|
21
|
+
}) {
|
|
22
|
+
const Preview = previews[kind];
|
|
23
|
+
return (
|
|
24
|
+
<Suspense fallback={null}>
|
|
25
|
+
<Preview file={file} />
|
|
26
|
+
</Suspense>
|
|
27
|
+
);
|
|
28
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import {
|
|
2
|
+
presentationRendererDefinition,
|
|
3
|
+
renderFileViewerPresentation,
|
|
4
|
+
} from "@file-viewer/renderer-presentation";
|
|
5
|
+
import { FilePreviewView } from "./file-preview-view.tsx";
|
|
6
|
+
|
|
7
|
+
const presentationRenderer = {
|
|
8
|
+
id: "intel-file-viewer-renderer-presentation",
|
|
9
|
+
label: "Intel PPTX renderer",
|
|
10
|
+
definitions: [presentationRendererDefinition],
|
|
11
|
+
handlers: [
|
|
12
|
+
{
|
|
13
|
+
rendererId: presentationRendererDefinition.id,
|
|
14
|
+
handler: renderFileViewerPresentation,
|
|
15
|
+
},
|
|
16
|
+
],
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export function PresentationFilePreview({ file }: { file: File }) {
|
|
20
|
+
return <FilePreviewView file={file} renderer={presentationRenderer} />;
|
|
21
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { spreadsheetRenderer } from "@file-viewer/renderer-spreadsheet";
|
|
2
|
+
import { FilePreviewView } from "./file-preview-view.tsx";
|
|
3
|
+
export function SpreadsheetFilePreview({ file }: { file: File }) {
|
|
4
|
+
return <FilePreviewView file={file} renderer={spreadsheetRenderer} />;
|
|
5
|
+
}
|
package/src/i18n/de.json
CHANGED
|
@@ -31,11 +31,20 @@
|
|
|
31
31
|
"archive.title": "Archiv",
|
|
32
32
|
"auth.signOut": "Abmelden",
|
|
33
33
|
"auth.signOutFailed": "Das Abmelden ist fehlgeschlagen. Prüfe deine Verbindung und versuche es erneut.",
|
|
34
|
+
"board.add": "Etwas hinzufügen",
|
|
35
|
+
"board.add.due": "Fällig",
|
|
36
|
+
"board.add.label": "Label",
|
|
37
|
+
"board.add.start": "Start",
|
|
34
38
|
"board.addCard": "+ Aufgabe",
|
|
35
39
|
"board.addCardIn": "Eine Aufgabe zu {column} hinzufügen",
|
|
36
40
|
"board.addLabel": "Label hinzufügen",
|
|
37
41
|
"board.addLink": "Verlinkung",
|
|
42
|
+
"board.backTo": "Zurück zu {board}",
|
|
38
43
|
"board.cardLabel": "{title} öffnen, in {column}. Alt und eine Pfeiltaste verschiebt sie.",
|
|
44
|
+
"board.clearAssignee": "Zuständigkeit von {name} entfernen",
|
|
45
|
+
"board.clearDependsOn": "nicht mehr darauf warten",
|
|
46
|
+
"board.clearDue": "entfernen",
|
|
47
|
+
"board.clearStart": "entfernen",
|
|
39
48
|
"board.column.archive": "Archiv",
|
|
40
49
|
"board.column.assignee": "Zuständig",
|
|
41
50
|
"board.column.default.backlog": "Backlog",
|
|
@@ -45,10 +54,12 @@
|
|
|
45
54
|
"board.column.dependsOn": "Wartet auf",
|
|
46
55
|
"board.column.due": "Fällig",
|
|
47
56
|
"board.column.labels": "Labels",
|
|
57
|
+
"board.column.start": "Start",
|
|
48
58
|
"board.column.status": "Spalte",
|
|
49
59
|
"board.column.title": "Titel",
|
|
50
|
-
"board.columnEmpty": "Hier ist noch nichts.",
|
|
51
60
|
"board.createFailed": "Die Aufgabe konnte nicht angelegt werden.",
|
|
61
|
+
"board.crumbs": "Wo diese Karte sitzt",
|
|
62
|
+
"board.crumbsFolded": "Die Ebenen dazwischen zeigen",
|
|
52
63
|
"board.drag.lifted": "{card} aufgenommen",
|
|
53
64
|
"board.drag.moved": "{card} nach {column} verschoben",
|
|
54
65
|
"board.drag.putBack": "{card} zurückgelegt",
|
|
@@ -65,9 +76,9 @@
|
|
|
65
76
|
"board.link.outside": "Außerhalb dieses Boards",
|
|
66
77
|
"board.link.subtask": "Unteraufgabe",
|
|
67
78
|
"board.links": "Verlinkt",
|
|
68
|
-
"board.moveTo": "
|
|
79
|
+
"board.moveTo": "in eine andere Spalte verschieben",
|
|
69
80
|
"board.progress": "{done} von {total} erledigt",
|
|
70
|
-
"board.removeLabel": "Label
|
|
81
|
+
"board.removeLabel": "dieses Label entfernen",
|
|
71
82
|
"board.settings.addColumn": "+ Spalte",
|
|
72
83
|
"board.settings.columnName": "Name der Spalte {column}",
|
|
73
84
|
"board.settings.description": "Spalten und was das Board zeigt.",
|
|
@@ -82,6 +93,10 @@
|
|
|
82
93
|
"board.settings.showArchive": "Archiv-Spalte zeigen",
|
|
83
94
|
"board.settings.showArchiveHint": "Sie ist auf jedem Board. Ausgeblendet sind ihre Karten überall aus dem Blick.",
|
|
84
95
|
"board.settings.title": "Board-Einstellungen",
|
|
96
|
+
"board.sort.asc": "{column}, A bis Z",
|
|
97
|
+
"board.sort.desc": "{column}, Z bis A",
|
|
98
|
+
"board.sort.none": "Unsortiert",
|
|
99
|
+
"board.sortBy": "Sortieren",
|
|
85
100
|
"board.stripes.root": "Ebene {level}, hat Unteraufgaben",
|
|
86
101
|
"board.stripes.under": "Ebene {level} · übergeordnet in {column}",
|
|
87
102
|
"board.table.collapse": "Verbergen, was unter {row} liegt",
|
|
@@ -213,14 +228,55 @@
|
|
|
213
228
|
"flows.validate": "Prüfen, ob er laufen würde",
|
|
214
229
|
"flows.validateReady": "Dieser Flow würde jetzt starten.",
|
|
215
230
|
"flows.validateWhen": "Geprüft {when}. Der Werkzeug-Zugriff wird jedes Mal mit deinem eigenen Token erfragt, diese Antwort ist also eine Momentaufnahme.",
|
|
231
|
+
"attachment.details.checksum": "Prüfsumme",
|
|
232
|
+
"attachment.details.dimensions": "Abmessungen",
|
|
233
|
+
"attachment.details.format": "Format",
|
|
234
|
+
"attachment.details.mimeType": "MIME-Typ",
|
|
235
|
+
"attachment.details.name": "Name",
|
|
236
|
+
"attachment.details.pages": "Seiten",
|
|
237
|
+
"attachment.details.private": "Privat",
|
|
238
|
+
"attachment.details.size": "Größe",
|
|
239
|
+
"attachment.details.sections": "Abschnitte",
|
|
240
|
+
"attachment.details.slides": "Folien",
|
|
241
|
+
"attachment.details.storage": "Speicher",
|
|
242
|
+
"attachment.details.technical": "Technisch",
|
|
243
|
+
"attachment.details.title": "Dateidetails",
|
|
244
|
+
"attachment.details.type": "Typ",
|
|
245
|
+
"attachment.details.uploaded": "Hochgeladen",
|
|
246
|
+
"attachment.details.uploadedBy": "Hochgeladen von",
|
|
247
|
+
"attachment.details.version": "Version",
|
|
248
|
+
"attachment.details.worksheets": "Tabellenblätter",
|
|
249
|
+
"attachment.kind.image": "Bild",
|
|
250
|
+
"attachment.kind.pdf": "PDF-Dokument",
|
|
251
|
+
"attachment.kind.presentation": "Präsentation",
|
|
252
|
+
"attachment.kind.spreadsheet": "Tabelle",
|
|
253
|
+
"attachment.kind.unsupported": "Datei",
|
|
254
|
+
"attachment.kind.word": "Word-Dokument",
|
|
255
|
+
"attachment.detailsHide": "Dateidetails ausblenden",
|
|
256
|
+
"attachment.detailsShow": "Dateidetails anzeigen",
|
|
257
|
+
"attachment.empty": "Es wurde noch keine Datei hochgeladen.",
|
|
258
|
+
"attachment.loadFailed": "Die Datei konnte nicht geladen werden. Das Original lässt sich weiterhin über das Menü exportieren.",
|
|
259
|
+
"attachment.unsupported": "Dieser Dateityp kann nicht angezeigt werden. Das Original lässt sich weiterhin über das Menü exportieren.",
|
|
260
|
+
"attachment.viewer.controls": "Dateisteuerung",
|
|
261
|
+
"attachment.viewer.navigation": "Seitennavigation anzeigen",
|
|
262
|
+
"attachment.viewer.nextPage": "Nächste Seite",
|
|
263
|
+
"attachment.viewer.nextResult": "Nächster Suchtreffer",
|
|
264
|
+
"attachment.viewer.previousPage": "Vorherige Seite",
|
|
265
|
+
"attachment.viewer.previousResult": "Vorheriger Suchtreffer",
|
|
266
|
+
"attachment.viewer.resetZoom": "Zoom zurücksetzen",
|
|
267
|
+
"attachment.viewer.rotateLeft": "Nach links drehen",
|
|
268
|
+
"attachment.viewer.rotateRight": "Nach rechts drehen",
|
|
269
|
+
"attachment.viewer.search": "Dokument durchsuchen",
|
|
270
|
+
"attachment.viewer.searchNoResults": "Keine Treffer",
|
|
271
|
+
"attachment.viewer.searchPlaceholder": "Dokument durchsuchen",
|
|
272
|
+
"attachment.viewer.searchResults": "Suchtreffer {current} von {total}",
|
|
273
|
+
"attachment.viewer.zoomIn": "Vergrößern",
|
|
274
|
+
"attachment.viewer.zoomOut": "Verkleinern",
|
|
216
275
|
"nav.primary": "Hauptnavigation",
|
|
217
276
|
"nav.tools": "Werkzeuge",
|
|
218
277
|
"node.access": "Zugriff",
|
|
219
278
|
"node.accessDetails": "Zugriffsdetails anzeigen ({count})",
|
|
220
|
-
"node.attachmentHelp": "Die kanonische Datei liegt privat in Intel. Ihre KI-lesbare Projektion wird getrennt indexiert.",
|
|
221
279
|
"node.changed": "Geändert",
|
|
222
|
-
"node.download": "Datei herunterladen",
|
|
223
|
-
"node.downloadFailed": "Der Anhang konnte nicht heruntergeladen werden. Prüfe deinen Zugriff und versuche es erneut.",
|
|
224
280
|
"node.email": "E-Mail-Adresse",
|
|
225
281
|
"node.empty": "Es wurde noch nichts hinzugefügt.",
|
|
226
282
|
"node.folderEmpty": "In diesem Ordner ist noch nichts. Lege etwas über das Plus in der Seitenleiste an.",
|
package/src/i18n/en.json
CHANGED
|
@@ -31,11 +31,20 @@
|
|
|
31
31
|
"archive.title": "Archive",
|
|
32
32
|
"auth.signOut": "Sign out",
|
|
33
33
|
"auth.signOutFailed": "Signing out failed. Check your connection and try again.",
|
|
34
|
+
"board.add": "Add something",
|
|
35
|
+
"board.add.due": "Due",
|
|
36
|
+
"board.add.label": "Label",
|
|
37
|
+
"board.add.start": "Start",
|
|
34
38
|
"board.addCard": "+ Task",
|
|
35
39
|
"board.addCardIn": "Add a task to {column}",
|
|
36
40
|
"board.addLabel": "Add a label",
|
|
37
41
|
"board.addLink": "Link",
|
|
42
|
+
"board.backTo": "Back to {board}",
|
|
38
43
|
"board.cardLabel": "Open {title}, in {column}. Alt and an arrow key moves it.",
|
|
44
|
+
"board.clearAssignee": "Take the assignment off {name}",
|
|
45
|
+
"board.clearDependsOn": "stop waiting for it",
|
|
46
|
+
"board.clearDue": "clear it",
|
|
47
|
+
"board.clearStart": "clear it",
|
|
39
48
|
"board.column.archive": "Archive",
|
|
40
49
|
"board.column.assignee": "Assigned to",
|
|
41
50
|
"board.column.default.backlog": "Backlog",
|
|
@@ -45,10 +54,12 @@
|
|
|
45
54
|
"board.column.dependsOn": "Waiting for",
|
|
46
55
|
"board.column.due": "Due",
|
|
47
56
|
"board.column.labels": "Labels",
|
|
57
|
+
"board.column.start": "Start",
|
|
48
58
|
"board.column.status": "Column",
|
|
49
59
|
"board.column.title": "Title",
|
|
50
|
-
"board.columnEmpty": "Nothing here yet.",
|
|
51
60
|
"board.createFailed": "The task could not be created.",
|
|
61
|
+
"board.crumbs": "Where this card sits",
|
|
62
|
+
"board.crumbsFolded": "Show the levels in between",
|
|
52
63
|
"board.drag.lifted": "{card} picked up",
|
|
53
64
|
"board.drag.moved": "{card} moved to {column}",
|
|
54
65
|
"board.drag.putBack": "{card} put back",
|
|
@@ -65,9 +76,9 @@
|
|
|
65
76
|
"board.link.outside": "Outside this board",
|
|
66
77
|
"board.link.subtask": "Subtask",
|
|
67
78
|
"board.links": "Linked",
|
|
68
|
-
"board.moveTo": "
|
|
79
|
+
"board.moveTo": "move it to another column",
|
|
69
80
|
"board.progress": "{done} of {total} done",
|
|
70
|
-
"board.removeLabel": "
|
|
81
|
+
"board.removeLabel": "remove this label",
|
|
71
82
|
"board.settings.addColumn": "+ Column",
|
|
72
83
|
"board.settings.columnName": "Name of the column {column}",
|
|
73
84
|
"board.settings.description": "Columns and what the board shows.",
|
|
@@ -82,6 +93,10 @@
|
|
|
82
93
|
"board.settings.showArchive": "Show the archive column",
|
|
83
94
|
"board.settings.showArchiveHint": "It is on every board. Hidden, its cards are out of sight everywhere.",
|
|
84
95
|
"board.settings.title": "Board settings",
|
|
96
|
+
"board.sort.asc": "{column}, A to Z",
|
|
97
|
+
"board.sort.desc": "{column}, Z to A",
|
|
98
|
+
"board.sort.none": "Unsorted",
|
|
99
|
+
"board.sortBy": "Sort",
|
|
85
100
|
"board.stripes.root": "Level {level}, has subtasks",
|
|
86
101
|
"board.stripes.under": "Level {level} · parent in {column}",
|
|
87
102
|
"board.table.collapse": "Hide what is under {row}",
|
|
@@ -213,14 +228,55 @@
|
|
|
213
228
|
"flows.validate": "Check whether it would run",
|
|
214
229
|
"flows.validateReady": "This flow would start now.",
|
|
215
230
|
"flows.validateWhen": "Checked {when}. Tool access is asked with your own token each time, so this answer is a snapshot.",
|
|
231
|
+
"attachment.details.checksum": "Checksum",
|
|
232
|
+
"attachment.details.dimensions": "Dimensions",
|
|
233
|
+
"attachment.details.format": "Format",
|
|
234
|
+
"attachment.details.mimeType": "MIME type",
|
|
235
|
+
"attachment.details.name": "Name",
|
|
236
|
+
"attachment.details.pages": "Pages",
|
|
237
|
+
"attachment.details.private": "Private",
|
|
238
|
+
"attachment.details.size": "Size",
|
|
239
|
+
"attachment.details.sections": "Sections",
|
|
240
|
+
"attachment.details.slides": "Slides",
|
|
241
|
+
"attachment.details.storage": "Storage",
|
|
242
|
+
"attachment.details.technical": "Technical",
|
|
243
|
+
"attachment.details.title": "File details",
|
|
244
|
+
"attachment.details.type": "Type",
|
|
245
|
+
"attachment.details.uploaded": "Uploaded",
|
|
246
|
+
"attachment.details.uploadedBy": "Uploaded by",
|
|
247
|
+
"attachment.details.version": "Version",
|
|
248
|
+
"attachment.details.worksheets": "Worksheets",
|
|
249
|
+
"attachment.kind.image": "Image",
|
|
250
|
+
"attachment.kind.pdf": "PDF document",
|
|
251
|
+
"attachment.kind.presentation": "Presentation",
|
|
252
|
+
"attachment.kind.spreadsheet": "Spreadsheet",
|
|
253
|
+
"attachment.kind.unsupported": "File",
|
|
254
|
+
"attachment.kind.word": "Word document",
|
|
255
|
+
"attachment.detailsHide": "Hide file details",
|
|
256
|
+
"attachment.detailsShow": "Show file details",
|
|
257
|
+
"attachment.empty": "No file has been uploaded yet.",
|
|
258
|
+
"attachment.loadFailed": "The file could not be loaded. You can still export the original from the menu.",
|
|
259
|
+
"attachment.unsupported": "This file type cannot be previewed. You can still export the original from the menu.",
|
|
260
|
+
"attachment.viewer.controls": "File controls",
|
|
261
|
+
"attachment.viewer.navigation": "Show page navigation",
|
|
262
|
+
"attachment.viewer.nextPage": "Next page",
|
|
263
|
+
"attachment.viewer.nextResult": "Next search result",
|
|
264
|
+
"attachment.viewer.previousPage": "Previous page",
|
|
265
|
+
"attachment.viewer.previousResult": "Previous search result",
|
|
266
|
+
"attachment.viewer.resetZoom": "Reset zoom",
|
|
267
|
+
"attachment.viewer.rotateLeft": "Rotate left",
|
|
268
|
+
"attachment.viewer.rotateRight": "Rotate right",
|
|
269
|
+
"attachment.viewer.search": "Search document",
|
|
270
|
+
"attachment.viewer.searchNoResults": "No results",
|
|
271
|
+
"attachment.viewer.searchPlaceholder": "Search document",
|
|
272
|
+
"attachment.viewer.searchResults": "Search result {current} of {total}",
|
|
273
|
+
"attachment.viewer.zoomIn": "Zoom in",
|
|
274
|
+
"attachment.viewer.zoomOut": "Zoom out",
|
|
216
275
|
"nav.primary": "Primary navigation",
|
|
217
276
|
"nav.tools": "Tools",
|
|
218
277
|
"node.access": "Access",
|
|
219
278
|
"node.accessDetails": "Show access details ({count})",
|
|
220
|
-
"node.attachmentHelp": "The canonical file is stored privately in Intel. Its AI-readable projection is indexed separately.",
|
|
221
279
|
"node.changed": "Changed",
|
|
222
|
-
"node.download": "Download file",
|
|
223
|
-
"node.downloadFailed": "The attachment could not be downloaded. Check your access and try again.",
|
|
224
280
|
"node.email": "Email address",
|
|
225
281
|
"node.empty": "Nothing has been added yet.",
|
|
226
282
|
"node.folderEmpty": "Nothing in this folder yet. Create something with the plus in the sidebar.",
|