@open-aippt/core 1.13.2
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/LICENSE +21 -0
- package/README.md +98 -0
- package/bin.js +2 -0
- package/dist/build-DxTqmvsO.js +17 -0
- package/dist/cli/bin.d.ts +1 -0
- package/dist/cli/bin.js +86 -0
- package/dist/config-CjzqjrEA.js +4280 -0
- package/dist/config-DIC-yVPp.d.ts +23 -0
- package/dist/design-cpzS8aud.js +35 -0
- package/dist/dev-BYuTeJbA.js +20 -0
- package/dist/format-BCeKbTOM.js +1605 -0
- package/dist/index.d.ts +134 -0
- package/dist/index.js +467 -0
- package/dist/locale/index.d.ts +24 -0
- package/dist/locale/index.js +3 -0
- package/dist/preview-DlQvnJPq.js +18 -0
- package/dist/sync-BPZ0m27m.js +139 -0
- package/dist/sync-EsYusbbL.js +3 -0
- package/dist/types-CHmFPIG_.d.ts +430 -0
- package/dist/vite/index.d.ts +14 -0
- package/dist/vite/index.js +4 -0
- package/env.d.ts +59 -0
- package/package.json +103 -0
- package/skills/apply-comments/SKILL.md +83 -0
- package/skills/create-slide/SKILL.md +91 -0
- package/skills/create-theme/SKILL.md +250 -0
- package/skills/current-slide/SKILL.md +110 -0
- package/skills/slide-authoring/SKILL.md +625 -0
- package/src/app/app.tsx +47 -0
- package/src/app/components/asset-view.tsx +966 -0
- package/src/app/components/history-provider.tsx +120 -0
- package/src/app/components/image-placeholder.tsx +243 -0
- package/src/app/components/inspector/asset-picker-dialog.tsx +196 -0
- package/src/app/components/inspector/comment-widget.tsx +93 -0
- package/src/app/components/inspector/image-crop-dialog.tsx +212 -0
- package/src/app/components/inspector/inspect-overlay.tsx +387 -0
- package/src/app/components/inspector/inspector-panel.tsx +1115 -0
- package/src/app/components/inspector/inspector-provider.tsx +1218 -0
- package/src/app/components/inspector/save-bar.tsx +48 -0
- package/src/app/components/language-toggle.tsx +39 -0
- package/src/app/components/notes-drawer.tsx +120 -0
- package/src/app/components/overview-grid.tsx +363 -0
- package/src/app/components/panel/panel-fields.tsx +60 -0
- package/src/app/components/panel/panel-shell.tsx +80 -0
- package/src/app/components/panel/save-card.tsx +142 -0
- package/src/app/components/pdf-progress-toast.tsx +32 -0
- package/src/app/components/player.tsx +466 -0
- package/src/app/components/pptx-progress-toast.tsx +32 -0
- package/src/app/components/present/blackout-overlay.tsx +18 -0
- package/src/app/components/present/control-bar.tsx +315 -0
- package/src/app/components/present/help-overlay.tsx +57 -0
- package/src/app/components/present/jump-input.tsx +74 -0
- package/src/app/components/present/laser-pointer.tsx +39 -0
- package/src/app/components/present/progress-bar.tsx +26 -0
- package/src/app/components/present/use-idle.ts +46 -0
- package/src/app/components/present/use-pointer-near-bottom.ts +34 -0
- package/src/app/components/present/use-presenter-channel.ts +66 -0
- package/src/app/components/present/use-touch-swipe.ts +66 -0
- package/src/app/components/shared-element.tsx +48 -0
- package/src/app/components/sidebar/folder-item.tsx +258 -0
- package/src/app/components/sidebar/icon-picker.tsx +61 -0
- package/src/app/components/sidebar/mobile-pill.tsx +34 -0
- package/src/app/components/sidebar/sidebar-footer.tsx +105 -0
- package/src/app/components/sidebar/sidebar.tsx +284 -0
- package/src/app/components/slide-canvas.tsx +102 -0
- package/src/app/components/slide-transition-layer.tsx +844 -0
- package/src/app/components/style-panel/design-provider.tsx +148 -0
- package/src/app/components/style-panel/style-panel.tsx +349 -0
- package/src/app/components/style-panel/use-design.ts +112 -0
- package/src/app/components/theme-toggle.tsx +59 -0
- package/src/app/components/themes/theme-detail.tsx +305 -0
- package/src/app/components/themes/themes-gallery.tsx +149 -0
- package/src/app/components/thumbnail-rail.tsx +805 -0
- package/src/app/components/ui/badge.tsx +45 -0
- package/src/app/components/ui/button.tsx +99 -0
- package/src/app/components/ui/card.tsx +92 -0
- package/src/app/components/ui/context-menu.tsx +237 -0
- package/src/app/components/ui/dialog.tsx +157 -0
- package/src/app/components/ui/dropdown-menu.tsx +245 -0
- package/src/app/components/ui/input.tsx +25 -0
- package/src/app/components/ui/label.tsx +24 -0
- package/src/app/components/ui/popover.tsx +75 -0
- package/src/app/components/ui/progress.tsx +31 -0
- package/src/app/components/ui/scroll-area.tsx +53 -0
- package/src/app/components/ui/select.tsx +196 -0
- package/src/app/components/ui/separator.tsx +28 -0
- package/src/app/components/ui/slider.tsx +61 -0
- package/src/app/components/ui/sonner.tsx +48 -0
- package/src/app/components/ui/tabs.tsx +79 -0
- package/src/app/components/ui/textarea.tsx +22 -0
- package/src/app/components/ui/toggle-group.tsx +83 -0
- package/src/app/components/ui/toggle.tsx +45 -0
- package/src/app/components/ui/tooltip.tsx +58 -0
- package/src/app/favicon.ico +0 -0
- package/src/app/index.html +13 -0
- package/src/app/lib/assets.ts +242 -0
- package/src/app/lib/design-presets.ts +94 -0
- package/src/app/lib/design.ts +58 -0
- package/src/app/lib/export-html.ts +326 -0
- package/src/app/lib/export-pdf.ts +298 -0
- package/src/app/lib/export-pptx.ts +284 -0
- package/src/app/lib/folders.ts +239 -0
- package/src/app/lib/inspector/fiber.test.ts +154 -0
- package/src/app/lib/inspector/fiber.ts +85 -0
- package/src/app/lib/inspector/use-comments.ts +74 -0
- package/src/app/lib/inspector/use-editor.ts +73 -0
- package/src/app/lib/inspector/use-notes.ts +134 -0
- package/src/app/lib/locale-store.ts +67 -0
- package/src/app/lib/page-context.tsx +38 -0
- package/src/app/lib/print-ready.test.ts +32 -0
- package/src/app/lib/print-ready.ts +51 -0
- package/src/app/lib/sdk.test.ts +13 -0
- package/src/app/lib/sdk.ts +37 -0
- package/src/app/lib/slides.ts +26 -0
- package/src/app/lib/step-context.tsx +261 -0
- package/src/app/lib/themes.ts +22 -0
- package/src/app/lib/transition.ts +30 -0
- package/src/app/lib/use-agent-socket.ts +18 -0
- package/src/app/lib/use-click-page-navigation.ts +60 -0
- package/src/app/lib/use-is-mobile.ts +21 -0
- package/src/app/lib/use-locale.ts +8 -0
- package/src/app/lib/use-prefers-reduced-motion.ts +19 -0
- package/src/app/lib/use-slide-module.ts +48 -0
- package/src/app/lib/use-wheel-page-navigation.ts +99 -0
- package/src/app/lib/utils.test.ts +25 -0
- package/src/app/lib/utils.ts +6 -0
- package/src/app/main.tsx +14 -0
- package/src/app/routes/assets.tsx +9 -0
- package/src/app/routes/home-shell.tsx +213 -0
- package/src/app/routes/home.tsx +807 -0
- package/src/app/routes/presenter.tsx +418 -0
- package/src/app/routes/slide.tsx +1108 -0
- package/src/app/routes/themes.tsx +34 -0
- package/src/app/styles.css +429 -0
- package/src/app/virtual.d.ts +51 -0
- package/src/locale/en.ts +416 -0
- package/src/locale/format.ts +12 -0
- package/src/locale/index.ts +6 -0
- package/src/locale/ja.ts +422 -0
- package/src/locale/types.ts +443 -0
- package/src/locale/zh-cn.ts +414 -0
- package/src/locale/zh-tw.ts +414 -0
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { useEffect, useState } from 'react';
|
|
2
|
+
import { ScrollArea } from '@/components/ui/scroll-area';
|
|
3
|
+
|
|
4
|
+
export const PANEL_W = 320;
|
|
5
|
+
export const PANEL_TRANSITION_MS = 240;
|
|
6
|
+
|
|
7
|
+
// Defer the width expansion to the next frame so the browser paints once
|
|
8
|
+
// at width=0 first; otherwise the transition has no starting frame.
|
|
9
|
+
export function useAnimatedOpen(open: boolean): boolean {
|
|
10
|
+
const [animVisible, setAnimVisible] = useState(false);
|
|
11
|
+
useEffect(() => {
|
|
12
|
+
if (open) {
|
|
13
|
+
const id = requestAnimationFrame(() => setAnimVisible(true));
|
|
14
|
+
return () => cancelAnimationFrame(id);
|
|
15
|
+
}
|
|
16
|
+
setAnimVisible(false);
|
|
17
|
+
}, [open]);
|
|
18
|
+
return animVisible;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// Stay mounted through the close-out width transition so the panel
|
|
22
|
+
// visibly collapses instead of vanishing.
|
|
23
|
+
export function usePanelMount(open: boolean): { mounted: boolean; animVisible: boolean } {
|
|
24
|
+
const [mounted, setMounted] = useState(false);
|
|
25
|
+
useEffect(() => {
|
|
26
|
+
if (open) {
|
|
27
|
+
setMounted(true);
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
const t = setTimeout(() => setMounted(false), PANEL_TRANSITION_MS);
|
|
31
|
+
return () => clearTimeout(t);
|
|
32
|
+
}, [open]);
|
|
33
|
+
const animVisible = useAnimatedOpen(open && mounted);
|
|
34
|
+
return { mounted, animVisible };
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
type PanelShellProps = {
|
|
38
|
+
animVisible: boolean;
|
|
39
|
+
uiAttr: 'inspector' | 'design';
|
|
40
|
+
header: React.ReactNode;
|
|
41
|
+
banner?: React.ReactNode;
|
|
42
|
+
footer?: React.ReactNode;
|
|
43
|
+
children: React.ReactNode;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
export function PanelShell({
|
|
47
|
+
animVisible,
|
|
48
|
+
uiAttr,
|
|
49
|
+
header,
|
|
50
|
+
banner,
|
|
51
|
+
footer,
|
|
52
|
+
children,
|
|
53
|
+
}: PanelShellProps) {
|
|
54
|
+
const dataAttrs = uiAttr === 'inspector' ? { 'data-inspector-ui': '' } : { 'data-design-ui': '' };
|
|
55
|
+
return (
|
|
56
|
+
<aside
|
|
57
|
+
{...dataAttrs}
|
|
58
|
+
className="flex h-full shrink-0 justify-end overflow-hidden bg-sidebar transition-[width,border-left-width] ease-out"
|
|
59
|
+
style={{
|
|
60
|
+
width: animVisible ? PANEL_W : 0,
|
|
61
|
+
borderLeftWidth: animVisible ? 1 : 0,
|
|
62
|
+
borderLeftColor: 'var(--hairline)',
|
|
63
|
+
transitionDuration: `${PANEL_TRANSITION_MS}ms`,
|
|
64
|
+
}}
|
|
65
|
+
>
|
|
66
|
+
<div style={{ width: PANEL_W }} className="flex h-full shrink-0 flex-col">
|
|
67
|
+
<header className="flex h-9 shrink-0 items-center justify-between gap-2 border-b border-hairline px-3">
|
|
68
|
+
{header}
|
|
69
|
+
</header>
|
|
70
|
+
{banner}
|
|
71
|
+
<ScrollArea className="min-h-0 flex-1">
|
|
72
|
+
<div className="flex min-h-full flex-col">
|
|
73
|
+
{children}
|
|
74
|
+
{footer && <div className="mt-auto border-t border-hairline">{footer}</div>}
|
|
75
|
+
</div>
|
|
76
|
+
</ScrollArea>
|
|
77
|
+
</div>
|
|
78
|
+
</aside>
|
|
79
|
+
);
|
|
80
|
+
}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { Check, Loader2, Redo2, Save, Undo2 } from 'lucide-react';
|
|
2
|
+
import { useEffect, useState } from 'react';
|
|
3
|
+
import { Button } from '@/components/ui/button';
|
|
4
|
+
import { useLocale } from '@/lib/use-locale';
|
|
5
|
+
|
|
6
|
+
type SaveCardProps = {
|
|
7
|
+
dirty: boolean;
|
|
8
|
+
committing: boolean;
|
|
9
|
+
onSave: () => Promise<void> | void;
|
|
10
|
+
onDiscard: () => void;
|
|
11
|
+
unsavedLabel: React.ReactNode;
|
|
12
|
+
savedLabel?: string;
|
|
13
|
+
uiAttr: 'inspector' | 'design';
|
|
14
|
+
onUndo?: () => void;
|
|
15
|
+
onRedo?: () => void;
|
|
16
|
+
canUndo?: boolean;
|
|
17
|
+
canRedo?: boolean;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
// Optimistic DOM updates make the canvas *look* saved, so without this
|
|
21
|
+
// affordance a user could close the tab thinking their tweaks hit disk
|
|
22
|
+
// when they're still buffered in memory.
|
|
23
|
+
export function SaveCard({
|
|
24
|
+
dirty,
|
|
25
|
+
committing,
|
|
26
|
+
onSave,
|
|
27
|
+
onDiscard,
|
|
28
|
+
unsavedLabel,
|
|
29
|
+
savedLabel,
|
|
30
|
+
uiAttr,
|
|
31
|
+
onUndo,
|
|
32
|
+
onRedo,
|
|
33
|
+
canUndo = false,
|
|
34
|
+
canRedo = false,
|
|
35
|
+
}: SaveCardProps) {
|
|
36
|
+
const t = useLocale();
|
|
37
|
+
const [justSaved, setJustSaved] = useState(false);
|
|
38
|
+
const resolvedSavedLabel = savedLabel ?? t.common.saved;
|
|
39
|
+
|
|
40
|
+
useEffect(() => {
|
|
41
|
+
if (!justSaved) return;
|
|
42
|
+
const t = setTimeout(() => setJustSaved(false), 1200);
|
|
43
|
+
return () => clearTimeout(t);
|
|
44
|
+
}, [justSaved]);
|
|
45
|
+
|
|
46
|
+
const visible = dirty || committing || justSaved || canUndo || canRedo;
|
|
47
|
+
if (!visible) return null;
|
|
48
|
+
|
|
49
|
+
const handleSave = async () => {
|
|
50
|
+
await onSave();
|
|
51
|
+
setJustSaved(true);
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
const dataAttrs = uiAttr === 'inspector' ? { 'data-inspector-ui': '' } : { 'data-design-ui': '' };
|
|
55
|
+
|
|
56
|
+
const showHistory = !justSaved && (onUndo || onRedo);
|
|
57
|
+
|
|
58
|
+
return (
|
|
59
|
+
<div
|
|
60
|
+
{...dataAttrs}
|
|
61
|
+
className="pointer-events-none absolute bottom-6 left-1/2 z-30 -translate-x-1/2 animate-in fade-in slide-in-from-bottom-2 duration-200 ease-out"
|
|
62
|
+
>
|
|
63
|
+
<div className="pointer-events-auto flex h-9 items-center gap-1 rounded-[8px] border border-border bg-popover/95 py-0.5 pr-0.5 pl-1 shadow-overlay backdrop-blur-md">
|
|
64
|
+
{showHistory && (
|
|
65
|
+
<div className="flex items-center">
|
|
66
|
+
<Button
|
|
67
|
+
size="icon-sm"
|
|
68
|
+
variant="ghost"
|
|
69
|
+
className="text-muted-foreground hover:text-foreground"
|
|
70
|
+
onClick={onUndo}
|
|
71
|
+
disabled={committing || !canUndo}
|
|
72
|
+
aria-label={t.common.undo}
|
|
73
|
+
title={t.common.undo}
|
|
74
|
+
>
|
|
75
|
+
<Undo2 className="size-3.5" />
|
|
76
|
+
</Button>
|
|
77
|
+
<Button
|
|
78
|
+
size="icon-sm"
|
|
79
|
+
variant="ghost"
|
|
80
|
+
className="text-muted-foreground hover:text-foreground"
|
|
81
|
+
onClick={onRedo}
|
|
82
|
+
disabled={committing || !canRedo}
|
|
83
|
+
aria-label={t.common.redo}
|
|
84
|
+
title={t.common.redo}
|
|
85
|
+
>
|
|
86
|
+
<Redo2 className="size-3.5" />
|
|
87
|
+
</Button>
|
|
88
|
+
{(justSaved || dirty || committing) && (
|
|
89
|
+
<span aria-hidden className="ml-1 mr-0.5 h-4 w-px bg-hairline" />
|
|
90
|
+
)}
|
|
91
|
+
</div>
|
|
92
|
+
)}
|
|
93
|
+
{justSaved ? (
|
|
94
|
+
<span className="flex items-center gap-1.5 whitespace-nowrap px-2.5 text-[12px] font-medium text-foreground">
|
|
95
|
+
<Check className="size-3.5 shrink-0 text-[oklch(0.55_0.13_165)]" strokeWidth={2.5} />
|
|
96
|
+
{resolvedSavedLabel}
|
|
97
|
+
</span>
|
|
98
|
+
) : dirty || committing ? (
|
|
99
|
+
<span className="inline-flex items-center gap-1.5 whitespace-nowrap px-2.5 text-[12px] font-medium text-foreground">
|
|
100
|
+
<span
|
|
101
|
+
aria-hidden
|
|
102
|
+
className="size-1.5 shrink-0 rounded-full bg-brand shadow-[0_0_0_3px_var(--brand-soft)]"
|
|
103
|
+
/>
|
|
104
|
+
<span className="nums">{unsavedLabel}</span>
|
|
105
|
+
</span>
|
|
106
|
+
) : null}
|
|
107
|
+
{!justSaved && dirty && (
|
|
108
|
+
<Button
|
|
109
|
+
size="sm"
|
|
110
|
+
variant="ghost"
|
|
111
|
+
className="text-muted-foreground hover:text-foreground"
|
|
112
|
+
onClick={onDiscard}
|
|
113
|
+
disabled={committing || !dirty}
|
|
114
|
+
>
|
|
115
|
+
{t.common.discard}
|
|
116
|
+
</Button>
|
|
117
|
+
)}
|
|
118
|
+
{(dirty || committing) && (
|
|
119
|
+
<Button
|
|
120
|
+
size="sm"
|
|
121
|
+
variant="brand"
|
|
122
|
+
className="h-7 px-3"
|
|
123
|
+
onClick={handleSave}
|
|
124
|
+
disabled={committing || !dirty}
|
|
125
|
+
>
|
|
126
|
+
{committing ? (
|
|
127
|
+
<>
|
|
128
|
+
<Loader2 className="size-3.5 animate-spin" />
|
|
129
|
+
{t.common.saving}
|
|
130
|
+
</>
|
|
131
|
+
) : (
|
|
132
|
+
<>
|
|
133
|
+
<Save className="size-3.5" />
|
|
134
|
+
{t.common.save}
|
|
135
|
+
</>
|
|
136
|
+
)}
|
|
137
|
+
</Button>
|
|
138
|
+
)}
|
|
139
|
+
</div>
|
|
140
|
+
</div>
|
|
141
|
+
);
|
|
142
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { Loader2 } from 'lucide-react';
|
|
2
|
+
import { format, useLocale } from '@/lib/use-locale';
|
|
3
|
+
import type { PdfExportProgress } from '../lib/export-pdf';
|
|
4
|
+
import { Progress } from './ui/progress';
|
|
5
|
+
|
|
6
|
+
export function PdfProgressToast({ progress }: { progress: PdfExportProgress }) {
|
|
7
|
+
const t = useLocale();
|
|
8
|
+
const text =
|
|
9
|
+
progress.phase === 'processing'
|
|
10
|
+
? format(t.pdfToast.processing, {
|
|
11
|
+
current: progress.current.toString().padStart(2, '0'),
|
|
12
|
+
total: progress.total.toString().padStart(2, '0'),
|
|
13
|
+
})
|
|
14
|
+
: progress.phase === 'printing'
|
|
15
|
+
? t.pdfToast.printing
|
|
16
|
+
: t.pdfToast.done;
|
|
17
|
+
|
|
18
|
+
return (
|
|
19
|
+
<div className="flex w-80 items-start gap-3 rounded-[8px] border border-border bg-popover px-3.5 py-3 text-popover-foreground shadow-floating">
|
|
20
|
+
<Loader2 className="mt-0.5 size-3.5 shrink-0 animate-spin text-brand" />
|
|
21
|
+
<div className="min-w-0 flex-1">
|
|
22
|
+
<p className="font-heading text-[12.5px] font-semibold tracking-tight">
|
|
23
|
+
{t.pdfToast.title}
|
|
24
|
+
</p>
|
|
25
|
+
<p className="truncate font-mono text-[10.5px] tracking-[0.04em] text-muted-foreground">
|
|
26
|
+
{text}
|
|
27
|
+
</p>
|
|
28
|
+
<Progress value={Math.round(progress.percent)} className="mt-2 h-[3px]" />
|
|
29
|
+
</div>
|
|
30
|
+
</div>
|
|
31
|
+
);
|
|
32
|
+
}
|