@open-slide/core 1.7.0 → 1.9.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/{build-tLrkKUHr.js → build-ZM7IfDO-.js} +1 -1
- package/dist/cli/bin.js +3 -3
- package/dist/{config-PwUHqZ_X.js → config-BAZeaz2P.js} +289 -246
- package/dist/{config-CfMThYN9.d.ts → config-D_5nlXFU.d.ts} +6 -1
- package/dist/{dev-DpCIRbhT.js → dev-BQkNTG_t.js} +1 -1
- package/dist/format-CYOb2cAQ.js +1573 -0
- package/dist/index.d.ts +4 -4
- package/dist/index.js +38 -4
- package/dist/locale/index.d.ts +1 -1
- package/dist/locale/index.js +1 -1144
- package/dist/{preview-BSGlM6Se.js → preview-D8hUtbRA.js} +1 -1
- package/dist/{types-B-KrjgX8.d.ts → types-AalTbxMj.d.ts} +17 -3
- package/dist/vite/index.d.ts +2 -2
- package/dist/vite/index.js +1 -1
- package/package.json +2 -1
- package/skills/create-theme/SKILL.md +1 -1
- package/src/app/components/inspector/comment-widget.tsx +16 -2
- package/src/app/components/language-toggle.tsx +39 -0
- package/src/app/components/player.tsx +12 -17
- package/src/app/components/pptx-progress-toast.tsx +32 -0
- package/src/app/components/sidebar/folder-item.tsx +7 -2
- package/src/app/components/sidebar/sidebar-footer.tsx +51 -0
- package/src/app/components/sidebar/sidebar.tsx +95 -17
- package/src/app/lib/design-presets.ts +1 -1
- package/src/app/lib/export-pptx.ts +284 -0
- package/src/app/lib/folders.ts +28 -0
- package/src/app/lib/inspector/fiber.test.ts +154 -0
- package/src/app/lib/inspector/fiber.ts +12 -1
- package/src/app/lib/locale-store.ts +67 -0
- package/src/app/lib/use-click-page-navigation.ts +52 -0
- package/src/app/lib/use-is-mobile.ts +21 -0
- package/src/app/lib/use-locale.ts +4 -16
- package/src/app/routes/home-shell.tsx +8 -0
- package/src/app/routes/home.tsx +1 -1
- package/src/app/routes/slide.tsx +145 -53
- package/src/app/virtual.d.ts +1 -0
- package/src/locale/en.ts +18 -3
- package/src/locale/ja.ts +19 -3
- package/src/locale/types.ts +18 -3
- package/src/locale/zh-cn.ts +17 -3
- package/src/locale/zh-tw.ts +17 -3
- package/dist/en-BDnM5zKJ.js +0 -378
- package/src/app/components/click-nav-zones.tsx +0 -36
|
@@ -1,20 +1,8 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
import type { Locale, Plural } from '../../locale/types';
|
|
4
|
-
|
|
5
|
-
const resolved: Locale = (config.locale as Locale | undefined) ?? en;
|
|
1
|
+
import type { Locale } from '../../locale/types';
|
|
2
|
+
import { useLocaleValue } from './locale-store';
|
|
6
3
|
|
|
7
4
|
export function useLocale(): Locale {
|
|
8
|
-
return
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export function format(template: string, vars: Record<string, string | number>): string {
|
|
12
|
-
return template.replace(/\{(\w+)\}/g, (m, key) => {
|
|
13
|
-
const v = vars[key];
|
|
14
|
-
return v === undefined ? m : String(v);
|
|
15
|
-
});
|
|
5
|
+
return useLocaleValue();
|
|
16
6
|
}
|
|
17
7
|
|
|
18
|
-
export
|
|
19
|
-
return count === 1 ? forms.one : forms.other;
|
|
20
|
-
}
|
|
8
|
+
export { format, plural } from '../../locale/format';
|
|
@@ -39,6 +39,7 @@ export function HomeShell() {
|
|
|
39
39
|
create,
|
|
40
40
|
update,
|
|
41
41
|
remove,
|
|
42
|
+
reorder,
|
|
42
43
|
assign,
|
|
43
44
|
renameSlide,
|
|
44
45
|
duplicateSlide,
|
|
@@ -147,6 +148,13 @@ export function HomeShell() {
|
|
|
147
148
|
}}
|
|
148
149
|
onDropToFolder={(folderId, slideId) => moveSlideWithToast(slideId, folderId)}
|
|
149
150
|
onDropToDraft={(slideId) => moveSlideWithToast(slideId, null)}
|
|
151
|
+
onReorder={async (ids) => {
|
|
152
|
+
try {
|
|
153
|
+
await reorder(ids);
|
|
154
|
+
} catch {
|
|
155
|
+
toast.error(t.home.toastFolderReorderFailed);
|
|
156
|
+
}
|
|
157
|
+
}}
|
|
150
158
|
/>
|
|
151
159
|
</div>
|
|
152
160
|
|
package/src/app/routes/home.tsx
CHANGED
|
@@ -242,7 +242,7 @@ function SortControl({ value, onChange }: { value: SortKey; onChange: (next: Sor
|
|
|
242
242
|
<button
|
|
243
243
|
type="button"
|
|
244
244
|
aria-label={`${t.home.sortLabel}: ${labels[value]}`}
|
|
245
|
-
className="flex h-8 items-center gap-1.5 rounded-[6px] border border-border bg-background pl-2 pr-1.5 text-[12.5px] font-medium text-foreground outline-none hover:bg-muted focus-visible:border-foreground/40 focus-visible:ring-2 focus-visible:ring-ring/30"
|
|
245
|
+
className="flex h-8 shrink-0 items-center gap-1.5 whitespace-nowrap rounded-[6px] border border-border bg-background pl-2 pr-1.5 text-[12.5px] font-medium text-foreground outline-none hover:bg-muted focus-visible:border-foreground/40 focus-visible:ring-2 focus-visible:ring-ring/30"
|
|
246
246
|
>
|
|
247
247
|
<FieldIcon k={value} className="size-3.5 text-muted-foreground" />
|
|
248
248
|
<span>{labels[value]}</span>
|
package/src/app/routes/slide.tsx
CHANGED
|
@@ -5,13 +5,14 @@ import {
|
|
|
5
5
|
ChevronLeft,
|
|
6
6
|
Download,
|
|
7
7
|
FileCode2,
|
|
8
|
+
FileImage,
|
|
8
9
|
FileText,
|
|
9
10
|
Link2,
|
|
10
11
|
Loader2,
|
|
11
12
|
Maximize,
|
|
12
13
|
MonitorSpeaker,
|
|
13
|
-
Pencil,
|
|
14
14
|
Play,
|
|
15
|
+
Presentation,
|
|
15
16
|
} from 'lucide-react';
|
|
16
17
|
import { type RefObject, useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
17
18
|
import { Link, useParams, useSearchParams } from 'react-router-dom';
|
|
@@ -34,24 +35,28 @@ import {
|
|
|
34
35
|
DropdownMenu,
|
|
35
36
|
DropdownMenuContent,
|
|
36
37
|
DropdownMenuItem,
|
|
38
|
+
DropdownMenuSeparator,
|
|
37
39
|
DropdownMenuTrigger,
|
|
38
40
|
} from '@/components/ui/dropdown-menu';
|
|
39
41
|
import { Tabs, TabsList, TabsTrigger } from '@/components/ui/tabs';
|
|
40
42
|
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip';
|
|
41
43
|
import { useFolders } from '@/lib/folders';
|
|
42
44
|
import { useAgentSocketConnected } from '@/lib/use-agent-socket';
|
|
45
|
+
import { useClickPageNavigation } from '@/lib/use-click-page-navigation';
|
|
46
|
+
import { useIsMobile } from '@/lib/use-is-mobile';
|
|
43
47
|
import { format, useLocale } from '@/lib/use-locale';
|
|
44
48
|
import { useWheelPageNavigation } from '@/lib/use-wheel-page-navigation';
|
|
45
49
|
import { cn } from '@/lib/utils';
|
|
46
|
-
import { ClickNavZones } from '../components/click-nav-zones';
|
|
47
50
|
import { NotesDrawer } from '../components/notes-drawer';
|
|
48
51
|
import { PdfProgressToast } from '../components/pdf-progress-toast';
|
|
49
52
|
import { openPresenterWindow, Player } from '../components/player';
|
|
53
|
+
import { PptxProgressToast } from '../components/pptx-progress-toast';
|
|
50
54
|
import { SlideCanvas } from '../components/slide-canvas';
|
|
51
55
|
import { SlideTransitionLayer } from '../components/slide-transition-layer';
|
|
52
56
|
import { type ThumbnailActions, ThumbnailRail } from '../components/thumbnail-rail';
|
|
53
57
|
import { exportSlideAsHtml } from '../lib/export-html';
|
|
54
58
|
import { exportSlideAsPdf, isSafari } from '../lib/export-pdf';
|
|
59
|
+
import { exportSlideAsImagePptx } from '../lib/export-pptx';
|
|
55
60
|
import { remapNotesSessionCacheAfterReorder } from '../lib/inspector/use-notes';
|
|
56
61
|
import type { SlideModule } from '../lib/sdk';
|
|
57
62
|
import { usePrefersReducedMotion } from '../lib/use-prefers-reduced-motion';
|
|
@@ -348,7 +353,7 @@ export function Slide() {
|
|
|
348
353
|
<SelectionReporter />
|
|
349
354
|
<div className="flex h-dvh flex-col overflow-hidden bg-background text-foreground">
|
|
350
355
|
{/* Editorial toolbar — three zones, hairline separators, mono-folio center */}
|
|
351
|
-
<header className="flex h-12 shrink-0 items-center gap-2 border-b border-hairline bg-sidebar/85 px-2 backdrop-blur-md md:px-3">
|
|
356
|
+
<header className="relative flex h-12 shrink-0 items-center gap-2 border-b border-hairline bg-sidebar/85 px-2 backdrop-blur-md md:px-3">
|
|
352
357
|
<div className="flex shrink-0 items-center gap-1.5 md:gap-2">
|
|
353
358
|
{showSlideBrowser && (
|
|
354
359
|
<Button asChild variant="ghost" size="icon-sm" title={t.slide.home}>
|
|
@@ -382,14 +387,14 @@ export function Slide() {
|
|
|
382
387
|
{import.meta.env.DEV && <AgentConnectedBadge />}
|
|
383
388
|
</div>
|
|
384
389
|
|
|
385
|
-
{/*
|
|
386
|
-
<div className="
|
|
387
|
-
<div className="min-w-0 max-w-[34rem]">
|
|
390
|
+
{/* Title centered to the viewport, not the leftover space between the side groups. */}
|
|
391
|
+
<div className="pointer-events-none absolute inset-x-0 flex justify-center px-2">
|
|
392
|
+
<div className="pointer-events-auto min-w-0 max-w-[34rem]">
|
|
388
393
|
<InlineTitleEditor title={title} onSubmit={(next) => renameSlide(slideId, next)} />
|
|
389
394
|
</div>
|
|
390
395
|
</div>
|
|
391
396
|
|
|
392
|
-
<div className="flex shrink-0 items-center gap-1">
|
|
397
|
+
<div className="ml-auto flex shrink-0 items-center gap-1">
|
|
393
398
|
{view === 'slides' && (
|
|
394
399
|
<button
|
|
395
400
|
type="button"
|
|
@@ -500,6 +505,69 @@ export function Slide() {
|
|
|
500
505
|
<FileText />
|
|
501
506
|
{t.slide.exportAsPdf}
|
|
502
507
|
</DropdownMenuItem>
|
|
508
|
+
<DropdownMenuSeparator />
|
|
509
|
+
<DropdownMenuItem
|
|
510
|
+
disabled={exporting}
|
|
511
|
+
onSelect={async () => {
|
|
512
|
+
if (!slide || exporting) return;
|
|
513
|
+
setExporting(true);
|
|
514
|
+
const toastId = `pptx-export-${slideId}`;
|
|
515
|
+
toast.custom(
|
|
516
|
+
() => (
|
|
517
|
+
<PptxProgressToast
|
|
518
|
+
progress={{
|
|
519
|
+
phase: 'processing',
|
|
520
|
+
current: 0,
|
|
521
|
+
total: pages.length,
|
|
522
|
+
percent: 0,
|
|
523
|
+
}}
|
|
524
|
+
/>
|
|
525
|
+
),
|
|
526
|
+
{ id: toastId, duration: Infinity },
|
|
527
|
+
);
|
|
528
|
+
try {
|
|
529
|
+
await exportSlideAsImagePptx(slide, slideId, (p) => {
|
|
530
|
+
toast.custom(() => <PptxProgressToast progress={p} />, {
|
|
531
|
+
id: toastId,
|
|
532
|
+
duration: Infinity,
|
|
533
|
+
});
|
|
534
|
+
});
|
|
535
|
+
} catch (err) {
|
|
536
|
+
console.error('[open-slide] image pptx export failed', err);
|
|
537
|
+
toast.error(t.slide.imagePptxExportFailed, {
|
|
538
|
+
id: toastId,
|
|
539
|
+
duration: 4000,
|
|
540
|
+
});
|
|
541
|
+
} finally {
|
|
542
|
+
setExporting(false);
|
|
543
|
+
toast.dismiss(toastId);
|
|
544
|
+
}
|
|
545
|
+
}}
|
|
546
|
+
>
|
|
547
|
+
<FileImage />
|
|
548
|
+
{t.slide.exportAsImagePptx}
|
|
549
|
+
</DropdownMenuItem>
|
|
550
|
+
<TooltipProvider delayDuration={200}>
|
|
551
|
+
<Tooltip>
|
|
552
|
+
<TooltipTrigger asChild>
|
|
553
|
+
<div
|
|
554
|
+
aria-disabled
|
|
555
|
+
className="relative flex cursor-help items-center justify-between gap-2 rounded-[5px] px-2 py-1.5 text-[12.5px] opacity-45 select-none [&_svg]:size-3.5 [&_svg]:shrink-0 [&_svg]:opacity-80"
|
|
556
|
+
>
|
|
557
|
+
<span className="flex items-center gap-2">
|
|
558
|
+
<Presentation />
|
|
559
|
+
{t.slide.exportAsPptx}
|
|
560
|
+
</span>
|
|
561
|
+
<span className="rounded-[3px] bg-muted px-1.5 py-0.5 font-mono text-[9.5px] tracking-[0.04em] text-muted-foreground">
|
|
562
|
+
{t.slide.comingSoon}
|
|
563
|
+
</span>
|
|
564
|
+
</div>
|
|
565
|
+
</TooltipTrigger>
|
|
566
|
+
<TooltipContent side="left" className="max-w-[240px] leading-relaxed">
|
|
567
|
+
{t.slide.pptxComingSoonTooltip}
|
|
568
|
+
</TooltipContent>
|
|
569
|
+
</Tooltip>
|
|
570
|
+
</TooltipProvider>
|
|
503
571
|
</DropdownMenuContent>
|
|
504
572
|
</DropdownMenu>
|
|
505
573
|
)}
|
|
@@ -581,7 +649,7 @@ export function Slide() {
|
|
|
581
649
|
data-slide-id={slideId}
|
|
582
650
|
className="paper relative min-h-0 min-w-0 flex-1 bg-canvas p-2 md:p-10"
|
|
583
651
|
>
|
|
584
|
-
<
|
|
652
|
+
<SlideViewportNavigation
|
|
585
653
|
targetRef={slideViewportRef}
|
|
586
654
|
onPrev={() => goTo(index - 1)}
|
|
587
655
|
onNext={() => goTo(index + 1)}
|
|
@@ -597,12 +665,6 @@ export function Slide() {
|
|
|
597
665
|
disabled={prefersReducedMotion}
|
|
598
666
|
/>
|
|
599
667
|
</SlideCanvas>
|
|
600
|
-
<ClickNavZones
|
|
601
|
-
onPrev={() => goTo(index - 1)}
|
|
602
|
-
onNext={() => goTo(index + 1)}
|
|
603
|
-
canPrev={index > 0}
|
|
604
|
-
canNext={index < pageCount - 1}
|
|
605
|
-
/>
|
|
606
668
|
<InspectOverlay />
|
|
607
669
|
<SaveBar />
|
|
608
670
|
{import.meta.env.DEV && <CommentWidget />}
|
|
@@ -814,7 +876,7 @@ function SelectionReporter() {
|
|
|
814
876
|
return null;
|
|
815
877
|
}
|
|
816
878
|
|
|
817
|
-
function
|
|
879
|
+
function SlideViewportNavigation({
|
|
818
880
|
targetRef,
|
|
819
881
|
onPrev,
|
|
820
882
|
onNext,
|
|
@@ -828,6 +890,7 @@ function SlideWheelNavigation({
|
|
|
828
890
|
canNext: boolean;
|
|
829
891
|
}) {
|
|
830
892
|
const { active } = useInspector();
|
|
893
|
+
const isMobile = useIsMobile();
|
|
831
894
|
|
|
832
895
|
useWheelPageNavigation({
|
|
833
896
|
ref: targetRef,
|
|
@@ -838,6 +901,19 @@ function SlideWheelNavigation({
|
|
|
838
901
|
onNext,
|
|
839
902
|
});
|
|
840
903
|
|
|
904
|
+
// Tap-to-navigate is a touch affordance — desktop has visible prev/next
|
|
905
|
+
// chrome, so it stays edge-only on small screens (matches the old md:hidden
|
|
906
|
+
// zones). Interactive slide content keeps its tap via the hook's passthrough.
|
|
907
|
+
useClickPageNavigation({
|
|
908
|
+
ref: targetRef,
|
|
909
|
+
enabled: isMobile && !active,
|
|
910
|
+
edgeRatio: 0.18,
|
|
911
|
+
canPrev,
|
|
912
|
+
canNext,
|
|
913
|
+
onPrev,
|
|
914
|
+
onNext,
|
|
915
|
+
});
|
|
916
|
+
|
|
841
917
|
return null;
|
|
842
918
|
}
|
|
843
919
|
|
|
@@ -890,49 +966,65 @@ function InlineTitleEditor({
|
|
|
890
966
|
|
|
891
967
|
if (editing) {
|
|
892
968
|
return (
|
|
893
|
-
<div className="flex flex-1 items-center justify-center">
|
|
894
|
-
<
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
}
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
969
|
+
<div className="flex min-w-0 flex-1 items-center justify-center">
|
|
970
|
+
<div className="inline-grid max-w-full items-center">
|
|
971
|
+
<span
|
|
972
|
+
aria-hidden
|
|
973
|
+
className="invisible col-start-1 row-start-1 overflow-hidden whitespace-pre border border-transparent px-2 py-0.5 font-heading text-[13.5px] font-semibold tracking-[-0.01em]"
|
|
974
|
+
>
|
|
975
|
+
{value || ' '}
|
|
976
|
+
</span>
|
|
977
|
+
<input
|
|
978
|
+
ref={inputRef}
|
|
979
|
+
size={1}
|
|
980
|
+
value={value}
|
|
981
|
+
disabled={saving}
|
|
982
|
+
onChange={(e) => setValue(e.target.value)}
|
|
983
|
+
onBlur={() => {
|
|
984
|
+
if (!saving) commit();
|
|
985
|
+
}}
|
|
986
|
+
onKeyDown={(e) => {
|
|
987
|
+
if (e.key === 'Enter') {
|
|
988
|
+
e.preventDefault();
|
|
989
|
+
commit();
|
|
990
|
+
} else if (e.key === 'Escape') {
|
|
991
|
+
e.preventDefault();
|
|
992
|
+
cancel();
|
|
993
|
+
}
|
|
994
|
+
}}
|
|
995
|
+
maxLength={80}
|
|
996
|
+
className="col-start-1 row-start-1 w-full min-w-0 rounded-[5px] border border-foreground/30 bg-card px-2 py-0.5 text-center font-heading text-[13.5px] font-semibold tracking-[-0.01em] outline-none"
|
|
997
|
+
/>
|
|
998
|
+
</div>
|
|
999
|
+
</div>
|
|
1000
|
+
);
|
|
1001
|
+
}
|
|
1002
|
+
|
|
1003
|
+
if (!import.meta.env.DEV) {
|
|
1004
|
+
return (
|
|
1005
|
+
<div className="flex min-w-0 items-baseline justify-center">
|
|
1006
|
+
<h1 className="truncate font-heading text-[13.5px] font-semibold tracking-[-0.01em]">
|
|
1007
|
+
{title}
|
|
1008
|
+
</h1>
|
|
914
1009
|
</div>
|
|
915
1010
|
);
|
|
916
1011
|
}
|
|
917
1012
|
|
|
918
1013
|
return (
|
|
919
|
-
<div className="
|
|
920
|
-
<
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
<Pencil className="size-3" />
|
|
934
|
-
</button>
|
|
935
|
-
)}
|
|
1014
|
+
<div className="flex min-w-0 items-center justify-center">
|
|
1015
|
+
<button
|
|
1016
|
+
type="button"
|
|
1017
|
+
onClick={() => setEditing(true)}
|
|
1018
|
+
aria-label={t.slide.renameSlide}
|
|
1019
|
+
className={cn(
|
|
1020
|
+
'min-w-0 max-w-full cursor-text rounded-[5px] border border-transparent px-2 py-0.5 transition-colors',
|
|
1021
|
+
'hover:border-foreground/30 hover:bg-card focus-visible:border-foreground/30 focus-visible:bg-card focus-visible:outline-none',
|
|
1022
|
+
)}
|
|
1023
|
+
>
|
|
1024
|
+
<h1 className="truncate font-heading text-[13.5px] font-semibold tracking-[-0.01em]">
|
|
1025
|
+
{title}
|
|
1026
|
+
</h1>
|
|
1027
|
+
</button>
|
|
936
1028
|
</div>
|
|
937
1029
|
);
|
|
938
1030
|
}
|
package/src/app/virtual.d.ts
CHANGED
package/src/locale/en.ts
CHANGED
|
@@ -44,6 +44,7 @@ export const en: Locale = {
|
|
|
44
44
|
folders: 'Folders',
|
|
45
45
|
newFolder: 'New folder',
|
|
46
46
|
folderName: 'Folder name',
|
|
47
|
+
updateAvailable: 'open-slide {version} is available — update the package to get the latest.',
|
|
47
48
|
changeIcon: 'Change icon',
|
|
48
49
|
iconEmojiTab: 'Emoji',
|
|
49
50
|
iconColorTab: 'Color',
|
|
@@ -86,6 +87,7 @@ export const en: Locale = {
|
|
|
86
87
|
toastSlideMoveFailed: 'Failed to move slide',
|
|
87
88
|
toastFolderDeleted: 'Deleted folder “{name}”',
|
|
88
89
|
toastFolderDeleteFailed: 'Failed to delete folder',
|
|
90
|
+
toastFolderReorderFailed: 'Failed to reorder folders',
|
|
89
91
|
pickIcon: 'Pick icon',
|
|
90
92
|
},
|
|
91
93
|
|
|
@@ -104,7 +106,13 @@ export const en: Locale = {
|
|
|
104
106
|
toastCopyLinkFailed: 'Failed to copy link',
|
|
105
107
|
exportAsHtml: 'Export as HTML',
|
|
106
108
|
exportAsPdf: 'Export as PDF',
|
|
109
|
+
exportAsImagePptx: 'Export as image PPTX',
|
|
110
|
+
exportAsPptx: 'Export as PPTX',
|
|
111
|
+
comingSoon: 'Coming soon',
|
|
112
|
+
pptxComingSoonTooltip:
|
|
113
|
+
'Editable PPTX export isn’t ready yet. For now, use “Export as image PPTX” instead.',
|
|
107
114
|
pdfExportFailed: 'PDF export failed',
|
|
115
|
+
imagePptxExportFailed: 'PPTX export failed',
|
|
108
116
|
pdfExportSafariUnsupported:
|
|
109
117
|
'Export as PDF is not supported on Safari. Please try a Chromium-based browser instead.',
|
|
110
118
|
present: 'Present',
|
|
@@ -344,6 +352,13 @@ export const en: Locale = {
|
|
|
344
352
|
done: 'Done',
|
|
345
353
|
},
|
|
346
354
|
|
|
355
|
+
pptxToast: {
|
|
356
|
+
title: 'Exporting PPTX',
|
|
357
|
+
processing: 'Rendering page {current} of {total}',
|
|
358
|
+
generating: 'Building presentation…',
|
|
359
|
+
done: 'Done',
|
|
360
|
+
},
|
|
361
|
+
|
|
347
362
|
themeToggle: {
|
|
348
363
|
toggleAria: 'Toggle theme',
|
|
349
364
|
title: 'Theme',
|
|
@@ -352,9 +367,9 @@ export const en: Locale = {
|
|
|
352
367
|
system: 'System',
|
|
353
368
|
},
|
|
354
369
|
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
370
|
+
languageToggle: {
|
|
371
|
+
toggleAria: 'Change language',
|
|
372
|
+
title: 'Language',
|
|
358
373
|
},
|
|
359
374
|
|
|
360
375
|
imagePlaceholder: {
|
package/src/locale/ja.ts
CHANGED
|
@@ -44,6 +44,8 @@ export const ja: Locale = {
|
|
|
44
44
|
folders: 'フォルダ',
|
|
45
45
|
newFolder: '新規フォルダ',
|
|
46
46
|
folderName: 'フォルダ名',
|
|
47
|
+
updateAvailable:
|
|
48
|
+
'open-slide {version} が利用可能です — パッケージを更新して最新版を入手してください。',
|
|
47
49
|
changeIcon: 'アイコンを変更',
|
|
48
50
|
iconEmojiTab: '絵文字',
|
|
49
51
|
iconColorTab: 'カラー',
|
|
@@ -86,6 +88,7 @@ export const ja: Locale = {
|
|
|
86
88
|
toastSlideMoveFailed: 'スライドの移動に失敗しました',
|
|
87
89
|
toastFolderDeleted: 'フォルダ「{name}」を削除しました',
|
|
88
90
|
toastFolderDeleteFailed: 'フォルダの削除に失敗しました',
|
|
91
|
+
toastFolderReorderFailed: 'フォルダの並び替えに失敗しました',
|
|
89
92
|
pickIcon: 'アイコンを選択',
|
|
90
93
|
},
|
|
91
94
|
|
|
@@ -104,7 +107,13 @@ export const ja: Locale = {
|
|
|
104
107
|
toastCopyLinkFailed: 'リンクのコピーに失敗しました',
|
|
105
108
|
exportAsHtml: 'HTML として書き出し',
|
|
106
109
|
exportAsPdf: 'PDF として書き出し',
|
|
110
|
+
exportAsImagePptx: '画像 PPTX として書き出し',
|
|
111
|
+
exportAsPptx: 'PPTX として書き出し',
|
|
112
|
+
comingSoon: '近日公開',
|
|
113
|
+
pptxComingSoonTooltip:
|
|
114
|
+
'編集可能な PPTX の書き出しはまだ対応していません。それまでは「画像 PPTX として書き出し」をご利用ください。',
|
|
107
115
|
pdfExportFailed: 'PDF の書き出しに失敗しました',
|
|
116
|
+
imagePptxExportFailed: 'PPTX の書き出しに失敗しました',
|
|
108
117
|
pdfExportSafariUnsupported:
|
|
109
118
|
'PDF の書き出しは現在 Safari では対応していません。Chromium ベースのブラウザでお試しください。',
|
|
110
119
|
present: '発表',
|
|
@@ -348,6 +357,13 @@ export const ja: Locale = {
|
|
|
348
357
|
done: '完了',
|
|
349
358
|
},
|
|
350
359
|
|
|
360
|
+
pptxToast: {
|
|
361
|
+
title: 'PPTX を書き出し中',
|
|
362
|
+
processing: 'ページ {current} / {total} を描画中',
|
|
363
|
+
generating: 'プレゼンテーションを構築中…',
|
|
364
|
+
done: '完了',
|
|
365
|
+
},
|
|
366
|
+
|
|
351
367
|
themeToggle: {
|
|
352
368
|
toggleAria: 'テーマを切り替え',
|
|
353
369
|
title: 'テーマ',
|
|
@@ -356,9 +372,9 @@ export const ja: Locale = {
|
|
|
356
372
|
system: 'システム',
|
|
357
373
|
},
|
|
358
374
|
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
375
|
+
languageToggle: {
|
|
376
|
+
toggleAria: '言語を切り替え',
|
|
377
|
+
title: '言語',
|
|
362
378
|
},
|
|
363
379
|
|
|
364
380
|
imagePlaceholder: {
|
package/src/locale/types.ts
CHANGED
|
@@ -44,6 +44,7 @@ export type Locale = {
|
|
|
44
44
|
folders: string;
|
|
45
45
|
newFolder: string;
|
|
46
46
|
folderName: string;
|
|
47
|
+
updateAvailable: string;
|
|
47
48
|
changeIcon: string;
|
|
48
49
|
iconEmojiTab: string;
|
|
49
50
|
iconColorTab: string;
|
|
@@ -90,6 +91,7 @@ export type Locale = {
|
|
|
90
91
|
/** template: "Deleted folder “{name}”" */
|
|
91
92
|
toastFolderDeleted: string;
|
|
92
93
|
toastFolderDeleteFailed: string;
|
|
94
|
+
toastFolderReorderFailed: string;
|
|
93
95
|
pickIcon: string;
|
|
94
96
|
};
|
|
95
97
|
|
|
@@ -106,7 +108,12 @@ export type Locale = {
|
|
|
106
108
|
toastCopyLinkFailed: string;
|
|
107
109
|
exportAsHtml: string;
|
|
108
110
|
exportAsPdf: string;
|
|
111
|
+
exportAsImagePptx: string;
|
|
112
|
+
exportAsPptx: string;
|
|
113
|
+
comingSoon: string;
|
|
114
|
+
pptxComingSoonTooltip: string;
|
|
109
115
|
pdfExportFailed: string;
|
|
116
|
+
imagePptxExportFailed: string;
|
|
110
117
|
pdfExportSafariUnsupported: string;
|
|
111
118
|
present: string;
|
|
112
119
|
presentMenuAria: string;
|
|
@@ -367,6 +374,14 @@ export type Locale = {
|
|
|
367
374
|
done: string;
|
|
368
375
|
};
|
|
369
376
|
|
|
377
|
+
pptxToast: {
|
|
378
|
+
title: string;
|
|
379
|
+
/** template: "Rendering page {current} of {total}" */
|
|
380
|
+
processing: string;
|
|
381
|
+
generating: string;
|
|
382
|
+
done: string;
|
|
383
|
+
};
|
|
384
|
+
|
|
370
385
|
themeToggle: {
|
|
371
386
|
toggleAria: string;
|
|
372
387
|
title: string;
|
|
@@ -375,9 +390,9 @@ export type Locale = {
|
|
|
375
390
|
system: string;
|
|
376
391
|
};
|
|
377
392
|
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
393
|
+
languageToggle: {
|
|
394
|
+
toggleAria: string;
|
|
395
|
+
title: string;
|
|
381
396
|
};
|
|
382
397
|
|
|
383
398
|
imagePlaceholder: {
|
package/src/locale/zh-cn.ts
CHANGED
|
@@ -44,6 +44,7 @@ export const zhCN: Locale = {
|
|
|
44
44
|
folders: '文件夹',
|
|
45
45
|
newFolder: '新建文件夹',
|
|
46
46
|
folderName: '文件夹名称',
|
|
47
|
+
updateAvailable: 'open-slide {version} 已发布,请更新软件包以获取最新版本。',
|
|
47
48
|
changeIcon: '更换图标',
|
|
48
49
|
iconEmojiTab: 'Emoji',
|
|
49
50
|
iconColorTab: '颜色',
|
|
@@ -86,6 +87,7 @@ export const zhCN: Locale = {
|
|
|
86
87
|
toastSlideMoveFailed: '移动幻灯片失败',
|
|
87
88
|
toastFolderDeleted: '已删除文件夹"{name}"',
|
|
88
89
|
toastFolderDeleteFailed: '删除文件夹失败',
|
|
90
|
+
toastFolderReorderFailed: '文件夹排序失败',
|
|
89
91
|
pickIcon: '选择图标',
|
|
90
92
|
},
|
|
91
93
|
|
|
@@ -103,7 +105,12 @@ export const zhCN: Locale = {
|
|
|
103
105
|
toastCopyLinkFailed: '复制链接失败',
|
|
104
106
|
exportAsHtml: '导出为 HTML',
|
|
105
107
|
exportAsPdf: '导出为 PDF',
|
|
108
|
+
exportAsImagePptx: '导出图片 PPTX',
|
|
109
|
+
exportAsPptx: '导出 PPTX',
|
|
110
|
+
comingSoon: '即将推出',
|
|
111
|
+
pptxComingSoonTooltip: '可编辑的 PPTX 导出尚未支持,在此之前可以先使用“导出图片 PPTX”。',
|
|
106
112
|
pdfExportFailed: 'PDF 导出失败',
|
|
113
|
+
imagePptxExportFailed: 'PPTX 导出失败',
|
|
107
114
|
pdfExportSafariUnsupported:
|
|
108
115
|
'导出 PDF 目前不支持 Safari 设备,请尝试使用基于 Chromium 的浏览器替代。',
|
|
109
116
|
present: '演示',
|
|
@@ -343,6 +350,13 @@ export const zhCN: Locale = {
|
|
|
343
350
|
done: '完成',
|
|
344
351
|
},
|
|
345
352
|
|
|
353
|
+
pptxToast: {
|
|
354
|
+
title: '导出 PPTX',
|
|
355
|
+
processing: '正在渲染第 {current} / {total} 页',
|
|
356
|
+
generating: '正在组合演示文稿…',
|
|
357
|
+
done: '完成',
|
|
358
|
+
},
|
|
359
|
+
|
|
346
360
|
themeToggle: {
|
|
347
361
|
toggleAria: '切换主题',
|
|
348
362
|
title: '主题',
|
|
@@ -351,9 +365,9 @@ export const zhCN: Locale = {
|
|
|
351
365
|
system: '系统',
|
|
352
366
|
},
|
|
353
367
|
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
368
|
+
languageToggle: {
|
|
369
|
+
toggleAria: '切换语言',
|
|
370
|
+
title: '语言',
|
|
357
371
|
},
|
|
358
372
|
|
|
359
373
|
imagePlaceholder: {
|
package/src/locale/zh-tw.ts
CHANGED
|
@@ -44,6 +44,7 @@ export const zhTW: Locale = {
|
|
|
44
44
|
folders: '資料夾',
|
|
45
45
|
newFolder: '新增資料夾',
|
|
46
46
|
folderName: '資料夾名稱',
|
|
47
|
+
updateAvailable: 'open-slide {version} 已發布,請更新套件以取得最新版本。',
|
|
47
48
|
changeIcon: '變更圖示',
|
|
48
49
|
iconEmojiTab: 'Emoji',
|
|
49
50
|
iconColorTab: '顏色',
|
|
@@ -86,6 +87,7 @@ export const zhTW: Locale = {
|
|
|
86
87
|
toastSlideMoveFailed: '移動投影片失敗',
|
|
87
88
|
toastFolderDeleted: '已刪除資料夾「{name}」',
|
|
88
89
|
toastFolderDeleteFailed: '刪除資料夾失敗',
|
|
90
|
+
toastFolderReorderFailed: '資料夾排序失敗',
|
|
89
91
|
pickIcon: '選擇圖示',
|
|
90
92
|
},
|
|
91
93
|
|
|
@@ -103,7 +105,12 @@ export const zhTW: Locale = {
|
|
|
103
105
|
toastCopyLinkFailed: '複製連結失敗',
|
|
104
106
|
exportAsHtml: '匯出為 HTML',
|
|
105
107
|
exportAsPdf: '匯出為 PDF',
|
|
108
|
+
exportAsImagePptx: '匯出圖片 PPTX',
|
|
109
|
+
exportAsPptx: '匯出 PPTX',
|
|
110
|
+
comingSoon: '即將推出',
|
|
111
|
+
pptxComingSoonTooltip: '可編輯的 PPTX 匯出尚未支援,在此之前可以先使用「匯出圖片 PPTX」。',
|
|
106
112
|
pdfExportFailed: 'PDF 匯出失敗',
|
|
113
|
+
imagePptxExportFailed: 'PPTX 匯出失敗',
|
|
107
114
|
pdfExportSafariUnsupported:
|
|
108
115
|
'匯出 PDF 目前不支援 Safari 裝置,請嘗試用 Chromium 基底瀏覽器替代。',
|
|
109
116
|
present: '簡報',
|
|
@@ -343,6 +350,13 @@ export const zhTW: Locale = {
|
|
|
343
350
|
done: '完成',
|
|
344
351
|
},
|
|
345
352
|
|
|
353
|
+
pptxToast: {
|
|
354
|
+
title: '匯出 PPTX',
|
|
355
|
+
processing: '正在算繪第 {current} / {total} 頁',
|
|
356
|
+
generating: '正在組合簡報…',
|
|
357
|
+
done: '完成',
|
|
358
|
+
},
|
|
359
|
+
|
|
346
360
|
themeToggle: {
|
|
347
361
|
toggleAria: '切換主題',
|
|
348
362
|
title: '主題',
|
|
@@ -351,9 +365,9 @@ export const zhTW: Locale = {
|
|
|
351
365
|
system: '系統',
|
|
352
366
|
},
|
|
353
367
|
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
368
|
+
languageToggle: {
|
|
369
|
+
toggleAria: '切換語言',
|
|
370
|
+
title: '語言',
|
|
357
371
|
},
|
|
358
372
|
|
|
359
373
|
imagePlaceholder: {
|