@particle-academy/fancy-slides 0.6.1 → 0.8.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/index.cjs +171 -17
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +29 -3
- package/dist/index.d.ts +29 -3
- package/dist/index.js +172 -20
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import { ReactNode, CSSProperties } from 'react';
|
|
3
|
-
import { h as Slide$1, o as Theme, j as SlideElement, D as Deck, d as DeckOp, g as ShapeKind, l as SlideTransition, i as SlideBackground, E as ElementAnimation, m as TextElement, I as ImageElement, S as ShapeElement
|
|
3
|
+
import { h as Slide$1, o as Theme, j as SlideElement, D as Deck, d as DeckOp, g as ShapeKind, l as SlideTransition, i as SlideBackground, k as SlideLayout, E as ElementAnimation, m as TextElement, I as ImageElement, S as ShapeElement } from './types-9BbelJX1.cjs';
|
|
4
4
|
export { A as AnimationEffect, a as AnimationTrigger, C as ChartElement, b as CodeElement, c as DeckActivity, e as ElementBase, f as EmbedElement, T as TableElement, n as TextStyle, p as ThemeColors, q as ThemeFonts, r as TransitionKind } from './types-9BbelJX1.cjs';
|
|
5
|
+
import { EditorAction } from '@particle-academy/react-fancy';
|
|
5
6
|
|
|
6
7
|
interface SlideProps {
|
|
7
8
|
/** The slide to render. */
|
|
@@ -322,6 +323,8 @@ interface ElementInspectorProps {
|
|
|
322
323
|
onSetTransition?: (transition?: SlideTransition) => void;
|
|
323
324
|
/** Set the slide's background. */
|
|
324
325
|
onSetBackground?: (background?: SlideBackground) => void;
|
|
326
|
+
/** Set the slide's layout preset. */
|
|
327
|
+
onSetLayout?: (layout: SlideLayout) => void;
|
|
325
328
|
/** Set or clear the selected element's entrance build animation. */
|
|
326
329
|
onSetAnimation?: (animation?: ElementAnimation) => void;
|
|
327
330
|
/** Set a specific element's build animation by id — used by the slide-level build-order list. */
|
|
@@ -333,7 +336,7 @@ interface ElementInspectorProps {
|
|
|
333
336
|
* react-fancy `Card`, `Tabs`, `Input`, `Select`, `Slider`, `ColorPicker`,
|
|
334
337
|
* `Action`.
|
|
335
338
|
*/
|
|
336
|
-
declare function ElementInspector({ element, onPatch, onDelete, onLockToggle, slide, onSetTransition, onSetBackground, onSetAnimation, onSetElementAnimation }: ElementInspectorProps): react_jsx_runtime.JSX.Element;
|
|
339
|
+
declare function ElementInspector({ element, onPatch, onDelete, onLockToggle, slide, onSetTransition, onSetBackground, onSetLayout, onSetAnimation, onSetElementAnimation }: ElementInspectorProps): react_jsx_runtime.JSX.Element;
|
|
337
340
|
|
|
338
341
|
interface SpeakerNotesProps {
|
|
339
342
|
notes?: string;
|
|
@@ -484,6 +487,29 @@ interface TextElementRendererProps {
|
|
|
484
487
|
*/
|
|
485
488
|
declare function TextElementRenderer({ element, theme, slideWidthPx, editing, selected, onContentChange, paraReveal, }: TextElementRendererProps): react_jsx_runtime.JSX.Element;
|
|
486
489
|
|
|
490
|
+
/**
|
|
491
|
+
* Presentation-tuned toolbar preset for the react-fancy `Editor` used to edit
|
|
492
|
+
* slide text inline. Only commands that round-trip cleanly through the editor's
|
|
493
|
+
* `htmlToMarkdown` output are included — bold (`**`), italic (`*`), heading
|
|
494
|
+
* (`## `), and bullet list (`- `). Box-level typography (alignment, color, font
|
|
495
|
+
* size, line height) is NOT here: those are per-element `TextStyle` properties
|
|
496
|
+
* edited in the ElementInspector, and `text-align`/color spans don't survive the
|
|
497
|
+
* markdown the slide content commits to.
|
|
498
|
+
*/
|
|
499
|
+
declare const PRESENTATION_EDITOR_ACTIONS: EditorAction[];
|
|
500
|
+
/**
|
|
501
|
+
* Normalize the `Editor`'s markdown output to the *line-based* paragraph model
|
|
502
|
+
* the slide content commits to. The editor emits a blank line (`\n\n`) between
|
|
503
|
+
* `<p>` blocks, but `splitParagraphs` (and the dark-slide pptx writer) treat a
|
|
504
|
+
* single `\n` as one paragraph / build unit, and a blank interior line as its
|
|
505
|
+
* own (phantom) build. Collapsing runs of newlines to a single `\n` keeps
|
|
506
|
+
* "by paragraph" reveals and per-paragraph pptx builds correct — bullets are
|
|
507
|
+
* already one-per-`\n`, so they're unaffected. The round-trip invariant
|
|
508
|
+
* (`content → Editor → normalize → content` preserves the `\n` paragraph count)
|
|
509
|
+
* is covered by a unit test.
|
|
510
|
+
*/
|
|
511
|
+
declare function normalizeSlideMarkdown(md: string): string;
|
|
512
|
+
|
|
487
513
|
interface ImageElementRendererProps {
|
|
488
514
|
element: ImageElement;
|
|
489
515
|
}
|
|
@@ -647,4 +673,4 @@ type ChartKind = "bar" | "line" | "pie" | "area" | "scatter";
|
|
|
647
673
|
type Option = Record<string, unknown>;
|
|
648
674
|
declare function chartStarterOption(kind: ChartKind): Option;
|
|
649
675
|
|
|
650
|
-
export { type Build, type BuildStep, type ChartKind$1 as ChartKind, Deck, DeckEditor, type DeckEditorProps, DeckOp, type DeckStateApi, EditorToolbar, type EditorToolbarProps, ElementAnimation, ElementInspector, type ElementInspectorProps, ImageElement, ImageElementRenderer, type ImageElementRendererProps, type ParaReveal, PresenterView, type PresenterViewProps, ShapeElement, ShapeElementRenderer, type ShapeElementRendererProps, ShapeKind, Slide, SlideBackground, type SlideContextValue, Slide$1 as SlideData, SlideElement, type SlideKeyboardOptions, SlideLayout, type SlideProps, SlideRail, type SlideRailProps, SlideThumbnail, type SlideThumbnailProps, SlideTransition, SlideViewer, type SlideViewerProps, SpeakerNotes, type SpeakerNotesProps, TextElement, TextElementRenderer, type TextElementRendererProps, Theme, type UseDeckStateOptions, buildSteps, buildsForStep, builtinThemes, chartStarterOption, collectBuilds, darkTheme, deckId, defaultTheme, defineTheme, elementId, isByParagraph, nextId, paragraphReveals, reduce as reduceDeck, resolveTheme, slideId, splitParagraphs, stepDelays, totalBuildSteps, useDeckState, useIsDarkSlide, useSlideContext, useSlideKeyboard, useSlideTheme, visibleElementIds, vividTheme };
|
|
676
|
+
export { type Build, type BuildStep, type ChartKind$1 as ChartKind, Deck, DeckEditor, type DeckEditorProps, DeckOp, type DeckStateApi, EditorToolbar, type EditorToolbarProps, ElementAnimation, ElementInspector, type ElementInspectorProps, ImageElement, ImageElementRenderer, type ImageElementRendererProps, PRESENTATION_EDITOR_ACTIONS, type ParaReveal, PresenterView, type PresenterViewProps, ShapeElement, ShapeElementRenderer, type ShapeElementRendererProps, ShapeKind, Slide, SlideBackground, type SlideContextValue, Slide$1 as SlideData, SlideElement, type SlideKeyboardOptions, SlideLayout, type SlideProps, SlideRail, type SlideRailProps, SlideThumbnail, type SlideThumbnailProps, SlideTransition, SlideViewer, type SlideViewerProps, SpeakerNotes, type SpeakerNotesProps, TextElement, TextElementRenderer, type TextElementRendererProps, Theme, type UseDeckStateOptions, buildSteps, buildsForStep, builtinThemes, chartStarterOption, collectBuilds, darkTheme, deckId, defaultTheme, defineTheme, elementId, isByParagraph, nextId, normalizeSlideMarkdown, paragraphReveals, reduce as reduceDeck, resolveTheme, slideId, splitParagraphs, stepDelays, totalBuildSteps, useDeckState, useIsDarkSlide, useSlideContext, useSlideKeyboard, useSlideTheme, visibleElementIds, vividTheme };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import { ReactNode, CSSProperties } from 'react';
|
|
3
|
-
import { h as Slide$1, o as Theme, j as SlideElement, D as Deck, d as DeckOp, g as ShapeKind, l as SlideTransition, i as SlideBackground, E as ElementAnimation, m as TextElement, I as ImageElement, S as ShapeElement
|
|
3
|
+
import { h as Slide$1, o as Theme, j as SlideElement, D as Deck, d as DeckOp, g as ShapeKind, l as SlideTransition, i as SlideBackground, k as SlideLayout, E as ElementAnimation, m as TextElement, I as ImageElement, S as ShapeElement } from './types-9BbelJX1.js';
|
|
4
4
|
export { A as AnimationEffect, a as AnimationTrigger, C as ChartElement, b as CodeElement, c as DeckActivity, e as ElementBase, f as EmbedElement, T as TableElement, n as TextStyle, p as ThemeColors, q as ThemeFonts, r as TransitionKind } from './types-9BbelJX1.js';
|
|
5
|
+
import { EditorAction } from '@particle-academy/react-fancy';
|
|
5
6
|
|
|
6
7
|
interface SlideProps {
|
|
7
8
|
/** The slide to render. */
|
|
@@ -322,6 +323,8 @@ interface ElementInspectorProps {
|
|
|
322
323
|
onSetTransition?: (transition?: SlideTransition) => void;
|
|
323
324
|
/** Set the slide's background. */
|
|
324
325
|
onSetBackground?: (background?: SlideBackground) => void;
|
|
326
|
+
/** Set the slide's layout preset. */
|
|
327
|
+
onSetLayout?: (layout: SlideLayout) => void;
|
|
325
328
|
/** Set or clear the selected element's entrance build animation. */
|
|
326
329
|
onSetAnimation?: (animation?: ElementAnimation) => void;
|
|
327
330
|
/** Set a specific element's build animation by id — used by the slide-level build-order list. */
|
|
@@ -333,7 +336,7 @@ interface ElementInspectorProps {
|
|
|
333
336
|
* react-fancy `Card`, `Tabs`, `Input`, `Select`, `Slider`, `ColorPicker`,
|
|
334
337
|
* `Action`.
|
|
335
338
|
*/
|
|
336
|
-
declare function ElementInspector({ element, onPatch, onDelete, onLockToggle, slide, onSetTransition, onSetBackground, onSetAnimation, onSetElementAnimation }: ElementInspectorProps): react_jsx_runtime.JSX.Element;
|
|
339
|
+
declare function ElementInspector({ element, onPatch, onDelete, onLockToggle, slide, onSetTransition, onSetBackground, onSetLayout, onSetAnimation, onSetElementAnimation }: ElementInspectorProps): react_jsx_runtime.JSX.Element;
|
|
337
340
|
|
|
338
341
|
interface SpeakerNotesProps {
|
|
339
342
|
notes?: string;
|
|
@@ -484,6 +487,29 @@ interface TextElementRendererProps {
|
|
|
484
487
|
*/
|
|
485
488
|
declare function TextElementRenderer({ element, theme, slideWidthPx, editing, selected, onContentChange, paraReveal, }: TextElementRendererProps): react_jsx_runtime.JSX.Element;
|
|
486
489
|
|
|
490
|
+
/**
|
|
491
|
+
* Presentation-tuned toolbar preset for the react-fancy `Editor` used to edit
|
|
492
|
+
* slide text inline. Only commands that round-trip cleanly through the editor's
|
|
493
|
+
* `htmlToMarkdown` output are included — bold (`**`), italic (`*`), heading
|
|
494
|
+
* (`## `), and bullet list (`- `). Box-level typography (alignment, color, font
|
|
495
|
+
* size, line height) is NOT here: those are per-element `TextStyle` properties
|
|
496
|
+
* edited in the ElementInspector, and `text-align`/color spans don't survive the
|
|
497
|
+
* markdown the slide content commits to.
|
|
498
|
+
*/
|
|
499
|
+
declare const PRESENTATION_EDITOR_ACTIONS: EditorAction[];
|
|
500
|
+
/**
|
|
501
|
+
* Normalize the `Editor`'s markdown output to the *line-based* paragraph model
|
|
502
|
+
* the slide content commits to. The editor emits a blank line (`\n\n`) between
|
|
503
|
+
* `<p>` blocks, but `splitParagraphs` (and the dark-slide pptx writer) treat a
|
|
504
|
+
* single `\n` as one paragraph / build unit, and a blank interior line as its
|
|
505
|
+
* own (phantom) build. Collapsing runs of newlines to a single `\n` keeps
|
|
506
|
+
* "by paragraph" reveals and per-paragraph pptx builds correct — bullets are
|
|
507
|
+
* already one-per-`\n`, so they're unaffected. The round-trip invariant
|
|
508
|
+
* (`content → Editor → normalize → content` preserves the `\n` paragraph count)
|
|
509
|
+
* is covered by a unit test.
|
|
510
|
+
*/
|
|
511
|
+
declare function normalizeSlideMarkdown(md: string): string;
|
|
512
|
+
|
|
487
513
|
interface ImageElementRendererProps {
|
|
488
514
|
element: ImageElement;
|
|
489
515
|
}
|
|
@@ -647,4 +673,4 @@ type ChartKind = "bar" | "line" | "pie" | "area" | "scatter";
|
|
|
647
673
|
type Option = Record<string, unknown>;
|
|
648
674
|
declare function chartStarterOption(kind: ChartKind): Option;
|
|
649
675
|
|
|
650
|
-
export { type Build, type BuildStep, type ChartKind$1 as ChartKind, Deck, DeckEditor, type DeckEditorProps, DeckOp, type DeckStateApi, EditorToolbar, type EditorToolbarProps, ElementAnimation, ElementInspector, type ElementInspectorProps, ImageElement, ImageElementRenderer, type ImageElementRendererProps, type ParaReveal, PresenterView, type PresenterViewProps, ShapeElement, ShapeElementRenderer, type ShapeElementRendererProps, ShapeKind, Slide, SlideBackground, type SlideContextValue, Slide$1 as SlideData, SlideElement, type SlideKeyboardOptions, SlideLayout, type SlideProps, SlideRail, type SlideRailProps, SlideThumbnail, type SlideThumbnailProps, SlideTransition, SlideViewer, type SlideViewerProps, SpeakerNotes, type SpeakerNotesProps, TextElement, TextElementRenderer, type TextElementRendererProps, Theme, type UseDeckStateOptions, buildSteps, buildsForStep, builtinThemes, chartStarterOption, collectBuilds, darkTheme, deckId, defaultTheme, defineTheme, elementId, isByParagraph, nextId, paragraphReveals, reduce as reduceDeck, resolveTheme, slideId, splitParagraphs, stepDelays, totalBuildSteps, useDeckState, useIsDarkSlide, useSlideContext, useSlideKeyboard, useSlideTheme, visibleElementIds, vividTheme };
|
|
676
|
+
export { type Build, type BuildStep, type ChartKind$1 as ChartKind, Deck, DeckEditor, type DeckEditorProps, DeckOp, type DeckStateApi, EditorToolbar, type EditorToolbarProps, ElementAnimation, ElementInspector, type ElementInspectorProps, ImageElement, ImageElementRenderer, type ImageElementRendererProps, PRESENTATION_EDITOR_ACTIONS, type ParaReveal, PresenterView, type PresenterViewProps, ShapeElement, ShapeElementRenderer, type ShapeElementRendererProps, ShapeKind, Slide, SlideBackground, type SlideContextValue, Slide$1 as SlideData, SlideElement, type SlideKeyboardOptions, SlideLayout, type SlideProps, SlideRail, type SlideRailProps, SlideThumbnail, type SlideThumbnailProps, SlideTransition, SlideViewer, type SlideViewerProps, SpeakerNotes, type SpeakerNotesProps, TextElement, TextElementRenderer, type TextElementRendererProps, Theme, type UseDeckStateOptions, buildSteps, buildsForStep, builtinThemes, chartStarterOption, collectBuilds, darkTheme, deckId, defaultTheme, defineTheme, elementId, isByParagraph, nextId, normalizeSlideMarkdown, paragraphReveals, reduce as reduceDeck, resolveTheme, slideId, splitParagraphs, stepDelays, totalBuildSteps, useDeckState, useIsDarkSlide, useSlideContext, useSlideKeyboard, useSlideTheme, visibleElementIds, vividTheme };
|
package/dist/index.js
CHANGED
|
@@ -2,8 +2,8 @@ import { defaultElementRegistry } from './chunk-YEJZYKVB.js';
|
|
|
2
2
|
import { isDarkColor, SlideContext } from './chunk-WIUXPQAK.js';
|
|
3
3
|
export { useIsDarkSlide, useSlideContext, useSlideTheme } from './chunk-WIUXPQAK.js';
|
|
4
4
|
import { useId, useRef, useState, useEffect, useMemo, useCallback } from 'react';
|
|
5
|
-
import { ContentRenderer, Text, Action, ContextMenu, Separator, Tooltip, Dropdown, Badge, Heading, Tabs, Card, Select, Input, ColorPicker, Slider, Switch
|
|
6
|
-
import {
|
|
5
|
+
import { Editor, ContentRenderer, Text, Action, ContextMenu, Separator, Tooltip, Dropdown, Badge, Heading, Tabs, Card, Select, Input, ColorPicker, Textarea, Slider, Switch } from '@particle-academy/react-fancy';
|
|
6
|
+
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
7
7
|
|
|
8
8
|
// src/theme/default-theme.ts
|
|
9
9
|
var defaultTheme = {
|
|
@@ -268,6 +268,18 @@ var BUILD_KEYFRAMES = `
|
|
|
268
268
|
}
|
|
269
269
|
}
|
|
270
270
|
`;
|
|
271
|
+
|
|
272
|
+
// src/components/elements/TextElement/editor-preset.ts
|
|
273
|
+
var PRESENTATION_EDITOR_ACTIONS = [
|
|
274
|
+
{ icon: "B", label: "Bold", command: "bold" },
|
|
275
|
+
{ icon: "I", label: "Italic", command: "italic" },
|
|
276
|
+
{ icon: "H", label: "Heading", command: "formatBlock", commandArg: "<h2>" },
|
|
277
|
+
{ icon: "P", label: "Paragraph", command: "formatBlock", commandArg: "<p>" },
|
|
278
|
+
{ icon: "\u2022", label: "Bullet list", command: "insertUnorderedList" }
|
|
279
|
+
];
|
|
280
|
+
function normalizeSlideMarkdown(md) {
|
|
281
|
+
return md.replace(/\r\n/g, "\n").replace(/\n{2,}/g, "\n").replace(/[ \t]+$/gm, "").trim();
|
|
282
|
+
}
|
|
271
283
|
function TextElementRenderer({
|
|
272
284
|
element,
|
|
273
285
|
theme,
|
|
@@ -306,19 +318,58 @@ function TextElementRenderer({
|
|
|
306
318
|
overflow: "hidden"
|
|
307
319
|
};
|
|
308
320
|
if (editing && selected) {
|
|
309
|
-
|
|
310
|
-
|
|
321
|
+
const fontPx = Math.round((style.fontSize ?? 28) * scale);
|
|
322
|
+
const lh = style.lineHeight ?? 1.4;
|
|
323
|
+
const editScope = scopeId;
|
|
324
|
+
return /* @__PURE__ */ jsxs(
|
|
325
|
+
"div",
|
|
311
326
|
{
|
|
312
|
-
|
|
313
|
-
onChange: (e) => onContentChange?.(e.target.value),
|
|
327
|
+
"data-fs-edit-scope": editScope,
|
|
314
328
|
style: {
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
resize: "none",
|
|
318
|
-
border: "none",
|
|
329
|
+
width: "100%",
|
|
330
|
+
height: "100%",
|
|
319
331
|
pointerEvents: "auto",
|
|
320
|
-
cursor: "text"
|
|
321
|
-
|
|
332
|
+
cursor: "text",
|
|
333
|
+
textAlign: style.align ?? "left",
|
|
334
|
+
color: style.color ?? t.colors?.text,
|
|
335
|
+
fontFamily: style.fontFamily ?? t.fonts?.body
|
|
336
|
+
},
|
|
337
|
+
onPointerDown: (e) => e.stopPropagation(),
|
|
338
|
+
children: [
|
|
339
|
+
/* @__PURE__ */ jsx("style", { children: `
|
|
340
|
+
[data-fs-edit-scope="${editScope}"] [data-react-fancy-editor] {
|
|
341
|
+
border: none; background: transparent; border-radius: 0;
|
|
342
|
+
height: 100%; display: flex; flex-direction: column; overflow: hidden;
|
|
343
|
+
}
|
|
344
|
+
[data-fs-edit-scope="${editScope}"] [data-react-fancy-editor-toolbar] {
|
|
345
|
+
background: rgba(244,244,245,0.85); border-radius: 6px 6px 0 0;
|
|
346
|
+
padding: 2px 4px;
|
|
347
|
+
}
|
|
348
|
+
[data-fs-edit-scope="${editScope}"] [data-react-fancy-editor-content] {
|
|
349
|
+
flex: 1; min-height: 0; padding: 4px 2px; overflow: auto;
|
|
350
|
+
font-size: ${fontPx}px; line-height: ${lh};
|
|
351
|
+
}
|
|
352
|
+
[data-fs-edit-scope="${editScope}"] [data-react-fancy-editor-content] :is(p, ul, ol, li) { font-size: inherit; margin: 0; }
|
|
353
|
+
[data-fs-edit-scope="${editScope}"] [data-react-fancy-editor-content] :where(p, li) + :where(p, li, ul, ol) { margin-top: 0.4em; }
|
|
354
|
+
[data-fs-edit-scope="${editScope}"] [data-react-fancy-editor-content] h1 { font-size: 1.6em; font-weight: 700; margin: 0; }
|
|
355
|
+
[data-fs-edit-scope="${editScope}"] [data-react-fancy-editor-content] h2 { font-size: 1.35em; font-weight: 700; margin: 0; }
|
|
356
|
+
[data-fs-edit-scope="${editScope}"] [data-react-fancy-editor-content] h3 { font-size: 1.15em; font-weight: 600; margin: 0; }
|
|
357
|
+
` }),
|
|
358
|
+
/* @__PURE__ */ jsxs(
|
|
359
|
+
Editor,
|
|
360
|
+
{
|
|
361
|
+
value: element.content,
|
|
362
|
+
onChange: (md) => onContentChange?.(normalizeSlideMarkdown(md)),
|
|
363
|
+
outputFormat: "markdown",
|
|
364
|
+
lineSpacing: lh,
|
|
365
|
+
children: [
|
|
366
|
+
/* @__PURE__ */ jsx(Editor.Toolbar, { actions: PRESENTATION_EDITOR_ACTIONS }),
|
|
367
|
+
/* @__PURE__ */ jsx(Editor.Content, {})
|
|
368
|
+
]
|
|
369
|
+
},
|
|
370
|
+
element.id
|
|
371
|
+
)
|
|
372
|
+
]
|
|
322
373
|
}
|
|
323
374
|
);
|
|
324
375
|
}
|
|
@@ -1948,10 +1999,10 @@ function EditorToolbar({
|
|
|
1948
1999
|
/* @__PURE__ */ jsx("div", { className: "ml-auto flex items-center gap-2", children: /* @__PURE__ */ jsx(Tooltip, { content: "Present (F)", children: /* @__PURE__ */ jsx(Action, { color: "violet", size: "sm", icon: "play", onClick: onPresent, children: "Present" }) }) })
|
|
1949
2000
|
] });
|
|
1950
2001
|
}
|
|
1951
|
-
function ElementInspector({ element, onPatch, onDelete, onLockToggle, slide, onSetTransition, onSetBackground, onSetAnimation, onSetElementAnimation }) {
|
|
2002
|
+
function ElementInspector({ element, onPatch, onDelete, onLockToggle, slide, onSetTransition, onSetBackground, onSetLayout, onSetAnimation, onSetElementAnimation }) {
|
|
1952
2003
|
if (!element) {
|
|
1953
2004
|
if (slide) {
|
|
1954
|
-
return /* @__PURE__ */ jsx(SlideSettings, { slide, onSetTransition, onSetBackground, onSetElementAnimation });
|
|
2005
|
+
return /* @__PURE__ */ jsx(SlideSettings, { slide, onSetTransition, onSetBackground, onSetLayout, onSetElementAnimation });
|
|
1955
2006
|
}
|
|
1956
2007
|
return /* @__PURE__ */ jsxs("div", { className: "fs-inspector flex h-full flex-col border-l border-zinc-200 bg-zinc-50 p-4 dark:border-zinc-800 dark:bg-zinc-900", children: [
|
|
1957
2008
|
/* @__PURE__ */ jsx(Heading, { as: "h3", size: "xs", className: "!uppercase !tracking-wider !text-zinc-500", children: "Inspector" }),
|
|
@@ -1988,10 +2039,26 @@ function ElementInspector({ element, onPatch, onDelete, onLockToggle, slide, onS
|
|
|
1988
2039
|
] }) })
|
|
1989
2040
|
] });
|
|
1990
2041
|
}
|
|
2042
|
+
var SLIDE_LAYOUTS = [
|
|
2043
|
+
{ value: "blank", label: "Blank" },
|
|
2044
|
+
{ value: "title", label: "Title" },
|
|
2045
|
+
{ value: "title-content", label: "Title + content" },
|
|
2046
|
+
{ value: "two-column", label: "Two column" },
|
|
2047
|
+
{ value: "section-divider", label: "Section divider" },
|
|
2048
|
+
{ value: "image-text", label: "Image + text" },
|
|
2049
|
+
{ value: "text-image", label: "Text + image" },
|
|
2050
|
+
{ value: "quote", label: "Quote" }
|
|
2051
|
+
];
|
|
2052
|
+
function backgroundMode(bg) {
|
|
2053
|
+
if (bg?.gradient) return "gradient";
|
|
2054
|
+
if (bg?.image) return "image";
|
|
2055
|
+
return "color";
|
|
2056
|
+
}
|
|
1991
2057
|
function SlideSettings({
|
|
1992
2058
|
slide,
|
|
1993
2059
|
onSetTransition,
|
|
1994
2060
|
onSetBackground,
|
|
2061
|
+
onSetLayout,
|
|
1995
2062
|
onSetElementAnimation
|
|
1996
2063
|
}) {
|
|
1997
2064
|
const transition = slide.transition;
|
|
@@ -2000,6 +2067,7 @@ function SlideSettings({
|
|
|
2000
2067
|
const merged = { kind, duration: transition?.duration, direction: transition?.direction, ...next };
|
|
2001
2068
|
onSetTransition?.(merged.kind === "none" ? { kind: "none" } : merged);
|
|
2002
2069
|
};
|
|
2070
|
+
const bgMode = backgroundMode(slide.background);
|
|
2003
2071
|
return /* @__PURE__ */ jsxs("div", { className: "fs-inspector flex h-full w-full flex-col border-l border-zinc-200 bg-zinc-50 dark:border-zinc-800 dark:bg-zinc-900", children: [
|
|
2004
2072
|
/* @__PURE__ */ jsx("div", { className: "flex items-center justify-between border-b border-zinc-200 px-3 py-2 dark:border-zinc-800", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
2005
2073
|
/* @__PURE__ */ jsx(Heading, { as: "h3", size: "xs", className: "!font-mono !uppercase !tracking-wider !text-zinc-500", children: "slide" }),
|
|
@@ -2009,6 +2077,19 @@ function SlideSettings({
|
|
|
2009
2077
|
] })
|
|
2010
2078
|
] }) }),
|
|
2011
2079
|
/* @__PURE__ */ jsxs("div", { className: "flex-1 overflow-y-auto p-3", children: [
|
|
2080
|
+
onSetLayout && /* @__PURE__ */ jsx(Card, { padding: "md", className: "mb-3 !bg-white dark:!bg-zinc-950", children: /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
|
|
2081
|
+
/* @__PURE__ */ jsx(Heading, { as: "h4", size: "xs", className: "!uppercase !tracking-wider !text-zinc-500", children: "Layout" }),
|
|
2082
|
+
/* @__PURE__ */ jsx(
|
|
2083
|
+
Select,
|
|
2084
|
+
{
|
|
2085
|
+
label: "Preset",
|
|
2086
|
+
list: SLIDE_LAYOUTS,
|
|
2087
|
+
value: slide.layout ?? "blank",
|
|
2088
|
+
onValueChange: (v) => onSetLayout(v)
|
|
2089
|
+
}
|
|
2090
|
+
),
|
|
2091
|
+
/* @__PURE__ */ jsx(Text, { size: "xs", className: "!text-zinc-500", children: "The layout hint the deck commits to \u2014 carried through to the pptx export's slide layout." })
|
|
2092
|
+
] }) }),
|
|
2012
2093
|
/* @__PURE__ */ jsx(Card, { padding: "md", className: "!bg-white dark:!bg-zinc-950", children: /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
|
|
2013
2094
|
/* @__PURE__ */ jsx(Heading, { as: "h4", size: "xs", className: "!uppercase !tracking-wider !text-zinc-500", children: "Transition" }),
|
|
2014
2095
|
/* @__PURE__ */ jsx(
|
|
@@ -2052,13 +2133,63 @@ function SlideSettings({
|
|
|
2052
2133
|
] }) }),
|
|
2053
2134
|
onSetBackground && /* @__PURE__ */ jsx(Card, { padding: "md", className: "mt-3 !bg-white dark:!bg-zinc-950", children: /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
|
|
2054
2135
|
/* @__PURE__ */ jsx(Heading, { as: "h4", size: "xs", className: "!uppercase !tracking-wider !text-zinc-500", children: "Background" }),
|
|
2055
|
-
/* @__PURE__ */ jsx(
|
|
2136
|
+
/* @__PURE__ */ jsx(
|
|
2137
|
+
Select,
|
|
2138
|
+
{
|
|
2139
|
+
label: "Type",
|
|
2140
|
+
list: [
|
|
2141
|
+
{ value: "color", label: "Solid color" },
|
|
2142
|
+
{ value: "gradient", label: "Gradient" },
|
|
2143
|
+
{ value: "image", label: "Image" }
|
|
2144
|
+
],
|
|
2145
|
+
value: bgMode,
|
|
2146
|
+
onValueChange: (v) => {
|
|
2147
|
+
if (v === "color") onSetBackground({ color: slide.background?.color ?? "#ffffff" });
|
|
2148
|
+
else if (v === "gradient") onSetBackground({ gradient: slide.background?.gradient ?? "linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%)" });
|
|
2149
|
+
else onSetBackground({ image: slide.background?.image ?? "", imageFit: slide.background?.imageFit ?? "cover", color: slide.background?.color });
|
|
2150
|
+
}
|
|
2151
|
+
}
|
|
2152
|
+
),
|
|
2153
|
+
bgMode === "color" && /* @__PURE__ */ jsx(FieldLabel, { label: "Color", children: /* @__PURE__ */ jsx(
|
|
2056
2154
|
ColorPicker,
|
|
2057
2155
|
{
|
|
2058
2156
|
value: slide.background?.color ?? "#ffffff",
|
|
2059
|
-
onChange: (c) => onSetBackground({
|
|
2157
|
+
onChange: (c) => onSetBackground({ color: c })
|
|
2158
|
+
}
|
|
2159
|
+
) }),
|
|
2160
|
+
bgMode === "gradient" && /* @__PURE__ */ jsx(
|
|
2161
|
+
Textarea,
|
|
2162
|
+
{
|
|
2163
|
+
label: "CSS gradient",
|
|
2164
|
+
value: slide.background?.gradient ?? "",
|
|
2165
|
+
onValueChange: (v) => onSetBackground({ gradient: v }),
|
|
2166
|
+
rows: 2
|
|
2060
2167
|
}
|
|
2061
|
-
)
|
|
2168
|
+
),
|
|
2169
|
+
bgMode === "image" && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2170
|
+
/* @__PURE__ */ jsx(
|
|
2171
|
+
Textarea,
|
|
2172
|
+
{
|
|
2173
|
+
label: "Image URL",
|
|
2174
|
+
value: slide.background?.image ?? "",
|
|
2175
|
+
onValueChange: (v) => onSetBackground({ ...slide.background, image: v }),
|
|
2176
|
+
rows: 2
|
|
2177
|
+
}
|
|
2178
|
+
),
|
|
2179
|
+
/* @__PURE__ */ jsx(
|
|
2180
|
+
Select,
|
|
2181
|
+
{
|
|
2182
|
+
label: "Fit",
|
|
2183
|
+
list: [
|
|
2184
|
+
{ value: "cover", label: "Cover" },
|
|
2185
|
+
{ value: "contain", label: "Contain" },
|
|
2186
|
+
{ value: "fill", label: "Fill (stretch)" }
|
|
2187
|
+
],
|
|
2188
|
+
value: slide.background?.imageFit ?? "cover",
|
|
2189
|
+
onValueChange: (v) => onSetBackground({ ...slide.background, imageFit: v })
|
|
2190
|
+
}
|
|
2191
|
+
)
|
|
2192
|
+
] })
|
|
2062
2193
|
] }) }),
|
|
2063
2194
|
onSetElementAnimation && /* @__PURE__ */ jsx(Card, { padding: "md", className: "mt-3 !bg-white dark:!bg-zinc-950", children: /* @__PURE__ */ jsx(BuildOrderList, { slide, onSetElementAnimation }) })
|
|
2064
2195
|
] })
|
|
@@ -2299,6 +2430,24 @@ function TextStyleControls({ element, onPatch }) {
|
|
|
2299
2430
|
onValueChange: (v) => setStyle({ align: v })
|
|
2300
2431
|
}
|
|
2301
2432
|
),
|
|
2433
|
+
/* @__PURE__ */ jsx(
|
|
2434
|
+
Select,
|
|
2435
|
+
{
|
|
2436
|
+
label: "Vertical align",
|
|
2437
|
+
list: [
|
|
2438
|
+
{ value: "top", label: "Top" },
|
|
2439
|
+
{ value: "middle", label: "Middle" },
|
|
2440
|
+
{ value: "bottom", label: "Bottom" }
|
|
2441
|
+
],
|
|
2442
|
+
value: s.verticalAlign ?? "top",
|
|
2443
|
+
onValueChange: (v) => setStyle({ verticalAlign: v })
|
|
2444
|
+
}
|
|
2445
|
+
),
|
|
2446
|
+
/* @__PURE__ */ jsx(Input, { label: "Line height", type: "number", value: String(s.lineHeight ?? 1.4), onChange: (e) => setStyle({ lineHeight: parseFloat(e.target.value) || 1.4 }) }),
|
|
2447
|
+
/* @__PURE__ */ jsxs("div", { className: "flex gap-4", children: [
|
|
2448
|
+
/* @__PURE__ */ jsx(Switch, { label: "Italic", checked: !!s.italic, onCheckedChange: (v) => setStyle({ italic: v }) }),
|
|
2449
|
+
/* @__PURE__ */ jsx(Switch, { label: "Underline", checked: !!s.underline, onCheckedChange: (v) => setStyle({ underline: v }) })
|
|
2450
|
+
] }),
|
|
2302
2451
|
/* @__PURE__ */ jsx(FieldLabel, { label: "Color", children: /* @__PURE__ */ jsx(ColorPicker, { value: s.color ?? "#0f172a", onChange: (c) => setStyle({ color: c }) }) })
|
|
2303
2452
|
] });
|
|
2304
2453
|
}
|
|
@@ -2381,6 +2530,7 @@ function ShapeStyleControls({ element, onPatch }) {
|
|
|
2381
2530
|
/* @__PURE__ */ jsx(FieldLabel, { label: "Fill", children: /* @__PURE__ */ jsx(ColorPicker, { value: element.fill ?? "#ffffff", onChange: (c) => onPatch({ fill: c }) }) }),
|
|
2382
2531
|
/* @__PURE__ */ jsx(FieldLabel, { label: "Stroke", children: /* @__PURE__ */ jsx(ColorPicker, { value: element.stroke ?? "#0f172a", onChange: (c) => onPatch({ stroke: c }) }) }),
|
|
2383
2532
|
/* @__PURE__ */ jsx(Slider, { label: "Stroke width", value: element.strokeWidth ?? 2, onValueChange: (v) => onPatch({ strokeWidth: Number(v) }), min: 0, max: 20, step: 0.5 }),
|
|
2533
|
+
/* @__PURE__ */ jsx(Switch, { label: "Dashed stroke", checked: !!element.dashed, onCheckedChange: (v) => onPatch({ dashed: v }) }),
|
|
2384
2534
|
(element.shape === "rounded-rect" || element.shape === "rect") && /* @__PURE__ */ jsx(Slider, { label: "Corner radius", value: element.radius ?? 0, onValueChange: (v) => onPatch({ radius: Number(v) }), min: 0, max: 40 })
|
|
2385
2535
|
] });
|
|
2386
2536
|
}
|
|
@@ -2400,7 +2550,8 @@ function CodeStyleControls({ element, onPatch }) {
|
|
|
2400
2550
|
value: element.codeTheme ?? "auto",
|
|
2401
2551
|
onValueChange: (v) => onPatch({ codeTheme: v })
|
|
2402
2552
|
}
|
|
2403
|
-
)
|
|
2553
|
+
),
|
|
2554
|
+
/* @__PURE__ */ jsx(Switch, { label: "Line numbers", checked: element.lineNumbers ?? true, onCheckedChange: (v) => onPatch({ lineNumbers: v }) })
|
|
2404
2555
|
] });
|
|
2405
2556
|
}
|
|
2406
2557
|
function ChartStyleControls({ element, onPatch }) {
|
|
@@ -2881,7 +3032,7 @@ function DeckEditor({
|
|
|
2881
3032
|
slide,
|
|
2882
3033
|
theme: deck.theme,
|
|
2883
3034
|
editing: true,
|
|
2884
|
-
onElementContentChange: (eid, content) => ops.updateElement(slide.id, eid, { content }),
|
|
3035
|
+
onElementContentChange: (eid, content) => ops.updateElement(slide.id, eid, { content, format: "markdown" }),
|
|
2885
3036
|
onElementSelect: setElementIdSelected,
|
|
2886
3037
|
selectedElementId: elementIdSelected,
|
|
2887
3038
|
onElementMove: (eid, x, y) => ops.moveElement(slide.id, eid, x, y),
|
|
@@ -2907,6 +3058,7 @@ function DeckEditor({
|
|
|
2907
3058
|
onLockToggle: (locked) => slide && elementIdSelected && ops.updateElement(slide.id, elementIdSelected, { locked }),
|
|
2908
3059
|
onSetTransition: (transition) => slide && ops.setTransition(slide.id, transition),
|
|
2909
3060
|
onSetBackground: (background) => slide && ops.setBackground(slide.id, background),
|
|
3061
|
+
onSetLayout: (layout) => slide && ops.setLayout(slide.id, layout),
|
|
2910
3062
|
onSetAnimation: (animation) => slide && elementIdSelected && ops.setAnimation(slide.id, elementIdSelected, animation),
|
|
2911
3063
|
onSetElementAnimation: (eid, animation) => slide && ops.setAnimation(slide.id, eid, animation)
|
|
2912
3064
|
}
|
|
@@ -2918,6 +3070,6 @@ function DeckEditor({
|
|
|
2918
3070
|
);
|
|
2919
3071
|
}
|
|
2920
3072
|
|
|
2921
|
-
export { DeckEditor, EditorToolbar, ElementInspector, ImageElementRenderer, PresenterView, ShapeElementRenderer, Slide, SlideRail, SlideThumbnail, SlideViewer, SpeakerNotes, TextElementRenderer, buildSteps, buildsForStep, builtinThemes, chartStarterOption, collectBuilds, darkTheme, deckId, defaultTheme, defineTheme, elementId, isByParagraph, nextId, paragraphReveals, reduce as reduceDeck, resolveTheme, slideId, splitParagraphs, stepDelays, totalBuildSteps, useDeckState, useSlideKeyboard, visibleElementIds, vividTheme };
|
|
3073
|
+
export { DeckEditor, EditorToolbar, ElementInspector, ImageElementRenderer, PRESENTATION_EDITOR_ACTIONS, PresenterView, ShapeElementRenderer, Slide, SlideRail, SlideThumbnail, SlideViewer, SpeakerNotes, TextElementRenderer, buildSteps, buildsForStep, builtinThemes, chartStarterOption, collectBuilds, darkTheme, deckId, defaultTheme, defineTheme, elementId, isByParagraph, nextId, normalizeSlideMarkdown, paragraphReveals, reduce as reduceDeck, resolveTheme, slideId, splitParagraphs, stepDelays, totalBuildSteps, useDeckState, useSlideKeyboard, visibleElementIds, vividTheme };
|
|
2922
3074
|
//# sourceMappingURL=index.js.map
|
|
2923
3075
|
//# sourceMappingURL=index.js.map
|