@particle-academy/fancy-slides 0.7.0 → 0.9.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.d.cts CHANGED
@@ -1,7 +1,7 @@
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, k as SlideLayout } from './types-9BbelJX1.cjs';
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';
3
+ import { i as Slide$1, p as Theme, k as SlideElement, D as Deck, d as DeckOp, h as ShapeKind, m as SlideTransition, j as SlideBackground, l as SlideLayout, E as ElementAnimation, n as TextElement, I as ImageElement, g as ShapeElement } from './types-2yYMJPhi.cjs';
4
+ export { A as AnimationEffect, a as AnimationTrigger, C as ChartElement, b as CodeElement, c as DeckActivity, e as ElementBase, f as EmbedElement, S as SCHEMA_VERSION, T as TableElement, o as TextStyle, q as ThemeColors, r as ThemeFonts, s as TransitionKind } from './types-2yYMJPhi.cjs';
5
5
  import { EditorAction } from '@particle-academy/react-fancy';
6
6
 
7
7
  interface SlideProps {
@@ -323,6 +323,8 @@ interface ElementInspectorProps {
323
323
  onSetTransition?: (transition?: SlideTransition) => void;
324
324
  /** Set the slide's background. */
325
325
  onSetBackground?: (background?: SlideBackground) => void;
326
+ /** Set the slide's layout preset. */
327
+ onSetLayout?: (layout: SlideLayout) => void;
326
328
  /** Set or clear the selected element's entrance build animation. */
327
329
  onSetAnimation?: (animation?: ElementAnimation) => void;
328
330
  /** Set a specific element's build animation by id — used by the slide-level build-order list. */
@@ -334,7 +336,7 @@ interface ElementInspectorProps {
334
336
  * react-fancy `Card`, `Tabs`, `Input`, `Select`, `Slider`, `ColorPicker`,
335
337
  * `Action`.
336
338
  */
337
- 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;
338
340
 
339
341
  interface SpeakerNotesProps {
340
342
  notes?: string;
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
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, k as SlideLayout } from './types-9BbelJX1.js';
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';
3
+ import { i as Slide$1, p as Theme, k as SlideElement, D as Deck, d as DeckOp, h as ShapeKind, m as SlideTransition, j as SlideBackground, l as SlideLayout, E as ElementAnimation, n as TextElement, I as ImageElement, g as ShapeElement } from './types-2yYMJPhi.js';
4
+ export { A as AnimationEffect, a as AnimationTrigger, C as ChartElement, b as CodeElement, c as DeckActivity, e as ElementBase, f as EmbedElement, S as SCHEMA_VERSION, T as TableElement, o as TextStyle, q as ThemeColors, r as ThemeFonts, s as TransitionKind } from './types-2yYMJPhi.js';
5
5
  import { EditorAction } from '@particle-academy/react-fancy';
6
6
 
7
7
  interface SlideProps {
@@ -323,6 +323,8 @@ interface ElementInspectorProps {
323
323
  onSetTransition?: (transition?: SlideTransition) => void;
324
324
  /** Set the slide's background. */
325
325
  onSetBackground?: (background?: SlideBackground) => void;
326
+ /** Set the slide's layout preset. */
327
+ onSetLayout?: (layout: SlideLayout) => void;
326
328
  /** Set or clear the selected element's entrance build animation. */
327
329
  onSetAnimation?: (animation?: ElementAnimation) => void;
328
330
  /** Set a specific element's build animation by id — used by the slide-level build-order list. */
@@ -334,7 +336,7 @@ interface ElementInspectorProps {
334
336
  * react-fancy `Card`, `Tabs`, `Input`, `Select`, `Slider`, `ColorPicker`,
335
337
  * `Action`.
336
338
  */
337
- 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;
338
340
 
339
341
  interface SpeakerNotesProps {
340
342
  notes?: string;
package/dist/index.js CHANGED
@@ -2,7 +2,7 @@ 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 { Editor, ContentRenderer, Text, Action, ContextMenu, Separator, Tooltip, Dropdown, Badge, Heading, Tabs, Card, Select, Input, ColorPicker, Slider, Switch, Textarea } from '@particle-academy/react-fancy';
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
6
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
7
7
 
8
8
  // src/theme/default-theme.ts
@@ -728,7 +728,18 @@ function SlideElementHost({
728
728
  touchAction: canMove ? "none" : void 0,
729
729
  ...buildAnimation ? buildEnterStyle(buildAnimation, buildDelay) : null
730
730
  };
731
- const inner = renderInner({ element, theme, slideWidthPx, editing, selected, onContentChange, paraReveal }) ?? renderElement?.(element, slideWidthPx) ?? elementPlaceholder(element);
731
+ const rendered = renderInner({ element, theme, slideWidthPx, editing, selected, onContentChange, paraReveal }) ?? renderElement?.(element, slideWidthPx) ?? elementPlaceholder(element);
732
+ const inner = element.href && !editing ? /* @__PURE__ */ jsx(
733
+ "a",
734
+ {
735
+ href: element.href,
736
+ target: "_blank",
737
+ rel: "noreferrer",
738
+ style: { display: "block", width: "100%", height: "100%", color: "inherit", textDecoration: "inherit" },
739
+ "data-fancy-slides-href": "",
740
+ children: rendered
741
+ }
742
+ ) : rendered;
732
743
  return /* @__PURE__ */ jsxs(
733
744
  "div",
734
745
  {
@@ -1999,10 +2010,10 @@ function EditorToolbar({
1999
2010
  /* @__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" }) }) })
2000
2011
  ] });
2001
2012
  }
2002
- function ElementInspector({ element, onPatch, onDelete, onLockToggle, slide, onSetTransition, onSetBackground, onSetAnimation, onSetElementAnimation }) {
2013
+ function ElementInspector({ element, onPatch, onDelete, onLockToggle, slide, onSetTransition, onSetBackground, onSetLayout, onSetAnimation, onSetElementAnimation }) {
2003
2014
  if (!element) {
2004
2015
  if (slide) {
2005
- return /* @__PURE__ */ jsx(SlideSettings, { slide, onSetTransition, onSetBackground, onSetElementAnimation });
2016
+ return /* @__PURE__ */ jsx(SlideSettings, { slide, onSetTransition, onSetBackground, onSetLayout, onSetElementAnimation });
2006
2017
  }
2007
2018
  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: [
2008
2019
  /* @__PURE__ */ jsx(Heading, { as: "h3", size: "xs", className: "!uppercase !tracking-wider !text-zinc-500", children: "Inspector" }),
@@ -2033,16 +2044,32 @@ function ElementInspector({ element, onPatch, onDelete, onLockToggle, slide, onS
2033
2044
  /* @__PURE__ */ jsxs(Tabs.Panels, { children: [
2034
2045
  /* @__PURE__ */ jsx(Tabs.Panel, { value: "style", children: /* @__PURE__ */ jsx(Card, { padding: "md", className: "!bg-white dark:!bg-zinc-950", children: /* @__PURE__ */ jsx(StyleSection, { element, onPatch }) }) }),
2035
2046
  /* @__PURE__ */ jsx(Tabs.Panel, { value: "build", children: /* @__PURE__ */ jsx(Card, { padding: "md", className: "!bg-white dark:!bg-zinc-950", children: /* @__PURE__ */ jsx(AnimateSection, { animation: element.animation, onSetAnimation, isText: element.type === "text" }) }) }),
2036
- /* @__PURE__ */ jsx(Tabs.Panel, { value: "layout", children: /* @__PURE__ */ jsx(Card, { padding: "md", className: "!bg-white dark:!bg-zinc-950", children: /* @__PURE__ */ jsx(LayoutSection, { element, onPatch }) }) }),
2047
+ /* @__PURE__ */ jsx(Tabs.Panel, { value: "layout", children: /* @__PURE__ */ jsx(Card, { padding: "md", className: "!bg-white dark:!bg-zinc-950", children: /* @__PURE__ */ jsx(LayoutSection, { element, onPatch, siblings: slide?.elements ?? [] }) }) }),
2037
2048
  /* @__PURE__ */ jsx(Tabs.Panel, { value: "advanced", children: /* @__PURE__ */ jsx(Card, { padding: "md", className: "!bg-white dark:!bg-zinc-950", children: /* @__PURE__ */ jsx(AdvancedSection, { element, onPatch }) }) })
2038
2049
  ] })
2039
2050
  ] }) })
2040
2051
  ] });
2041
2052
  }
2053
+ var SLIDE_LAYOUTS = [
2054
+ { value: "blank", label: "Blank" },
2055
+ { value: "title", label: "Title" },
2056
+ { value: "title-content", label: "Title + content" },
2057
+ { value: "two-column", label: "Two column" },
2058
+ { value: "section-divider", label: "Section divider" },
2059
+ { value: "image-text", label: "Image + text" },
2060
+ { value: "text-image", label: "Text + image" },
2061
+ { value: "quote", label: "Quote" }
2062
+ ];
2063
+ function backgroundMode(bg) {
2064
+ if (bg?.gradient) return "gradient";
2065
+ if (bg?.image) return "image";
2066
+ return "color";
2067
+ }
2042
2068
  function SlideSettings({
2043
2069
  slide,
2044
2070
  onSetTransition,
2045
2071
  onSetBackground,
2072
+ onSetLayout,
2046
2073
  onSetElementAnimation
2047
2074
  }) {
2048
2075
  const transition = slide.transition;
@@ -2051,6 +2078,7 @@ function SlideSettings({
2051
2078
  const merged = { kind, duration: transition?.duration, direction: transition?.direction, ...next };
2052
2079
  onSetTransition?.(merged.kind === "none" ? { kind: "none" } : merged);
2053
2080
  };
2081
+ const bgMode = backgroundMode(slide.background);
2054
2082
  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: [
2055
2083
  /* @__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: [
2056
2084
  /* @__PURE__ */ jsx(Heading, { as: "h3", size: "xs", className: "!font-mono !uppercase !tracking-wider !text-zinc-500", children: "slide" }),
@@ -2060,6 +2088,19 @@ function SlideSettings({
2060
2088
  ] })
2061
2089
  ] }) }),
2062
2090
  /* @__PURE__ */ jsxs("div", { className: "flex-1 overflow-y-auto p-3", children: [
2091
+ onSetLayout && /* @__PURE__ */ jsx(Card, { padding: "md", className: "mb-3 !bg-white dark:!bg-zinc-950", children: /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
2092
+ /* @__PURE__ */ jsx(Heading, { as: "h4", size: "xs", className: "!uppercase !tracking-wider !text-zinc-500", children: "Layout" }),
2093
+ /* @__PURE__ */ jsx(
2094
+ Select,
2095
+ {
2096
+ label: "Preset",
2097
+ list: SLIDE_LAYOUTS,
2098
+ value: slide.layout ?? "blank",
2099
+ onValueChange: (v) => onSetLayout(v)
2100
+ }
2101
+ ),
2102
+ /* @__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." })
2103
+ ] }) }),
2063
2104
  /* @__PURE__ */ jsx(Card, { padding: "md", className: "!bg-white dark:!bg-zinc-950", children: /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
2064
2105
  /* @__PURE__ */ jsx(Heading, { as: "h4", size: "xs", className: "!uppercase !tracking-wider !text-zinc-500", children: "Transition" }),
2065
2106
  /* @__PURE__ */ jsx(
@@ -2103,13 +2144,63 @@ function SlideSettings({
2103
2144
  ] }) }),
2104
2145
  onSetBackground && /* @__PURE__ */ jsx(Card, { padding: "md", className: "mt-3 !bg-white dark:!bg-zinc-950", children: /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
2105
2146
  /* @__PURE__ */ jsx(Heading, { as: "h4", size: "xs", className: "!uppercase !tracking-wider !text-zinc-500", children: "Background" }),
2106
- /* @__PURE__ */ jsx(FieldLabel, { label: "Color", children: /* @__PURE__ */ jsx(
2147
+ /* @__PURE__ */ jsx(
2148
+ Select,
2149
+ {
2150
+ label: "Type",
2151
+ list: [
2152
+ { value: "color", label: "Solid color" },
2153
+ { value: "gradient", label: "Gradient" },
2154
+ { value: "image", label: "Image" }
2155
+ ],
2156
+ value: bgMode,
2157
+ onValueChange: (v) => {
2158
+ if (v === "color") onSetBackground({ color: slide.background?.color ?? "#ffffff" });
2159
+ else if (v === "gradient") onSetBackground({ gradient: slide.background?.gradient ?? "linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%)" });
2160
+ else onSetBackground({ image: slide.background?.image ?? "", imageFit: slide.background?.imageFit ?? "cover", color: slide.background?.color });
2161
+ }
2162
+ }
2163
+ ),
2164
+ bgMode === "color" && /* @__PURE__ */ jsx(FieldLabel, { label: "Color", children: /* @__PURE__ */ jsx(
2107
2165
  ColorPicker,
2108
2166
  {
2109
2167
  value: slide.background?.color ?? "#ffffff",
2110
- onChange: (c) => onSetBackground({ ...slide.background, color: c })
2168
+ onChange: (c) => onSetBackground({ color: c })
2169
+ }
2170
+ ) }),
2171
+ bgMode === "gradient" && /* @__PURE__ */ jsx(
2172
+ Textarea,
2173
+ {
2174
+ label: "CSS gradient",
2175
+ value: slide.background?.gradient ?? "",
2176
+ onValueChange: (v) => onSetBackground({ gradient: v }),
2177
+ rows: 2
2111
2178
  }
2112
- ) })
2179
+ ),
2180
+ bgMode === "image" && /* @__PURE__ */ jsxs(Fragment, { children: [
2181
+ /* @__PURE__ */ jsx(
2182
+ Textarea,
2183
+ {
2184
+ label: "Image URL",
2185
+ value: slide.background?.image ?? "",
2186
+ onValueChange: (v) => onSetBackground({ ...slide.background, image: v }),
2187
+ rows: 2
2188
+ }
2189
+ ),
2190
+ /* @__PURE__ */ jsx(
2191
+ Select,
2192
+ {
2193
+ label: "Fit",
2194
+ list: [
2195
+ { value: "cover", label: "Cover" },
2196
+ { value: "contain", label: "Contain" },
2197
+ { value: "fill", label: "Fill (stretch)" }
2198
+ ],
2199
+ value: slide.background?.imageFit ?? "cover",
2200
+ onValueChange: (v) => onSetBackground({ ...slide.background, imageFit: v })
2201
+ }
2202
+ )
2203
+ ] })
2113
2204
  ] }) }),
2114
2205
  onSetElementAnimation && /* @__PURE__ */ jsx(Card, { padding: "md", className: "mt-3 !bg-white dark:!bg-zinc-950", children: /* @__PURE__ */ jsx(BuildOrderList, { slide, onSetElementAnimation }) })
2115
2206
  ] })
@@ -2158,7 +2249,10 @@ function buildLabel(element) {
2158
2249
  }
2159
2250
  return `${element.type} #${element.id.slice(-6)}`;
2160
2251
  }
