@open-slide/core 1.2.0 → 1.3.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-6BeQ3cxb.js → build-_276DMmJ.js} +2 -2
- package/dist/cli/bin.js +5 -5
- package/dist/{config-AxZ5OE1u.js → config-BAwKWNtW.js} +215 -18
- package/dist/{config-CtT8K4VF.d.ts → config-D9cZ1A0X.d.ts} +2 -1
- package/dist/{dev-C9eLmUEq.js → dev-BoqeVXVq.js} +2 -2
- package/dist/en-CDKzoZvf.js +351 -0
- package/dist/index.d.ts +4 -3
- package/dist/index.js +229 -39
- package/dist/locale/index.d.ts +1 -1
- package/dist/locale/index.js +97 -333
- package/dist/{preview-Cunm-f4i.js → preview-BLPxspc9.js} +2 -2
- package/dist/sync-j9_QPovT.js +3 -0
- package/dist/{types-CRHIeoNq.d.ts → types-JYG1cmwC.d.ts} +31 -1
- package/dist/vite/index.d.ts +2 -2
- package/dist/vite/index.js +2 -2
- package/package.json +9 -1
- package/skills/create-slide/SKILL.md +1 -1
- package/skills/create-theme/SKILL.md +60 -12
- package/skills/slide-authoring/SKILL.md +11 -0
- package/src/app/app.tsx +11 -1
- package/src/app/components/asset-view.tsx +1 -13
- package/src/app/components/image-placeholder.tsx +123 -1
- package/src/app/components/inspector/inspector-panel.tsx +123 -10
- package/src/app/components/sidebar/folder-item.tsx +16 -5
- package/src/app/components/sidebar/mobile-pill.tsx +34 -0
- package/src/app/components/sidebar/sidebar.tsx +10 -0
- package/src/app/components/themes/theme-detail.tsx +300 -0
- package/src/app/components/themes/themes-gallery.tsx +146 -0
- package/src/app/components/thumbnail-rail.tsx +17 -5
- package/src/app/lib/assets.ts +55 -2
- package/src/app/lib/sdk.ts +1 -0
- package/src/app/lib/slides.ts +10 -1
- package/src/app/lib/themes.ts +22 -0
- package/src/app/lib/use-agent-socket.ts +18 -0
- package/src/app/routes/home-shell.tsx +173 -0
- package/src/app/routes/home.tsx +89 -207
- package/src/app/routes/slide.tsx +144 -14
- package/src/app/routes/themes.tsx +34 -0
- package/src/app/virtual.d.ts +20 -0
- package/src/locale/en.ts +35 -3
- package/src/locale/ja.ts +36 -3
- package/src/locale/types.ts +33 -1
- package/src/locale/zh-cn.ts +35 -3
- package/src/locale/zh-tw.ts +35 -3
- package/dist/sync-B4eLo2H6.js +0 -3
- /package/dist/{design-C13iz9_4.js → design-cpzS8aud.js} +0 -0
- /package/dist/{sync-3oqN1WyK.js → sync-BCJDRIqo.js} +0 -0
package/src/app/routes/slide.tsx
CHANGED
|
@@ -26,6 +26,7 @@ import {
|
|
|
26
26
|
import { Tabs, TabsList, TabsTrigger } from '@/components/ui/tabs';
|
|
27
27
|
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip';
|
|
28
28
|
import { useFolders } from '@/lib/folders';
|
|
29
|
+
import { useAgentSocketConnected } from '@/lib/use-agent-socket';
|
|
29
30
|
import { format, useLocale } from '@/lib/use-locale';
|
|
30
31
|
import { useWheelPageNavigation } from '@/lib/use-wheel-page-navigation';
|
|
31
32
|
import { cn } from '@/lib/utils';
|
|
@@ -483,19 +484,18 @@ export function Slide() {
|
|
|
483
484
|
<DesignProvider slideId={slideId}>
|
|
484
485
|
<div className="flex min-h-0 flex-1 flex-col">
|
|
485
486
|
<div className="flex min-h-0 flex-1 flex-col md:flex-row">
|
|
486
|
-
<
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
/>
|
|
495
|
-
</div>
|
|
487
|
+
<ResizableRail
|
|
488
|
+
pages={pages}
|
|
489
|
+
design={slide.design}
|
|
490
|
+
current={index}
|
|
491
|
+
onSelect={goTo}
|
|
492
|
+
onReorder={import.meta.env.DEV ? reorderPage : undefined}
|
|
493
|
+
actions={thumbnailActions}
|
|
494
|
+
/>
|
|
496
495
|
<main
|
|
497
496
|
ref={slideViewportRef}
|
|
498
497
|
data-inspector-root
|
|
498
|
+
data-slide-id={slideId}
|
|
499
499
|
className="paper relative min-h-0 min-w-0 flex-1 bg-canvas p-2 md:p-10"
|
|
500
500
|
>
|
|
501
501
|
<SlideWheelNavigation
|
|
@@ -553,8 +553,132 @@ export function Slide() {
|
|
|
553
553
|
);
|
|
554
554
|
}
|
|
555
555
|
|
|
556
|
+
const RAIL_WIDTH_STORAGE_KEY = 'open-slide:thumbnail-rail-width';
|
|
557
|
+
const DEFAULT_RAIL_WIDTH = 264;
|
|
558
|
+
const MIN_RAIL_WIDTH = 200;
|
|
559
|
+
const MAX_RAIL_WIDTH = 480;
|
|
560
|
+
|
|
561
|
+
function readStoredRailWidth(): number {
|
|
562
|
+
if (typeof window === 'undefined') return DEFAULT_RAIL_WIDTH;
|
|
563
|
+
const raw = window.localStorage.getItem(RAIL_WIDTH_STORAGE_KEY);
|
|
564
|
+
const parsed = raw == null ? Number.NaN : Number(raw);
|
|
565
|
+
if (!Number.isFinite(parsed)) return DEFAULT_RAIL_WIDTH;
|
|
566
|
+
return Math.min(MAX_RAIL_WIDTH, Math.max(MIN_RAIL_WIDTH, parsed));
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
function ResizableRail(props: {
|
|
570
|
+
pages: SlideModule['default'];
|
|
571
|
+
design?: SlideModule['design'];
|
|
572
|
+
current: number;
|
|
573
|
+
onSelect: (i: number) => void;
|
|
574
|
+
onReorder?: (from: number, to: number) => void;
|
|
575
|
+
actions?: ThumbnailActions;
|
|
576
|
+
}) {
|
|
577
|
+
const t = useLocale();
|
|
578
|
+
const [width, setWidth] = useState<number>(readStoredRailWidth);
|
|
579
|
+
const [resizing, setResizing] = useState(false);
|
|
580
|
+
const dragRef = useRef<{ startX: number; startWidth: number } | null>(null);
|
|
581
|
+
|
|
582
|
+
useEffect(() => {
|
|
583
|
+
if (typeof window === 'undefined') return;
|
|
584
|
+
window.localStorage.setItem(RAIL_WIDTH_STORAGE_KEY, String(width));
|
|
585
|
+
}, [width]);
|
|
586
|
+
|
|
587
|
+
useEffect(() => {
|
|
588
|
+
if (!resizing) return;
|
|
589
|
+
const prev = {
|
|
590
|
+
cursor: document.body.style.cursor,
|
|
591
|
+
userSelect: document.body.style.userSelect,
|
|
592
|
+
};
|
|
593
|
+
document.body.style.cursor = 'col-resize';
|
|
594
|
+
document.body.style.userSelect = 'none';
|
|
595
|
+
return () => {
|
|
596
|
+
document.body.style.cursor = prev.cursor;
|
|
597
|
+
document.body.style.userSelect = prev.userSelect;
|
|
598
|
+
};
|
|
599
|
+
}, [resizing]);
|
|
600
|
+
|
|
601
|
+
const onPointerDown = (e: React.PointerEvent<HTMLDivElement>) => {
|
|
602
|
+
e.preventDefault();
|
|
603
|
+
e.currentTarget.setPointerCapture(e.pointerId);
|
|
604
|
+
dragRef.current = { startX: e.clientX, startWidth: width };
|
|
605
|
+
setResizing(true);
|
|
606
|
+
};
|
|
607
|
+
|
|
608
|
+
const onPointerMove = (e: React.PointerEvent<HTMLDivElement>) => {
|
|
609
|
+
if (!dragRef.current) return;
|
|
610
|
+
const delta = e.clientX - dragRef.current.startX;
|
|
611
|
+
const next = Math.min(
|
|
612
|
+
MAX_RAIL_WIDTH,
|
|
613
|
+
Math.max(MIN_RAIL_WIDTH, dragRef.current.startWidth + delta),
|
|
614
|
+
);
|
|
615
|
+
setWidth(next);
|
|
616
|
+
};
|
|
617
|
+
|
|
618
|
+
const onPointerUp = (e: React.PointerEvent<HTMLDivElement>) => {
|
|
619
|
+
if (e.currentTarget.hasPointerCapture(e.pointerId)) {
|
|
620
|
+
e.currentTarget.releasePointerCapture(e.pointerId);
|
|
621
|
+
}
|
|
622
|
+
dragRef.current = null;
|
|
623
|
+
setResizing(false);
|
|
624
|
+
};
|
|
625
|
+
|
|
626
|
+
const onKeyDown = (e: React.KeyboardEvent<HTMLDivElement>) => {
|
|
627
|
+
const step = e.shiftKey ? 32 : 8;
|
|
628
|
+
if (e.key === 'ArrowLeft') {
|
|
629
|
+
e.preventDefault();
|
|
630
|
+
e.stopPropagation();
|
|
631
|
+
setWidth((w) => Math.max(MIN_RAIL_WIDTH, w - step));
|
|
632
|
+
} else if (e.key === 'ArrowRight') {
|
|
633
|
+
e.preventDefault();
|
|
634
|
+
e.stopPropagation();
|
|
635
|
+
setWidth((w) => Math.min(MAX_RAIL_WIDTH, w + step));
|
|
636
|
+
} else if (e.key === 'Home') {
|
|
637
|
+
e.preventDefault();
|
|
638
|
+
e.stopPropagation();
|
|
639
|
+
setWidth(DEFAULT_RAIL_WIDTH);
|
|
640
|
+
}
|
|
641
|
+
};
|
|
642
|
+
|
|
643
|
+
return (
|
|
644
|
+
<div className="relative hidden shrink-0 md:block" style={{ width }}>
|
|
645
|
+
<ThumbnailRail width={width} {...props} />
|
|
646
|
+
{/* biome-ignore lint/a11y/useSemanticElements: focusable resize handle (splitter pattern), not a static <hr> */}
|
|
647
|
+
<div
|
|
648
|
+
role="separator"
|
|
649
|
+
aria-orientation="vertical"
|
|
650
|
+
aria-label={t.thumbnailRail.resizeRail}
|
|
651
|
+
aria-valuenow={width}
|
|
652
|
+
aria-valuemin={MIN_RAIL_WIDTH}
|
|
653
|
+
aria-valuemax={MAX_RAIL_WIDTH}
|
|
654
|
+
tabIndex={0}
|
|
655
|
+
onPointerDown={onPointerDown}
|
|
656
|
+
onPointerMove={onPointerMove}
|
|
657
|
+
onPointerUp={onPointerUp}
|
|
658
|
+
onPointerCancel={onPointerUp}
|
|
659
|
+
onKeyDown={onKeyDown}
|
|
660
|
+
onDoubleClick={() => setWidth(DEFAULT_RAIL_WIDTH)}
|
|
661
|
+
className={cn(
|
|
662
|
+
'group/resize absolute inset-y-0 right-0 z-20 w-1.5 translate-x-1/2 cursor-col-resize touch-none outline-none',
|
|
663
|
+
'focus-visible:bg-brand/20',
|
|
664
|
+
)}
|
|
665
|
+
>
|
|
666
|
+
<span
|
|
667
|
+
aria-hidden
|
|
668
|
+
className={cn(
|
|
669
|
+
'pointer-events-none absolute inset-y-0 left-1/2 w-px -translate-x-1/2 bg-brand opacity-0 transition-opacity',
|
|
670
|
+
'group-hover/resize:opacity-100 group-focus-visible/resize:opacity-100',
|
|
671
|
+
resizing && 'opacity-100',
|
|
672
|
+
)}
|
|
673
|
+
/>
|
|
674
|
+
</div>
|
|
675
|
+
</div>
|
|
676
|
+
);
|
|
677
|
+
}
|
|
678
|
+
|
|
556
679
|
function AgentConnectedBadge() {
|
|
557
680
|
const t = useLocale();
|
|
681
|
+
const connected = useAgentSocketConnected();
|
|
558
682
|
return (
|
|
559
683
|
<TooltipProvider delayDuration={200}>
|
|
560
684
|
<Tooltip>
|
|
@@ -564,14 +688,20 @@ function AgentConnectedBadge() {
|
|
|
564
688
|
className="ml-1 flex shrink-0 cursor-help items-center gap-1.5 rounded-[3px] border border-hairline bg-card px-1.5 py-0.5 text-[10.5px] text-foreground/85 outline-none focus-visible:ring-2 focus-visible:ring-ring/30"
|
|
565
689
|
>
|
|
566
690
|
<span aria-hidden className="relative flex size-1.5 items-center justify-center">
|
|
567
|
-
|
|
568
|
-
|
|
691
|
+
{connected ? (
|
|
692
|
+
<>
|
|
693
|
+
<span className="absolute inline-flex size-full animate-ping rounded-full bg-emerald-500 opacity-60" />
|
|
694
|
+
<span className="relative inline-flex size-1.5 rounded-full bg-emerald-500" />
|
|
695
|
+
</>
|
|
696
|
+
) : (
|
|
697
|
+
<span className="relative inline-flex size-1.5 rounded-full bg-rose-500" />
|
|
698
|
+
)}
|
|
569
699
|
</span>
|
|
570
|
-
{t.slide.agentConnected}
|
|
700
|
+
{connected ? t.slide.agentConnected : t.slide.agentDisconnected}
|
|
571
701
|
</button>
|
|
572
702
|
</TooltipTrigger>
|
|
573
703
|
<TooltipContent side="bottom" align="start" className="max-w-[280px] leading-relaxed">
|
|
574
|
-
{t.slide.agentConnectedTooltip}
|
|
704
|
+
{connected ? t.slide.agentConnectedTooltip : t.slide.agentDisconnectedTooltip}
|
|
575
705
|
</TooltipContent>
|
|
576
706
|
</Tooltip>
|
|
577
707
|
</TooltipProvider>
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { useNavigate, useParams } from 'react-router-dom';
|
|
2
|
+
import { useLocale } from '@/lib/use-locale';
|
|
3
|
+
import { FolderIconChip } from '../components/sidebar/folder-item';
|
|
4
|
+
import { ThemeDetail } from '../components/themes/theme-detail';
|
|
5
|
+
import { ThemesGallery } from '../components/themes/themes-gallery';
|
|
6
|
+
import { themes as themeRegistry } from '../lib/themes';
|
|
7
|
+
|
|
8
|
+
export function ThemesGalleryPage() {
|
|
9
|
+
const navigate = useNavigate();
|
|
10
|
+
const t = useLocale();
|
|
11
|
+
return (
|
|
12
|
+
<>
|
|
13
|
+
<header className="mb-8 md:mb-12">
|
|
14
|
+
<div className="flex flex-wrap items-center gap-3">
|
|
15
|
+
<FolderIconChip icon={{ type: 'emoji', value: '🎨' }} className="size-7 text-2xl" />
|
|
16
|
+
<h1 className="font-heading text-[32px] font-semibold leading-[1.05] tracking-[-0.025em] md:text-[44px]">
|
|
17
|
+
{t.themes.title}
|
|
18
|
+
</h1>
|
|
19
|
+
<span className="folio ml-1 self-end pb-2">
|
|
20
|
+
{themeRegistry.length.toString().padStart(2, '0')}
|
|
21
|
+
</span>
|
|
22
|
+
</div>
|
|
23
|
+
</header>
|
|
24
|
+
<ThemesGallery onOpen={(id) => navigate(`/themes/${encodeURIComponent(id)}`)} />
|
|
25
|
+
</>
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function ThemeDetailPage() {
|
|
30
|
+
const { themeId } = useParams<{ themeId: string }>();
|
|
31
|
+
const navigate = useNavigate();
|
|
32
|
+
if (!themeId) return null;
|
|
33
|
+
return <ThemeDetail themeId={themeId} onBack={() => navigate('/themes')} />;
|
|
34
|
+
}
|
package/src/app/virtual.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
declare module 'virtual:open-slide/slides' {
|
|
2
2
|
import type { SlideModule } from './lib/sdk';
|
|
3
3
|
export const slideIds: string[];
|
|
4
|
+
export const slideThemes: Record<string, string>;
|
|
4
5
|
export function loadSlide(id: string): Promise<SlideModule>;
|
|
5
6
|
}
|
|
6
7
|
|
|
@@ -26,3 +27,22 @@ declare module 'virtual:open-slide/folders' {
|
|
|
26
27
|
const manifest: FoldersManifest;
|
|
27
28
|
export default manifest;
|
|
28
29
|
}
|
|
30
|
+
|
|
31
|
+
declare module 'virtual:open-slide/themes' {
|
|
32
|
+
import type { DesignSystem } from './lib/design';
|
|
33
|
+
import type { Page } from './lib/sdk';
|
|
34
|
+
|
|
35
|
+
export type ThemeMeta = {
|
|
36
|
+
id: string;
|
|
37
|
+
name: string;
|
|
38
|
+
description: string;
|
|
39
|
+
body: string;
|
|
40
|
+
hasDemo: boolean;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
export const themes: ThemeMeta[];
|
|
44
|
+
export function loadThemeDemo(id: string): Promise<{
|
|
45
|
+
default: Page[];
|
|
46
|
+
design?: DesignSystem;
|
|
47
|
+
}>;
|
|
48
|
+
}
|
package/src/locale/en.ts
CHANGED
|
@@ -38,6 +38,7 @@ export const en: Locale = {
|
|
|
38
38
|
home: {
|
|
39
39
|
appTitle: 'open-slide',
|
|
40
40
|
draft: 'Draft',
|
|
41
|
+
themes: 'Themes',
|
|
41
42
|
folders: 'Folders',
|
|
42
43
|
newFolder: 'New folder',
|
|
43
44
|
folderName: 'Folder name',
|
|
@@ -51,9 +52,8 @@ export const en: Locale = {
|
|
|
51
52
|
nothingMatchesPrefix: 'Nothing matches ',
|
|
52
53
|
nothingMatchesSuffix: ' in this folder.',
|
|
53
54
|
noSlidesYet: 'No slides yet',
|
|
54
|
-
createSlideHintPrefix: '
|
|
55
|
-
|
|
56
|
-
createSlideHintSuffix: '.',
|
|
55
|
+
createSlideHintPrefix: 'Run ',
|
|
56
|
+
createSlideHintSuffix: ' in your agent to scaffold one.',
|
|
57
57
|
folderEmptyTitle: '{name} is empty',
|
|
58
58
|
folderEmptyHint: 'Drag a slide from Draft into this folder in the sidebar.',
|
|
59
59
|
slideActions: 'Slide actions',
|
|
@@ -86,6 +86,9 @@ export const en: Locale = {
|
|
|
86
86
|
agentConnected: 'Agent connected',
|
|
87
87
|
agentConnectedTooltip:
|
|
88
88
|
'The dev server is publishing your current slide and inspector selection to your agent. Ask "this slide" or "this element" in chat and it will resolve. Disappears in production builds.',
|
|
89
|
+
agentDisconnected: 'Agent disconnected',
|
|
90
|
+
agentDisconnectedTooltip:
|
|
91
|
+
'Lost connection to the dev server, so your agent can no longer see the current slide or inspector selection. Restart the dev server to restore the connection.',
|
|
89
92
|
download: 'Download',
|
|
90
93
|
exportAsHtml: 'Export as HTML',
|
|
91
94
|
exportAsPdf: 'Export as PDF',
|
|
@@ -162,6 +165,9 @@ export const en: Locale = {
|
|
|
162
165
|
agentWatching: 'Agent is watching',
|
|
163
166
|
agentWatchingTooltip:
|
|
164
167
|
'Your agent already sees the selected element via the dev server — just ask it in chat. Leave comments here only when you want to queue a few before asking.',
|
|
168
|
+
agentNotWatching: 'Agent not watching',
|
|
169
|
+
agentNotWatchingTooltip:
|
|
170
|
+
'Lost connection to the dev server, so your agent can no longer see the selected element. Restart the dev server to restore the connection.',
|
|
165
171
|
contentSection: 'Content',
|
|
166
172
|
typographySection: 'Typography',
|
|
167
173
|
colorSection: 'Color',
|
|
@@ -301,6 +307,7 @@ export const en: Locale = {
|
|
|
301
307
|
toastDeleted: 'Deleted page {n}',
|
|
302
308
|
toastDuplicateFailed: 'Could not duplicate page',
|
|
303
309
|
toastDeleteFailed: 'Could not delete page',
|
|
310
|
+
resizeRail: 'Resize thumbnail rail',
|
|
304
311
|
},
|
|
305
312
|
|
|
306
313
|
pdfToast: {
|
|
@@ -323,6 +330,12 @@ export const en: Locale = {
|
|
|
323
330
|
nextAria: 'Next page',
|
|
324
331
|
},
|
|
325
332
|
|
|
333
|
+
imagePlaceholder: {
|
|
334
|
+
dropOverlay: 'Drop image to use here',
|
|
335
|
+
uploading: 'Uploading…',
|
|
336
|
+
uploadFailed: "Couldn't upload image",
|
|
337
|
+
},
|
|
338
|
+
|
|
326
339
|
notesDrawer: {
|
|
327
340
|
toggle: 'Notes',
|
|
328
341
|
pageLabel: 'page {n}/{total}',
|
|
@@ -331,4 +344,23 @@ export const en: Locale = {
|
|
|
331
344
|
statusSaved: 'Saved',
|
|
332
345
|
statusError: 'Save failed: {msg}',
|
|
333
346
|
},
|
|
347
|
+
|
|
348
|
+
themes: {
|
|
349
|
+
title: 'Themes',
|
|
350
|
+
noThemesTitle: 'No themes yet',
|
|
351
|
+
noThemesHintPrefix: 'Run ',
|
|
352
|
+
noThemesHintSuffix: ' to author one — a markdown file under themes/ plus a sibling demo slide.',
|
|
353
|
+
noDemoYet: 'No demo yet',
|
|
354
|
+
noDemoHintPrefix: 'Re-run ',
|
|
355
|
+
noDemoHintSuffix: ' for this theme to generate a preview slide.',
|
|
356
|
+
backToGallery: 'Back to themes',
|
|
357
|
+
pageOf: 'page {n}/{total}',
|
|
358
|
+
nextPageAria: 'Next page',
|
|
359
|
+
prevPageAria: 'Previous page',
|
|
360
|
+
openThemeAria: 'Open theme {name}',
|
|
361
|
+
usedBy: 'Slides using this theme',
|
|
362
|
+
usedByEmpty: 'No slides use this theme yet.',
|
|
363
|
+
expandPromptAria: 'Expand prompt',
|
|
364
|
+
collapsePromptAria: 'Collapse prompt',
|
|
365
|
+
},
|
|
334
366
|
};
|
package/src/locale/ja.ts
CHANGED
|
@@ -38,6 +38,7 @@ export const ja: Locale = {
|
|
|
38
38
|
home: {
|
|
39
39
|
appTitle: 'open-slide',
|
|
40
40
|
draft: '下書き',
|
|
41
|
+
themes: 'テーマ',
|
|
41
42
|
folders: 'フォルダ',
|
|
42
43
|
newFolder: '新規フォルダ',
|
|
43
44
|
folderName: 'フォルダ名',
|
|
@@ -51,9 +52,8 @@ export const ja: Locale = {
|
|
|
51
52
|
nothingMatchesPrefix: 'このフォルダ内に ',
|
|
52
53
|
nothingMatchesSuffix: ' に一致する項目はありません。',
|
|
53
54
|
noSlidesYet: 'スライドはまだありません',
|
|
54
|
-
createSlideHintPrefix: '',
|
|
55
|
-
|
|
56
|
-
createSlideHintSuffix: ' してください。',
|
|
55
|
+
createSlideHintPrefix: 'エージェントで ',
|
|
56
|
+
createSlideHintSuffix: ' を実行してスライドを作成しましょう。',
|
|
57
57
|
folderEmptyTitle: '{name} は空です',
|
|
58
58
|
folderEmptyHint: 'サイドバーから下書きのスライドをこのフォルダにドラッグしてください。',
|
|
59
59
|
slideActions: 'スライド操作',
|
|
@@ -84,6 +84,9 @@ export const ja: Locale = {
|
|
|
84
84
|
agentConnected: 'エージェント接続中',
|
|
85
85
|
agentConnectedTooltip:
|
|
86
86
|
'現在のスライドと Inspector の選択状態を dev server がエージェントに公開しています。チャットで「このスライド」「この要素」と言えば認識されます。本番ビルドでは表示されません。',
|
|
87
|
+
agentDisconnected: 'エージェント切断',
|
|
88
|
+
agentDisconnectedTooltip:
|
|
89
|
+
'dev server との接続が切れたため、現在のスライドや Inspector の選択がエージェントに届かなくなっています。dev server を再起動して接続を復旧してください。',
|
|
87
90
|
home: 'ホーム',
|
|
88
91
|
backToHome: 'ホームへ戻る',
|
|
89
92
|
download: 'ダウンロード',
|
|
@@ -199,6 +202,9 @@ export const ja: Locale = {
|
|
|
199
202
|
agentWatching: 'エージェント監視中',
|
|
200
203
|
agentWatchingTooltip:
|
|
201
204
|
'エージェントは選択中の要素を dev server 経由で把握しています。直接チャットで頼めます。ここにコメントを残すのは、複数の依頼をまとめて出したいときだけで OK。',
|
|
205
|
+
agentNotWatching: 'エージェント未接続',
|
|
206
|
+
agentNotWatchingTooltip:
|
|
207
|
+
'dev server との接続が切れたため、選択中の要素がエージェントに見えなくなっています。dev server を再起動して接続を復旧してください。',
|
|
202
208
|
leaveComment: 'コメントを残す',
|
|
203
209
|
commentPlaceholder: 'エージェントに依頼する変更を記述…',
|
|
204
210
|
commentShortcutHint: '⌘↵ で追加',
|
|
@@ -305,6 +311,7 @@ export const ja: Locale = {
|
|
|
305
311
|
toastDeleted: 'ページ {n} を削除しました',
|
|
306
312
|
toastDuplicateFailed: 'ページを複製できませんでした',
|
|
307
313
|
toastDeleteFailed: 'ページを削除できませんでした',
|
|
314
|
+
resizeRail: 'サムネイル幅を調整',
|
|
308
315
|
},
|
|
309
316
|
|
|
310
317
|
pdfToast: {
|
|
@@ -327,6 +334,12 @@ export const ja: Locale = {
|
|
|
327
334
|
nextAria: '次のページ',
|
|
328
335
|
},
|
|
329
336
|
|
|
337
|
+
imagePlaceholder: {
|
|
338
|
+
dropOverlay: 'ここにドロップして使用',
|
|
339
|
+
uploading: 'アップロード中…',
|
|
340
|
+
uploadFailed: '画像のアップロードに失敗しました',
|
|
341
|
+
},
|
|
342
|
+
|
|
330
343
|
notesDrawer: {
|
|
331
344
|
toggle: '発表者ノート',
|
|
332
345
|
pageLabel: '{n} / {total} ページ',
|
|
@@ -335,4 +348,24 @@ export const ja: Locale = {
|
|
|
335
348
|
statusSaved: '保存済み',
|
|
336
349
|
statusError: '保存に失敗しました: {msg}',
|
|
337
350
|
},
|
|
351
|
+
|
|
352
|
+
themes: {
|
|
353
|
+
title: 'テーマ',
|
|
354
|
+
noThemesTitle: 'テーマがまだありません',
|
|
355
|
+
noThemesHintPrefix: '',
|
|
356
|
+
noThemesHintSuffix:
|
|
357
|
+
' を実行して作成 — themes/ に markdown ファイルと同名の demo スライドを置きます。',
|
|
358
|
+
noDemoYet: 'デモがまだありません',
|
|
359
|
+
noDemoHintPrefix: 'このテーマで ',
|
|
360
|
+
noDemoHintSuffix: ' を再実行するとプレビュー用スライドが生成されます。',
|
|
361
|
+
backToGallery: 'テーマ一覧へ戻る',
|
|
362
|
+
pageOf: '{n}/{total} ページ',
|
|
363
|
+
nextPageAria: '次のページ',
|
|
364
|
+
prevPageAria: '前のページ',
|
|
365
|
+
openThemeAria: 'テーマ {name} を開く',
|
|
366
|
+
usedBy: 'このテーマを使うスライド',
|
|
367
|
+
usedByEmpty: 'このテーマを使うスライドはまだありません。',
|
|
368
|
+
expandPromptAria: 'プロンプトを展開',
|
|
369
|
+
collapsePromptAria: 'プロンプトを折りたたむ',
|
|
370
|
+
},
|
|
338
371
|
};
|
package/src/locale/types.ts
CHANGED
|
@@ -38,6 +38,7 @@ export type Locale = {
|
|
|
38
38
|
home: {
|
|
39
39
|
appTitle: string;
|
|
40
40
|
draft: string;
|
|
41
|
+
themes: string;
|
|
41
42
|
folders: string;
|
|
42
43
|
newFolder: string;
|
|
43
44
|
folderName: string;
|
|
@@ -52,7 +53,6 @@ export type Locale = {
|
|
|
52
53
|
nothingMatchesSuffix: string;
|
|
53
54
|
noSlidesYet: string;
|
|
54
55
|
createSlideHintPrefix: string;
|
|
55
|
-
createSlideHintMid: string;
|
|
56
56
|
createSlideHintSuffix: string;
|
|
57
57
|
folderEmptyTitle: string;
|
|
58
58
|
folderEmptyHint: string;
|
|
@@ -88,6 +88,8 @@ export type Locale = {
|
|
|
88
88
|
backToHome: string;
|
|
89
89
|
agentConnected: string;
|
|
90
90
|
agentConnectedTooltip: string;
|
|
91
|
+
agentDisconnected: string;
|
|
92
|
+
agentDisconnectedTooltip: string;
|
|
91
93
|
download: string;
|
|
92
94
|
exportAsHtml: string;
|
|
93
95
|
exportAsPdf: string;
|
|
@@ -165,6 +167,8 @@ export type Locale = {
|
|
|
165
167
|
deselect: string;
|
|
166
168
|
agentWatching: string;
|
|
167
169
|
agentWatchingTooltip: string;
|
|
170
|
+
agentNotWatching: string;
|
|
171
|
+
agentNotWatchingTooltip: string;
|
|
168
172
|
contentSection: string;
|
|
169
173
|
typographySection: string;
|
|
170
174
|
colorSection: string;
|
|
@@ -321,6 +325,7 @@ export type Locale = {
|
|
|
321
325
|
toastDeleted: string;
|
|
322
326
|
toastDuplicateFailed: string;
|
|
323
327
|
toastDeleteFailed: string;
|
|
328
|
+
resizeRail: string;
|
|
324
329
|
};
|
|
325
330
|
|
|
326
331
|
pdfToast: {
|
|
@@ -344,6 +349,12 @@ export type Locale = {
|
|
|
344
349
|
nextAria: string;
|
|
345
350
|
};
|
|
346
351
|
|
|
352
|
+
imagePlaceholder: {
|
|
353
|
+
dropOverlay: string;
|
|
354
|
+
uploading: string;
|
|
355
|
+
uploadFailed: string;
|
|
356
|
+
};
|
|
357
|
+
|
|
347
358
|
notesDrawer: {
|
|
348
359
|
toggle: string;
|
|
349
360
|
/** template: "page {n}/{total}" */
|
|
@@ -354,4 +365,25 @@ export type Locale = {
|
|
|
354
365
|
/** template: "Save failed: {msg}" */
|
|
355
366
|
statusError: string;
|
|
356
367
|
};
|
|
368
|
+
|
|
369
|
+
themes: {
|
|
370
|
+
title: string;
|
|
371
|
+
noThemesTitle: string;
|
|
372
|
+
noThemesHintPrefix: string;
|
|
373
|
+
noThemesHintSuffix: string;
|
|
374
|
+
noDemoYet: string;
|
|
375
|
+
noDemoHintPrefix: string;
|
|
376
|
+
noDemoHintSuffix: string;
|
|
377
|
+
backToGallery: string;
|
|
378
|
+
/** template: "page {n}/{total}" */
|
|
379
|
+
pageOf: string;
|
|
380
|
+
nextPageAria: string;
|
|
381
|
+
prevPageAria: string;
|
|
382
|
+
/** template: "Open theme {name}" */
|
|
383
|
+
openThemeAria: string;
|
|
384
|
+
usedBy: string;
|
|
385
|
+
usedByEmpty: string;
|
|
386
|
+
expandPromptAria: string;
|
|
387
|
+
collapsePromptAria: string;
|
|
388
|
+
};
|
|
357
389
|
};
|
package/src/locale/zh-cn.ts
CHANGED
|
@@ -38,6 +38,7 @@ export const zhCN: Locale = {
|
|
|
38
38
|
home: {
|
|
39
39
|
appTitle: 'open-slide',
|
|
40
40
|
draft: '草稿',
|
|
41
|
+
themes: '主题',
|
|
41
42
|
folders: '文件夹',
|
|
42
43
|
newFolder: '新建文件夹',
|
|
43
44
|
folderName: '文件夹名称',
|
|
@@ -51,9 +52,8 @@ export const zhCN: Locale = {
|
|
|
51
52
|
nothingMatchesPrefix: '该文件夹中没有匹配 ',
|
|
52
53
|
nothingMatchesSuffix: ' 的内容。',
|
|
53
54
|
noSlidesYet: '尚无幻灯片',
|
|
54
|
-
createSlideHintPrefix: '
|
|
55
|
-
|
|
56
|
-
createSlideHintSuffix: '。',
|
|
55
|
+
createSlideHintPrefix: '在 agent 中执行 ',
|
|
56
|
+
createSlideHintSuffix: ' 开始创建。',
|
|
57
57
|
folderEmptyTitle: '{name} 为空',
|
|
58
58
|
folderEmptyHint: '从侧边栏将幻灯片从草稿拖入此文件夹。',
|
|
59
59
|
slideActions: '幻灯片操作',
|
|
@@ -84,6 +84,9 @@ export const zhCN: Locale = {
|
|
|
84
84
|
agentConnected: 'Agent 已连接',
|
|
85
85
|
agentConnectedTooltip:
|
|
86
86
|
'Dev server 正在把你目前在哪张 slide、Inspector 选了哪个元素发布给 agent。直接到聊天说"这张 slide"或"这个元素"就行。Production build 不会出现。',
|
|
87
|
+
agentDisconnected: 'Agent 已断开',
|
|
88
|
+
agentDisconnectedTooltip:
|
|
89
|
+
'已和 dev server 断开连接,agent 没办法再看到你目前的 slide 或 Inspector 选择。请重新启动 dev server 来恢复连接。',
|
|
87
90
|
home: '首页',
|
|
88
91
|
backToHome: '返回首页',
|
|
89
92
|
download: '下载',
|
|
@@ -198,6 +201,9 @@ export const zhCN: Locale = {
|
|
|
198
201
|
agentWatching: 'Agent 正在关注',
|
|
199
202
|
agentWatchingTooltip:
|
|
200
203
|
'Agent 已经通过 dev server 看到你选的元素了,直接到聊天请它修改就行。想累积几个再一次问才需要在这里留 comments。',
|
|
204
|
+
agentNotWatching: 'Agent 没在关注',
|
|
205
|
+
agentNotWatchingTooltip:
|
|
206
|
+
'已和 dev server 断开连接,agent 看不到你选的元素了。请重新启动 dev server 来恢复连接。',
|
|
201
207
|
leaveComment: '留个 comment',
|
|
202
208
|
commentPlaceholder: '描述你希望代理执行的更改…',
|
|
203
209
|
commentShortcutHint: '⌘↵ 添加',
|
|
@@ -301,6 +307,7 @@ export const zhCN: Locale = {
|
|
|
301
307
|
toastDeleted: '已删除第 {n} 页',
|
|
302
308
|
toastDuplicateFailed: '无法复制页面',
|
|
303
309
|
toastDeleteFailed: '无法删除页面',
|
|
310
|
+
resizeRail: '调整缩略图栏宽度',
|
|
304
311
|
},
|
|
305
312
|
|
|
306
313
|
pdfToast: {
|
|
@@ -323,6 +330,12 @@ export const zhCN: Locale = {
|
|
|
323
330
|
nextAria: '下一页',
|
|
324
331
|
},
|
|
325
332
|
|
|
333
|
+
imagePlaceholder: {
|
|
334
|
+
dropOverlay: '拖入图片以使用',
|
|
335
|
+
uploading: '上传中…',
|
|
336
|
+
uploadFailed: '图片上传失败',
|
|
337
|
+
},
|
|
338
|
+
|
|
326
339
|
notesDrawer: {
|
|
327
340
|
toggle: '演讲备注',
|
|
328
341
|
pageLabel: '第 {n} / {total} 页',
|
|
@@ -331,4 +344,23 @@ export const zhCN: Locale = {
|
|
|
331
344
|
statusSaved: '已保存',
|
|
332
345
|
statusError: '保存失败:{msg}',
|
|
333
346
|
},
|
|
347
|
+
|
|
348
|
+
themes: {
|
|
349
|
+
title: '主题',
|
|
350
|
+
noThemesTitle: '尚无主题',
|
|
351
|
+
noThemesHintPrefix: '运行 ',
|
|
352
|
+
noThemesHintSuffix: ' 来创建一个 — 一个位于 themes/ 的 markdown 文件,加上同名的 demo slide。',
|
|
353
|
+
noDemoYet: '尚无 demo',
|
|
354
|
+
noDemoHintPrefix: '对此主题重新运行 ',
|
|
355
|
+
noDemoHintSuffix: ' 即可生成预览用的 slide。',
|
|
356
|
+
backToGallery: '返回主题列表',
|
|
357
|
+
pageOf: '第 {n}/{total} 页',
|
|
358
|
+
nextPageAria: '下一页',
|
|
359
|
+
prevPageAria: '上一页',
|
|
360
|
+
openThemeAria: '打开主题 {name}',
|
|
361
|
+
usedBy: '使用此主题的 slides',
|
|
362
|
+
usedByEmpty: '尚未有 slides 使用此主题。',
|
|
363
|
+
expandPromptAria: '展开 prompt',
|
|
364
|
+
collapsePromptAria: '收起 prompt',
|
|
365
|
+
},
|
|
334
366
|
};
|
package/src/locale/zh-tw.ts
CHANGED
|
@@ -38,6 +38,7 @@ export const zhTW: Locale = {
|
|
|
38
38
|
home: {
|
|
39
39
|
appTitle: 'open-slide',
|
|
40
40
|
draft: '草稿',
|
|
41
|
+
themes: '主題',
|
|
41
42
|
folders: '資料夾',
|
|
42
43
|
newFolder: '新增資料夾',
|
|
43
44
|
folderName: '資料夾名稱',
|
|
@@ -51,9 +52,8 @@ export const zhTW: Locale = {
|
|
|
51
52
|
nothingMatchesPrefix: '此資料夾中沒有相符 ',
|
|
52
53
|
nothingMatchesSuffix: ' 的項目。',
|
|
53
54
|
noSlidesYet: '尚無投影片',
|
|
54
|
-
createSlideHintPrefix: '
|
|
55
|
-
|
|
56
|
-
createSlideHintSuffix: '。',
|
|
55
|
+
createSlideHintPrefix: '在 agent 中執行 ',
|
|
56
|
+
createSlideHintSuffix: ' 開始建立。',
|
|
57
57
|
folderEmptyTitle: '{name} 為空',
|
|
58
58
|
folderEmptyHint: '從側邊欄將投影片從草稿拖入此資料夾。',
|
|
59
59
|
slideActions: '投影片操作',
|
|
@@ -84,6 +84,9 @@ export const zhTW: Locale = {
|
|
|
84
84
|
agentConnected: 'Agent 已連線',
|
|
85
85
|
agentConnectedTooltip:
|
|
86
86
|
'Dev server 正在把你目前在哪張 slide、Inspector 選了哪個元素發布給 agent。直接到聊天說「這張 slide」或「這個元素」就行。Production build 不會出現。',
|
|
87
|
+
agentDisconnected: 'Agent 已斷線',
|
|
88
|
+
agentDisconnectedTooltip:
|
|
89
|
+
'已和 dev server 斷線,agent 沒辦法再看到你目前的 slide 或 Inspector 選擇。請重新啟動 dev server 來恢復連線。',
|
|
87
90
|
home: '首頁',
|
|
88
91
|
backToHome: '返回首頁',
|
|
89
92
|
download: '下載',
|
|
@@ -198,6 +201,9 @@ export const zhTW: Locale = {
|
|
|
198
201
|
agentWatching: 'Agent 正在關注',
|
|
199
202
|
agentWatchingTooltip:
|
|
200
203
|
'Agent 已經透過 dev server 看到你選的元素了,直接到聊天請它修改就行。想累積幾個再一次問才需要在這裡留 comments。',
|
|
204
|
+
agentNotWatching: 'Agent 沒在關注',
|
|
205
|
+
agentNotWatchingTooltip:
|
|
206
|
+
'已和 dev server 斷線,agent 看不到你選的元素了。請重新啟動 dev server 來恢復連線。',
|
|
201
207
|
leaveComment: '留個 comment',
|
|
202
208
|
commentPlaceholder: '描述你希望代理進行的修改…',
|
|
203
209
|
commentShortcutHint: '⌘↵ 新增',
|
|
@@ -301,6 +307,7 @@ export const zhTW: Locale = {
|
|
|
301
307
|
toastDeleted: '已刪除第 {n} 頁',
|
|
302
308
|
toastDuplicateFailed: '無法複製頁面',
|
|
303
309
|
toastDeleteFailed: '無法刪除頁面',
|
|
310
|
+
resizeRail: '調整縮圖欄寬度',
|
|
304
311
|
},
|
|
305
312
|
|
|
306
313
|
pdfToast: {
|
|
@@ -323,6 +330,12 @@ export const zhTW: Locale = {
|
|
|
323
330
|
nextAria: '下一頁',
|
|
324
331
|
},
|
|
325
332
|
|
|
333
|
+
imagePlaceholder: {
|
|
334
|
+
dropOverlay: '拖入圖片以使用',
|
|
335
|
+
uploading: '上傳中…',
|
|
336
|
+
uploadFailed: '圖片上傳失敗',
|
|
337
|
+
},
|
|
338
|
+
|
|
326
339
|
notesDrawer: {
|
|
327
340
|
toggle: '講稿',
|
|
328
341
|
pageLabel: '第 {n} / {total} 頁',
|
|
@@ -331,4 +344,23 @@ export const zhTW: Locale = {
|
|
|
331
344
|
statusSaved: '已儲存',
|
|
332
345
|
statusError: '儲存失敗:{msg}',
|
|
333
346
|
},
|
|
347
|
+
|
|
348
|
+
themes: {
|
|
349
|
+
title: '主題',
|
|
350
|
+
noThemesTitle: '尚無主題',
|
|
351
|
+
noThemesHintPrefix: '執行 ',
|
|
352
|
+
noThemesHintSuffix: ' 來建立一個 — 一個位於 themes/ 的 markdown 檔案,加上同名的 demo slide。',
|
|
353
|
+
noDemoYet: '尚無 demo',
|
|
354
|
+
noDemoHintPrefix: '對此主題重新執行 ',
|
|
355
|
+
noDemoHintSuffix: ' 即可產生預覽用的 slide。',
|
|
356
|
+
backToGallery: '返回主題列表',
|
|
357
|
+
pageOf: '第 {n}/{total} 頁',
|
|
358
|
+
nextPageAria: '下一頁',
|
|
359
|
+
prevPageAria: '上一頁',
|
|
360
|
+
openThemeAria: '開啟主題 {name}',
|
|
361
|
+
usedBy: '使用此主題的 slides',
|
|
362
|
+
usedByEmpty: '尚未有 slides 使用此主題。',
|
|
363
|
+
expandPromptAria: '展開 prompt',
|
|
364
|
+
collapsePromptAria: '收合 prompt',
|
|
365
|
+
},
|
|
334
366
|
};
|
package/dist/sync-B4eLo2H6.js
DELETED
|
File without changes
|
|
File without changes
|