@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
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { Locale, Plural } from "./types-CHmFPIG_.js";
|
|
2
|
+
import { OpenAipptConfig } from "./config-DIC-yVPp.js";
|
|
3
|
+
import { CSSProperties, ComponentType, HTMLAttributes, PropsWithChildren, ReactNode } from "react";
|
|
4
|
+
import * as react_jsx_runtime0 from "react/jsx-runtime";
|
|
5
|
+
import * as react_jsx_runtime4 from "react/jsx-runtime";
|
|
6
|
+
import * as react_jsx_runtime2 from "react/jsx-runtime";
|
|
7
|
+
import * as react_jsx_runtime3 from "react/jsx-runtime";
|
|
8
|
+
|
|
9
|
+
//#region src/app/components/image-placeholder.d.ts
|
|
10
|
+
type ImagePlaceholderProps = {
|
|
11
|
+
hint: string;
|
|
12
|
+
width?: number;
|
|
13
|
+
height?: number;
|
|
14
|
+
style?: CSSProperties;
|
|
15
|
+
className?: string;
|
|
16
|
+
} & Omit<HTMLAttributes<HTMLDivElement>, 'children' | 'style' | 'className'>;
|
|
17
|
+
declare function ImagePlaceholder({
|
|
18
|
+
hint,
|
|
19
|
+
width,
|
|
20
|
+
height,
|
|
21
|
+
style,
|
|
22
|
+
className,
|
|
23
|
+
...rest
|
|
24
|
+
}: ImagePlaceholderProps): react_jsx_runtime0.JSX.Element;
|
|
25
|
+
|
|
26
|
+
//#endregion
|
|
27
|
+
//#region src/app/components/shared-element.d.ts
|
|
28
|
+
type unstable_SharedElementProps = {
|
|
29
|
+
id: string;
|
|
30
|
+
children: ReactNode;
|
|
31
|
+
className?: string;
|
|
32
|
+
style?: CSSProperties;
|
|
33
|
+
};
|
|
34
|
+
declare function unstable_SharedElement({
|
|
35
|
+
id,
|
|
36
|
+
children,
|
|
37
|
+
className,
|
|
38
|
+
style
|
|
39
|
+
}: unstable_SharedElementProps): react_jsx_runtime4.JSX.Element;
|
|
40
|
+
|
|
41
|
+
//#endregion
|
|
42
|
+
//#region src/app/lib/design.d.ts
|
|
43
|
+
type DesignPalette = {
|
|
44
|
+
bg: string;
|
|
45
|
+
text: string;
|
|
46
|
+
accent: string;
|
|
47
|
+
};
|
|
48
|
+
type DesignFonts = {
|
|
49
|
+
display: string;
|
|
50
|
+
body: string;
|
|
51
|
+
};
|
|
52
|
+
type DesignTypeScale = {
|
|
53
|
+
hero: number;
|
|
54
|
+
body: number;
|
|
55
|
+
};
|
|
56
|
+
type DesignSystem = {
|
|
57
|
+
palette: DesignPalette;
|
|
58
|
+
fonts: DesignFonts;
|
|
59
|
+
typeScale: DesignTypeScale;
|
|
60
|
+
radius: number;
|
|
61
|
+
};
|
|
62
|
+
declare function designToCssVars(d: DesignSystem): Record<string, string>;
|
|
63
|
+
declare function cssVarsToString(vars: Record<string, string>): string;
|
|
64
|
+
declare const defaultDesign: DesignSystem;
|
|
65
|
+
|
|
66
|
+
//#endregion
|
|
67
|
+
//#region src/app/lib/page-context.d.ts
|
|
68
|
+
declare function useSlidePageNumber(): {
|
|
69
|
+
current: number;
|
|
70
|
+
total: number;
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
//#endregion
|
|
74
|
+
//#region src/app/lib/transition.d.ts
|
|
75
|
+
type TransitionPhase = {
|
|
76
|
+
keyframes: Keyframe[] | PropertyIndexedKeyframes;
|
|
77
|
+
easing?: string;
|
|
78
|
+
duration?: number;
|
|
79
|
+
delay?: number;
|
|
80
|
+
};
|
|
81
|
+
type SlideTransition = {
|
|
82
|
+
duration: number;
|
|
83
|
+
easing?: string;
|
|
84
|
+
enter?: TransitionPhase;
|
|
85
|
+
exit?: TransitionPhase;
|
|
86
|
+
sharedElements?: boolean | SharedElementTransition;
|
|
87
|
+
};
|
|
88
|
+
type SharedElementTransition = {
|
|
89
|
+
duration?: number;
|
|
90
|
+
easing?: string;
|
|
91
|
+
delay?: number;
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
//#endregion
|
|
95
|
+
//#region src/app/lib/sdk.d.ts
|
|
96
|
+
type Page = ComponentType & {
|
|
97
|
+
transition?: SlideTransition;
|
|
98
|
+
};
|
|
99
|
+
type SlideMeta = {
|
|
100
|
+
title?: string;
|
|
101
|
+
theme?: string;
|
|
102
|
+
/** ISO 8601 timestamp. Set once at scaffold time; used to sort the slide list. */
|
|
103
|
+
createdAt?: string;
|
|
104
|
+
};
|
|
105
|
+
type SlideModule = {
|
|
106
|
+
default: Page[];
|
|
107
|
+
meta?: SlideMeta;
|
|
108
|
+
design?: DesignSystem;
|
|
109
|
+
notes?: (string | undefined)[];
|
|
110
|
+
transition?: SlideTransition;
|
|
111
|
+
};
|
|
112
|
+
declare const CANVAS_WIDTH = 1920;
|
|
113
|
+
declare const CANVAS_HEIGHT = 1080;
|
|
114
|
+
|
|
115
|
+
//#endregion
|
|
116
|
+
//#region src/app/lib/step-context.d.ts
|
|
117
|
+
type StepsProps = PropsWithChildren;
|
|
118
|
+
declare function Steps({
|
|
119
|
+
children
|
|
120
|
+
}: StepsProps): react_jsx_runtime2.JSX.Element;
|
|
121
|
+
type StepProps = PropsWithChildren<{
|
|
122
|
+
duration?: number;
|
|
123
|
+
}>;
|
|
124
|
+
type InternalStepProps = StepProps & {
|
|
125
|
+
_revealed?: boolean;
|
|
126
|
+
};
|
|
127
|
+
declare function Step({
|
|
128
|
+
children,
|
|
129
|
+
duration,
|
|
130
|
+
_revealed
|
|
131
|
+
}: InternalStepProps): react_jsx_runtime3.JSX.Element;
|
|
132
|
+
|
|
133
|
+
//#endregion
|
|
134
|
+
export { CANVAS_HEIGHT, CANVAS_WIDTH, DesignFonts, DesignPalette, DesignSystem, DesignTypeScale, ImagePlaceholder, ImagePlaceholderProps, Locale, OpenAipptConfig, Page, Plural, SharedElementTransition, SlideMeta, SlideModule, SlideTransition, Step, StepProps, Steps, StepsProps, TransitionPhase, cssVarsToString, defaultDesign, designToCssVars, unstable_SharedElement, unstable_SharedElementProps, useSlidePageNumber };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,467 @@
|
|
|
1
|
+
import { en, ja, zhCN, zhTW } from "./format-BCeKbTOM.js";
|
|
2
|
+
import { cssVarsToString, defaultDesign, designToCssVars } from "./design-cpzS8aud.js";
|
|
3
|
+
import { Children, cloneElement, createContext, isValidElement, useCallback, useContext, useEffect, useLayoutEffect, useRef, useState, useSyncExternalStore } from "react";
|
|
4
|
+
import { toast } from "sonner";
|
|
5
|
+
import config from "virtual:open-aippt/config";
|
|
6
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
7
|
+
|
|
8
|
+
//#region src/app/lib/assets.ts
|
|
9
|
+
async function listAssets(slideId) {
|
|
10
|
+
const res = await fetch(`/__assets/${slideId}`);
|
|
11
|
+
if (!res.ok) throw new Error(`GET /__assets/${slideId} ${res.status}`);
|
|
12
|
+
const data = await res.json();
|
|
13
|
+
return data.assets ?? [];
|
|
14
|
+
}
|
|
15
|
+
async function uploadAsset(slideId, file, opts = {}) {
|
|
16
|
+
const qs = opts.overwrite ? "?overwrite=1" : "";
|
|
17
|
+
return fetch(`/__assets/${slideId}/${encodeURIComponent(file.name)}${qs}`, {
|
|
18
|
+
method: "POST",
|
|
19
|
+
headers: {
|
|
20
|
+
"content-type": file.type || "application/octet-stream",
|
|
21
|
+
"content-length": String(file.size)
|
|
22
|
+
},
|
|
23
|
+
body: file
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
async function uploadWithAutoRename(slideId, file) {
|
|
27
|
+
let uploaded = lowercaseExtension(file);
|
|
28
|
+
let res = await uploadAsset(slideId, uploaded);
|
|
29
|
+
if (res.status === 409) {
|
|
30
|
+
const list = await listAssets(slideId);
|
|
31
|
+
const taken = new Set(list.map((a) => a.name));
|
|
32
|
+
uploaded = renamedCopy(uploaded, taken);
|
|
33
|
+
res = await uploadAsset(slideId, uploaded);
|
|
34
|
+
}
|
|
35
|
+
if (!res.ok) return {
|
|
36
|
+
ok: false,
|
|
37
|
+
status: res.status,
|
|
38
|
+
entry: null
|
|
39
|
+
};
|
|
40
|
+
const body = await res.json().catch(() => null);
|
|
41
|
+
const entry = {
|
|
42
|
+
name: body?.name ?? uploaded.name,
|
|
43
|
+
size: body?.size ?? uploaded.size,
|
|
44
|
+
mtime: body?.mtime ?? Date.now(),
|
|
45
|
+
mime: body?.mime ?? uploaded.type ?? "application/octet-stream",
|
|
46
|
+
url: body?.url ?? `/__assets/${slideId}/${encodeURIComponent(uploaded.name)}`,
|
|
47
|
+
unused: body?.unused ?? false
|
|
48
|
+
};
|
|
49
|
+
return {
|
|
50
|
+
ok: true,
|
|
51
|
+
status: res.status,
|
|
52
|
+
entry
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
function lowercaseExtension(file) {
|
|
56
|
+
const dot = file.name.lastIndexOf(".");
|
|
57
|
+
if (dot <= 0) return file;
|
|
58
|
+
const ext = file.name.slice(dot);
|
|
59
|
+
const lower = ext.toLowerCase();
|
|
60
|
+
if (ext === lower) return file;
|
|
61
|
+
return new File([file], file.name.slice(0, dot) + lower, {
|
|
62
|
+
type: file.type,
|
|
63
|
+
lastModified: file.lastModified
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
function renamedCopy(file, taken) {
|
|
67
|
+
const dot = file.name.lastIndexOf(".");
|
|
68
|
+
const stem = dot > 0 ? file.name.slice(0, dot) : file.name;
|
|
69
|
+
const ext = dot > 0 ? file.name.slice(dot) : "";
|
|
70
|
+
let i = 1;
|
|
71
|
+
let next = `${stem}-${i}${ext}`;
|
|
72
|
+
while (taken.has(next)) {
|
|
73
|
+
i += 1;
|
|
74
|
+
next = `${stem}-${i}${ext}`;
|
|
75
|
+
}
|
|
76
|
+
return new File([file], next, {
|
|
77
|
+
type: file.type,
|
|
78
|
+
lastModified: file.lastModified
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
//#endregion
|
|
83
|
+
//#region src/app/lib/locale-store.ts
|
|
84
|
+
const LOCALES = {
|
|
85
|
+
en,
|
|
86
|
+
"zh-TW": zhTW,
|
|
87
|
+
"zh-CN": zhCN,
|
|
88
|
+
ja
|
|
89
|
+
};
|
|
90
|
+
const STORAGE_KEY = "open-aippt:locale";
|
|
91
|
+
const configLocale = config.locale;
|
|
92
|
+
function isLocaleId(value) {
|
|
93
|
+
return value === "en" || value === "zh-TW" || value === "zh-CN" || value === "ja";
|
|
94
|
+
}
|
|
95
|
+
function readStored() {
|
|
96
|
+
try {
|
|
97
|
+
const stored = localStorage.getItem(STORAGE_KEY);
|
|
98
|
+
if (isLocaleId(stored)) return LOCALES[stored];
|
|
99
|
+
} catch {}
|
|
100
|
+
return configLocale ?? en;
|
|
101
|
+
}
|
|
102
|
+
let current = readStored();
|
|
103
|
+
const listeners = new Set();
|
|
104
|
+
function subscribe(listener) {
|
|
105
|
+
listeners.add(listener);
|
|
106
|
+
return () => {
|
|
107
|
+
listeners.delete(listener);
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
function getSnapshot() {
|
|
111
|
+
return current;
|
|
112
|
+
}
|
|
113
|
+
function useLocaleValue() {
|
|
114
|
+
return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
//#endregion
|
|
118
|
+
//#region src/app/lib/use-locale.ts
|
|
119
|
+
function useLocale() {
|
|
120
|
+
return useLocaleValue();
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
//#endregion
|
|
124
|
+
//#region src/app/components/image-placeholder.tsx
|
|
125
|
+
function ImagePlaceholder({ hint, width, height, style, className,...rest }) {
|
|
126
|
+
const dims = width && height ? `${width} × ${height}` : null;
|
|
127
|
+
const [dragActive, setDragActive] = useState(false);
|
|
128
|
+
const [uploading, setUploading] = useState(false);
|
|
129
|
+
const dragDepth = useRef(0);
|
|
130
|
+
const t = useLocale();
|
|
131
|
+
const dndProps = import.meta.env.DEV ? {
|
|
132
|
+
onDragEnter: (e) => {
|
|
133
|
+
if (uploading || !hasImageFile(e)) return;
|
|
134
|
+
e.preventDefault();
|
|
135
|
+
dragDepth.current += 1;
|
|
136
|
+
setDragActive(true);
|
|
137
|
+
},
|
|
138
|
+
onDragOver: (e) => {
|
|
139
|
+
if (uploading || !hasImageFile(e)) return;
|
|
140
|
+
e.preventDefault();
|
|
141
|
+
e.dataTransfer.dropEffect = "copy";
|
|
142
|
+
},
|
|
143
|
+
onDragLeave: () => {
|
|
144
|
+
dragDepth.current = Math.max(0, dragDepth.current - 1);
|
|
145
|
+
if (dragDepth.current === 0) setDragActive(false);
|
|
146
|
+
},
|
|
147
|
+
onDrop: (e) => {
|
|
148
|
+
if (uploading || !hasImageFile(e)) return;
|
|
149
|
+
e.preventDefault();
|
|
150
|
+
dragDepth.current = 0;
|
|
151
|
+
setDragActive(false);
|
|
152
|
+
const file = pickImageFile(e.dataTransfer.files);
|
|
153
|
+
if (!file) return;
|
|
154
|
+
const root = e.currentTarget;
|
|
155
|
+
const slideId = root.closest("[data-slide-id]")?.dataset.slideId;
|
|
156
|
+
const loc = root.dataset.slideLoc;
|
|
157
|
+
if (!slideId || !loc) return;
|
|
158
|
+
const idx = loc.indexOf(":");
|
|
159
|
+
if (idx <= 0) return;
|
|
160
|
+
const line = Number(loc.slice(0, idx));
|
|
161
|
+
const column = Number(loc.slice(idx + 1));
|
|
162
|
+
if (!Number.isFinite(line) || !Number.isFinite(column)) return;
|
|
163
|
+
setUploading(true);
|
|
164
|
+
handleDrop(slideId, file, line, column).catch(() => toast.error(t.imagePlaceholder.uploadFailed)).finally(() => setUploading(false));
|
|
165
|
+
}
|
|
166
|
+
} : null;
|
|
167
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
168
|
+
...rest,
|
|
169
|
+
...dndProps,
|
|
170
|
+
"data-slide-placeholder": hint,
|
|
171
|
+
"data-placeholder-w": width,
|
|
172
|
+
"data-placeholder-h": height,
|
|
173
|
+
role: "img",
|
|
174
|
+
"aria-label": hint,
|
|
175
|
+
style: {
|
|
176
|
+
position: "relative",
|
|
177
|
+
width: width ?? "100%",
|
|
178
|
+
height: height ?? "100%",
|
|
179
|
+
display: "flex",
|
|
180
|
+
alignItems: "center",
|
|
181
|
+
justifyContent: "center",
|
|
182
|
+
flexDirection: "column",
|
|
183
|
+
gap: 14,
|
|
184
|
+
border: "1px dashed rgba(120, 120, 130, 0.35)",
|
|
185
|
+
borderRadius: 12,
|
|
186
|
+
background: "linear-gradient(135deg, rgba(120,120,130,0.06) 0%, rgba(120,120,130,0.02) 50%, rgba(120,120,130,0.06) 100%)",
|
|
187
|
+
color: "rgba(90, 90, 100, 0.7)",
|
|
188
|
+
fontFamily: "-apple-system, BlinkMacSystemFont, \"Inter\", \"Segoe UI\", system-ui, sans-serif",
|
|
189
|
+
textAlign: "center",
|
|
190
|
+
padding: 24,
|
|
191
|
+
boxSizing: "border-box",
|
|
192
|
+
overflow: "hidden",
|
|
193
|
+
...style
|
|
194
|
+
},
|
|
195
|
+
className,
|
|
196
|
+
children: [
|
|
197
|
+
/* @__PURE__ */ jsx(PlaceholderIcon, {}),
|
|
198
|
+
/* @__PURE__ */ jsxs("div", {
|
|
199
|
+
style: {
|
|
200
|
+
display: "flex",
|
|
201
|
+
flexDirection: "column",
|
|
202
|
+
alignItems: "center",
|
|
203
|
+
gap: 6,
|
|
204
|
+
maxWidth: "85%"
|
|
205
|
+
},
|
|
206
|
+
children: [
|
|
207
|
+
/* @__PURE__ */ jsx("span", {
|
|
208
|
+
style: {
|
|
209
|
+
fontSize: 11,
|
|
210
|
+
fontWeight: 600,
|
|
211
|
+
letterSpacing: "0.14em",
|
|
212
|
+
textTransform: "uppercase",
|
|
213
|
+
opacity: .55
|
|
214
|
+
},
|
|
215
|
+
children: "Image"
|
|
216
|
+
}),
|
|
217
|
+
/* @__PURE__ */ jsx("span", {
|
|
218
|
+
style: {
|
|
219
|
+
fontSize: 16,
|
|
220
|
+
fontWeight: 500,
|
|
221
|
+
lineHeight: 1.4,
|
|
222
|
+
color: "rgba(60, 60, 70, 0.85)"
|
|
223
|
+
},
|
|
224
|
+
children: hint
|
|
225
|
+
}),
|
|
226
|
+
dims && /* @__PURE__ */ jsx("span", {
|
|
227
|
+
style: {
|
|
228
|
+
fontSize: 11,
|
|
229
|
+
fontVariantNumeric: "tabular-nums",
|
|
230
|
+
fontFamily: "ui-monospace, \"SF Mono\", Menlo, Consolas, monospace",
|
|
231
|
+
opacity: .5,
|
|
232
|
+
marginTop: 2
|
|
233
|
+
},
|
|
234
|
+
children: dims
|
|
235
|
+
})
|
|
236
|
+
]
|
|
237
|
+
}),
|
|
238
|
+
import.meta.env.DEV && (dragActive || uploading) && /* @__PURE__ */ jsx(DropOverlay, { label: uploading ? t.imagePlaceholder.uploading : t.imagePlaceholder.dropOverlay })
|
|
239
|
+
]
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
function DropOverlay({ label }) {
|
|
243
|
+
return /* @__PURE__ */ jsx("div", {
|
|
244
|
+
"aria-hidden": true,
|
|
245
|
+
style: {
|
|
246
|
+
position: "absolute",
|
|
247
|
+
inset: 0,
|
|
248
|
+
pointerEvents: "none",
|
|
249
|
+
borderRadius: 12,
|
|
250
|
+
border: "2px dashed oklch(0.62 0.18 250)",
|
|
251
|
+
background: "oklch(0.62 0.18 250 / 0.08)",
|
|
252
|
+
display: "flex",
|
|
253
|
+
alignItems: "center",
|
|
254
|
+
justifyContent: "center"
|
|
255
|
+
},
|
|
256
|
+
children: /* @__PURE__ */ jsx("span", {
|
|
257
|
+
style: {
|
|
258
|
+
fontSize: 12,
|
|
259
|
+
fontWeight: 600,
|
|
260
|
+
letterSpacing: "0.02em",
|
|
261
|
+
color: "oklch(0.45 0.16 250)",
|
|
262
|
+
background: "rgba(255,255,255,0.92)",
|
|
263
|
+
padding: "6px 10px",
|
|
264
|
+
borderRadius: 6,
|
|
265
|
+
boxShadow: "0 1px 2px rgba(0,0,0,0.08)"
|
|
266
|
+
},
|
|
267
|
+
children: label
|
|
268
|
+
})
|
|
269
|
+
});
|
|
270
|
+
}
|
|
271
|
+
function hasImageFile(e) {
|
|
272
|
+
const types = e.dataTransfer?.types;
|
|
273
|
+
if (!types) return false;
|
|
274
|
+
for (let i = 0; i < types.length; i++) if (types[i] === "Files") return true;
|
|
275
|
+
return false;
|
|
276
|
+
}
|
|
277
|
+
function pickImageFile(files) {
|
|
278
|
+
for (let i = 0; i < files.length; i++) {
|
|
279
|
+
const f = files[i];
|
|
280
|
+
if (f.type.startsWith("image/")) return f;
|
|
281
|
+
}
|
|
282
|
+
return null;
|
|
283
|
+
}
|
|
284
|
+
async function handleDrop(slideId, file, line, column) {
|
|
285
|
+
const { ok, entry } = await uploadWithAutoRename(slideId, file);
|
|
286
|
+
if (!ok || !entry) throw new Error("upload failed");
|
|
287
|
+
const res = await fetch("/__edit", {
|
|
288
|
+
method: "POST",
|
|
289
|
+
headers: { "content-type": "application/json" },
|
|
290
|
+
body: JSON.stringify({
|
|
291
|
+
slideId,
|
|
292
|
+
line,
|
|
293
|
+
column,
|
|
294
|
+
ops: [{
|
|
295
|
+
kind: "replace-placeholder-with-image",
|
|
296
|
+
assetPath: `./assets/${entry.name}`
|
|
297
|
+
}]
|
|
298
|
+
})
|
|
299
|
+
});
|
|
300
|
+
if (!res.ok) throw new Error(`edit failed (${res.status})`);
|
|
301
|
+
}
|
|
302
|
+
function PlaceholderIcon() {
|
|
303
|
+
return /* @__PURE__ */ jsxs("svg", {
|
|
304
|
+
width: "32",
|
|
305
|
+
height: "32",
|
|
306
|
+
viewBox: "0 0 32 32",
|
|
307
|
+
fill: "none",
|
|
308
|
+
stroke: "currentColor",
|
|
309
|
+
strokeWidth: "1.5",
|
|
310
|
+
strokeLinecap: "round",
|
|
311
|
+
strokeLinejoin: "round",
|
|
312
|
+
style: { opacity: .55 },
|
|
313
|
+
role: "img",
|
|
314
|
+
"aria-label": "image placeholder",
|
|
315
|
+
children: [
|
|
316
|
+
/* @__PURE__ */ jsx("title", { children: "image placeholder" }),
|
|
317
|
+
/* @__PURE__ */ jsx("rect", {
|
|
318
|
+
x: "4",
|
|
319
|
+
y: "6",
|
|
320
|
+
width: "24",
|
|
321
|
+
height: "20",
|
|
322
|
+
rx: "2.5"
|
|
323
|
+
}),
|
|
324
|
+
/* @__PURE__ */ jsx("circle", {
|
|
325
|
+
cx: "11",
|
|
326
|
+
cy: "13",
|
|
327
|
+
r: "2"
|
|
328
|
+
}),
|
|
329
|
+
/* @__PURE__ */ jsx("path", { d: "M4 22l7-7 6 6 4-4 7 7" })
|
|
330
|
+
]
|
|
331
|
+
});
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
//#endregion
|
|
335
|
+
//#region src/app/components/shared-element.tsx
|
|
336
|
+
function unstable_SharedElement({ id, children, className, style }) {
|
|
337
|
+
const child = Children.toArray(children)[0] ?? null;
|
|
338
|
+
if (Children.count(children) === 1 && isValidElement(child) && typeof child.type === "string") return cloneElement(child, {
|
|
339
|
+
"data-osd-shared-element": id,
|
|
340
|
+
className: [child.props.className, className].filter(Boolean).join(" ") || void 0,
|
|
341
|
+
style: style ? {
|
|
342
|
+
...child.props.style,
|
|
343
|
+
...style
|
|
344
|
+
} : child.props.style
|
|
345
|
+
});
|
|
346
|
+
return /* @__PURE__ */ jsx("div", {
|
|
347
|
+
className,
|
|
348
|
+
style,
|
|
349
|
+
"data-osd-shared-element": id,
|
|
350
|
+
children
|
|
351
|
+
});
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
//#endregion
|
|
355
|
+
//#region src/app/lib/page-context.tsx
|
|
356
|
+
const GLOBAL_KEY$1 = "__open_aippt_page_context__";
|
|
357
|
+
const g$1 = globalThis;
|
|
358
|
+
if (!g$1[GLOBAL_KEY$1]) g$1[GLOBAL_KEY$1] = createContext(null);
|
|
359
|
+
const SlidePageContext = g$1[GLOBAL_KEY$1];
|
|
360
|
+
function useSlidePageNumber() {
|
|
361
|
+
const ctx = useContext(SlidePageContext);
|
|
362
|
+
if (!ctx) throw new Error("useSlidePageNumber must be called from a slide page rendered by @open-aippt/core");
|
|
363
|
+
return {
|
|
364
|
+
current: ctx.index + 1,
|
|
365
|
+
total: ctx.total
|
|
366
|
+
};
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
//#endregion
|
|
370
|
+
//#region src/app/lib/sdk.ts
|
|
371
|
+
const CANVAS_WIDTH = 1920;
|
|
372
|
+
const CANVAS_HEIGHT = 1080;
|
|
373
|
+
|
|
374
|
+
//#endregion
|
|
375
|
+
//#region src/app/lib/use-prefers-reduced-motion.ts
|
|
376
|
+
const QUERY = "(prefers-reduced-motion: reduce)";
|
|
377
|
+
function usePrefersReducedMotion() {
|
|
378
|
+
const [reduce, setReduce] = useState(() => {
|
|
379
|
+
if (typeof window === "undefined") return false;
|
|
380
|
+
return window.matchMedia(QUERY).matches;
|
|
381
|
+
});
|
|
382
|
+
useEffect(() => {
|
|
383
|
+
const mql = window.matchMedia(QUERY);
|
|
384
|
+
const onChange = (e) => setReduce(e.matches);
|
|
385
|
+
mql.addEventListener("change", onChange);
|
|
386
|
+
return () => mql.removeEventListener("change", onChange);
|
|
387
|
+
}, []);
|
|
388
|
+
return reduce;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
//#endregion
|
|
392
|
+
//#region src/app/lib/step-context.tsx
|
|
393
|
+
const GLOBAL_KEY = "__open_aippt_step_host_context__";
|
|
394
|
+
const g = globalThis;
|
|
395
|
+
if (!g[GLOBAL_KEY]) g[GLOBAL_KEY] = createContext(null);
|
|
396
|
+
const StepHostContext = g[GLOBAL_KEY];
|
|
397
|
+
function Steps({ children }) {
|
|
398
|
+
const host = useContext(StepHostContext);
|
|
399
|
+
const flat = Children.toArray(children);
|
|
400
|
+
const stepCount = flat.filter((c) => isValidElement(c) && c.type === Step).length;
|
|
401
|
+
const initial = host?.controlled ? 0 : host?.entryDirection === "forward" ? 0 : stepCount;
|
|
402
|
+
const revealedRef = useRef(initial);
|
|
403
|
+
const [revealed, setRevealed] = useState(initial);
|
|
404
|
+
const idRef = useRef({});
|
|
405
|
+
const applyRevealed = useCallback((n) => {
|
|
406
|
+
revealedRef.current = n;
|
|
407
|
+
setRevealed(n);
|
|
408
|
+
}, []);
|
|
409
|
+
useLayoutEffect(() => {
|
|
410
|
+
if (!host) return;
|
|
411
|
+
const id = idRef.current;
|
|
412
|
+
const ctrl = {
|
|
413
|
+
advance: () => {
|
|
414
|
+
if (revealedRef.current >= stepCount) return false;
|
|
415
|
+
applyRevealed(revealedRef.current + 1);
|
|
416
|
+
host.reportRevealed(id, revealedRef.current);
|
|
417
|
+
return true;
|
|
418
|
+
},
|
|
419
|
+
retreat: () => {
|
|
420
|
+
if (revealedRef.current <= 0) return false;
|
|
421
|
+
applyRevealed(revealedRef.current - 1);
|
|
422
|
+
host.reportRevealed(id, revealedRef.current);
|
|
423
|
+
return true;
|
|
424
|
+
}
|
|
425
|
+
};
|
|
426
|
+
return host.register({
|
|
427
|
+
id,
|
|
428
|
+
stepCount,
|
|
429
|
+
initialRevealed: revealedRef.current,
|
|
430
|
+
controller: ctrl,
|
|
431
|
+
setRevealed: applyRevealed
|
|
432
|
+
});
|
|
433
|
+
}, [
|
|
434
|
+
host,
|
|
435
|
+
stepCount,
|
|
436
|
+
applyRevealed
|
|
437
|
+
]);
|
|
438
|
+
const effectiveRevealed = host ? revealed : stepCount;
|
|
439
|
+
let stepIdx = 0;
|
|
440
|
+
return /* @__PURE__ */ jsx(Fragment, { children: flat.map((child, key) => {
|
|
441
|
+
if (isValidElement(child) && child.type === Step) {
|
|
442
|
+
const idx = stepIdx++;
|
|
443
|
+
return cloneElement(child, {
|
|
444
|
+
key: child.key ?? key,
|
|
445
|
+
_revealed: idx < effectiveRevealed
|
|
446
|
+
});
|
|
447
|
+
}
|
|
448
|
+
return child;
|
|
449
|
+
}) });
|
|
450
|
+
}
|
|
451
|
+
function Step({ children, duration = 180, _revealed }) {
|
|
452
|
+
const reduceMotion = usePrefersReducedMotion();
|
|
453
|
+
const revealed = _revealed ?? true;
|
|
454
|
+
const ms = reduceMotion ? 0 : duration;
|
|
455
|
+
return /* @__PURE__ */ jsx("div", {
|
|
456
|
+
"data-osd-step": revealed ? "revealed" : "pending",
|
|
457
|
+
style: {
|
|
458
|
+
opacity: revealed ? 1 : 0,
|
|
459
|
+
visibility: revealed ? "visible" : "hidden",
|
|
460
|
+
transition: `opacity ${ms}ms cubic-bezier(0, 0, 0.2, 1)`
|
|
461
|
+
},
|
|
462
|
+
children
|
|
463
|
+
});
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
//#endregion
|
|
467
|
+
export { CANVAS_HEIGHT, CANVAS_WIDTH, ImagePlaceholder, Step, Steps, cssVarsToString, defaultDesign, designToCssVars, unstable_SharedElement, useSlidePageNumber };
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Locale, Plural } from "../types-CHmFPIG_.js";
|
|
2
|
+
|
|
3
|
+
//#region src/locale/en.d.ts
|
|
4
|
+
declare const en: Locale;
|
|
5
|
+
|
|
6
|
+
//#endregion
|
|
7
|
+
//#region src/locale/format.d.ts
|
|
8
|
+
declare function format(template: string, vars: Record<string, string | number>): string;
|
|
9
|
+
declare function plural(count: number, forms: Plural): string;
|
|
10
|
+
|
|
11
|
+
//#endregion
|
|
12
|
+
//#region src/locale/ja.d.ts
|
|
13
|
+
declare const ja: Locale;
|
|
14
|
+
|
|
15
|
+
//#endregion
|
|
16
|
+
//#region src/locale/zh-cn.d.ts
|
|
17
|
+
declare const zhCN: Locale;
|
|
18
|
+
|
|
19
|
+
//#endregion
|
|
20
|
+
//#region src/locale/zh-tw.d.ts
|
|
21
|
+
declare const zhTW: Locale;
|
|
22
|
+
|
|
23
|
+
//#endregion
|
|
24
|
+
export { Locale, Plural, en, format, ja, plural, zhCN, zhTW };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import "./design-cpzS8aud.js";
|
|
2
|
+
import { createViteConfig } from "./config-CjzqjrEA.js";
|
|
3
|
+
import { mergeConfig, preview as preview$1 } from "vite";
|
|
4
|
+
|
|
5
|
+
//#region src/cli/preview.ts
|
|
6
|
+
async function preview(opts = {}) {
|
|
7
|
+
const base = await createViteConfig({ userCwd: process.cwd() });
|
|
8
|
+
const config = mergeConfig(base, { preview: {
|
|
9
|
+
...opts.port !== void 0 ? { port: opts.port } : {},
|
|
10
|
+
...opts.host !== void 0 ? { host: opts.host } : {},
|
|
11
|
+
...opts.open !== void 0 ? { open: opts.open } : {}
|
|
12
|
+
} });
|
|
13
|
+
const server = await preview$1(config);
|
|
14
|
+
server.printUrls();
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
//#endregion
|
|
18
|
+
export { preview };
|