2161
- function LayoutSection({ element, onPatch }) {
2252
+ function LayoutSection({ element, onPatch, siblings }) {
2253
+ const zs = siblings.map((e) => e.z ?? 0);
2254
+ const bringToFront = () => onPatch({ z: (zs.length ? Math.max(...zs) : 0) + 1 });
2255
+ const sendToBack = () => onPatch({ z: (zs.length ? Math.min(...zs) : 0) - 1 });
2162
2256
  return /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
2163
2257
  /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-2", children: [
2164
2258
  /* @__PURE__ */ jsx(Input, { label: "X", type: "number", value: String(roundFrac(element.x)), onChange: (e) => onPatch({ x: clamp2(parseFloat(e.target.value), 0, 1) }) }),
@@ -2168,7 +2262,26 @@ function LayoutSection({ element, onPatch }) {
2168
2262
  ] }),
2169
2263
  /* @__PURE__ */ jsx(Separator, {}),
2170
2264
  /* @__PURE__ */ jsx(Slider, { label: "Rotation", value: element.rotation ?? 0, onValueChange: (v) => onPatch({ rotation: Number(v) }), min: -180, max: 180 }),
2171
- /* @__PURE__ */ jsx(Input, { label: "Z-index", type: "number", value: String(element.z ?? 0), onChange: (e) => onPatch({ z: parseInt(e.target.value, 10) || 0 }) })
2265
+ /* @__PURE__ */ jsxs("div", { className: "flex items-end gap-2", children: [
2266
+ /* @__PURE__ */ jsx(Input, { label: "Z-index", type: "number", value: String(element.z ?? 0), onChange: (e) => onPatch({ z: parseInt(e.target.value, 10) || 0 }), className: "flex-1" }),
2267
+ /* @__PURE__ */ jsx(Action, { size: "sm", variant: "ghost", onClick: bringToFront, "aria-label": "Bring to front", children: "Front" }),
2268
+ /* @__PURE__ */ jsx(Action, { size: "sm", variant: "ghost", onClick: sendToBack, "aria-label": "Send to back", children: "Back" })
2269
+ ] }),
2270
+ /* @__PURE__ */ jsx(Separator, {}),
2271
+ /* @__PURE__ */ jsx(
2272
+ Input,
2273
+ {
2274
+ label: "Link (href)",
2275
+ value: element.href ?? "",
2276
+ placeholder: "https://\u2026",
2277
+ onChange: (e) => onPatch({ href: e.target.value || void 0 })
2278
+ }
2279
+ ),
2280
+ /* @__PURE__ */ jsxs(Text, { size: "xs", className: "!text-zinc-500", children: [
2281
+ "Makes the whole element a click target in the viewer (opens a new tab) and exports as a pptx hyperlink. For links inside text, use markdown ",
2282
+ /* @__PURE__ */ jsx("code", { children: "[label](url)" }),
2283
+ "."
2284
+ ] })
2172
2285
  ] });
