@starrykit/slides-editor 0.1.30 → 0.1.31
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/components/editor-header.d.ts +7 -1
- package/dist/components/editor-workspace.d.ts +7 -1
- package/dist/index.d.ts +14 -1
- package/dist/index.js +194 -48
- package/package.json +2 -2
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { PdfExportSelection } from "@starrykit/slides-core";
|
|
2
|
+
import type { DeckSwitcherOption } from "../index";
|
|
2
3
|
export interface PdfExportSlideOption {
|
|
3
4
|
id: string;
|
|
4
5
|
title: string;
|
|
@@ -6,7 +7,11 @@ export interface PdfExportSlideOption {
|
|
|
6
7
|
}
|
|
7
8
|
interface EditorHeaderProps {
|
|
8
9
|
title: string;
|
|
10
|
+
decks?: DeckSwitcherOption[];
|
|
11
|
+
currentDeckId?: string | null;
|
|
9
12
|
onTitleChange?: (t: string) => void;
|
|
13
|
+
onDeckSwitch?: (deckId: string) => void;
|
|
14
|
+
onDeckImport?: (files: FileList) => void;
|
|
10
15
|
onPresent?: () => void;
|
|
11
16
|
onExportPdf?: (selection: PdfExportSelection) => void;
|
|
12
17
|
onExportHtml?: () => void;
|
|
@@ -14,6 +19,7 @@ interface EditorHeaderProps {
|
|
|
14
19
|
pdfSlides?: PdfExportSlideOption[];
|
|
15
20
|
pdfThumbnails?: Record<string, string>;
|
|
16
21
|
isSaving: boolean;
|
|
22
|
+
isSwitchingDeck?: boolean;
|
|
17
23
|
}
|
|
18
|
-
export declare function EditorHeader({ title, onTitleChange, onPresent, onExportPdf, onExportHtml, onExportSourceFiles, pdfSlides, pdfThumbnails, isSaving, }: EditorHeaderProps): import("react/jsx-runtime").JSX.Element;
|
|
24
|
+
export declare function EditorHeader({ title, decks, currentDeckId, onTitleChange, onDeckSwitch, onDeckImport, onPresent, onExportPdf, onExportHtml, onExportSourceFiles, pdfSlides, pdfThumbnails, isSaving, isSwitchingDeck, }: EditorHeaderProps): import("react/jsx-runtime").JSX.Element;
|
|
19
25
|
export {};
|
|
@@ -2,6 +2,7 @@ import type { EditableType, PdfExportSelection, SlideModel, StageRect } from "@s
|
|
|
2
2
|
import type { MouseEvent as ReactMouseEvent, RefObject } from "react";
|
|
3
3
|
import type { BlockManipulationOverlay as BlockManipulationOverlayModel } from "../hooks/block-manipulation-types";
|
|
4
4
|
import type { ImageCropOverlay as ImageCropOverlayModel } from "../hooks/use-image-crop";
|
|
5
|
+
import type { DeckSwitcherOption } from "../index";
|
|
5
6
|
import type { ResizeHandleCorner, ResizeHandlePosition } from "../lib/block-snap-types";
|
|
6
7
|
import type { CssPropertyRow } from "../lib/collect-css-properties";
|
|
7
8
|
import type { SelectionCommandAvailability } from "./floating-toolbar";
|
|
@@ -9,7 +10,10 @@ interface EditorWorkspaceProps {
|
|
|
9
10
|
slides: SlideModel[];
|
|
10
11
|
activeSlide: SlideModel;
|
|
11
12
|
deckTitle: string;
|
|
13
|
+
decks?: DeckSwitcherOption[];
|
|
14
|
+
currentDeckId?: string | null;
|
|
12
15
|
isSaving: boolean;
|
|
16
|
+
isSwitchingDeck: boolean;
|
|
13
17
|
isPresenting: boolean;
|
|
14
18
|
thumbnails: Record<string, string>;
|
|
15
19
|
slideWidth: number;
|
|
@@ -42,6 +46,8 @@ interface EditorWorkspaceProps {
|
|
|
42
46
|
isManipulating: boolean;
|
|
43
47
|
isToolbarSuppressed: boolean;
|
|
44
48
|
onDeckTitleChange?: (title: string) => void;
|
|
49
|
+
onDeckSwitch?: (deckId: string) => void;
|
|
50
|
+
onDeckImport?: (files: FileList) => void;
|
|
45
51
|
onExportPdf?: (selection: PdfExportSelection) => void;
|
|
46
52
|
onExportHtml?: () => void;
|
|
47
53
|
onExportSourceFiles?: () => void;
|
|
@@ -84,5 +90,5 @@ interface EditorWorkspaceProps {
|
|
|
84
90
|
onDuplicateElement: () => void;
|
|
85
91
|
onDeleteElement: () => void;
|
|
86
92
|
}
|
|
87
|
-
declare function EditorWorkspace({ slides, activeSlide, deckTitle, isSaving, isPresenting, thumbnails, slideWidth, slideHeight, offsetX, offsetY, scale, preselectionOverlay, marqueeOverlay, selectionOverlay, toolbarKey, inspectedStyles, selectedElementType, selectionCommandAvailability, isSelectedElementLocked, groupScopeOverlayPassive, isEditingText, isCropMode, cropOverlay, manipulationOverlay, attributeValues, iframeRef, stageViewportRef, selectionOverlayRef, selectionContextMenuTriggerRef, isManipulating, isToolbarSuppressed, onDeckTitleChange, onExportPdf, onExportHtml, onExportSourceFiles, onPresent, onExitPresenting, onSelectSlide, onSidebarSlideFocusChange, onAddSlide, onAddSlideAbove, onAddSlideBelow, onDuplicateSlide, onDeleteSlide, onToggleSlideHidden, onRenameSlide, onReorderSlide, onSidebarFocusChange, onSelectionOverlayMouseDown, onSelectionOverlayMouseUp, onSelectionOverlayMouseMove, onSelectionOverlayContextMenu, onStageMouseLeave, onResizeHandleMouseDown, onCornerRotationZoneMouseDown, onCropHandleMouseDown, onSelectionOverlayDoubleClick, onBackgroundClick, onStyleChange, onStyleChanges, onStylePreview, onAttributeChange, onAlignToSlide, onCropImage, onDistribute, onGroup, onLayerOrder, onUngroup, onDuplicateElement, onDeleteElement, }: EditorWorkspaceProps): import("react/jsx-runtime").JSX.Element;
|
|
93
|
+
declare function EditorWorkspace({ slides, activeSlide, deckTitle, decks, currentDeckId, isSaving, isSwitchingDeck, isPresenting, thumbnails, slideWidth, slideHeight, offsetX, offsetY, scale, preselectionOverlay, marqueeOverlay, selectionOverlay, toolbarKey, inspectedStyles, selectedElementType, selectionCommandAvailability, isSelectedElementLocked, groupScopeOverlayPassive, isEditingText, isCropMode, cropOverlay, manipulationOverlay, attributeValues, iframeRef, stageViewportRef, selectionOverlayRef, selectionContextMenuTriggerRef, isManipulating, isToolbarSuppressed, onDeckTitleChange, onDeckSwitch, onDeckImport, onExportPdf, onExportHtml, onExportSourceFiles, onPresent, onExitPresenting, onSelectSlide, onSidebarSlideFocusChange, onAddSlide, onAddSlideAbove, onAddSlideBelow, onDuplicateSlide, onDeleteSlide, onToggleSlideHidden, onRenameSlide, onReorderSlide, onSidebarFocusChange, onSelectionOverlayMouseDown, onSelectionOverlayMouseUp, onSelectionOverlayMouseMove, onSelectionOverlayContextMenu, onStageMouseLeave, onResizeHandleMouseDown, onCornerRotationZoneMouseDown, onCropHandleMouseDown, onSelectionOverlayDoubleClick, onBackgroundClick, onStyleChange, onStyleChanges, onStylePreview, onAttributeChange, onAlignToSlide, onCropImage, onDistribute, onGroup, onLayerOrder, onUngroup, onDuplicateElement, onDeleteElement, }: EditorWorkspaceProps): import("react/jsx-runtime").JSX.Element;
|
|
88
94
|
export { EditorWorkspace };
|
package/dist/index.d.ts
CHANGED
|
@@ -2,13 +2,26 @@ import { type PdfExportSelection, type SlideModel } from "@starrykit/slides-core
|
|
|
2
2
|
export interface SlidesEditorProps {
|
|
3
3
|
slides: SlideModel[];
|
|
4
4
|
deckTitle?: string;
|
|
5
|
+
decks?: DeckSwitcherOption[];
|
|
6
|
+
currentDeckId?: string | null;
|
|
5
7
|
isSaving?: boolean;
|
|
8
|
+
isSwitchingDeck?: boolean;
|
|
6
9
|
onSlidesChange?: (slides: SlideModel[]) => void;
|
|
7
10
|
onDeckTitleChange?: (title: string) => void;
|
|
11
|
+
onDeckSwitch?: (deckId: string) => void;
|
|
12
|
+
onDeckImport?: (files: FileList) => void;
|
|
8
13
|
onExportPdf?: (selection: PdfExportSelection) => void;
|
|
9
14
|
onExportHtml?: () => void;
|
|
10
15
|
onExportSourceFiles?: () => void;
|
|
11
16
|
}
|
|
12
|
-
|
|
17
|
+
export interface DeckSwitcherOption {
|
|
18
|
+
id: string;
|
|
19
|
+
title: string;
|
|
20
|
+
description?: string;
|
|
21
|
+
directoryName: string;
|
|
22
|
+
relativePath: string;
|
|
23
|
+
isCurrent: boolean;
|
|
24
|
+
}
|
|
25
|
+
declare function SlidesEditor({ slides: loadedSlides, deckTitle, decks, currentDeckId, isSaving, isSwitchingDeck, onSlidesChange, onDeckTitleChange, onDeckSwitch, onDeckImport, onExportPdf, onExportHtml, onExportSourceFiles, }: SlidesEditorProps): import("react/jsx-runtime").JSX.Element;
|
|
13
26
|
export { SlidesEditor };
|
|
14
27
|
export * from "@starrykit/slides-core";
|
package/dist/index.js
CHANGED
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
FileCheck2,
|
|
15
15
|
FileCode2,
|
|
16
16
|
FileText,
|
|
17
|
+
FolderInput,
|
|
17
18
|
Layers3,
|
|
18
19
|
Play,
|
|
19
20
|
Presentation,
|
|
@@ -33,7 +34,7 @@ function cn(...inputs) {
|
|
|
33
34
|
}
|
|
34
35
|
|
|
35
36
|
// src/components/editor-header.tsx
|
|
36
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
37
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
37
38
|
var EXPORTS = [
|
|
38
39
|
{
|
|
39
40
|
id: "html",
|
|
@@ -60,23 +61,37 @@ var EXPORTS = [
|
|
|
60
61
|
var GITHUB_REPO_URL = "https://github.com/StarryKit/starry-slides";
|
|
61
62
|
function EditorHeader({
|
|
62
63
|
title,
|
|
64
|
+
decks = [],
|
|
65
|
+
currentDeckId,
|
|
63
66
|
onTitleChange,
|
|
67
|
+
onDeckSwitch,
|
|
68
|
+
onDeckImport,
|
|
64
69
|
onPresent,
|
|
65
70
|
onExportPdf,
|
|
66
71
|
onExportHtml,
|
|
67
72
|
onExportSourceFiles,
|
|
68
73
|
pdfSlides = [],
|
|
69
74
|
pdfThumbnails = {},
|
|
70
|
-
isSaving
|
|
75
|
+
isSaving,
|
|
76
|
+
isSwitchingDeck = false
|
|
71
77
|
}) {
|
|
72
|
-
const [
|
|
78
|
+
const [exportOpen, setExportOpen] = useState(false);
|
|
79
|
+
const [deckOpen, setDeckOpen] = useState(false);
|
|
73
80
|
const [pdfDialogOpen, setPdfDialogOpen] = useState(false);
|
|
74
81
|
const [titleWidth, setTitleWidth] = useState(0);
|
|
75
|
-
const
|
|
82
|
+
const exportRef = useRef(null);
|
|
83
|
+
const deckRef = useRef(null);
|
|
84
|
+
const deckImportInputRef = useRef(null);
|
|
76
85
|
const titleDisplay = title || "Untitled presentation";
|
|
86
|
+
const canOpenDeckMenu = decks.length > 0 || Boolean(onDeckImport);
|
|
77
87
|
useEffect(() => {
|
|
78
88
|
const onDoc = (e) => {
|
|
79
|
-
if (
|
|
89
|
+
if (exportRef.current && !exportRef.current.contains(e.target)) {
|
|
90
|
+
setExportOpen(false);
|
|
91
|
+
}
|
|
92
|
+
if (deckRef.current && !deckRef.current.contains(e.target)) {
|
|
93
|
+
setDeckOpen(false);
|
|
94
|
+
}
|
|
80
95
|
};
|
|
81
96
|
document.addEventListener("mousedown", onDoc);
|
|
82
97
|
return () => document.removeEventListener("mousedown", onDoc);
|
|
@@ -89,7 +104,7 @@ function EditorHeader({
|
|
|
89
104
|
setTitleWidth(Math.ceil(nextWidth));
|
|
90
105
|
}, []);
|
|
91
106
|
const handleExport = (e) => {
|
|
92
|
-
|
|
107
|
+
setExportOpen(false);
|
|
93
108
|
if (e.soon) {
|
|
94
109
|
toast(`${e.label} is not available yet.`, {
|
|
95
110
|
description: "We are still building this export option."
|
|
@@ -124,28 +139,134 @@ function EditorHeader({
|
|
|
124
139
|
}
|
|
125
140
|
),
|
|
126
141
|
/* @__PURE__ */ jsx("div", { className: "w-px h-5 bg-foreground/10" }),
|
|
127
|
-
/* @__PURE__ */ jsxs("div", { className: "
|
|
128
|
-
/* @__PURE__ */
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
142
|
+
/* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-1 items-center gap-1.5", children: [
|
|
143
|
+
/* @__PURE__ */ jsxs("div", { className: "relative min-w-0 shrink", children: [
|
|
144
|
+
/* @__PURE__ */ jsx(
|
|
145
|
+
"input",
|
|
146
|
+
{
|
|
147
|
+
value: title,
|
|
148
|
+
onChange: (e) => onTitleChange?.(e.target.value),
|
|
149
|
+
"aria-label": "Deck title",
|
|
150
|
+
className: "max-w-full min-w-0 flex-none rounded-md bg-transparent px-2 py-1 text-[18px] font-semibold text-foreground outline-none focus:bg-foreground/[0.04]",
|
|
151
|
+
style: titleWidth ? { width: `${titleWidth}px` } : void 0,
|
|
152
|
+
placeholder: "Untitled presentation"
|
|
153
|
+
}
|
|
154
|
+
),
|
|
155
|
+
/* @__PURE__ */ jsx(
|
|
156
|
+
"span",
|
|
157
|
+
{
|
|
158
|
+
ref: measureTitleRef,
|
|
159
|
+
"aria-hidden": "true",
|
|
160
|
+
className: "pointer-events-none invisible absolute left-0 top-0 whitespace-pre rounded-md px-2 py-1 text-[18px] font-semibold",
|
|
161
|
+
children: titleDisplay
|
|
162
|
+
},
|
|
163
|
+
titleDisplay
|
|
164
|
+
)
|
|
165
|
+
] }),
|
|
166
|
+
/* @__PURE__ */ jsxs("div", { className: "relative shrink-0", ref: deckRef, children: [
|
|
167
|
+
/* @__PURE__ */ jsx(
|
|
168
|
+
"button",
|
|
169
|
+
{
|
|
170
|
+
type: "button",
|
|
171
|
+
"aria-label": "Switch deck",
|
|
172
|
+
"aria-expanded": deckOpen,
|
|
173
|
+
"aria-haspopup": "menu",
|
|
174
|
+
disabled: !canOpenDeckMenu || isSwitchingDeck,
|
|
175
|
+
onClick: () => {
|
|
176
|
+
if (canOpenDeckMenu && !isSwitchingDeck) {
|
|
177
|
+
setDeckOpen((open) => !open);
|
|
178
|
+
}
|
|
179
|
+
},
|
|
180
|
+
className: "flex h-7 w-7 items-center justify-center rounded-md text-foreground/45 transition-colors hover:bg-foreground/[0.04] hover:text-foreground disabled:cursor-not-allowed disabled:opacity-35",
|
|
181
|
+
children: /* @__PURE__ */ jsx(
|
|
182
|
+
ChevronDown,
|
|
183
|
+
{
|
|
184
|
+
className: cn("h-3.5 w-3.5 transition-transform", deckOpen && "rotate-180")
|
|
185
|
+
}
|
|
186
|
+
)
|
|
187
|
+
}
|
|
188
|
+
),
|
|
189
|
+
/* @__PURE__ */ jsx(
|
|
190
|
+
"input",
|
|
191
|
+
{
|
|
192
|
+
ref: deckImportInputRef,
|
|
193
|
+
type: "file",
|
|
194
|
+
multiple: true,
|
|
195
|
+
"aria-label": "Import deck folder",
|
|
196
|
+
className: "hidden",
|
|
197
|
+
...{ webkitdirectory: "", directory: "" },
|
|
198
|
+
onChange: (event) => {
|
|
199
|
+
const files = event.currentTarget.files;
|
|
200
|
+
if (files?.length) {
|
|
201
|
+
onDeckImport?.(files);
|
|
202
|
+
}
|
|
203
|
+
event.currentTarget.value = "";
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
),
|
|
207
|
+
deckOpen && /* @__PURE__ */ jsxs(
|
|
208
|
+
"div",
|
|
209
|
+
{
|
|
210
|
+
role: "menu",
|
|
211
|
+
"aria-label": "Local decks",
|
|
212
|
+
className: "absolute left-0 z-50 mt-1.5 w-[300px] rounded-lg border border-foreground/[0.08] bg-white p-1.5 shadow-[0_4px_20px_rgba(0,0,0,0.06),0_12px_40px_rgba(0,0,0,0.08)] animate-fade-in",
|
|
213
|
+
children: [
|
|
214
|
+
/* @__PURE__ */ jsx("div", { className: "px-2.5 py-1.5 text-[10px] font-medium uppercase tracking-wider text-foreground/40", children: "Local decks" }),
|
|
215
|
+
decks.map((deck) => {
|
|
216
|
+
const current = deck.isCurrent || deck.id === currentDeckId;
|
|
217
|
+
return /* @__PURE__ */ jsxs(
|
|
218
|
+
"button",
|
|
219
|
+
{
|
|
220
|
+
type: "button",
|
|
221
|
+
role: "menuitemradio",
|
|
222
|
+
"aria-checked": current,
|
|
223
|
+
disabled: current || isSwitchingDeck,
|
|
224
|
+
onClick: () => {
|
|
225
|
+
setDeckOpen(false);
|
|
226
|
+
onDeckSwitch?.(deck.id);
|
|
227
|
+
},
|
|
228
|
+
className: cn(
|
|
229
|
+
"flex w-full items-start gap-2.5 rounded-md px-2.5 py-2 text-left transition-colors",
|
|
230
|
+
current ? "bg-foreground/[0.045] text-foreground" : "text-foreground/72 hover:bg-foreground/[0.04] hover:text-foreground",
|
|
231
|
+
isSwitchingDeck && "cursor-wait opacity-60"
|
|
232
|
+
),
|
|
233
|
+
children: [
|
|
234
|
+
/* @__PURE__ */ jsx("span", { className: "mt-0.5 flex h-4 w-4 shrink-0 items-center justify-center", children: current ? /* @__PURE__ */ jsx(Check, { className: "h-3.5 w-3.5" }) : null }),
|
|
235
|
+
/* @__PURE__ */ jsxs("span", { className: "min-w-0 flex-1", children: [
|
|
236
|
+
/* @__PURE__ */ jsx("span", { className: "block truncate text-[13px] font-medium", children: deck.title }),
|
|
237
|
+
/* @__PURE__ */ jsx("span", { className: "mt-0.5 block truncate text-[11px] text-foreground/45", children: deck.relativePath === "." ? deck.directoryName : deck.relativePath })
|
|
238
|
+
] })
|
|
239
|
+
]
|
|
240
|
+
},
|
|
241
|
+
deck.id
|
|
242
|
+
);
|
|
243
|
+
}),
|
|
244
|
+
onDeckImport ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
245
|
+
/* @__PURE__ */ jsx("div", { className: "my-1 h-px bg-foreground/[0.08]" }),
|
|
246
|
+
/* @__PURE__ */ jsxs(
|
|
247
|
+
"button",
|
|
248
|
+
{
|
|
249
|
+
type: "button",
|
|
250
|
+
role: "menuitem",
|
|
251
|
+
onClick: () => {
|
|
252
|
+
setDeckOpen(false);
|
|
253
|
+
deckImportInputRef.current?.click();
|
|
254
|
+
},
|
|
255
|
+
className: "flex w-full items-start gap-2.5 rounded-md px-2.5 py-2 text-left text-foreground/72 transition-colors hover:bg-foreground/[0.04] hover:text-foreground",
|
|
256
|
+
children: [
|
|
257
|
+
/* @__PURE__ */ jsx("span", { className: "mt-0.5 flex h-4 w-4 shrink-0 items-center justify-center", children: /* @__PURE__ */ jsx(FolderInput, { className: "h-3.5 w-3.5" }) }),
|
|
258
|
+
/* @__PURE__ */ jsxs("span", { className: "min-w-0 flex-1", children: [
|
|
259
|
+
/* @__PURE__ */ jsx("span", { className: "block truncate text-[13px] font-medium", children: "Import deck..." }),
|
|
260
|
+
/* @__PURE__ */ jsx("span", { className: "mt-0.5 block truncate text-[11px] text-foreground/45", children: "Choose a folder with manifest.json" })
|
|
261
|
+
] })
|
|
262
|
+
]
|
|
263
|
+
}
|
|
264
|
+
)
|
|
265
|
+
] }) : null
|
|
266
|
+
]
|
|
267
|
+
}
|
|
268
|
+
)
|
|
269
|
+
] })
|
|
149
270
|
] }),
|
|
150
271
|
isSaving ? /* @__PURE__ */ jsx(
|
|
151
272
|
"span",
|
|
@@ -157,21 +278,26 @@ function EditorHeader({
|
|
|
157
278
|
) : null
|
|
158
279
|
] }),
|
|
159
280
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
160
|
-
/* @__PURE__ */ jsxs("div", { className: "relative", ref, children: [
|
|
281
|
+
/* @__PURE__ */ jsxs("div", { className: "relative", ref: exportRef, children: [
|
|
161
282
|
/* @__PURE__ */ jsxs(
|
|
162
283
|
"button",
|
|
163
284
|
{
|
|
164
285
|
type: "button",
|
|
165
|
-
onClick: () =>
|
|
286
|
+
onClick: () => setExportOpen((o) => !o),
|
|
166
287
|
className: "h-8 px-3 rounded-md flex items-center gap-1.5 text-[13px] text-foreground/70 hover:bg-foreground/[0.04] hover:text-foreground transition-colors",
|
|
167
288
|
children: [
|
|
168
289
|
/* @__PURE__ */ jsx(Download, { className: "w-3.5 h-3.5" }),
|
|
169
290
|
/* @__PURE__ */ jsx("span", { children: "Export" }),
|
|
170
|
-
/* @__PURE__ */ jsx(
|
|
291
|
+
/* @__PURE__ */ jsx(
|
|
292
|
+
ChevronDown,
|
|
293
|
+
{
|
|
294
|
+
className: cn("w-3 h-3 transition-transform", exportOpen && "rotate-180")
|
|
295
|
+
}
|
|
296
|
+
)
|
|
171
297
|
]
|
|
172
298
|
}
|
|
173
299
|
),
|
|
174
|
-
|
|
300
|
+
exportOpen && /* @__PURE__ */ jsxs("div", { className: "absolute right-0 mt-1.5 w-[280px] bg-white rounded-xl border border-foreground/[0.08] shadow-[0_4px_20px_rgba(0,0,0,0.06),0_12px_40px_rgba(0,0,0,0.08)] p-1.5 animate-fade-in z-50", children: [
|
|
175
301
|
/* @__PURE__ */ jsx("div", { className: "text-[10px] uppercase tracking-wider text-foreground/40 px-2.5 py-1.5 font-medium", children: "Export formats" }),
|
|
176
302
|
EXPORTS.map((e) => {
|
|
177
303
|
const Icon = e.icon;
|
|
@@ -1060,7 +1186,7 @@ function Input({ className, type, ...props }) {
|
|
|
1060
1186
|
}
|
|
1061
1187
|
|
|
1062
1188
|
// src/components/slide-sidebar.tsx
|
|
1063
|
-
import { Fragment, jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
1189
|
+
import { Fragment as Fragment2, jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
1064
1190
|
function SlideSidebar({
|
|
1065
1191
|
slides,
|
|
1066
1192
|
activeSlideId,
|
|
@@ -1132,7 +1258,7 @@ function SlideSidebar({
|
|
|
1132
1258
|
onRename?.(renameDialogSlideId, renameDraft);
|
|
1133
1259
|
cancelRename();
|
|
1134
1260
|
}, [cancelRename, onRename, renameDialogSlideId, renameDraft]);
|
|
1135
|
-
return /* @__PURE__ */ jsxs4(
|
|
1261
|
+
return /* @__PURE__ */ jsxs4(Fragment2, { children: [
|
|
1136
1262
|
/* @__PURE__ */ jsx6(
|
|
1137
1263
|
"aside",
|
|
1138
1264
|
{
|
|
@@ -1482,7 +1608,7 @@ function rangesOverlapOrNear(startA, endA, startB, endB, proximity) {
|
|
|
1482
1608
|
}
|
|
1483
1609
|
|
|
1484
1610
|
// src/components/block-manipulation-overlay.tsx
|
|
1485
|
-
import { Fragment as
|
|
1611
|
+
import { Fragment as Fragment3, jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
1486
1612
|
function makeRotationCursor(svgBody) {
|
|
1487
1613
|
return encodeURIComponent(
|
|
1488
1614
|
`<svg width="32" height="32" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg"><g fill="none">${svgBody}</g></svg>`
|
|
@@ -1515,7 +1641,7 @@ function BlockManipulationOverlay({
|
|
|
1515
1641
|
onCornerRotationZoneMouseDown
|
|
1516
1642
|
}) {
|
|
1517
1643
|
const handleClassName = "absolute z-[5] size-[13px] -translate-x-1/2 -translate-y-1/2 rounded-full border border-white bg-foreground shadow-[0_2px_8px_rgba(0,0,0,0.16)] transition-colors before:absolute before:inset-[3px] before:rounded-full before:bg-white/90 hover:bg-foreground/80";
|
|
1518
|
-
return /* @__PURE__ */ jsxs5(
|
|
1644
|
+
return /* @__PURE__ */ jsxs5(Fragment3, { children: [
|
|
1519
1645
|
snapGuides.map((guide, index) => {
|
|
1520
1646
|
const lineWidth = guide.variant === "spacing" ? "2px" : "1px";
|
|
1521
1647
|
const capLength = 14;
|
|
@@ -1558,7 +1684,7 @@ function BlockManipulationOverlay({
|
|
|
1558
1684
|
"data-testid": `snap-guide-${guide.orientation}`,
|
|
1559
1685
|
"data-variant": guide.variant,
|
|
1560
1686
|
style: lineStyle,
|
|
1561
|
-
children: guide.variant === "spacing" ? /* @__PURE__ */ jsxs5(
|
|
1687
|
+
children: guide.variant === "spacing" ? /* @__PURE__ */ jsxs5(Fragment3, { children: [
|
|
1562
1688
|
/* @__PURE__ */ jsx7(
|
|
1563
1689
|
"span",
|
|
1564
1690
|
{
|
|
@@ -3820,7 +3946,7 @@ import {
|
|
|
3820
3946
|
useRef as useRef7,
|
|
3821
3947
|
useState as useState8
|
|
3822
3948
|
} from "react";
|
|
3823
|
-
import { Fragment as
|
|
3949
|
+
import { Fragment as Fragment4, jsx as jsx18, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
3824
3950
|
function ColorPopover({
|
|
3825
3951
|
activePopoverId,
|
|
3826
3952
|
commitFeature,
|
|
@@ -3956,10 +4082,10 @@ function OptionsPopover({
|
|
|
3956
4082
|
onPointerDown: () => {
|
|
3957
4083
|
skipNextPreviewClearRef.current = true;
|
|
3958
4084
|
},
|
|
3959
|
-
children: showOptionPreviewAfterLabel ? /* @__PURE__ */ jsxs11(
|
|
4085
|
+
children: showOptionPreviewAfterLabel ? /* @__PURE__ */ jsxs11(Fragment4, { children: [
|
|
3960
4086
|
/* @__PURE__ */ jsx18("span", { className: "min-w-0 truncate", children: option.label }),
|
|
3961
4087
|
/* @__PURE__ */ jsx18(OptionSwatch, { feature, option })
|
|
3962
|
-
] }) : /* @__PURE__ */ jsxs11(
|
|
4088
|
+
] }) : /* @__PURE__ */ jsxs11(Fragment4, { children: [
|
|
3963
4089
|
Icon ? /* @__PURE__ */ jsx18(ToolbarIcon, { icon: Icon }) : /* @__PURE__ */ jsx18(OptionSwatch, { feature, option }),
|
|
3964
4090
|
/* @__PURE__ */ jsx18("span", { className: "truncate", children: option.label })
|
|
3965
4091
|
] })
|
|
@@ -4186,7 +4312,7 @@ var LINE_HEIGHT_SLIDER_STEP = 0.01;
|
|
|
4186
4312
|
var LINE_HEIGHT_SLIDER_DEFAULT = 1.2;
|
|
4187
4313
|
|
|
4188
4314
|
// src/components/floating-toolbar-sections.tsx
|
|
4189
|
-
import { Fragment as
|
|
4315
|
+
import { Fragment as Fragment5, jsx as jsx19, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
4190
4316
|
var BORDER_RANGE_DEBOUNCE_MS = 160;
|
|
4191
4317
|
function FloatingToolbarSections({
|
|
4192
4318
|
activePopoverId,
|
|
@@ -4203,7 +4329,7 @@ function FloatingToolbarSections({
|
|
|
4203
4329
|
setActivePopoverId
|
|
4204
4330
|
}) {
|
|
4205
4331
|
const isImageSelection = selectedElementType === "image";
|
|
4206
|
-
return /* @__PURE__ */ jsxs12(
|
|
4332
|
+
return /* @__PURE__ */ jsxs12(Fragment5, { children: [
|
|
4207
4333
|
/* @__PURE__ */ jsx19(
|
|
4208
4334
|
LockSection,
|
|
4209
4335
|
{
|
|
@@ -4214,9 +4340,9 @@ function FloatingToolbarSections({
|
|
|
4214
4340
|
showGroupTool
|
|
4215
4341
|
}
|
|
4216
4342
|
),
|
|
4217
|
-
isSelectedElementLocked ? null : /* @__PURE__ */ jsxs12(
|
|
4343
|
+
isSelectedElementLocked ? null : /* @__PURE__ */ jsxs12(Fragment5, { children: [
|
|
4218
4344
|
/* @__PURE__ */ jsx19(Divider, {}),
|
|
4219
|
-
isImageSelection ? /* @__PURE__ */ jsx19(ImageSection, { commitFeature, getFeature: getFeature2 }) : /* @__PURE__ */ jsxs12(
|
|
4345
|
+
isImageSelection ? /* @__PURE__ */ jsx19(ImageSection, { commitFeature, getFeature: getFeature2 }) : /* @__PURE__ */ jsxs12(Fragment5, { children: [
|
|
4220
4346
|
/* @__PURE__ */ jsx19(
|
|
4221
4347
|
FontSection,
|
|
4222
4348
|
{
|
|
@@ -4263,7 +4389,7 @@ function FloatingToolbarSections({
|
|
|
4263
4389
|
}
|
|
4264
4390
|
)
|
|
4265
4391
|
] }),
|
|
4266
|
-
isImageSelection ? /* @__PURE__ */ jsxs12(
|
|
4392
|
+
isImageSelection ? /* @__PURE__ */ jsxs12(Fragment5, { children: [
|
|
4267
4393
|
/* @__PURE__ */ jsx19(Divider, {}),
|
|
4268
4394
|
/* @__PURE__ */ jsx19(
|
|
4269
4395
|
BorderSection,
|
|
@@ -4278,7 +4404,7 @@ function FloatingToolbarSections({
|
|
|
4278
4404
|
}
|
|
4279
4405
|
)
|
|
4280
4406
|
] }) : null,
|
|
4281
|
-
showMultiTools ? /* @__PURE__ */ jsxs12(
|
|
4407
|
+
showMultiTools ? /* @__PURE__ */ jsxs12(Fragment5, { children: [
|
|
4282
4408
|
/* @__PURE__ */ jsx19(Divider, {}),
|
|
4283
4409
|
/* @__PURE__ */ jsx19(
|
|
4284
4410
|
MultiArrangeSection,
|
|
@@ -5242,7 +5368,7 @@ function getFeature(featureId) {
|
|
|
5242
5368
|
}
|
|
5243
5369
|
|
|
5244
5370
|
// src/components/image-crop-overlay.tsx
|
|
5245
|
-
import { Fragment as
|
|
5371
|
+
import { Fragment as Fragment6, jsx as jsx21, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
5246
5372
|
var CROP_CURSOR_PATHS = {
|
|
5247
5373
|
"top-left": "M12 22V12H22",
|
|
5248
5374
|
"top-right": "M2 12h10v10",
|
|
@@ -5252,7 +5378,7 @@ var CROP_CURSOR_PATHS = {
|
|
|
5252
5378
|
function ImageCropOverlay({ overlay, onCropHandleMouseDown }) {
|
|
5253
5379
|
const handleClassName = "absolute z-[7] size-8 -translate-x-1/2 -translate-y-1/2 rounded-sm bg-transparent text-white drop-shadow-[0_1px_2px_rgba(0,0,0,0.7)]";
|
|
5254
5380
|
const maskRegions = createMaskRegions(overlay.selectionBounds, overlay.cropBounds);
|
|
5255
|
-
return /* @__PURE__ */ jsxs14(
|
|
5381
|
+
return /* @__PURE__ */ jsxs14(Fragment6, { children: [
|
|
5256
5382
|
/* @__PURE__ */ jsx21("div", { className: "pointer-events-none absolute inset-0 z-[5]", "data-testid": "image-crop-mask", children: maskRegions.map((region) => /* @__PURE__ */ jsx21(
|
|
5257
5383
|
"div",
|
|
5258
5384
|
{
|
|
@@ -5648,7 +5774,10 @@ function EditorWorkspace({
|
|
|
5648
5774
|
slides,
|
|
5649
5775
|
activeSlide,
|
|
5650
5776
|
deckTitle,
|
|
5777
|
+
decks,
|
|
5778
|
+
currentDeckId,
|
|
5651
5779
|
isSaving,
|
|
5780
|
+
isSwitchingDeck,
|
|
5652
5781
|
isPresenting,
|
|
5653
5782
|
thumbnails,
|
|
5654
5783
|
slideWidth,
|
|
@@ -5677,6 +5806,8 @@ function EditorWorkspace({
|
|
|
5677
5806
|
isManipulating,
|
|
5678
5807
|
isToolbarSuppressed,
|
|
5679
5808
|
onDeckTitleChange,
|
|
5809
|
+
onDeckSwitch,
|
|
5810
|
+
onDeckImport,
|
|
5680
5811
|
onExportPdf,
|
|
5681
5812
|
onExportHtml,
|
|
5682
5813
|
onExportSourceFiles,
|
|
@@ -5727,6 +5858,11 @@ function EditorWorkspace({
|
|
|
5727
5858
|
{
|
|
5728
5859
|
title: deckTitle,
|
|
5729
5860
|
onTitleChange: onDeckTitleChange,
|
|
5861
|
+
decks,
|
|
5862
|
+
currentDeckId,
|
|
5863
|
+
isSwitchingDeck,
|
|
5864
|
+
onDeckSwitch,
|
|
5865
|
+
onDeckImport,
|
|
5730
5866
|
isSaving,
|
|
5731
5867
|
onPresent,
|
|
5732
5868
|
onExportHtml,
|
|
@@ -11206,9 +11342,14 @@ var EMPTY_LOCKED_ELEMENT_IDS = [];
|
|
|
11206
11342
|
function SlidesEditor({
|
|
11207
11343
|
slides: loadedSlides,
|
|
11208
11344
|
deckTitle,
|
|
11345
|
+
decks,
|
|
11346
|
+
currentDeckId,
|
|
11209
11347
|
isSaving = false,
|
|
11348
|
+
isSwitchingDeck = false,
|
|
11210
11349
|
onSlidesChange,
|
|
11211
11350
|
onDeckTitleChange,
|
|
11351
|
+
onDeckSwitch,
|
|
11352
|
+
onDeckImport,
|
|
11212
11353
|
onExportPdf,
|
|
11213
11354
|
onExportHtml,
|
|
11214
11355
|
onExportSourceFiles
|
|
@@ -11471,7 +11612,10 @@ function SlidesEditor({
|
|
|
11471
11612
|
slides,
|
|
11472
11613
|
activeSlide,
|
|
11473
11614
|
deckTitle: resolvedDeckTitle,
|
|
11615
|
+
decks,
|
|
11616
|
+
currentDeckId,
|
|
11474
11617
|
isSaving,
|
|
11618
|
+
isSwitchingDeck,
|
|
11475
11619
|
isPresenting,
|
|
11476
11620
|
thumbnails,
|
|
11477
11621
|
slideWidth,
|
|
@@ -11499,6 +11643,8 @@ function SlidesEditor({
|
|
|
11499
11643
|
isManipulating: isManipulating || isMarqueeSelecting,
|
|
11500
11644
|
isToolbarSuppressed,
|
|
11501
11645
|
onDeckTitleChange,
|
|
11646
|
+
onDeckSwitch,
|
|
11647
|
+
onDeckImport,
|
|
11502
11648
|
onExportHtml,
|
|
11503
11649
|
onExportSourceFiles,
|
|
11504
11650
|
onExportPdf,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@starrykit/slides-editor",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.31",
|
|
4
4
|
"description": "Embeddable React editor UI for Starry Slides — host-driven through props and callbacks.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"homepage": "https://github.com/StarryKit/starry-slides#readme",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"build": "tsc -p tsconfig.json && tsup src/index.tsx --format esm --external react --external react-dom"
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@starrykit/slides-core": "0.1.
|
|
33
|
+
"@starrykit/slides-core": "0.1.31",
|
|
34
34
|
"class-variance-authority": "^0.7.1",
|
|
35
35
|
"clsx": "^2.1.1",
|
|
36
36
|
"html-to-image": "^1.11.11",
|