2173
2286
  }
2174
2287
  function AdvancedSection({ element, onPatch }) {
@@ -2350,6 +2463,24 @@ function TextStyleControls({ element, onPatch }) {
2350
2463
  onValueChange: (v) => setStyle({ align: v })
2351
2464
  }
2352
2465
  ),
2466
+ /* @__PURE__ */ jsx(
2467
+ Select,
2468
+ {
2469
+ label: "Vertical align",
2470
+ list: [
2471
+ { value: "top", label: "Top" },
2472
+ { value: "middle", label: "Middle" },
2473
+ { value: "bottom", label: "Bottom" }
2474
+ ],
2475
+ value: s.verticalAlign ?? "top",
2476
+ onValueChange: (v) => setStyle({ verticalAlign: v })
2477
+ }
2478
+ ),
2479
+ /* @__PURE__ */ jsx(Input, { label: "Line height", type: "number", value: String(s.lineHeight ?? 1.4), onChange: (e) => setStyle({ lineHeight: parseFloat(e.target.value) || 1.4 }) }),
2480
+ /* @__PURE__ */ jsxs("div", { className: "flex gap-4", children: [
2481
+ /* @__PURE__ */ jsx(Switch, { label: "Italic", checked: !!s.italic, onCheckedChange: (v) => setStyle({ italic: v }) }),
2482
+ /* @__PURE__ */ jsx(Switch, { label: "Underline", checked: !!s.underline, onCheckedChange: (v) => setStyle({ underline: v }) })
2483
+ ] }),
2353
2484
  /* @__PURE__ */ jsx(FieldLabel, { label: "Color", children: /* @__PURE__ */ jsx(ColorPicker, { value: s.color ?? "#0f172a", onChange: (c) => setStyle({ color: c }) }) })
2354
2485
  ] });
2355
2486
  }
@@ -2432,6 +2563,7 @@ function ShapeStyleControls({ element, onPatch }) {
2432
2563
  /* @__PURE__ */ jsx(FieldLabel, { label: "Fill", children: /* @__PURE__ */ jsx(ColorPicker, { value: element.fill ?? "#ffffff", onChange: (c) => onPatch({ fill: c }) }) }),
2433
2564
  /* @__PURE__ */ jsx(FieldLabel, { label: "Stroke", children: /* @__PURE__ */ jsx(ColorPicker, { value: element.stroke ?? "#0f172a", onChange: (c) => onPatch({ stroke: c }) }) }),
2434
2565
  /* @__PURE__ */ jsx(Slider, { label: "Stroke width", value: element.strokeWidth ?? 2, onValueChange: (v) => onPatch({ strokeWidth: Number(v) }), min: 0, max: 20, step: 0.5 }),
2566
+ /* @__PURE__ */ jsx(Switch, { label: "Dashed stroke", checked: !!element.dashed, onCheckedChange: (v) => onPatch({ dashed: v }) }),
2435
2567
  (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 })
2436
2568
  ] });
2437
2569
  }
@@ -2451,7 +2583,8 @@ function CodeStyleControls({ element, onPatch }) {
2451
2583
  value: element.codeTheme ?? "auto",
2452
2584
  onValueChange: (v) => onPatch({ codeTheme: v })
2453
2585
  }
2454
- )
2586
+ ),
2587
+ /* @__PURE__ */ jsx(Switch, { label: "Line numbers", checked: element.lineNumbers ?? true, onCheckedChange: (v) => onPatch({ lineNumbers: v }) })
2455
2588
  ] });
2456
2589
  }
2457
2590
  function ChartStyleControls({ element, onPatch }) {
@@ -2958,6 +3091,7 @@ function DeckEditor({
2958
3091
  onLockToggle: (locked) => slide && elementIdSelected && ops.updateElement(slide.id, elementIdSelected, { locked }),
2959
3092
  onSetTransition: (transition) => slide && ops.setTransition(slide.id, transition),
2960
3093
  onSetBackground: (background) => slide && ops.setBackground(slide.id, background),
3094
+ onSetLayout: (layout) => slide && ops.setLayout(slide.id, layout),
2961
3095
  onSetAnimation: (animation) => slide && elementIdSelected && ops.setAnimation(slide.id, elementIdSelected, animation),
2962
3096
  onSetElementAnimation: (eid, animation) => slide && ops.setAnimation(slide.id, eid, animation)
2963
3097
  }
@@ -2969,6 +3103,9 @@ function DeckEditor({
2969
3103
  );
2970
3104
  }
2971
3105
 
2972
- 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 };
3106
+ // src/types.ts
3107
+ var SCHEMA_VERSION = 1;
3108
+
3109
+ export { DeckEditor, EditorToolbar, ElementInspector, ImageElementRenderer, PRESENTATION_EDITOR_ACTIONS, PresenterView, SCHEMA_VERSION, 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 };
2973
3110
  //# sourceMappingURL=index.js.map
2974
3111
  //# sourceMappingURL=index.js.map