promptslide 0.3.9 → 0.3.10

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/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.3.10](https://github.com/prompticeu/promptslide/compare/promptslide-v0.3.9...promptslide-v0.3.10) (2026-03-25)
4
+
5
+
6
+ ### Bug Fixes
7
+
8
+ * **slide-embed:** scale slides to cover viewport ([9f07aed](https://github.com/prompticeu/promptslide/commit/9f07aedec92fb6531f101c108144b16e78e746af))
9
+
3
10
  ## [0.3.9](https://github.com/prompticeu/promptslide/compare/promptslide-v0.3.8...promptslide-v0.3.9) (2026-03-24)
4
11
 
5
12
 
package/dist/index.js CHANGED
@@ -630,7 +630,9 @@ function SlideEmbed({ slides, transition, directionalTransition }) {
630
630
  }, [handleMessage]);
631
631
  useEffect2(() => {
632
632
  const calculateScale = () => {
633
- setScale(window.innerWidth / SLIDE_DIMENSIONS.width);
633
+ const scaleX = window.innerWidth / SLIDE_DIMENSIONS.width;
634
+ const scaleY = window.innerHeight / SLIDE_DIMENSIONS.height;
635
+ setScale(Math.max(scaleX, scaleY));
634
636
  };
635
637
  calculateScale();
636
638
  window.addEventListener("resize", calculateScale);
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/core/animation-config.ts","../src/core/animation-context.tsx","../src/core/animated.tsx","../src/core/transitions.ts","../src/core/morph.tsx","../src/core/use-slide-navigation.ts","../src/core/theme-context.tsx","../src/core/slide-renderer.tsx","../src/core/slide-error-boundary.tsx","../src/core/slide-embed.tsx","../src/core/slide-deck.tsx","../src/core/annotations/annotation-overlay.tsx","../src/core/annotations/annotation-form.tsx","../src/core/annotations/annotation-pin.tsx","../src/core/annotations/selectors.ts","../src/core/annotations/annotation-panel.tsx","../src/core/annotations/use-annotations.ts","../src/core/annotations/adapters/http.ts","../src/core/utils.ts"],"sourcesContent":["/**\n * Centralized animation configuration for the slide deck framework.\n * All animation timings, easings, and spring configs are defined here.\n */\n\n// =============================================================================\n// TIMING CONSTANTS\n// =============================================================================\n\n/** Duration for slide-to-slide transitions (seconds) */\nexport const SLIDE_TRANSITION_DURATION = 0.3\n\n/** Duration for morph/layout animations between slides (seconds) */\nexport const MORPH_DURATION = 0.8\n\n/** Duration for within-slide step animations (seconds) */\nexport const STEP_ANIMATION_DURATION = 0.4\n\n/** Default stagger delay for grouped animations (seconds) */\nexport const STAGGER_DELAY = 0.1\n\n// =============================================================================\n// EASING PRESETS\n// =============================================================================\n\nexport const EASE_DEFAULT = \"easeInOut\" as const\nexport const EASE_OUT = \"easeOut\" as const\nexport const EASE_IN = \"easeIn\" as const\n\n/** Smooth ease-in-out curve for morph animations (cubic bezier) */\nexport const EASE_MORPH = [0.4, 0, 0.2, 1] as const\n\n// =============================================================================\n// SPRING CONFIGURATIONS\n// =============================================================================\n\n/** Spring config for snappy, responsive animations */\nexport const SPRING_SNAPPY = {\n type: \"spring\" as const,\n stiffness: 300,\n damping: 30\n}\n\n/** Spring config for smooth, gentle animations */\nexport const SPRING_SMOOTH = {\n type: \"spring\" as const,\n stiffness: 200,\n damping: 25\n}\n\n/** Spring config for bouncy animations */\nexport const SPRING_BOUNCY = {\n type: \"spring\" as const,\n stiffness: 400,\n damping: 20\n}\n\n// =============================================================================\n// TRANSITION PRESETS\n// =============================================================================\n\n/** Standard transition for slide transitions */\nexport const SLIDE_TRANSITION = {\n duration: SLIDE_TRANSITION_DURATION,\n ease: EASE_DEFAULT\n} as const\n\n/** Standard transition for morph animations (smooth ease-in-out) */\nexport const MORPH_TRANSITION = {\n duration: MORPH_DURATION,\n ease: EASE_MORPH\n}\n\n/** Standard transition for step animations (spring-based, duration computed from stiffness/damping) */\nexport const STEP_TRANSITION = {\n ...SPRING_SNAPPY\n}\n\n// =============================================================================\n// DISTANCE CONSTANTS (pixels)\n// =============================================================================\n\n/** Distance for slide animations */\nexport const SLIDE_DISTANCE = 100\n\n/** Distance for within-slide element animations */\nexport const ELEMENT_SLIDE_DISTANCE = 30\n\n// =============================================================================\n// SLIDE DIMENSIONS\n// =============================================================================\n\n/** Standard slide dimensions (16:9 aspect ratio) */\nexport const SLIDE_DIMENSIONS = {\n width: 1280,\n height: 720,\n aspectRatio: 16 / 9\n} as const\n","import { createContext, useContext, useMemo } from \"react\"\n\ninterface AnimationContextValue {\n /** Current animation step (0 = no animations shown yet) */\n currentStep: number\n /** Total animation steps in this slide (declared in slide config) */\n totalSteps: number\n /** When true, all animation steps should be visible (used for backward navigation) */\n showAllAnimations: boolean\n}\n\nconst AnimationContext = createContext<AnimationContextValue>({\n currentStep: 0,\n totalSteps: 0,\n showAllAnimations: false\n})\n\ninterface AnimationProviderProps {\n children: React.ReactNode\n /** Current animation step (0 = no animations shown yet) */\n currentStep: number\n /** Total animation steps declared in slide config */\n totalSteps: number\n /** When true, show all animations regardless of currentStep (for backward navigation) */\n showAllAnimations?: boolean\n}\n\n/**\n * Provides animation context to child components.\n *\n * The totalSteps is now passed from parent (declared in slide config)\n * rather than discovered at runtime, eliminating race conditions.\n */\nexport function AnimationProvider({\n children,\n currentStep,\n totalSteps,\n showAllAnimations = false\n}: AnimationProviderProps) {\n const value = useMemo(\n () => ({\n currentStep,\n totalSteps,\n showAllAnimations\n }),\n [currentStep, totalSteps, showAllAnimations]\n )\n\n return <AnimationContext.Provider value={value}>{children}</AnimationContext.Provider>\n}\n\nexport function useAnimationContext() {\n return useContext(AnimationContext)\n}\n","import { motion, Variants } from \"framer-motion\"\n\nimport {\n ELEMENT_SLIDE_DISTANCE,\n SPRING_SNAPPY,\n STAGGER_DELAY,\n STEP_ANIMATION_DURATION\n} from \"./animation-config\"\nimport { useAnimationContext } from \"./animation-context\"\n\n// =============================================================================\n// ANIMATION TYPES & VARIANTS\n// =============================================================================\n\nexport type AnimationType =\n | \"fade\"\n | \"slide-up\"\n | \"slide-down\"\n | \"slide-left\"\n | \"slide-right\"\n | \"scale\"\n\nconst animationVariants: Record<AnimationType, Variants> = {\n fade: {\n hidden: { opacity: 0 },\n visible: { opacity: 1 }\n },\n \"slide-up\": {\n hidden: { opacity: 0, y: ELEMENT_SLIDE_DISTANCE },\n visible: { opacity: 1, y: 0 }\n },\n \"slide-down\": {\n hidden: { opacity: 0, y: -ELEMENT_SLIDE_DISTANCE },\n visible: { opacity: 1, y: 0 }\n },\n \"slide-left\": {\n hidden: { opacity: 0, x: ELEMENT_SLIDE_DISTANCE },\n visible: { opacity: 1, x: 0 }\n },\n \"slide-right\": {\n hidden: { opacity: 0, x: -ELEMENT_SLIDE_DISTANCE },\n visible: { opacity: 1, x: 0 }\n },\n scale: {\n hidden: { opacity: 0, scale: 0.8 },\n visible: { opacity: 1, scale: 1 }\n }\n}\n\ninterface AnimatedProps {\n /** Which step reveals this content (1-indexed) */\n step: number\n /** Animation type */\n animation?: AnimationType\n /** Animation duration in seconds */\n duration?: number\n /** Delay after trigger in seconds */\n delay?: number\n /** Custom className */\n className?: string\n children: React.ReactNode\n}\n\n/**\n * Animated element that appears at a specific animation step.\n *\n * The step count is now declared in slide config rather than discovered\n * at runtime, so this component simply consumes the context without\n * needing to register itself.\n */\nexport function Animated({\n step,\n animation = \"slide-up\",\n duration = STEP_ANIMATION_DURATION,\n delay = 0,\n className,\n children\n}: AnimatedProps) {\n const { currentStep, showAllAnimations } = useAnimationContext()\n\n // Show all animations when navigating backward, otherwise check step\n const isVisible = showAllAnimations || currentStep >= step\n\n return (\n <motion.div\n initial=\"hidden\"\n animate={isVisible ? \"visible\" : \"hidden\"}\n variants={animationVariants[animation]}\n transition={{\n ...SPRING_SNAPPY,\n duration,\n delay: isVisible ? delay : 0\n }}\n className={className}\n >\n {children}\n </motion.div>\n )\n}\n\n/**\n * Wrapper for staggering multiple children.\n * Each direct child will be animated in sequence.\n */\ninterface AnimatedGroupProps {\n /** Starting step for the first child */\n startStep: number\n /** Animation type for all children */\n animation?: AnimationType\n /** Delay between each child in seconds */\n staggerDelay?: number\n className?: string\n children: React.ReactNode\n}\n\nexport function AnimatedGroup({\n startStep,\n animation = \"slide-up\",\n staggerDelay = STAGGER_DELAY,\n className,\n children\n}: AnimatedGroupProps) {\n const { currentStep, showAllAnimations } = useAnimationContext()\n\n const childArray = Array.isArray(children) ? children : [children]\n\n // Show all animations when navigating backward, otherwise check step\n const isVisible = showAllAnimations || currentStep >= startStep\n\n const containerVariants: Variants = {\n hidden: {},\n visible: {\n transition: {\n staggerChildren: staggerDelay\n }\n }\n }\n\n return (\n <motion.div\n initial=\"hidden\"\n animate={isVisible ? \"visible\" : \"hidden\"}\n variants={containerVariants}\n className={className}\n >\n {childArray.map((child, index) => (\n <motion.div key={index} variants={animationVariants[animation]}>\n {child}\n </motion.div>\n ))}\n </motion.div>\n )\n}\n","/**\n * Slide transition variants for the slide deck framework.\n * These define how slides enter and exit during navigation.\n */\n\nimport type { Variants } from \"framer-motion\"\n\nimport {\n EASE_MORPH,\n MORPH_DURATION,\n SLIDE_DISTANCE,\n SLIDE_TRANSITION,\n SLIDE_TRANSITION_DURATION\n} from \"./animation-config\"\n\n// =============================================================================\n// TYPES\n// =============================================================================\n\nexport type SlideTransitionType =\n | \"fade\"\n | \"slide-left\"\n | \"slide-right\"\n | \"slide-up\"\n | \"slide-down\"\n | \"zoom\"\n | \"zoom-fade\"\n | \"morph\"\n | \"none\"\n\nexport interface SlideTransitionConfig {\n /** The transition type */\n type: SlideTransitionType\n /** Optional custom duration (overrides default) */\n duration?: number\n /** Whether to use directional transitions based on navigation direction */\n directional?: boolean\n}\n\n// =============================================================================\n// STATIC VARIANTS (non-directional)\n// =============================================================================\n\nconst fadeVariants: Variants = {\n enter: { opacity: 0 },\n center: { opacity: 1 },\n exit: { opacity: 0 }\n}\n\nconst slideLeftVariants: Variants = {\n enter: { x: SLIDE_DISTANCE, opacity: 0 },\n center: { x: 0, opacity: 1 },\n exit: { x: -SLIDE_DISTANCE, opacity: 0 }\n}\n\nconst slideRightVariants: Variants = {\n enter: { x: -SLIDE_DISTANCE, opacity: 0 },\n center: { x: 0, opacity: 1 },\n exit: { x: SLIDE_DISTANCE, opacity: 0 }\n}\n\nconst slideUpVariants: Variants = {\n enter: { y: SLIDE_DISTANCE, opacity: 0 },\n center: { y: 0, opacity: 1 },\n exit: { y: -SLIDE_DISTANCE, opacity: 0 }\n}\n\nconst slideDownVariants: Variants = {\n enter: { y: -SLIDE_DISTANCE, opacity: 0 },\n center: { y: 0, opacity: 1 },\n exit: { y: SLIDE_DISTANCE, opacity: 0 }\n}\n\nconst zoomVariants: Variants = {\n enter: { scale: 0.8, opacity: 0 },\n center: { scale: 1, opacity: 1 },\n exit: { scale: 1.2, opacity: 0 }\n}\n\nconst zoomFadeVariants: Variants = {\n enter: { scale: 0.95, opacity: 0 },\n center: { scale: 1, opacity: 1 },\n exit: { scale: 1.05, opacity: 0 }\n}\n\nconst morphVariants: Variants = {\n enter: {\n opacity: 0,\n zIndex: 1\n },\n center: {\n opacity: 1,\n zIndex: 1,\n transition: {\n opacity: { delay: 0.05, duration: 0.25 }\n }\n },\n exit: {\n opacity: 0,\n zIndex: 0,\n transition: {\n opacity: { duration: MORPH_DURATION, ease: EASE_MORPH }\n }\n }\n}\n\nconst noneVariants: Variants = {\n enter: {},\n center: {},\n exit: {}\n}\n\n// =============================================================================\n// VARIANT REGISTRY\n// =============================================================================\n\nexport const SLIDE_VARIANTS: Record<SlideTransitionType, Variants> = {\n fade: fadeVariants,\n \"slide-left\": slideLeftVariants,\n \"slide-right\": slideRightVariants,\n \"slide-up\": slideUpVariants,\n \"slide-down\": slideDownVariants,\n zoom: zoomVariants,\n \"zoom-fade\": zoomFadeVariants,\n morph: morphVariants,\n none: noneVariants\n}\n\n// =============================================================================\n// DIRECTIONAL VARIANTS (based on navigation direction)\n// =============================================================================\n\nexport function createDirectionalVariants(axis: \"x\" | \"y\" = \"x\"): (direction: number) => Variants {\n return (direction: number) => ({\n enter: {\n [axis]: direction > 0 ? SLIDE_DISTANCE : -SLIDE_DISTANCE,\n opacity: 0\n },\n center: {\n [axis]: 0,\n opacity: 1\n },\n exit: {\n [axis]: direction < 0 ? SLIDE_DISTANCE : -SLIDE_DISTANCE,\n opacity: 0\n }\n })\n}\n\n/** Horizontal directional slide (left/right based on direction) */\nexport const directionalSlideX = createDirectionalVariants(\"x\")\n\n/** Vertical directional slide (up/down based on direction) */\nexport const directionalSlideY = createDirectionalVariants(\"y\")\n\n// =============================================================================\n// HELPER FUNCTIONS\n// =============================================================================\n\nexport function getSlideVariants(\n config: SlideTransitionConfig | SlideTransitionType,\n direction: number = 1\n): Variants {\n const type = typeof config === \"string\" ? config : config.type\n const directional = typeof config === \"object\" ? config.directional : false\n\n if (directional && (type === \"slide-left\" || type === \"slide-right\")) {\n return directionalSlideX(direction)\n }\n\n if (directional && (type === \"slide-up\" || type === \"slide-down\")) {\n return directionalSlideY(direction)\n }\n\n return SLIDE_VARIANTS[type]\n}\n\nexport function getSlideTransition(config?: SlideTransitionConfig | SlideTransitionType): {\n duration: number\n ease: typeof SLIDE_TRANSITION.ease\n} {\n if (!config) return SLIDE_TRANSITION\n\n const type = typeof config === \"string\" ? config : config.type\n\n const defaultDuration = type === \"morph\" ? MORPH_DURATION : SLIDE_TRANSITION_DURATION\n\n const duration = typeof config === \"object\" && config.duration ? config.duration : defaultDuration\n\n return {\n ...SLIDE_TRANSITION,\n duration\n }\n}\n\n// =============================================================================\n// DEFAULT EXPORT\n// =============================================================================\n\nexport const DEFAULT_SLIDE_TRANSITION: SlideTransitionType = \"fade\"\n","import type { Transition } from \"framer-motion\"\n\nimport { motion } from \"framer-motion\"\n\nimport { MORPH_TRANSITION } from \"./animation-config\"\n\n// =============================================================================\n// TYPES\n// =============================================================================\n\ninterface MorphProps {\n layoutId: string\n transition?: Transition\n className?: string\n children: React.ReactNode\n}\n\ninterface MorphGroupProps {\n groupId: string\n transition?: Transition\n className?: string\n children: React.ReactNode\n}\n\n// =============================================================================\n// MORPH COMPONENT\n// =============================================================================\n\n/**\n * Wrapper component that enables morph/shared-layout animations between slides.\n *\n * Usage:\n * ```tsx\n * // Slide 1 - Large version\n * <Morph layoutId=\"hero-title\">\n * <h1 className=\"text-6xl\">Title</h1>\n * </Morph>\n *\n * // Slide 2 - Small version (same layoutId = morphs between them)\n * <Morph layoutId=\"hero-title\">\n * <h1 className=\"text-2xl\">Title</h1>\n * </Morph>\n * ```\n */\nexport function Morph({\n layoutId,\n transition = MORPH_TRANSITION,\n className,\n children\n}: MorphProps) {\n return (\n <motion.div\n layout\n layoutId={layoutId}\n initial={false}\n transition={transition}\n className={className}\n >\n {children}\n </motion.div>\n )\n}\n\n// =============================================================================\n// MORPH GROUP COMPONENT\n// =============================================================================\n\nexport function MorphGroup({\n groupId,\n transition = MORPH_TRANSITION,\n className,\n children\n}: MorphGroupProps) {\n return (\n <motion.div\n layout\n layoutId={groupId}\n initial={false}\n transition={transition}\n className={className}\n >\n {children}\n </motion.div>\n )\n}\n\n// =============================================================================\n// MORPH ITEM (for use within MorphGroup pattern)\n// =============================================================================\n\ninterface MorphItemProps {\n id: string\n prefix?: string\n transition?: Transition\n className?: string\n children: React.ReactNode\n}\n\nexport function MorphItem({\n id,\n prefix,\n transition = MORPH_TRANSITION,\n className,\n children\n}: MorphItemProps) {\n const layoutId = prefix ? `${prefix}-${id}` : id\n\n return (\n <motion.div\n layout\n layoutId={layoutId}\n initial={false}\n transition={transition}\n className={className}\n >\n {children}\n </motion.div>\n )\n}\n\n// =============================================================================\n// MORPH TEXT (specialized for text that changes size)\n// =============================================================================\n\ninterface MorphTextProps {\n layoutId: string\n as?: \"h1\" | \"h2\" | \"h3\" | \"h4\" | \"p\" | \"span\"\n transition?: Transition\n className?: string\n children: React.ReactNode\n}\n\nexport function MorphText({\n layoutId,\n as: Component = \"span\",\n transition = MORPH_TRANSITION,\n className,\n children\n}: MorphTextProps) {\n const MotionComponent = motion[Component]\n\n return (\n <MotionComponent\n layout\n layoutId={layoutId}\n initial={false}\n transition={transition}\n className={className}\n >\n {children}\n </MotionComponent>\n )\n}\n","import { useCallback, useEffect, useState } from \"react\"\n\nimport type { NavigationDirection, SlideConfig } from \"./types\"\n\n// =============================================================================\n// TYPES\n// =============================================================================\n\ntype NavigationStatus = \"idle\" | \"transitioning\"\n\ntype QueuedAction = \"advance\" | \"goBack\" | null\n\ninterface NavigationState {\n status: NavigationStatus\n direction: NavigationDirection\n}\n\nexport interface UseSlideNavigationOptions {\n slides: SlideConfig[]\n initialSlide?: number\n onSlideChange?: (slideIndex: number) => void\n}\n\nexport interface UseSlideNavigationReturn {\n currentSlide: number\n animationStep: number\n totalSteps: number\n direction: NavigationDirection\n isTransitioning: boolean\n showAllAnimations: boolean\n advance: () => void\n goBack: () => void\n goToSlide: (index: number) => void\n onTransitionComplete: () => void\n}\n\n// =============================================================================\n// HOOK\n// =============================================================================\n\nexport function useSlideNavigation({\n slides,\n initialSlide = 0,\n onSlideChange\n}: UseSlideNavigationOptions): UseSlideNavigationReturn {\n const [currentSlide, setCurrentSlide] = useState(initialSlide)\n const [animationStep, setAnimationStep] = useState(0)\n\n const [navState, setNavState] = useState<NavigationState>({\n status: \"idle\",\n direction: 0\n })\n\n const [queuedAction, setQueuedAction] = useState<QueuedAction>(null)\n\n const totalSteps = slides[currentSlide]?.steps ?? 0\n\n const onTransitionComplete = useCallback(() => {\n setNavState(prev => {\n if (prev.status === \"transitioning\") {\n return { status: \"idle\", direction: 0 }\n }\n return prev\n })\n }, [])\n\n const advance = useCallback(() => {\n if (navState.status === \"transitioning\") {\n setQueuedAction(\"advance\")\n return\n }\n\n const currentTotalSteps = slides[currentSlide]?.steps ?? 0\n\n if (animationStep >= currentTotalSteps) {\n const nextSlide = (currentSlide + 1) % slides.length\n setNavState({ status: \"transitioning\", direction: 1 })\n setAnimationStep(0)\n setCurrentSlide(nextSlide)\n onSlideChange?.(nextSlide)\n } else {\n setAnimationStep(prev => prev + 1)\n }\n }, [navState.status, animationStep, currentSlide, slides, onSlideChange])\n\n const goBack = useCallback(() => {\n if (navState.status === \"transitioning\") {\n setQueuedAction(\"goBack\")\n return\n }\n\n if (animationStep <= 0) {\n const prevSlide = (currentSlide - 1 + slides.length) % slides.length\n const prevSlideSteps = slides[prevSlide]?.steps ?? 0\n setNavState({ status: \"transitioning\", direction: -1 })\n setAnimationStep(prevSlideSteps)\n setCurrentSlide(prevSlide)\n onSlideChange?.(prevSlide)\n } else {\n setAnimationStep(prev => prev - 1)\n }\n }, [navState.status, animationStep, currentSlide, slides, onSlideChange])\n\n const goToSlide = useCallback(\n (index: number) => {\n if (index < 0 || index >= slides.length || index === currentSlide) {\n return\n }\n\n const direction = index > currentSlide ? 1 : -1\n setNavState({ status: \"transitioning\", direction })\n setAnimationStep(0)\n setCurrentSlide(index)\n onSlideChange?.(index)\n },\n [currentSlide, slides.length, onSlideChange]\n )\n\n useEffect(() => {\n if (navState.status === \"idle\" && queuedAction !== null) {\n setQueuedAction(null)\n if (queuedAction === \"advance\") {\n advance()\n } else if (queuedAction === \"goBack\") {\n goBack()\n }\n }\n }, [navState.status, queuedAction, advance, goBack])\n\n return {\n currentSlide,\n animationStep,\n totalSteps,\n direction: navState.direction,\n isTransitioning: navState.status !== \"idle\",\n showAllAnimations: navState.direction === -1 && navState.status === \"transitioning\",\n advance,\n goBack,\n goToSlide,\n onTransitionComplete\n }\n}\n","import { createContext, useContext, useMemo } from \"react\"\nimport type { ThemeConfig } from \"./types\"\n\nconst ThemeContext = createContext<ThemeConfig | null>(null)\n\n/**\n * Access the full theme config. Returns null outside SlideThemeProvider.\n */\nexport function useTheme(): ThemeConfig | null {\n return useContext(ThemeContext)\n}\n\nfunction buildCssOverrides(theme: ThemeConfig): React.CSSProperties {\n const style: Record<string, string> = {}\n\n if (theme.colors?.primary) style[\"--primary\"] = theme.colors.primary\n if (theme.colors?.primaryForeground) style[\"--primary-foreground\"] = theme.colors.primaryForeground\n if (theme.colors?.secondary) style[\"--secondary\"] = theme.colors.secondary\n if (theme.colors?.secondaryForeground) style[\"--secondary-foreground\"] = theme.colors.secondaryForeground\n if (theme.colors?.accent) style[\"--accent\"] = theme.colors.accent\n if (theme.colors?.accentForeground) style[\"--accent-foreground\"] = theme.colors.accentForeground\n\n if (theme.fonts?.heading) style[\"--font-heading\"] = theme.fonts.heading\n if (theme.fonts?.body) style[\"--font-body\"] = theme.fonts.body\n\n return style as React.CSSProperties\n}\n\ninterface SlideThemeProviderProps {\n theme: ThemeConfig\n children: React.ReactNode\n}\n\n/**\n * Provides the full theme to all descendants.\n * Injects CSS variable overrides via inline style.\n */\nexport function SlideThemeProvider({ theme, children }: SlideThemeProviderProps) {\n const cssOverrides = useMemo(() => buildCssOverrides(theme), [theme])\n\n return (\n <ThemeContext.Provider value={theme}>\n <div style={cssOverrides} className=\"contents\">\n {children}\n </div>\n </ThemeContext.Provider>\n )\n}\n","import { AnimatePresence, motion } from \"framer-motion\"\n\nimport type { SlideTransitionType } from \"./transitions\"\nimport type { NavigationDirection, SlideConfig } from \"./types\"\n\nimport { SLIDE_TRANSITION } from \"./animation-config\"\nimport { AnimationProvider } from \"./animation-context\"\nimport { SlideErrorBoundary } from \"./slide-error-boundary\"\nimport { DEFAULT_SLIDE_TRANSITION, getSlideVariants } from \"./transitions\"\n\n// =============================================================================\n// TYPES\n// =============================================================================\n\nexport interface SlideRendererProps {\n slides: SlideConfig[]\n currentSlide: number\n animationStep: number\n totalSteps: number\n direction: NavigationDirection\n showAllAnimations: boolean\n transition?: SlideTransitionType\n directionalTransition?: boolean\n onTransitionComplete: () => void\n}\n\n// =============================================================================\n// COMPONENT\n// =============================================================================\n\n/**\n * Renders a single slide with animated transitions.\n * Extracted from SlideDeck so it can be reused in SlideEmbed and other contexts.\n */\nexport function SlideRenderer({\n slides,\n currentSlide,\n animationStep,\n totalSteps,\n direction,\n showAllAnimations,\n transition,\n directionalTransition,\n onTransitionComplete\n}: SlideRendererProps) {\n const currentSlideTransition = slides[currentSlide]?.transition\n const transitionType = currentSlideTransition ?? transition ?? DEFAULT_SLIDE_TRANSITION\n const isDirectional = directionalTransition ?? false\n\n const slideVariants = getSlideVariants(\n { type: transitionType, directional: isDirectional },\n direction\n )\n\n const CurrentSlideComponent = slides[currentSlide]!.component\n\n return (\n <AnimatePresence initial={false}>\n <motion.div\n key={currentSlide}\n variants={slideVariants}\n initial=\"enter\"\n animate=\"center\"\n exit=\"exit\"\n transition={SLIDE_TRANSITION}\n onAnimationComplete={definition => {\n if (definition === \"center\") {\n onTransitionComplete()\n }\n }}\n className=\"absolute inset-0 h-full w-full\"\n >\n <AnimationProvider\n currentStep={animationStep}\n totalSteps={totalSteps}\n showAllAnimations={showAllAnimations}\n >\n <SlideErrorBoundary\n slideIndex={currentSlide}\n slideTitle={slides[currentSlide]?.title}\n >\n <CurrentSlideComponent\n slideNumber={currentSlide + 1}\n totalSlides={slides.length}\n />\n </SlideErrorBoundary>\n </AnimationProvider>\n </motion.div>\n </AnimatePresence>\n )\n}\n","import React from \"react\"\n\ninterface SlideErrorBoundaryProps {\n slideIndex: number\n slideTitle?: string\n children: React.ReactNode\n}\n\ninterface SlideErrorBoundaryState {\n hasError: boolean\n error: Error | null\n}\n\nexport class SlideErrorBoundary extends React.Component<\n SlideErrorBoundaryProps,\n SlideErrorBoundaryState\n> {\n state: SlideErrorBoundaryState = { hasError: false, error: null }\n\n static getDerivedStateFromError(error: Error) {\n return { hasError: true, error }\n }\n\n componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {\n console.error(\n `[PromptSlide] Slide ${this.props.slideIndex + 1}${this.props.slideTitle ? ` (\"${this.props.slideTitle}\")` : \"\"} crashed:`,\n error,\n errorInfo\n )\n }\n\n render() {\n if (this.state.hasError) {\n return (\n <div className=\"flex h-full w-full flex-col items-center justify-center bg-red-950/20 p-12\">\n <div className=\"mb-4 text-lg font-semibold text-red-400\">\n Slide {this.props.slideIndex + 1} Error\n {this.props.slideTitle && (\n <span className=\"ml-2 font-normal text-red-400/70\">({this.props.slideTitle})</span>\n )}\n </div>\n <div className=\"max-w-2xl text-center font-mono text-sm break-words text-red-300/80\">\n {this.state.error?.message ?? \"Unknown error\"}\n </div>\n </div>\n )\n }\n return this.props.children\n }\n}\n","import { useCallback, useEffect, useState } from \"react\"\n\nimport type { SlideTransitionType } from \"./transitions\"\nimport type { SlideConfig } from \"./types\"\n\nimport { SLIDE_DIMENSIONS } from \"./animation-config\"\nimport { SlideRenderer } from \"./slide-renderer\"\nimport { useSlideNavigation } from \"./use-slide-navigation\"\n\n// =============================================================================\n// TYPES\n// =============================================================================\n\ninterface SlideEmbedProps {\n slides: SlideConfig[]\n transition?: SlideTransitionType\n directionalTransition?: boolean\n}\n\n// =============================================================================\n// COMPONENT\n// =============================================================================\n\n/**\n * Headless slide viewer controlled via window.postMessage.\n * Designed for embedding in an iframe (e.g. the registry editor preview).\n *\n * Inbound messages (parent → embed):\n * { type: \"navigate\", data: { slide: number } }\n * { type: \"advance\" }\n * { type: \"goBack\" }\n *\n * Outbound messages (embed → parent):\n * { type: \"slideReady\" }\n * { type: \"slideState\", data: { currentSlide, totalSlides, animationStep, totalSteps, titles } }\n * { type: \"hmrUpdate\" }\n */\nexport function SlideEmbed({ slides, transition, directionalTransition }: SlideEmbedProps) {\n const [scale, setScale] = useState(1)\n\n const {\n currentSlide,\n animationStep,\n totalSteps,\n direction,\n showAllAnimations,\n advance,\n goBack,\n goToSlide,\n onTransitionComplete\n } = useSlideNavigation({ slides })\n\n // Post slide state to parent whenever it changes\n useEffect(() => {\n const state = {\n currentSlide,\n totalSlides: slides.length,\n animationStep,\n totalSteps,\n titles: slides.map(s => s.title || \"\")\n }\n window.parent.postMessage({ type: \"slideState\", data: state }, \"*\")\n }, [currentSlide, animationStep, totalSteps, slides])\n\n // Signal readiness on mount\n useEffect(() => {\n window.parent.postMessage({ type: \"slideReady\" }, \"*\")\n }, [])\n\n // Listen for Vite HMR updates\n useEffect(() => {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const hot = (import.meta as any).hot as { on: (event: string, cb: () => void) => void } | undefined\n if (hot) {\n hot.on(\"vite:afterUpdate\", () => {\n window.parent.postMessage({ type: \"hmrUpdate\" }, \"*\")\n })\n }\n }, [])\n\n // Listen for inbound messages from parent\n const handleMessage = useCallback(\n (event: MessageEvent) => {\n const { type, data } = event.data || {}\n switch (type) {\n case \"navigate\":\n if (typeof data?.slide === \"number\") goToSlide(data.slide)\n break\n case \"advance\":\n advance()\n break\n case \"goBack\":\n goBack()\n break\n }\n },\n [advance, goBack, goToSlide]\n )\n\n useEffect(() => {\n window.addEventListener(\"message\", handleMessage)\n return () => window.removeEventListener(\"message\", handleMessage)\n }, [handleMessage])\n\n // Scale to fill viewport\n useEffect(() => {\n const calculateScale = () => {\n setScale(window.innerWidth / SLIDE_DIMENSIONS.width)\n }\n\n calculateScale()\n window.addEventListener(\"resize\", calculateScale)\n return () => window.removeEventListener(\"resize\", calculateScale)\n }, [])\n\n return (\n <div className=\"flex h-screen w-screen items-center justify-center overflow-hidden bg-black\">\n <div\n className=\"relative overflow-hidden bg-black\"\n style={{\n width: SLIDE_DIMENSIONS.width,\n height: SLIDE_DIMENSIONS.height,\n transform: `scale(${scale})`,\n transformOrigin: \"center center\"\n }}\n >\n <SlideRenderer\n slides={slides}\n currentSlide={currentSlide}\n animationStep={animationStep}\n totalSteps={totalSteps}\n direction={direction}\n showAllAnimations={showAllAnimations}\n transition={transition}\n directionalTransition={directionalTransition}\n onTransitionComplete={onTransitionComplete}\n />\n </div>\n </div>\n )\n}\n","import { LayoutGroup } from \"framer-motion\"\nimport { ChevronLeft, ChevronRight, Download, Grid3X3, List, Maximize, MessageCircle, Monitor } from \"lucide-react\"\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\"\n\nimport type { SlideTransitionType } from \"./transitions\"\nimport type { SlideConfig } from \"./types\"\n\nimport { SLIDE_DIMENSIONS } from \"./animation-config\"\nimport { AnimationProvider } from \"./animation-context\"\nimport { AnnotationOverlay, AnnotationPanel, useAnnotations } from \"./annotations\"\nimport type { Annotation, AnnotationTarget } from \"./annotations\"\nimport { SlideErrorBoundary } from \"./slide-error-boundary\"\nimport { SlideRenderer } from \"./slide-renderer\"\nimport { useSlideNavigation } from \"./use-slide-navigation\"\nimport { cn } from \"./utils\"\n\n// =============================================================================\n// TYPES\n// =============================================================================\n\ntype ViewMode = \"slide\" | \"list\" | \"grid\"\n\ninterface SlideDeckProps {\n slides: SlideConfig[]\n transition?: SlideTransitionType\n directionalTransition?: boolean\n /** Annotation data to display. When provided (even empty array), annotation UI is enabled. When undefined, annotation UI is hidden. */\n annotations?: Annotation[]\n /** Called when the user creates an annotation */\n onAnnotationAdd?: (slideIndex: number, slideTitle: string, target: AnnotationTarget, body: string) => void\n /** Called when the user deletes an annotation */\n onAnnotationDelete?: (id: string) => void\n}\n\n// =============================================================================\n// EXPORT VIEW (for Playwright screenshot capture)\n// =============================================================================\n\nfunction SlideExportView({ slides, slideIndex }: { slides: SlideConfig[]; slideIndex: number }) {\n const [ready, setReady] = useState(false)\n const clampedIndex = Math.max(0, Math.min(slideIndex, slides.length - 1))\n const slideConfig = slides[clampedIndex]!\n const SlideComponent = slideConfig.component\n\n useEffect(() => {\n setReady(true)\n }, [])\n\n return (\n <div\n data-export-ready={ready ? \"true\" : undefined}\n style={{\n width: SLIDE_DIMENSIONS.width,\n height: SLIDE_DIMENSIONS.height,\n overflow: \"hidden\",\n position: \"relative\",\n background: \"black\"\n }}\n >\n <AnimationProvider\n currentStep={slideConfig.steps}\n totalSteps={slideConfig.steps}\n showAllAnimations={true}\n >\n <SlideErrorBoundary slideIndex={clampedIndex} slideTitle={slideConfig.title}>\n <SlideComponent slideNumber={clampedIndex + 1} totalSlides={slides.length} />\n </SlideErrorBoundary>\n </AnimationProvider>\n </div>\n )\n}\n\n// =============================================================================\n// COMPONENT\n// =============================================================================\n\nexport function SlideDeck({ slides, transition, directionalTransition, annotations, onAnnotationAdd, onAnnotationDelete }: SlideDeckProps) {\n // Check for export mode via URL params\n const [exportParams] = useState(() => {\n if (typeof window === \"undefined\") return null\n const params = new URLSearchParams(window.location.search)\n if (params.get(\"export\") !== \"true\") return null\n return { slideIndex: parseInt(params.get(\"slide\") || \"0\", 10) }\n })\n\n if (exportParams) {\n return <SlideExportView slides={slides} slideIndex={exportParams.slideIndex} />\n }\n\n // Use internal useAnnotations as fallback when no external annotations prop is provided\n const internal = useAnnotations()\n const isExternallyManaged = annotations !== undefined\n const effectiveAnnotations = isExternallyManaged ? annotations : internal.annotations\n const effectiveAdd = isExternallyManaged ? onAnnotationAdd : internal.addAnnotation\n const effectiveDelete = isExternallyManaged ? onAnnotationDelete : internal.deleteAnnotation\n\n const openCount = useMemo(() => effectiveAnnotations.filter(a => a.status === \"open\").length, [effectiveAnnotations])\n const getSlideAnnotations = useCallback(\n (slideIndex: number) => effectiveAnnotations.filter(a => a.slideIndex === slideIndex),\n [effectiveAnnotations]\n )\n\n const [viewMode, setViewMode] = useState<ViewMode>(\"slide\")\n const [isPresentationMode, setIsPresentationMode] = useState(false)\n const [isAnnotationMode, setIsAnnotationMode] = useState(false)\n const [showAnnotationPanel, setShowAnnotationPanel] = useState(false)\n const [selectedAnnotationId, setSelectedAnnotationId] = useState<string | null>(null)\n const [scale, setScale] = useState(1)\n const containerRef = useRef<HTMLDivElement>(null)\n const slideContainerRef = useRef<HTMLDivElement>(null)\n\n const {\n currentSlide,\n animationStep,\n totalSteps,\n direction,\n showAllAnimations,\n advance,\n goBack,\n goToSlide,\n onTransitionComplete\n } = useSlideNavigation({\n slides\n })\n\n const togglePresentationMode = useCallback(async () => {\n if (!document.fullscreenElement) {\n await document.documentElement.requestFullscreen()\n } else {\n await document.exitFullscreen()\n }\n }, [])\n\n // Listen for fullscreen changes\n useEffect(() => {\n const handleFullscreenChange = () => {\n setIsPresentationMode(!!document.fullscreenElement)\n }\n document.addEventListener(\"fullscreenchange\", handleFullscreenChange)\n return () => document.removeEventListener(\"fullscreenchange\", handleFullscreenChange)\n }, [])\n\n // Calculate scale factor for presentation mode\n useEffect(() => {\n const calculateScale = () => {\n if (!isPresentationMode) {\n setScale(1)\n return\n }\n const viewportWidth = window.innerWidth\n const viewportHeight = window.innerHeight\n const scaleX = viewportWidth / SLIDE_DIMENSIONS.width\n const scaleY = viewportHeight / SLIDE_DIMENSIONS.height\n setScale(Math.min(scaleX, scaleY))\n }\n\n calculateScale()\n window.addEventListener(\"resize\", calculateScale)\n return () => window.removeEventListener(\"resize\", calculateScale)\n }, [isPresentationMode])\n\n const handleExportPdf = () => {\n const previousMode = viewMode\n setViewMode(\"list\")\n\n setTimeout(() => {\n const handleAfterPrint = () => {\n setViewMode(previousMode)\n window.removeEventListener(\"afterprint\", handleAfterPrint)\n }\n window.addEventListener(\"afterprint\", handleAfterPrint)\n window.print()\n }, 100)\n }\n\n // Keyboard navigation\n useEffect(() => {\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.key === \"f\" || e.key === \"F\") {\n togglePresentationMode()\n return\n }\n\n // G for grid view toggle\n if (e.key === \"g\" || e.key === \"G\") {\n setViewMode(prev => (prev === \"grid\" ? \"slide\" : \"grid\"))\n return\n }\n\n if (viewMode !== \"slide\" || isAnnotationMode) return\n\n if (e.key === \"ArrowRight\" || e.key === \" \") {\n e.preventDefault()\n advance()\n } else if (e.key === \"ArrowLeft\") {\n e.preventDefault()\n goBack()\n }\n }\n\n window.addEventListener(\"keydown\", handleKeyDown)\n return () => window.removeEventListener(\"keydown\", handleKeyDown)\n }, [advance, goBack, viewMode, togglePresentationMode, isAnnotationMode])\n\n return (\n <div className=\"min-h-screen w-full bg-neutral-950 text-foreground\">\n <style>{`\n @media print {\n @page {\n size: 1920px 1080px;\n margin: 0;\n }\n html,\n body {\n width: 100%;\n height: 100%;\n margin: 0 !important;\n padding: 0 !important;\n overflow: visible !important;\n }\n body {\n print-color-adjust: exact;\n -webkit-print-color-adjust: exact;\n background: transparent !important;\n }\n }\n `}</style>\n\n {/* Toolbar */}\n <div\n className={cn(\n \"fixed top-4 z-50 flex gap-1 rounded-lg border border-neutral-800 bg-neutral-950/90 p-1 backdrop-blur-sm transition-[right] print:hidden\",\n isPresentationMode && \"hidden\",\n isAnnotationMode && showAnnotationPanel ? \"right-[19.5rem]\" : \"right-4\"\n )}\n >\n <button\n onClick={() => setViewMode(\"slide\")}\n className={cn(\n \"rounded-md p-2 text-neutral-400 transition-colors hover:bg-neutral-800 hover:text-white\",\n viewMode === \"slide\" && \"bg-neutral-800 text-white\"\n )}\n title=\"Presentation View\"\n >\n <Monitor className=\"h-4 w-4\" />\n </button>\n <button\n onClick={() => setViewMode(\"list\")}\n className={cn(\n \"rounded-md p-2 text-neutral-400 transition-colors hover:bg-neutral-800 hover:text-white\",\n viewMode === \"list\" && \"bg-neutral-800 text-white\"\n )}\n title=\"List View\"\n >\n <List className=\"h-4 w-4\" />\n </button>\n <button\n onClick={() => setViewMode(\"grid\")}\n className={cn(\n \"rounded-md p-2 text-neutral-400 transition-colors hover:bg-neutral-800 hover:text-white\",\n viewMode === \"grid\" && \"bg-neutral-800 text-white\"\n )}\n title=\"Grid View\"\n >\n <Grid3X3 className=\"h-4 w-4\" />\n </button>\n\n <div className=\"mx-1 w-px bg-neutral-800\" />\n\n <button\n onClick={() => {\n setIsAnnotationMode(prev => {\n const next = !prev\n setShowAnnotationPanel(next)\n if (!next) setSelectedAnnotationId(null)\n return next\n })\n }}\n className={cn(\n \"relative rounded-md p-2 text-neutral-400 transition-colors hover:bg-neutral-800 hover:text-white\",\n isAnnotationMode && \"bg-[#FF6B35] text-white hover:bg-[#FF7A4A]\"\n )}\n title=\"Annotate slides\"\n >\n <MessageCircle className=\"h-4 w-4\" />\n {openCount > 0 && (\n <span className=\"absolute -top-1 -right-1 flex h-4 w-4 items-center justify-center rounded-full bg-[#FF6B35] text-[10px] font-bold text-white\">\n {openCount}\n </span>\n )}\n </button>\n\n <div className=\"mx-1 w-px bg-neutral-800\" />\n\n <button\n onClick={handleExportPdf}\n className=\"rounded-md p-2 text-neutral-400 transition-colors hover:bg-neutral-800 hover:text-white\"\n title=\"Download PDF\"\n >\n <Download className=\"h-4 w-4\" />\n </button>\n <button\n onClick={togglePresentationMode}\n className=\"rounded-md p-2 text-neutral-400 transition-colors hover:bg-neutral-800 hover:text-white\"\n title=\"Present (F)\"\n >\n <Maximize className=\"h-4 w-4\" />\n </button>\n </div>\n\n {/* Slide View */}\n {viewMode === \"slide\" && (\n <div\n className={cn(\n \"flex h-screen w-full print:hidden\",\n isPresentationMode ? \"bg-black\" : \"\"\n )}\n >\n <div\n ref={containerRef}\n role=\"presentation\"\n tabIndex={isPresentationMode ? 0 : undefined}\n className={cn(\n \"flex flex-1 flex-col items-center justify-center overflow-hidden\",\n isPresentationMode ? \"bg-black p-0\" : \"p-4 md:p-8\"\n )}\n onClick={isPresentationMode ? advance : undefined}\n onKeyDown={\n isPresentationMode\n ? e => {\n if (e.key === \"Enter\" || e.key === \" \") advance()\n }\n : undefined\n }\n >\n <LayoutGroup id=\"slide-deck\">\n {isPresentationMode ? (\n <div\n className=\"pointer-events-none relative overflow-hidden bg-black\"\n style={{\n width: SLIDE_DIMENSIONS.width,\n height: SLIDE_DIMENSIONS.height,\n transform: `scale(${scale})`,\n transformOrigin: \"center center\"\n }}\n >\n <SlideRenderer\n slides={slides}\n currentSlide={currentSlide}\n animationStep={animationStep}\n totalSteps={totalSteps}\n direction={direction}\n showAllAnimations={showAllAnimations}\n transition={transition}\n directionalTransition={directionalTransition}\n onTransitionComplete={onTransitionComplete}\n />\n </div>\n ) : (\n <div ref={slideContainerRef} className=\"relative aspect-video w-full max-w-7xl overflow-hidden rounded-xl border border-neutral-800 bg-black shadow-2xl\">\n <SlideRenderer\n slides={slides}\n currentSlide={currentSlide}\n animationStep={animationStep}\n totalSteps={totalSteps}\n direction={direction}\n showAllAnimations={showAllAnimations}\n transition={transition}\n directionalTransition={directionalTransition}\n onTransitionComplete={onTransitionComplete}\n />\n {isAnnotationMode && (\n <AnnotationOverlay\n slides={slides}\n currentSlide={currentSlide}\n slideContainerRef={slideContainerRef}\n selectedId={selectedAnnotationId}\n onSelectId={setSelectedAnnotationId}\n onShowPanel={() => setShowAnnotationPanel(true)}\n slideAnnotations={getSlideAnnotations(currentSlide)}\n addAnnotation={effectiveAdd ?? (() => {})}\n\n />\n )}\n </div>\n )}\n </LayoutGroup>\n\n {/* Navigation Controls */}\n {!isPresentationMode && (\n <div className=\"mt-6 flex items-center gap-4\">\n <button\n onClick={goBack}\n className=\"rounded-full border border-neutral-800 bg-black/50 p-2 text-neutral-400 backdrop-blur-sm transition-colors hover:bg-neutral-900 hover:text-white\"\n >\n <ChevronLeft className=\"h-5 w-5\" />\n </button>\n <div className=\"flex min-w-[4rem] flex-col items-center\">\n <span className=\"font-mono text-sm text-neutral-500\">\n {currentSlide + 1} / {slides.length}\n </span>\n {slides[currentSlide]?.title && (\n <span className=\"mt-0.5 text-xs text-neutral-600\">\n {slides[currentSlide].title}\n </span>\n )}\n </div>\n <button\n onClick={advance}\n className=\"rounded-full border border-neutral-800 bg-black/50 p-2 text-neutral-400 backdrop-blur-sm transition-colors hover:bg-neutral-900 hover:text-white\"\n >\n <ChevronRight className=\"h-5 w-5\" />\n </button>\n </div>\n )}\n </div>\n\n {/* Annotation Panel — beside the slide */}\n {isAnnotationMode && showAnnotationPanel && !isPresentationMode && (\n <AnnotationPanel\n annotations={getSlideAnnotations(currentSlide)}\n selectedId={selectedAnnotationId}\n onSelect={setSelectedAnnotationId}\n onDelete={effectiveDelete ?? (() => {})}\n onClose={() => {\n setShowAnnotationPanel(false)\n setSelectedAnnotationId(null)\n }}\n />\n )}\n </div>\n )}\n\n {/* Grid View */}\n {viewMode === \"grid\" && (\n <div className=\"mx-auto max-w-7xl p-8 pt-16 print:hidden\">\n <div className=\"grid grid-cols-2 gap-4 md:grid-cols-3 lg:grid-cols-4\">\n {slides.map((slideConfig, index) => {\n const SlideComponent = slideConfig.component\n const prevSection = index > 0 ? slides[index - 1]?.section : undefined\n const showSectionHeader = slideConfig.section && slideConfig.section !== prevSection\n\n return (\n <div key={index} className={showSectionHeader ? \"col-span-full\" : undefined}>\n {showSectionHeader && (\n <h3 className=\"mt-4 mb-3 text-xs font-bold tracking-[0.2em] text-neutral-500 uppercase first:mt-0\">\n {slideConfig.section}\n </h3>\n )}\n <button\n onClick={() => {\n goToSlide(index)\n setViewMode(\"slide\")\n }}\n className=\"group relative aspect-video w-full overflow-hidden rounded-lg border border-neutral-800 bg-black shadow-sm transition-all hover:border-primary hover:shadow-lg hover:shadow-primary/10\"\n >\n <div\n className=\"h-full w-full origin-top-left scale-[0.25]\"\n style={{ width: \"400%\", height: \"400%\" }}\n >\n <AnimationProvider\n currentStep={slideConfig.steps}\n totalSteps={slideConfig.steps}\n showAllAnimations={true}\n >\n <SlideErrorBoundary slideIndex={index} slideTitle={slideConfig.title}>\n <SlideComponent slideNumber={index + 1} totalSlides={slides.length} />\n </SlideErrorBoundary>\n </AnimationProvider>\n </div>\n <div className=\"absolute inset-0 bg-black/0 transition-colors group-hover:bg-black/20\" />\n <div className=\"absolute bottom-2 left-2 rounded bg-black/70 px-2 py-1 text-xs font-medium text-white\">\n {slideConfig.title ? `${index + 1}. ${slideConfig.title}` : index + 1}\n </div>\n </button>\n </div>\n )\n })}\n </div>\n </div>\n )}\n\n {/* List View */}\n <div\n className={cn(\n \"mx-auto max-w-7xl p-8 pt-16\",\n \"print:m-0 print:block print:max-w-none print:p-0\",\n viewMode === \"list\" ? \"block\" : \"hidden print:block\"\n )}\n >\n <div className=\"grid grid-cols-1 gap-8 print:block\">\n {slides.map((slideConfig, index) => {\n const SlideComponent = slideConfig.component\n return (\n <div\n key={index}\n className=\"aspect-video w-full overflow-hidden rounded-xl border border-neutral-800 bg-black shadow-sm print:relative print:m-0 print:h-[1080px] print:w-[1920px] print:break-after-page print:overflow-hidden print:rounded-none print:border-0 print:shadow-none\"\n >\n <div className=\"h-full w-full print:h-[720px] print:w-[1280px] print:origin-top-left print:scale-[1.5]\">\n <AnimationProvider\n currentStep={slideConfig.steps}\n totalSteps={slideConfig.steps}\n showAllAnimations={true}\n >\n <SlideErrorBoundary slideIndex={index} slideTitle={slideConfig.title}>\n <SlideComponent slideNumber={index + 1} totalSlides={slides.length} />\n </SlideErrorBoundary>\n </AnimationProvider>\n </div>\n </div>\n )\n })}\n </div>\n </div>\n </div>\n )\n}\n","import { useCallback, useEffect, useRef, useState } from \"react\"\nimport type { SlideConfig } from \"../types\"\nimport { AnnotationForm } from \"./annotation-form\"\nimport { AnnotationPin } from \"./annotation-pin\"\nimport { buildElementTarget, resolveTarget } from \"./selectors\"\nimport type { Annotation, AnnotationTarget } from \"./types\"\n\ninterface AnnotationOverlayProps {\n slides: SlideConfig[]\n currentSlide: number\n /** Ref to the slide container element (the div wrapping SlideRenderer) */\n slideContainerRef: React.RefObject<HTMLDivElement | null>\n selectedId: string | null\n onSelectId: (id: string | null) => void\n onShowPanel: () => void\n slideAnnotations: Annotation[]\n addAnnotation: (slideIndex: number, slideTitle: string, target: AnnotationTarget, body: string) => void\n}\n\ninterface PendingAnnotation {\n target: AnnotationTarget\n xPercent: number\n yPercent: number\n}\n\nexport function AnnotationOverlay({ slides, currentSlide, slideContainerRef, selectedId, onSelectId, onShowPanel, slideAnnotations, addAnnotation }: AnnotationOverlayProps) {\n const [pending, setPending] = useState<PendingAnnotation | null>(null)\n const [hoveredElement, setHoveredElement] = useState<DOMRect | null>(null)\n const overlayRef = useRef<HTMLDivElement>(null)\n\n const slideTitle = slides[currentSlide]?.title || `Slide ${currentSlide + 1}`\n\n // Resolve annotation positions — use the element if found, otherwise fallback coordinates\n const resolvedAnnotations = slideAnnotations.map((a, i) => {\n const container = slideContainerRef.current\n if (!container) {\n return { annotation: a, xPercent: a.target.position.xPercent, yPercent: a.target.position.yPercent, number: i + 1 }\n }\n\n const { element } = resolveTarget(a.target, container)\n if (element) {\n const rect = element.getBoundingClientRect()\n const containerRect = container.getBoundingClientRect()\n const xPercent = ((rect.left + rect.width / 2 - containerRect.left) / containerRect.width) * 100\n const yPercent = ((rect.top + rect.height / 2 - containerRect.top) / containerRect.height) * 100\n return { annotation: a, xPercent, yPercent, number: i + 1 }\n }\n\n return { annotation: a, xPercent: a.target.position.xPercent, yPercent: a.target.position.yPercent, number: i + 1 }\n })\n\n const handleOverlayClick = useCallback(\n (e: React.MouseEvent) => {\n const container = slideContainerRef.current\n if (!container) return\n\n // Get the element under the click by temporarily hiding the overlay\n const overlay = overlayRef.current\n if (overlay) overlay.style.pointerEvents = \"none\"\n const elementUnder = document.elementFromPoint(e.clientX, e.clientY) as HTMLElement | null\n if (overlay) overlay.style.pointerEvents = \"\"\n\n if (!elementUnder || !container.contains(elementUnder)) {\n setPending(null)\n onSelectId(null)\n return\n }\n\n // Pick the most specific meaningful element (skip tiny text nodes, pick their parent)\n let target = elementUnder\n if (target.tagName === \"SPAN\" && target.parentElement && container.contains(target.parentElement)) {\n // For inline spans, prefer their parent for a more meaningful target\n const parent = target.parentElement\n if (parent.tagName !== \"DIV\" || parent.children.length <= 3) {\n target = parent\n }\n }\n\n const annotationTarget = buildElementTarget(target, container)\n const containerRect = container.getBoundingClientRect()\n const xPercent = ((e.clientX - containerRect.left) / containerRect.width) * 100\n const yPercent = ((e.clientY - containerRect.top) / containerRect.height) * 100\n\n setPending({ target: annotationTarget, xPercent, yPercent })\n onSelectId(null)\n },\n [slideContainerRef, onSelectId]\n )\n\n const handleSubmit = useCallback(\n (text: string) => {\n if (!pending) return\n addAnnotation(currentSlide, slideTitle, pending.target, text)\n setPending(null)\n onShowPanel()\n },\n [pending, currentSlide, slideTitle, addAnnotation, onShowPanel]\n )\n\n // Track hover for element highlighting\n const handleMouseMove = useCallback(\n (e: React.MouseEvent) => {\n if (pending) {\n setHoveredElement(null)\n return\n }\n\n const container = slideContainerRef.current\n if (!container) return\n\n const overlay = overlayRef.current\n if (overlay) overlay.style.pointerEvents = \"none\"\n const elementUnder = document.elementFromPoint(e.clientX, e.clientY) as HTMLElement | null\n if (overlay) overlay.style.pointerEvents = \"\"\n\n if (elementUnder && container.contains(elementUnder) && elementUnder !== container) {\n const containerRect = container.getBoundingClientRect()\n const elRect = elementUnder.getBoundingClientRect()\n setHoveredElement(\n new DOMRect(\n elRect.left - containerRect.left,\n elRect.top - containerRect.top,\n elRect.width,\n elRect.height\n )\n )\n } else {\n setHoveredElement(null)\n }\n },\n [slideContainerRef, pending]\n )\n\n // Clear pending when slide changes\n useEffect(() => {\n setPending(null)\n onSelectId(null)\n setHoveredElement(null)\n }, [currentSlide, onSelectId])\n\n return (\n <>\n {/* Hover highlight */}\n {hoveredElement && (\n <div\n className=\"pointer-events-none absolute z-20 rounded-lg border-2 border-dashed border-[#FF6B35]/50 bg-[#FF6B35]/5\"\n style={{\n left: hoveredElement.x,\n top: hoveredElement.y,\n width: hoveredElement.width,\n height: hoveredElement.height\n }}\n />\n )}\n\n {/* Click capture overlay */}\n <div\n ref={overlayRef}\n role=\"button\"\n tabIndex={0}\n className=\"absolute inset-0 z-20\"\n style={{ cursor: `url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none'%3E%3Ccircle cx='12' cy='12' r='8' stroke='%23FF6B35' stroke-width='2' opacity='0.8'/%3E%3Ccircle cx='12' cy='12' r='2' fill='%23FF6B35'/%3E%3C/svg%3E\") 12 12, crosshair` }}\n onClick={handleOverlayClick}\n onKeyDown={e => { if (e.key === \"Escape\") { setPending(null); onSelectId(null) } }}\n onMouseMove={handleMouseMove}\n onMouseLeave={() => setHoveredElement(null)}\n />\n\n {/* Annotation pins */}\n {resolvedAnnotations.map(({ annotation, xPercent, yPercent, number }) => (\n <AnnotationPin\n key={annotation.id}\n number={number}\n status={annotation.status}\n xPercent={xPercent}\n yPercent={yPercent}\n isSelected={annotation.id === selectedId}\n onClick={() => {\n onSelectId(annotation.id === selectedId ? null : annotation.id)\n onShowPanel()\n setPending(null)\n }}\n />\n ))}\n\n {/* New annotation form */}\n {pending && (\n <AnnotationForm\n xPercent={pending.xPercent}\n yPercent={pending.yPercent}\n onSubmit={handleSubmit}\n onCancel={() => setPending(null)}\n />\n )}\n\n </>\n )\n}\n","import { useEffect, useRef, useState } from \"react\"\nimport { ArrowUp, X } from \"lucide-react\"\n\ninterface AnnotationFormProps {\n xPercent: number\n yPercent: number\n onSubmit: (text: string) => void\n onCancel: () => void\n}\n\nexport function AnnotationForm({ xPercent, yPercent, onSubmit, onCancel }: AnnotationFormProps) {\n const [text, setText] = useState(\"\")\n const textareaRef = useRef<HTMLTextAreaElement>(null)\n\n useEffect(() => {\n textareaRef.current?.focus()\n }, [])\n\n const handleSubmit = () => {\n const trimmed = text.trim()\n if (!trimmed) return\n onSubmit(trimmed)\n }\n\n const handleKeyDown = (e: React.KeyboardEvent) => {\n if (e.key === \"Enter\" && !e.shiftKey) {\n e.preventDefault()\n handleSubmit()\n }\n if (e.key === \"Escape\") {\n onCancel()\n }\n e.stopPropagation()\n }\n\n // Position the form, flipping if near edges\n const left = xPercent > 70 ? undefined : `${xPercent}%`\n const right = xPercent > 70 ? `${100 - xPercent}%` : undefined\n const top = yPercent > 70 ? undefined : `${yPercent}%`\n const bottom = yPercent > 70 ? `${100 - yPercent}%` : undefined\n\n return (\n <div\n role=\"dialog\"\n className=\"absolute z-40 w-72 overflow-hidden rounded-xl border border-white/[0.08] bg-neutral-900/95 shadow-2xl backdrop-blur-2xl\"\n style={{ left, right, top, bottom }}\n onClick={e => e.stopPropagation()}\n onKeyDown={e => e.stopPropagation()}\n >\n <div className=\"flex items-center justify-between border-b border-white/[0.06] px-3.5 py-2.5\">\n <span className=\"text-xs font-medium tracking-wide text-neutral-400\">Add annotation</span>\n <button\n onClick={onCancel}\n className=\"rounded-lg p-1 text-neutral-500 transition-colors hover:bg-white/[0.06] hover:text-neutral-300\"\n >\n <X className=\"h-3.5 w-3.5\" />\n </button>\n </div>\n <div className=\"p-3\">\n <textarea\n ref={textareaRef}\n value={text}\n onChange={e => setText(e.target.value)}\n onKeyDown={handleKeyDown}\n placeholder=\"Describe the change you want...\"\n className=\"w-full resize-none rounded-lg border border-white/[0.08] bg-white/[0.04] px-3 py-2 text-sm text-white placeholder-neutral-500 outline-none transition-colors focus:border-[#FF6B35]/50 focus:bg-white/[0.06]\"\n rows={3}\n />\n <div className=\"mt-2.5 flex items-center justify-between\">\n <span className=\"text-[11px] text-neutral-600\">Enter to send</span>\n <button\n onClick={handleSubmit}\n disabled={!text.trim()}\n className=\"flex h-7 w-7 items-center justify-center rounded-lg bg-[#FF6B35] text-white shadow-lg shadow-[#FF6B35]/20 transition-all hover:bg-[#FF7A4A] hover:shadow-[#FF6B35]/30 disabled:opacity-30 disabled:shadow-none disabled:hover:bg-[#FF6B35]\"\n >\n <ArrowUp className=\"h-3.5 w-3.5\" strokeWidth={2.5} />\n </button>\n </div>\n </div>\n </div>\n )\n}\n","interface AnnotationPinProps {\n number: number\n status: \"open\" | \"resolved\"\n xPercent: number\n yPercent: number\n isSelected: boolean\n onClick: () => void\n}\n\nexport function AnnotationPin({ number, status, xPercent, yPercent, isSelected, onClick }: AnnotationPinProps) {\n const isResolved = status === \"resolved\"\n\n return (\n <button\n onClick={e => {\n e.stopPropagation()\n onClick()\n }}\n className=\"absolute z-30 -translate-x-1/2 -translate-y-1/2 transition-all duration-200 hover:scale-110\"\n style={{ left: `${xPercent}%`, top: `${yPercent}%` }}\n title={`Annotation #${number}`}\n >\n {/* Glow ring */}\n {isSelected && !isResolved && (\n <div className=\"absolute inset-[-4px] animate-pulse rounded-full bg-[#FF6B35]/25 blur-sm\" />\n )}\n <div\n className={`relative flex h-7 w-7 items-center justify-center rounded-full text-[11px] font-semibold shadow-lg backdrop-blur-sm transition-all duration-200 ${\n isSelected\n ? isResolved\n ? \"bg-neutral-500/90 text-white ring-2 ring-neutral-400/50\"\n : \"bg-[#FF6B35] text-white ring-2 ring-[#FF6B35]/40 ring-offset-1 ring-offset-black/50\"\n : isResolved\n ? \"bg-neutral-700/80 text-neutral-400\"\n : \"bg-[#FF6B35]/90 text-white hover:bg-[#FF6B35]\"\n }`}\n >\n {number}\n </div>\n </button>\n )\n}\n","import type { AnnotationTarget } from \"./types\"\n\n/**\n * Build a composite target descriptor from a clicked DOM element.\n */\nexport function buildElementTarget(\n element: HTMLElement,\n slideRoot: HTMLElement\n): AnnotationTarget {\n const rect = element.getBoundingClientRect()\n const rootRect = slideRoot.getBoundingClientRect()\n\n const xPercent = ((rect.left + rect.width / 2 - rootRect.left) / rootRect.width) * 100\n const yPercent = ((rect.top + rect.height / 2 - rootRect.top) / rootRect.height) * 100\n\n return {\n dataAnnotate: element.getAttribute(\"data-annotate\") || undefined,\n contentNearPin: getTextFingerprint(element),\n position: { xPercent, yPercent }\n }\n}\n\n/**\n * Resolve a stored target back to a DOM element, trying strategies in priority order.\n */\nexport function resolveTarget(\n target: AnnotationTarget,\n slideRoot: HTMLElement\n): { element: HTMLElement | null; method: \"dataAnnotate\" | \"contentNearPin\" | \"position\" } {\n // 1. Try data-annotate attribute\n if (target.dataAnnotate) {\n const el = slideRoot.querySelector<HTMLElement>(`[data-annotate=\"${target.dataAnnotate}\"]`)\n if (el) return { element: el, method: \"dataAnnotate\" }\n }\n\n // 2. Try text content match\n if (target.contentNearPin) {\n const match = findByTextContent(slideRoot, target.contentNearPin)\n if (match) return { element: match, method: \"contentNearPin\" }\n }\n\n // 3. Fallback to coordinates (no element found)\n return { element: null, method: \"position\" }\n}\n\n/**\n * Extract a text fingerprint from an element (first 100 chars, trimmed).\n */\nfunction getTextFingerprint(element: HTMLElement): string | undefined {\n const text = element.textContent?.trim()\n if (!text) return undefined\n return text.slice(0, 100)\n}\n\n/**\n * Find an element by matching its text content.\n */\nfunction findByTextContent(root: HTMLElement, text: string): HTMLElement | null {\n const walker = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT)\n let best: HTMLElement | null = null\n let bestLength = Infinity\n\n while (walker.nextNode()) {\n const el = walker.currentNode as HTMLElement\n const elText = el.textContent?.trim()\n if (!elText) continue\n\n const elFingerprint = elText.slice(0, 100)\n if (elFingerprint === text && elText.length < bestLength) {\n best = el\n bestLength = elText.length\n }\n }\n\n return best\n}\n","import { MessageCircle, Trash2, X } from \"lucide-react\"\nimport type { Annotation } from \"./types\"\n\ninterface AnnotationPanelProps {\n annotations: Annotation[]\n selectedId: string | null\n onSelect: (id: string) => void\n onDelete: (id: string) => void\n onClose: () => void\n}\n\nexport function AnnotationPanel({ annotations, selectedId, onSelect, onDelete, onClose }: AnnotationPanelProps) {\n const open = annotations.filter(a => a.status === \"open\")\n const resolved = annotations.filter(a => a.status === \"resolved\")\n\n return (\n <div className=\"flex h-full w-80 flex-shrink-0 flex-col border-l border-white/[0.06] bg-neutral-950/95 backdrop-blur-2xl\">\n <div className=\"flex items-center justify-between px-4 py-3.5\">\n <div className=\"flex items-center gap-2.5\">\n <div className=\"flex h-6 w-6 items-center justify-center rounded-lg bg-[#FF6B35]/15\">\n <MessageCircle className=\"h-3.5 w-3.5 text-[#FF6B35]\" />\n </div>\n <span className=\"text-sm font-medium text-white\">Annotations</span>\n {open.length > 0 && (\n <span className=\"flex h-5 min-w-5 items-center justify-center rounded-full bg-[#FF6B35]/15 px-1.5 text-[11px] font-semibold text-[#FF6B35]\">\n {open.length}\n </span>\n )}\n </div>\n <button\n onClick={onClose}\n className=\"rounded-lg p-1.5 text-neutral-500 transition-colors hover:bg-white/[0.06] hover:text-neutral-300\"\n >\n <X className=\"h-4 w-4\" />\n </button>\n </div>\n\n <div className=\"h-px bg-gradient-to-r from-transparent via-white/[0.06] to-transparent\" />\n\n <div className=\"flex-1 overflow-y-auto p-2\">\n {annotations.length === 0 && (\n <div className=\"flex flex-col items-center gap-2 px-4 py-8 text-center\">\n <div className=\"flex h-10 w-10 items-center justify-center rounded-xl bg-white/[0.04]\">\n <MessageCircle className=\"h-5 w-5 text-neutral-600\" />\n </div>\n <p className=\"text-sm text-neutral-500\">Click on slide elements to add annotations</p>\n </div>\n )}\n\n {open.length > 0 && (\n <div>\n <div className=\"mb-1.5 px-2 pt-1 text-[11px] font-medium tracking-wider text-neutral-500 uppercase\">\n Open\n </div>\n {open.map((a, i) => (\n <AnnotationItem\n key={a.id}\n annotation={a}\n number={i + 1}\n isSelected={a.id === selectedId}\n onSelect={() => onSelect(a.id)}\n onDelete={() => onDelete(a.id)}\n />\n ))}\n </div>\n )}\n\n {resolved.length > 0 && (\n <div className={open.length > 0 ? \"mt-3\" : \"\"}>\n <div className=\"mb-1.5 px-2 pt-1 text-[11px] font-medium tracking-wider text-neutral-500 uppercase\">\n Resolved\n </div>\n {resolved.map((a, i) => (\n <AnnotationItem\n key={a.id}\n annotation={a}\n number={open.length + i + 1}\n isSelected={a.id === selectedId}\n onSelect={() => onSelect(a.id)}\n onDelete={() => onDelete(a.id)}\n />\n ))}\n </div>\n )}\n </div>\n </div>\n )\n}\n\nfunction AnnotationItem({\n annotation,\n number,\n isSelected,\n onSelect,\n onDelete\n}: {\n annotation: Annotation\n number: number\n isSelected: boolean\n onSelect: () => void\n onDelete: () => void\n}) {\n return (\n <div\n role=\"button\"\n tabIndex={0}\n onClick={onSelect}\n onKeyDown={e => { if (e.key === \"Enter\" || e.key === \" \") onSelect() }}\n className={`group relative mb-0.5 cursor-pointer rounded-xl p-2.5 transition-all duration-150 ${\n isSelected\n ? \"bg-[#FF6B35]/10 ring-1 ring-[#FF6B35]/20\"\n : \"hover:bg-white/[0.04]\"\n }`}\n >\n <button\n onClick={e => {\n e.stopPropagation()\n onDelete()\n }}\n className=\"absolute top-2 right-2 rounded-lg p-1 text-neutral-600 opacity-0 transition-all hover:bg-white/[0.08] hover:text-neutral-300 group-hover:opacity-100\"\n >\n <Trash2 className=\"h-3 w-3\" />\n </button>\n <div className=\"flex items-start gap-2.5\">\n <div\n className={`mt-0.5 flex h-5 w-5 flex-shrink-0 items-center justify-center rounded-full text-[11px] font-semibold ${\n annotation.status === \"open\"\n ? \"bg-[#FF6B35] text-white\"\n : \"bg-neutral-700 text-neutral-400\"\n }`}\n >\n {number}\n </div>\n <div className=\"min-w-0 pr-4\">\n <p className=\"text-[13px] leading-relaxed text-neutral-200\">{annotation.body}</p>\n {annotation.target.contentNearPin && (\n <p className=\"mt-1 truncate text-[11px] text-neutral-600\">\n {annotation.target.contentNearPin}\n </p>\n )}\n {annotation.resolution && (\n <p className=\"mt-1.5 text-[11px] text-emerald-400/80 italic\">\n {annotation.resolution}\n </p>\n )}\n </div>\n </div>\n </div>\n )\n}\n","import { useCallback, useEffect, useMemo, useRef, useState } from \"react\"\nimport { createHttpAdapter } from \"./adapters/http\"\nimport type { Annotation, AnnotationStorageAdapter, AnnotationTarget } from \"./types\"\n\nexport function useAnnotations(adapter?: AnnotationStorageAdapter) {\n const adapterRef = useRef(adapter ?? createHttpAdapter())\n const [annotations, setAnnotations] = useState<Annotation[]>([])\n\n // Load on mount and subscribe to external updates\n useEffect(() => {\n adapterRef.current.load().then(setAnnotations)\n return adapterRef.current.subscribe?.(setAnnotations)\n }, [])\n\n const addAnnotation = useCallback(\n (slideIndex: number, slideTitle: string, target: AnnotationTarget, body: string) => {\n const annotation: Annotation = {\n id: crypto.randomUUID(),\n slideIndex,\n slideTitle,\n target,\n body,\n createdAt: new Date().toISOString(),\n status: \"open\"\n }\n setAnnotations(prev => [...prev, annotation])\n adapterRef.current.add(annotation)\n },\n []\n )\n\n const deleteAnnotation = useCallback((id: string) => {\n setAnnotations(prev => prev.filter(a => a.id !== id))\n adapterRef.current.remove(id)\n }, [])\n\n const getSlideAnnotations = useCallback(\n (slideIndex: number) => annotations.filter(a => a.slideIndex === slideIndex),\n [annotations]\n )\n\n const openCount = useMemo(() => annotations.filter(a => a.status === \"open\").length, [annotations])\n\n // Allow external state updates (e.g. from postMessage adapter)\n const updateAnnotations = useCallback((updated: Annotation[]) => {\n setAnnotations(updated)\n }, [])\n\n return { annotations, addAnnotation, deleteAnnotation, getSlideAnnotations, openCount, updateAnnotations }\n}\n","import type { Annotation, AnnotationsFile, AnnotationStorageAdapter } from \"../types\"\n\nconst ENDPOINT = \"/__promptslide_annotations\"\n\nasync function loadAll(): Promise<Annotation[]> {\n try {\n const res = await fetch(ENDPOINT)\n if (!res.ok) return []\n const data: AnnotationsFile = await res.json()\n return data.annotations || []\n } catch {\n return []\n }\n}\n\nasync function saveAll(annotations: Annotation[]): Promise<void> {\n const data: AnnotationsFile = { version: 1, annotations }\n await fetch(ENDPOINT, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(data)\n })\n}\n\n/** Storage adapter for local Vite dev server (reads/writes annotations.json via middleware) */\nexport function createHttpAdapter(): AnnotationStorageAdapter {\n let cache: Annotation[] = []\n\n return {\n async load() {\n cache = await loadAll()\n return cache\n },\n async add(annotation) {\n cache = [...cache, annotation]\n await saveAll(cache)\n },\n async remove(id) {\n cache = cache.filter(a => a.id !== id)\n await saveAll(cache)\n }\n }\n}\n","import type { ClassValue } from \"clsx\"\n\nimport { clsx } from \"clsx\"\nimport { twMerge } from \"tailwind-merge\"\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs))\n}\n"],"mappings":"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","names":["jsx","motion","jsx","motion","createContext","useContext","useMemo","jsx","motion","jsx","jsx","motion","useCallback","useEffect","useState","jsx","useState","useEffect","useCallback","MessageCircle","useCallback","useEffect","useMemo","useRef","useState","useCallback","useEffect","useRef","useState","useEffect","useState","jsx","jsxs","jsx","jsxs","jsx","jsxs","useState","useRef","useCallback","useEffect","X","jsx","jsxs","useCallback","useEffect","useMemo","useRef","useState","useRef","useState","useEffect","useCallback","useMemo","jsx","jsxs","useState","useEffect","useMemo","useCallback","useRef","MessageCircle"]}
1
+ {"version":3,"sources":["../src/core/animation-config.ts","../src/core/animation-context.tsx","../src/core/animated.tsx","../src/core/transitions.ts","../src/core/morph.tsx","../src/core/use-slide-navigation.ts","../src/core/theme-context.tsx","../src/core/slide-renderer.tsx","../src/core/slide-error-boundary.tsx","../src/core/slide-embed.tsx","../src/core/slide-deck.tsx","../src/core/annotations/annotation-overlay.tsx","../src/core/annotations/annotation-form.tsx","../src/core/annotations/annotation-pin.tsx","../src/core/annotations/selectors.ts","../src/core/annotations/annotation-panel.tsx","../src/core/annotations/use-annotations.ts","../src/core/annotations/adapters/http.ts","../src/core/utils.ts"],"sourcesContent":["/**\n * Centralized animation configuration for the slide deck framework.\n * All animation timings, easings, and spring configs are defined here.\n */\n\n// =============================================================================\n// TIMING CONSTANTS\n// =============================================================================\n\n/** Duration for slide-to-slide transitions (seconds) */\nexport const SLIDE_TRANSITION_DURATION = 0.3\n\n/** Duration for morph/layout animations between slides (seconds) */\nexport const MORPH_DURATION = 0.8\n\n/** Duration for within-slide step animations (seconds) */\nexport const STEP_ANIMATION_DURATION = 0.4\n\n/** Default stagger delay for grouped animations (seconds) */\nexport const STAGGER_DELAY = 0.1\n\n// =============================================================================\n// EASING PRESETS\n// =============================================================================\n\nexport const EASE_DEFAULT = \"easeInOut\" as const\nexport const EASE_OUT = \"easeOut\" as const\nexport const EASE_IN = \"easeIn\" as const\n\n/** Smooth ease-in-out curve for morph animations (cubic bezier) */\nexport const EASE_MORPH = [0.4, 0, 0.2, 1] as const\n\n// =============================================================================\n// SPRING CONFIGURATIONS\n// =============================================================================\n\n/** Spring config for snappy, responsive animations */\nexport const SPRING_SNAPPY = {\n type: \"spring\" as const,\n stiffness: 300,\n damping: 30\n}\n\n/** Spring config for smooth, gentle animations */\nexport const SPRING_SMOOTH = {\n type: \"spring\" as const,\n stiffness: 200,\n damping: 25\n}\n\n/** Spring config for bouncy animations */\nexport const SPRING_BOUNCY = {\n type: \"spring\" as const,\n stiffness: 400,\n damping: 20\n}\n\n// =============================================================================\n// TRANSITION PRESETS\n// =============================================================================\n\n/** Standard transition for slide transitions */\nexport const SLIDE_TRANSITION = {\n duration: SLIDE_TRANSITION_DURATION,\n ease: EASE_DEFAULT\n} as const\n\n/** Standard transition for morph animations (smooth ease-in-out) */\nexport const MORPH_TRANSITION = {\n duration: MORPH_DURATION,\n ease: EASE_MORPH\n}\n\n/** Standard transition for step animations (spring-based, duration computed from stiffness/damping) */\nexport const STEP_TRANSITION = {\n ...SPRING_SNAPPY\n}\n\n// =============================================================================\n// DISTANCE CONSTANTS (pixels)\n// =============================================================================\n\n/** Distance for slide animations */\nexport const SLIDE_DISTANCE = 100\n\n/** Distance for within-slide element animations */\nexport const ELEMENT_SLIDE_DISTANCE = 30\n\n// =============================================================================\n// SLIDE DIMENSIONS\n// =============================================================================\n\n/** Standard slide dimensions (16:9 aspect ratio) */\nexport const SLIDE_DIMENSIONS = {\n width: 1280,\n height: 720,\n aspectRatio: 16 / 9\n} as const\n","import { createContext, useContext, useMemo } from \"react\"\n\ninterface AnimationContextValue {\n /** Current animation step (0 = no animations shown yet) */\n currentStep: number\n /** Total animation steps in this slide (declared in slide config) */\n totalSteps: number\n /** When true, all animation steps should be visible (used for backward navigation) */\n showAllAnimations: boolean\n}\n\nconst AnimationContext = createContext<AnimationContextValue>({\n currentStep: 0,\n totalSteps: 0,\n showAllAnimations: false\n})\n\ninterface AnimationProviderProps {\n children: React.ReactNode\n /** Current animation step (0 = no animations shown yet) */\n currentStep: number\n /** Total animation steps declared in slide config */\n totalSteps: number\n /** When true, show all animations regardless of currentStep (for backward navigation) */\n showAllAnimations?: boolean\n}\n\n/**\n * Provides animation context to child components.\n *\n * The totalSteps is now passed from parent (declared in slide config)\n * rather than discovered at runtime, eliminating race conditions.\n */\nexport function AnimationProvider({\n children,\n currentStep,\n totalSteps,\n showAllAnimations = false\n}: AnimationProviderProps) {\n const value = useMemo(\n () => ({\n currentStep,\n totalSteps,\n showAllAnimations\n }),\n [currentStep, totalSteps, showAllAnimations]\n )\n\n return <AnimationContext.Provider value={value}>{children}</AnimationContext.Provider>\n}\n\nexport function useAnimationContext() {\n return useContext(AnimationContext)\n}\n","import { motion, Variants } from \"framer-motion\"\n\nimport {\n ELEMENT_SLIDE_DISTANCE,\n SPRING_SNAPPY,\n STAGGER_DELAY,\n STEP_ANIMATION_DURATION\n} from \"./animation-config\"\nimport { useAnimationContext } from \"./animation-context\"\n\n// =============================================================================\n// ANIMATION TYPES & VARIANTS\n// =============================================================================\n\nexport type AnimationType =\n | \"fade\"\n | \"slide-up\"\n | \"slide-down\"\n | \"slide-left\"\n | \"slide-right\"\n | \"scale\"\n\nconst animationVariants: Record<AnimationType, Variants> = {\n fade: {\n hidden: { opacity: 0 },\n visible: { opacity: 1 }\n },\n \"slide-up\": {\n hidden: { opacity: 0, y: ELEMENT_SLIDE_DISTANCE },\n visible: { opacity: 1, y: 0 }\n },\n \"slide-down\": {\n hidden: { opacity: 0, y: -ELEMENT_SLIDE_DISTANCE },\n visible: { opacity: 1, y: 0 }\n },\n \"slide-left\": {\n hidden: { opacity: 0, x: ELEMENT_SLIDE_DISTANCE },\n visible: { opacity: 1, x: 0 }\n },\n \"slide-right\": {\n hidden: { opacity: 0, x: -ELEMENT_SLIDE_DISTANCE },\n visible: { opacity: 1, x: 0 }\n },\n scale: {\n hidden: { opacity: 0, scale: 0.8 },\n visible: { opacity: 1, scale: 1 }\n }\n}\n\ninterface AnimatedProps {\n /** Which step reveals this content (1-indexed) */\n step: number\n /** Animation type */\n animation?: AnimationType\n /** Animation duration in seconds */\n duration?: number\n /** Delay after trigger in seconds */\n delay?: number\n /** Custom className */\n className?: string\n children: React.ReactNode\n}\n\n/**\n * Animated element that appears at a specific animation step.\n *\n * The step count is now declared in slide config rather than discovered\n * at runtime, so this component simply consumes the context without\n * needing to register itself.\n */\nexport function Animated({\n step,\n animation = \"slide-up\",\n duration = STEP_ANIMATION_DURATION,\n delay = 0,\n className,\n children\n}: AnimatedProps) {\n const { currentStep, showAllAnimations } = useAnimationContext()\n\n // Show all animations when navigating backward, otherwise check step\n const isVisible = showAllAnimations || currentStep >= step\n\n return (\n <motion.div\n initial=\"hidden\"\n animate={isVisible ? \"visible\" : \"hidden\"}\n variants={animationVariants[animation]}\n transition={{\n ...SPRING_SNAPPY,\n duration,\n delay: isVisible ? delay : 0\n }}\n className={className}\n >\n {children}\n </motion.div>\n )\n}\n\n/**\n * Wrapper for staggering multiple children.\n * Each direct child will be animated in sequence.\n */\ninterface AnimatedGroupProps {\n /** Starting step for the first child */\n startStep: number\n /** Animation type for all children */\n animation?: AnimationType\n /** Delay between each child in seconds */\n staggerDelay?: number\n className?: string\n children: React.ReactNode\n}\n\nexport function AnimatedGroup({\n startStep,\n animation = \"slide-up\",\n staggerDelay = STAGGER_DELAY,\n className,\n children\n}: AnimatedGroupProps) {\n const { currentStep, showAllAnimations } = useAnimationContext()\n\n const childArray = Array.isArray(children) ? children : [children]\n\n // Show all animations when navigating backward, otherwise check step\n const isVisible = showAllAnimations || currentStep >= startStep\n\n const containerVariants: Variants = {\n hidden: {},\n visible: {\n transition: {\n staggerChildren: staggerDelay\n }\n }\n }\n\n return (\n <motion.div\n initial=\"hidden\"\n animate={isVisible ? \"visible\" : \"hidden\"}\n variants={containerVariants}\n className={className}\n >\n {childArray.map((child, index) => (\n <motion.div key={index} variants={animationVariants[animation]}>\n {child}\n </motion.div>\n ))}\n </motion.div>\n )\n}\n","/**\n * Slide transition variants for the slide deck framework.\n * These define how slides enter and exit during navigation.\n */\n\nimport type { Variants } from \"framer-motion\"\n\nimport {\n EASE_MORPH,\n MORPH_DURATION,\n SLIDE_DISTANCE,\n SLIDE_TRANSITION,\n SLIDE_TRANSITION_DURATION\n} from \"./animation-config\"\n\n// =============================================================================\n// TYPES\n// =============================================================================\n\nexport type SlideTransitionType =\n | \"fade\"\n | \"slide-left\"\n | \"slide-right\"\n | \"slide-up\"\n | \"slide-down\"\n | \"zoom\"\n | \"zoom-fade\"\n | \"morph\"\n | \"none\"\n\nexport interface SlideTransitionConfig {\n /** The transition type */\n type: SlideTransitionType\n /** Optional custom duration (overrides default) */\n duration?: number\n /** Whether to use directional transitions based on navigation direction */\n directional?: boolean\n}\n\n// =============================================================================\n// STATIC VARIANTS (non-directional)\n// =============================================================================\n\nconst fadeVariants: Variants = {\n enter: { opacity: 0 },\n center: { opacity: 1 },\n exit: { opacity: 0 }\n}\n\nconst slideLeftVariants: Variants = {\n enter: { x: SLIDE_DISTANCE, opacity: 0 },\n center: { x: 0, opacity: 1 },\n exit: { x: -SLIDE_DISTANCE, opacity: 0 }\n}\n\nconst slideRightVariants: Variants = {\n enter: { x: -SLIDE_DISTANCE, opacity: 0 },\n center: { x: 0, opacity: 1 },\n exit: { x: SLIDE_DISTANCE, opacity: 0 }\n}\n\nconst slideUpVariants: Variants = {\n enter: { y: SLIDE_DISTANCE, opacity: 0 },\n center: { y: 0, opacity: 1 },\n exit: { y: -SLIDE_DISTANCE, opacity: 0 }\n}\n\nconst slideDownVariants: Variants = {\n enter: { y: -SLIDE_DISTANCE, opacity: 0 },\n center: { y: 0, opacity: 1 },\n exit: { y: SLIDE_DISTANCE, opacity: 0 }\n}\n\nconst zoomVariants: Variants = {\n enter: { scale: 0.8, opacity: 0 },\n center: { scale: 1, opacity: 1 },\n exit: { scale: 1.2, opacity: 0 }\n}\n\nconst zoomFadeVariants: Variants = {\n enter: { scale: 0.95, opacity: 0 },\n center: { scale: 1, opacity: 1 },\n exit: { scale: 1.05, opacity: 0 }\n}\n\nconst morphVariants: Variants = {\n enter: {\n opacity: 0,\n zIndex: 1\n },\n center: {\n opacity: 1,\n zIndex: 1,\n transition: {\n opacity: { delay: 0.05, duration: 0.25 }\n }\n },\n exit: {\n opacity: 0,\n zIndex: 0,\n transition: {\n opacity: { duration: MORPH_DURATION, ease: EASE_MORPH }\n }\n }\n}\n\nconst noneVariants: Variants = {\n enter: {},\n center: {},\n exit: {}\n}\n\n// =============================================================================\n// VARIANT REGISTRY\n// =============================================================================\n\nexport const SLIDE_VARIANTS: Record<SlideTransitionType, Variants> = {\n fade: fadeVariants,\n \"slide-left\": slideLeftVariants,\n \"slide-right\": slideRightVariants,\n \"slide-up\": slideUpVariants,\n \"slide-down\": slideDownVariants,\n zoom: zoomVariants,\n \"zoom-fade\": zoomFadeVariants,\n morph: morphVariants,\n none: noneVariants\n}\n\n// =============================================================================\n// DIRECTIONAL VARIANTS (based on navigation direction)\n// =============================================================================\n\nexport function createDirectionalVariants(axis: \"x\" | \"y\" = \"x\"): (direction: number) => Variants {\n return (direction: number) => ({\n enter: {\n [axis]: direction > 0 ? SLIDE_DISTANCE : -SLIDE_DISTANCE,\n opacity: 0\n },\n center: {\n [axis]: 0,\n opacity: 1\n },\n exit: {\n [axis]: direction < 0 ? SLIDE_DISTANCE : -SLIDE_DISTANCE,\n opacity: 0\n }\n })\n}\n\n/** Horizontal directional slide (left/right based on direction) */\nexport const directionalSlideX = createDirectionalVariants(\"x\")\n\n/** Vertical directional slide (up/down based on direction) */\nexport const directionalSlideY = createDirectionalVariants(\"y\")\n\n// =============================================================================\n// HELPER FUNCTIONS\n// =============================================================================\n\nexport function getSlideVariants(\n config: SlideTransitionConfig | SlideTransitionType,\n direction: number = 1\n): Variants {\n const type = typeof config === \"string\" ? config : config.type\n const directional = typeof config === \"object\" ? config.directional : false\n\n if (directional && (type === \"slide-left\" || type === \"slide-right\")) {\n return directionalSlideX(direction)\n }\n\n if (directional && (type === \"slide-up\" || type === \"slide-down\")) {\n return directionalSlideY(direction)\n }\n\n return SLIDE_VARIANTS[type]\n}\n\nexport function getSlideTransition(config?: SlideTransitionConfig | SlideTransitionType): {\n duration: number\n ease: typeof SLIDE_TRANSITION.ease\n} {\n if (!config) return SLIDE_TRANSITION\n\n const type = typeof config === \"string\" ? config : config.type\n\n const defaultDuration = type === \"morph\" ? MORPH_DURATION : SLIDE_TRANSITION_DURATION\n\n const duration = typeof config === \"object\" && config.duration ? config.duration : defaultDuration\n\n return {\n ...SLIDE_TRANSITION,\n duration\n }\n}\n\n// =============================================================================\n// DEFAULT EXPORT\n// =============================================================================\n\nexport const DEFAULT_SLIDE_TRANSITION: SlideTransitionType = \"fade\"\n","import type { Transition } from \"framer-motion\"\n\nimport { motion } from \"framer-motion\"\n\nimport { MORPH_TRANSITION } from \"./animation-config\"\n\n// =============================================================================\n// TYPES\n// =============================================================================\n\ninterface MorphProps {\n layoutId: string\n transition?: Transition\n className?: string\n children: React.ReactNode\n}\n\ninterface MorphGroupProps {\n groupId: string\n transition?: Transition\n className?: string\n children: React.ReactNode\n}\n\n// =============================================================================\n// MORPH COMPONENT\n// =============================================================================\n\n/**\n * Wrapper component that enables morph/shared-layout animations between slides.\n *\n * Usage:\n * ```tsx\n * // Slide 1 - Large version\n * <Morph layoutId=\"hero-title\">\n * <h1 className=\"text-6xl\">Title</h1>\n * </Morph>\n *\n * // Slide 2 - Small version (same layoutId = morphs between them)\n * <Morph layoutId=\"hero-title\">\n * <h1 className=\"text-2xl\">Title</h1>\n * </Morph>\n * ```\n */\nexport function Morph({\n layoutId,\n transition = MORPH_TRANSITION,\n className,\n children\n}: MorphProps) {\n return (\n <motion.div\n layout\n layoutId={layoutId}\n initial={false}\n transition={transition}\n className={className}\n >\n {children}\n </motion.div>\n )\n}\n\n// =============================================================================\n// MORPH GROUP COMPONENT\n// =============================================================================\n\nexport function MorphGroup({\n groupId,\n transition = MORPH_TRANSITION,\n className,\n children\n}: MorphGroupProps) {\n return (\n <motion.div\n layout\n layoutId={groupId}\n initial={false}\n transition={transition}\n className={className}\n >\n {children}\n </motion.div>\n )\n}\n\n// =============================================================================\n// MORPH ITEM (for use within MorphGroup pattern)\n// =============================================================================\n\ninterface MorphItemProps {\n id: string\n prefix?: string\n transition?: Transition\n className?: string\n children: React.ReactNode\n}\n\nexport function MorphItem({\n id,\n prefix,\n transition = MORPH_TRANSITION,\n className,\n children\n}: MorphItemProps) {\n const layoutId = prefix ? `${prefix}-${id}` : id\n\n return (\n <motion.div\n layout\n layoutId={layoutId}\n initial={false}\n transition={transition}\n className={className}\n >\n {children}\n </motion.div>\n )\n}\n\n// =============================================================================\n// MORPH TEXT (specialized for text that changes size)\n// =============================================================================\n\ninterface MorphTextProps {\n layoutId: string\n as?: \"h1\" | \"h2\" | \"h3\" | \"h4\" | \"p\" | \"span\"\n transition?: Transition\n className?: string\n children: React.ReactNode\n}\n\nexport function MorphText({\n layoutId,\n as: Component = \"span\",\n transition = MORPH_TRANSITION,\n className,\n children\n}: MorphTextProps) {\n const MotionComponent = motion[Component]\n\n return (\n <MotionComponent\n layout\n layoutId={layoutId}\n initial={false}\n transition={transition}\n className={className}\n >\n {children}\n </MotionComponent>\n )\n}\n","import { useCallback, useEffect, useState } from \"react\"\n\nimport type { NavigationDirection, SlideConfig } from \"./types\"\n\n// =============================================================================\n// TYPES\n// =============================================================================\n\ntype NavigationStatus = \"idle\" | \"transitioning\"\n\ntype QueuedAction = \"advance\" | \"goBack\" | null\n\ninterface NavigationState {\n status: NavigationStatus\n direction: NavigationDirection\n}\n\nexport interface UseSlideNavigationOptions {\n slides: SlideConfig[]\n initialSlide?: number\n onSlideChange?: (slideIndex: number) => void\n}\n\nexport interface UseSlideNavigationReturn {\n currentSlide: number\n animationStep: number\n totalSteps: number\n direction: NavigationDirection\n isTransitioning: boolean\n showAllAnimations: boolean\n advance: () => void\n goBack: () => void\n goToSlide: (index: number) => void\n onTransitionComplete: () => void\n}\n\n// =============================================================================\n// HOOK\n// =============================================================================\n\nexport function useSlideNavigation({\n slides,\n initialSlide = 0,\n onSlideChange\n}: UseSlideNavigationOptions): UseSlideNavigationReturn {\n const [currentSlide, setCurrentSlide] = useState(initialSlide)\n const [animationStep, setAnimationStep] = useState(0)\n\n const [navState, setNavState] = useState<NavigationState>({\n status: \"idle\",\n direction: 0\n })\n\n const [queuedAction, setQueuedAction] = useState<QueuedAction>(null)\n\n const totalSteps = slides[currentSlide]?.steps ?? 0\n\n const onTransitionComplete = useCallback(() => {\n setNavState(prev => {\n if (prev.status === \"transitioning\") {\n return { status: \"idle\", direction: 0 }\n }\n return prev\n })\n }, [])\n\n const advance = useCallback(() => {\n if (navState.status === \"transitioning\") {\n setQueuedAction(\"advance\")\n return\n }\n\n const currentTotalSteps = slides[currentSlide]?.steps ?? 0\n\n if (animationStep >= currentTotalSteps) {\n const nextSlide = (currentSlide + 1) % slides.length\n setNavState({ status: \"transitioning\", direction: 1 })\n setAnimationStep(0)\n setCurrentSlide(nextSlide)\n onSlideChange?.(nextSlide)\n } else {\n setAnimationStep(prev => prev + 1)\n }\n }, [navState.status, animationStep, currentSlide, slides, onSlideChange])\n\n const goBack = useCallback(() => {\n if (navState.status === \"transitioning\") {\n setQueuedAction(\"goBack\")\n return\n }\n\n if (animationStep <= 0) {\n const prevSlide = (currentSlide - 1 + slides.length) % slides.length\n const prevSlideSteps = slides[prevSlide]?.steps ?? 0\n setNavState({ status: \"transitioning\", direction: -1 })\n setAnimationStep(prevSlideSteps)\n setCurrentSlide(prevSlide)\n onSlideChange?.(prevSlide)\n } else {\n setAnimationStep(prev => prev - 1)\n }\n }, [navState.status, animationStep, currentSlide, slides, onSlideChange])\n\n const goToSlide = useCallback(\n (index: number) => {\n if (index < 0 || index >= slides.length || index === currentSlide) {\n return\n }\n\n const direction = index > currentSlide ? 1 : -1\n setNavState({ status: \"transitioning\", direction })\n setAnimationStep(0)\n setCurrentSlide(index)\n onSlideChange?.(index)\n },\n [currentSlide, slides.length, onSlideChange]\n )\n\n useEffect(() => {\n if (navState.status === \"idle\" && queuedAction !== null) {\n setQueuedAction(null)\n if (queuedAction === \"advance\") {\n advance()\n } else if (queuedAction === \"goBack\") {\n goBack()\n }\n }\n }, [navState.status, queuedAction, advance, goBack])\n\n return {\n currentSlide,\n animationStep,\n totalSteps,\n direction: navState.direction,\n isTransitioning: navState.status !== \"idle\",\n showAllAnimations: navState.direction === -1 && navState.status === \"transitioning\",\n advance,\n goBack,\n goToSlide,\n onTransitionComplete\n }\n}\n","import { createContext, useContext, useMemo } from \"react\"\nimport type { ThemeConfig } from \"./types\"\n\nconst ThemeContext = createContext<ThemeConfig | null>(null)\n\n/**\n * Access the full theme config. Returns null outside SlideThemeProvider.\n */\nexport function useTheme(): ThemeConfig | null {\n return useContext(ThemeContext)\n}\n\nfunction buildCssOverrides(theme: ThemeConfig): React.CSSProperties {\n const style: Record<string, string> = {}\n\n if (theme.colors?.primary) style[\"--primary\"] = theme.colors.primary\n if (theme.colors?.primaryForeground) style[\"--primary-foreground\"] = theme.colors.primaryForeground\n if (theme.colors?.secondary) style[\"--secondary\"] = theme.colors.secondary\n if (theme.colors?.secondaryForeground) style[\"--secondary-foreground\"] = theme.colors.secondaryForeground\n if (theme.colors?.accent) style[\"--accent\"] = theme.colors.accent\n if (theme.colors?.accentForeground) style[\"--accent-foreground\"] = theme.colors.accentForeground\n\n if (theme.fonts?.heading) style[\"--font-heading\"] = theme.fonts.heading\n if (theme.fonts?.body) style[\"--font-body\"] = theme.fonts.body\n\n return style as React.CSSProperties\n}\n\ninterface SlideThemeProviderProps {\n theme: ThemeConfig\n children: React.ReactNode\n}\n\n/**\n * Provides the full theme to all descendants.\n * Injects CSS variable overrides via inline style.\n */\nexport function SlideThemeProvider({ theme, children }: SlideThemeProviderProps) {\n const cssOverrides = useMemo(() => buildCssOverrides(theme), [theme])\n\n return (\n <ThemeContext.Provider value={theme}>\n <div style={cssOverrides} className=\"contents\">\n {children}\n </div>\n </ThemeContext.Provider>\n )\n}\n","import { AnimatePresence, motion } from \"framer-motion\"\n\nimport type { SlideTransitionType } from \"./transitions\"\nimport type { NavigationDirection, SlideConfig } from \"./types\"\n\nimport { SLIDE_TRANSITION } from \"./animation-config\"\nimport { AnimationProvider } from \"./animation-context\"\nimport { SlideErrorBoundary } from \"./slide-error-boundary\"\nimport { DEFAULT_SLIDE_TRANSITION, getSlideVariants } from \"./transitions\"\n\n// =============================================================================\n// TYPES\n// =============================================================================\n\nexport interface SlideRendererProps {\n slides: SlideConfig[]\n currentSlide: number\n animationStep: number\n totalSteps: number\n direction: NavigationDirection\n showAllAnimations: boolean\n transition?: SlideTransitionType\n directionalTransition?: boolean\n onTransitionComplete: () => void\n}\n\n// =============================================================================\n// COMPONENT\n// =============================================================================\n\n/**\n * Renders a single slide with animated transitions.\n * Extracted from SlideDeck so it can be reused in SlideEmbed and other contexts.\n */\nexport function SlideRenderer({\n slides,\n currentSlide,\n animationStep,\n totalSteps,\n direction,\n showAllAnimations,\n transition,\n directionalTransition,\n onTransitionComplete\n}: SlideRendererProps) {\n const currentSlideTransition = slides[currentSlide]?.transition\n const transitionType = currentSlideTransition ?? transition ?? DEFAULT_SLIDE_TRANSITION\n const isDirectional = directionalTransition ?? false\n\n const slideVariants = getSlideVariants(\n { type: transitionType, directional: isDirectional },\n direction\n )\n\n const CurrentSlideComponent = slides[currentSlide]!.component\n\n return (\n <AnimatePresence initial={false}>\n <motion.div\n key={currentSlide}\n variants={slideVariants}\n initial=\"enter\"\n animate=\"center\"\n exit=\"exit\"\n transition={SLIDE_TRANSITION}\n onAnimationComplete={definition => {\n if (definition === \"center\") {\n onTransitionComplete()\n }\n }}\n className=\"absolute inset-0 h-full w-full\"\n >\n <AnimationProvider\n currentStep={animationStep}\n totalSteps={totalSteps}\n showAllAnimations={showAllAnimations}\n >\n <SlideErrorBoundary\n slideIndex={currentSlide}\n slideTitle={slides[currentSlide]?.title}\n >\n <CurrentSlideComponent\n slideNumber={currentSlide + 1}\n totalSlides={slides.length}\n />\n </SlideErrorBoundary>\n </AnimationProvider>\n </motion.div>\n </AnimatePresence>\n )\n}\n","import React from \"react\"\n\ninterface SlideErrorBoundaryProps {\n slideIndex: number\n slideTitle?: string\n children: React.ReactNode\n}\n\ninterface SlideErrorBoundaryState {\n hasError: boolean\n error: Error | null\n}\n\nexport class SlideErrorBoundary extends React.Component<\n SlideErrorBoundaryProps,\n SlideErrorBoundaryState\n> {\n state: SlideErrorBoundaryState = { hasError: false, error: null }\n\n static getDerivedStateFromError(error: Error) {\n return { hasError: true, error }\n }\n\n componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {\n console.error(\n `[PromptSlide] Slide ${this.props.slideIndex + 1}${this.props.slideTitle ? ` (\"${this.props.slideTitle}\")` : \"\"} crashed:`,\n error,\n errorInfo\n )\n }\n\n render() {\n if (this.state.hasError) {\n return (\n <div className=\"flex h-full w-full flex-col items-center justify-center bg-red-950/20 p-12\">\n <div className=\"mb-4 text-lg font-semibold text-red-400\">\n Slide {this.props.slideIndex + 1} Error\n {this.props.slideTitle && (\n <span className=\"ml-2 font-normal text-red-400/70\">({this.props.slideTitle})</span>\n )}\n </div>\n <div className=\"max-w-2xl text-center font-mono text-sm break-words text-red-300/80\">\n {this.state.error?.message ?? \"Unknown error\"}\n </div>\n </div>\n )\n }\n return this.props.children\n }\n}\n","import { useCallback, useEffect, useState } from \"react\"\n\nimport type { SlideTransitionType } from \"./transitions\"\nimport type { SlideConfig } from \"./types\"\n\nimport { SLIDE_DIMENSIONS } from \"./animation-config\"\nimport { SlideRenderer } from \"./slide-renderer\"\nimport { useSlideNavigation } from \"./use-slide-navigation\"\n\n// =============================================================================\n// TYPES\n// =============================================================================\n\ninterface SlideEmbedProps {\n slides: SlideConfig[]\n transition?: SlideTransitionType\n directionalTransition?: boolean\n}\n\n// =============================================================================\n// COMPONENT\n// =============================================================================\n\n/**\n * Headless slide viewer controlled via window.postMessage.\n * Designed for embedding in an iframe (e.g. the registry editor preview).\n *\n * Inbound messages (parent → embed):\n * { type: \"navigate\", data: { slide: number } }\n * { type: \"advance\" }\n * { type: \"goBack\" }\n *\n * Outbound messages (embed → parent):\n * { type: \"slideReady\" }\n * { type: \"slideState\", data: { currentSlide, totalSlides, animationStep, totalSteps, titles } }\n * { type: \"hmrUpdate\" }\n */\nexport function SlideEmbed({ slides, transition, directionalTransition }: SlideEmbedProps) {\n const [scale, setScale] = useState(1)\n\n const {\n currentSlide,\n animationStep,\n totalSteps,\n direction,\n showAllAnimations,\n advance,\n goBack,\n goToSlide,\n onTransitionComplete\n } = useSlideNavigation({ slides })\n\n // Post slide state to parent whenever it changes\n useEffect(() => {\n const state = {\n currentSlide,\n totalSlides: slides.length,\n animationStep,\n totalSteps,\n titles: slides.map(s => s.title || \"\")\n }\n window.parent.postMessage({ type: \"slideState\", data: state }, \"*\")\n }, [currentSlide, animationStep, totalSteps, slides])\n\n // Signal readiness on mount\n useEffect(() => {\n window.parent.postMessage({ type: \"slideReady\" }, \"*\")\n }, [])\n\n // Listen for Vite HMR updates\n useEffect(() => {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const hot = (import.meta as any).hot as { on: (event: string, cb: () => void) => void } | undefined\n if (hot) {\n hot.on(\"vite:afterUpdate\", () => {\n window.parent.postMessage({ type: \"hmrUpdate\" }, \"*\")\n })\n }\n }, [])\n\n // Listen for inbound messages from parent\n const handleMessage = useCallback(\n (event: MessageEvent) => {\n const { type, data } = event.data || {}\n switch (type) {\n case \"navigate\":\n if (typeof data?.slide === \"number\") goToSlide(data.slide)\n break\n case \"advance\":\n advance()\n break\n case \"goBack\":\n goBack()\n break\n }\n },\n [advance, goBack, goToSlide]\n )\n\n useEffect(() => {\n window.addEventListener(\"message\", handleMessage)\n return () => window.removeEventListener(\"message\", handleMessage)\n }, [handleMessage])\n\n // Scale to cover viewport (fills completely, may crop overflow)\n useEffect(() => {\n const calculateScale = () => {\n const scaleX = window.innerWidth / SLIDE_DIMENSIONS.width\n const scaleY = window.innerHeight / SLIDE_DIMENSIONS.height\n setScale(Math.max(scaleX, scaleY))\n }\n\n calculateScale()\n window.addEventListener(\"resize\", calculateScale)\n return () => window.removeEventListener(\"resize\", calculateScale)\n }, [])\n\n return (\n <div className=\"flex h-screen w-screen items-center justify-center overflow-hidden bg-black\">\n <div\n className=\"relative overflow-hidden bg-black\"\n style={{\n width: SLIDE_DIMENSIONS.width,\n height: SLIDE_DIMENSIONS.height,\n transform: `scale(${scale})`,\n transformOrigin: \"center center\"\n }}\n >\n <SlideRenderer\n slides={slides}\n currentSlide={currentSlide}\n animationStep={animationStep}\n totalSteps={totalSteps}\n direction={direction}\n showAllAnimations={showAllAnimations}\n transition={transition}\n directionalTransition={directionalTransition}\n onTransitionComplete={onTransitionComplete}\n />\n </div>\n </div>\n )\n}\n","import { LayoutGroup } from \"framer-motion\"\nimport { ChevronLeft, ChevronRight, Download, Grid3X3, List, Maximize, MessageCircle, Monitor } from \"lucide-react\"\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\"\n\nimport type { SlideTransitionType } from \"./transitions\"\nimport type { SlideConfig } from \"./types\"\n\nimport { SLIDE_DIMENSIONS } from \"./animation-config\"\nimport { AnimationProvider } from \"./animation-context\"\nimport { AnnotationOverlay, AnnotationPanel, useAnnotations } from \"./annotations\"\nimport type { Annotation, AnnotationTarget } from \"./annotations\"\nimport { SlideErrorBoundary } from \"./slide-error-boundary\"\nimport { SlideRenderer } from \"./slide-renderer\"\nimport { useSlideNavigation } from \"./use-slide-navigation\"\nimport { cn } from \"./utils\"\n\n// =============================================================================\n// TYPES\n// =============================================================================\n\ntype ViewMode = \"slide\" | \"list\" | \"grid\"\n\ninterface SlideDeckProps {\n slides: SlideConfig[]\n transition?: SlideTransitionType\n directionalTransition?: boolean\n /** Annotation data to display. When provided (even empty array), annotation UI is enabled. When undefined, annotation UI is hidden. */\n annotations?: Annotation[]\n /** Called when the user creates an annotation */\n onAnnotationAdd?: (slideIndex: number, slideTitle: string, target: AnnotationTarget, body: string) => void\n /** Called when the user deletes an annotation */\n onAnnotationDelete?: (id: string) => void\n}\n\n// =============================================================================\n// EXPORT VIEW (for Playwright screenshot capture)\n// =============================================================================\n\nfunction SlideExportView({ slides, slideIndex }: { slides: SlideConfig[]; slideIndex: number }) {\n const [ready, setReady] = useState(false)\n const clampedIndex = Math.max(0, Math.min(slideIndex, slides.length - 1))\n const slideConfig = slides[clampedIndex]!\n const SlideComponent = slideConfig.component\n\n useEffect(() => {\n setReady(true)\n }, [])\n\n return (\n <div\n data-export-ready={ready ? \"true\" : undefined}\n style={{\n width: SLIDE_DIMENSIONS.width,\n height: SLIDE_DIMENSIONS.height,\n overflow: \"hidden\",\n position: \"relative\",\n background: \"black\"\n }}\n >\n <AnimationProvider\n currentStep={slideConfig.steps}\n totalSteps={slideConfig.steps}\n showAllAnimations={true}\n >\n <SlideErrorBoundary slideIndex={clampedIndex} slideTitle={slideConfig.title}>\n <SlideComponent slideNumber={clampedIndex + 1} totalSlides={slides.length} />\n </SlideErrorBoundary>\n </AnimationProvider>\n </div>\n )\n}\n\n// =============================================================================\n// COMPONENT\n// =============================================================================\n\nexport function SlideDeck({ slides, transition, directionalTransition, annotations, onAnnotationAdd, onAnnotationDelete }: SlideDeckProps) {\n // Check for export mode via URL params\n const [exportParams] = useState(() => {\n if (typeof window === \"undefined\") return null\n const params = new URLSearchParams(window.location.search)\n if (params.get(\"export\") !== \"true\") return null\n return { slideIndex: parseInt(params.get(\"slide\") || \"0\", 10) }\n })\n\n if (exportParams) {\n return <SlideExportView slides={slides} slideIndex={exportParams.slideIndex} />\n }\n\n // Use internal useAnnotations as fallback when no external annotations prop is provided\n const internal = useAnnotations()\n const isExternallyManaged = annotations !== undefined\n const effectiveAnnotations = isExternallyManaged ? annotations : internal.annotations\n const effectiveAdd = isExternallyManaged ? onAnnotationAdd : internal.addAnnotation\n const effectiveDelete = isExternallyManaged ? onAnnotationDelete : internal.deleteAnnotation\n\n const openCount = useMemo(() => effectiveAnnotations.filter(a => a.status === \"open\").length, [effectiveAnnotations])\n const getSlideAnnotations = useCallback(\n (slideIndex: number) => effectiveAnnotations.filter(a => a.slideIndex === slideIndex),\n [effectiveAnnotations]\n )\n\n const [viewMode, setViewMode] = useState<ViewMode>(\"slide\")\n const [isPresentationMode, setIsPresentationMode] = useState(false)\n const [isAnnotationMode, setIsAnnotationMode] = useState(false)\n const [showAnnotationPanel, setShowAnnotationPanel] = useState(false)\n const [selectedAnnotationId, setSelectedAnnotationId] = useState<string | null>(null)\n const [scale, setScale] = useState(1)\n const containerRef = useRef<HTMLDivElement>(null)\n const slideContainerRef = useRef<HTMLDivElement>(null)\n\n const {\n currentSlide,\n animationStep,\n totalSteps,\n direction,\n showAllAnimations,\n advance,\n goBack,\n goToSlide,\n onTransitionComplete\n } = useSlideNavigation({\n slides\n })\n\n const togglePresentationMode = useCallback(async () => {\n if (!document.fullscreenElement) {\n await document.documentElement.requestFullscreen()\n } else {\n await document.exitFullscreen()\n }\n }, [])\n\n // Listen for fullscreen changes\n useEffect(() => {\n const handleFullscreenChange = () => {\n setIsPresentationMode(!!document.fullscreenElement)\n }\n document.addEventListener(\"fullscreenchange\", handleFullscreenChange)\n return () => document.removeEventListener(\"fullscreenchange\", handleFullscreenChange)\n }, [])\n\n // Calculate scale factor for presentation mode\n useEffect(() => {\n const calculateScale = () => {\n if (!isPresentationMode) {\n setScale(1)\n return\n }\n const viewportWidth = window.innerWidth\n const viewportHeight = window.innerHeight\n const scaleX = viewportWidth / SLIDE_DIMENSIONS.width\n const scaleY = viewportHeight / SLIDE_DIMENSIONS.height\n setScale(Math.min(scaleX, scaleY))\n }\n\n calculateScale()\n window.addEventListener(\"resize\", calculateScale)\n return () => window.removeEventListener(\"resize\", calculateScale)\n }, [isPresentationMode])\n\n const handleExportPdf = () => {\n const previousMode = viewMode\n setViewMode(\"list\")\n\n setTimeout(() => {\n const handleAfterPrint = () => {\n setViewMode(previousMode)\n window.removeEventListener(\"afterprint\", handleAfterPrint)\n }\n window.addEventListener(\"afterprint\", handleAfterPrint)\n window.print()\n }, 100)\n }\n\n // Keyboard navigation\n useEffect(() => {\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.key === \"f\" || e.key === \"F\") {\n togglePresentationMode()\n return\n }\n\n // G for grid view toggle\n if (e.key === \"g\" || e.key === \"G\") {\n setViewMode(prev => (prev === \"grid\" ? \"slide\" : \"grid\"))\n return\n }\n\n if (viewMode !== \"slide\" || isAnnotationMode) return\n\n if (e.key === \"ArrowRight\" || e.key === \" \") {\n e.preventDefault()\n advance()\n } else if (e.key === \"ArrowLeft\") {\n e.preventDefault()\n goBack()\n }\n }\n\n window.addEventListener(\"keydown\", handleKeyDown)\n return () => window.removeEventListener(\"keydown\", handleKeyDown)\n }, [advance, goBack, viewMode, togglePresentationMode, isAnnotationMode])\n\n return (\n <div className=\"min-h-screen w-full bg-neutral-950 text-foreground\">\n <style>{`\n @media print {\n @page {\n size: 1920px 1080px;\n margin: 0;\n }\n html,\n body {\n width: 100%;\n height: 100%;\n margin: 0 !important;\n padding: 0 !important;\n overflow: visible !important;\n }\n body {\n print-color-adjust: exact;\n -webkit-print-color-adjust: exact;\n background: transparent !important;\n }\n }\n `}</style>\n\n {/* Toolbar */}\n <div\n className={cn(\n \"fixed top-4 z-50 flex gap-1 rounded-lg border border-neutral-800 bg-neutral-950/90 p-1 backdrop-blur-sm transition-[right] print:hidden\",\n isPresentationMode && \"hidden\",\n isAnnotationMode && showAnnotationPanel ? \"right-[19.5rem]\" : \"right-4\"\n )}\n >\n <button\n onClick={() => setViewMode(\"slide\")}\n className={cn(\n \"rounded-md p-2 text-neutral-400 transition-colors hover:bg-neutral-800 hover:text-white\",\n viewMode === \"slide\" && \"bg-neutral-800 text-white\"\n )}\n title=\"Presentation View\"\n >\n <Monitor className=\"h-4 w-4\" />\n </button>\n <button\n onClick={() => setViewMode(\"list\")}\n className={cn(\n \"rounded-md p-2 text-neutral-400 transition-colors hover:bg-neutral-800 hover:text-white\",\n viewMode === \"list\" && \"bg-neutral-800 text-white\"\n )}\n title=\"List View\"\n >\n <List className=\"h-4 w-4\" />\n </button>\n <button\n onClick={() => setViewMode(\"grid\")}\n className={cn(\n \"rounded-md p-2 text-neutral-400 transition-colors hover:bg-neutral-800 hover:text-white\",\n viewMode === \"grid\" && \"bg-neutral-800 text-white\"\n )}\n title=\"Grid View\"\n >\n <Grid3X3 className=\"h-4 w-4\" />\n </button>\n\n <div className=\"mx-1 w-px bg-neutral-800\" />\n\n <button\n onClick={() => {\n setIsAnnotationMode(prev => {\n const next = !prev\n setShowAnnotationPanel(next)\n if (!next) setSelectedAnnotationId(null)\n return next\n })\n }}\n className={cn(\n \"relative rounded-md p-2 text-neutral-400 transition-colors hover:bg-neutral-800 hover:text-white\",\n isAnnotationMode && \"bg-[#FF6B35] text-white hover:bg-[#FF7A4A]\"\n )}\n title=\"Annotate slides\"\n >\n <MessageCircle className=\"h-4 w-4\" />\n {openCount > 0 && (\n <span className=\"absolute -top-1 -right-1 flex h-4 w-4 items-center justify-center rounded-full bg-[#FF6B35] text-[10px] font-bold text-white\">\n {openCount}\n </span>\n )}\n </button>\n\n <div className=\"mx-1 w-px bg-neutral-800\" />\n\n <button\n onClick={handleExportPdf}\n className=\"rounded-md p-2 text-neutral-400 transition-colors hover:bg-neutral-800 hover:text-white\"\n title=\"Download PDF\"\n >\n <Download className=\"h-4 w-4\" />\n </button>\n <button\n onClick={togglePresentationMode}\n className=\"rounded-md p-2 text-neutral-400 transition-colors hover:bg-neutral-800 hover:text-white\"\n title=\"Present (F)\"\n >\n <Maximize className=\"h-4 w-4\" />\n </button>\n </div>\n\n {/* Slide View */}\n {viewMode === \"slide\" && (\n <div\n className={cn(\n \"flex h-screen w-full print:hidden\",\n isPresentationMode ? \"bg-black\" : \"\"\n )}\n >\n <div\n ref={containerRef}\n role=\"presentation\"\n tabIndex={isPresentationMode ? 0 : undefined}\n className={cn(\n \"flex flex-1 flex-col items-center justify-center overflow-hidden\",\n isPresentationMode ? \"bg-black p-0\" : \"p-4 md:p-8\"\n )}\n onClick={isPresentationMode ? advance : undefined}\n onKeyDown={\n isPresentationMode\n ? e => {\n if (e.key === \"Enter\" || e.key === \" \") advance()\n }\n : undefined\n }\n >\n <LayoutGroup id=\"slide-deck\">\n {isPresentationMode ? (\n <div\n className=\"pointer-events-none relative overflow-hidden bg-black\"\n style={{\n width: SLIDE_DIMENSIONS.width,\n height: SLIDE_DIMENSIONS.height,\n transform: `scale(${scale})`,\n transformOrigin: \"center center\"\n }}\n >\n <SlideRenderer\n slides={slides}\n currentSlide={currentSlide}\n animationStep={animationStep}\n totalSteps={totalSteps}\n direction={direction}\n showAllAnimations={showAllAnimations}\n transition={transition}\n directionalTransition={directionalTransition}\n onTransitionComplete={onTransitionComplete}\n />\n </div>\n ) : (\n <div ref={slideContainerRef} className=\"relative aspect-video w-full max-w-7xl overflow-hidden rounded-xl border border-neutral-800 bg-black shadow-2xl\">\n <SlideRenderer\n slides={slides}\n currentSlide={currentSlide}\n animationStep={animationStep}\n totalSteps={totalSteps}\n direction={direction}\n showAllAnimations={showAllAnimations}\n transition={transition}\n directionalTransition={directionalTransition}\n onTransitionComplete={onTransitionComplete}\n />\n {isAnnotationMode && (\n <AnnotationOverlay\n slides={slides}\n currentSlide={currentSlide}\n slideContainerRef={slideContainerRef}\n selectedId={selectedAnnotationId}\n onSelectId={setSelectedAnnotationId}\n onShowPanel={() => setShowAnnotationPanel(true)}\n slideAnnotations={getSlideAnnotations(currentSlide)}\n addAnnotation={effectiveAdd ?? (() => {})}\n\n />\n )}\n </div>\n )}\n </LayoutGroup>\n\n {/* Navigation Controls */}\n {!isPresentationMode && (\n <div className=\"mt-6 flex items-center gap-4\">\n <button\n onClick={goBack}\n className=\"rounded-full border border-neutral-800 bg-black/50 p-2 text-neutral-400 backdrop-blur-sm transition-colors hover:bg-neutral-900 hover:text-white\"\n >\n <ChevronLeft className=\"h-5 w-5\" />\n </button>\n <div className=\"flex min-w-[4rem] flex-col items-center\">\n <span className=\"font-mono text-sm text-neutral-500\">\n {currentSlide + 1} / {slides.length}\n </span>\n {slides[currentSlide]?.title && (\n <span className=\"mt-0.5 text-xs text-neutral-600\">\n {slides[currentSlide].title}\n </span>\n )}\n </div>\n <button\n onClick={advance}\n className=\"rounded-full border border-neutral-800 bg-black/50 p-2 text-neutral-400 backdrop-blur-sm transition-colors hover:bg-neutral-900 hover:text-white\"\n >\n <ChevronRight className=\"h-5 w-5\" />\n </button>\n </div>\n )}\n </div>\n\n {/* Annotation Panel — beside the slide */}\n {isAnnotationMode && showAnnotationPanel && !isPresentationMode && (\n <AnnotationPanel\n annotations={getSlideAnnotations(currentSlide)}\n selectedId={selectedAnnotationId}\n onSelect={setSelectedAnnotationId}\n onDelete={effectiveDelete ?? (() => {})}\n onClose={() => {\n setShowAnnotationPanel(false)\n setSelectedAnnotationId(null)\n }}\n />\n )}\n </div>\n )}\n\n {/* Grid View */}\n {viewMode === \"grid\" && (\n <div className=\"mx-auto max-w-7xl p-8 pt-16 print:hidden\">\n <div className=\"grid grid-cols-2 gap-4 md:grid-cols-3 lg:grid-cols-4\">\n {slides.map((slideConfig, index) => {\n const SlideComponent = slideConfig.component\n const prevSection = index > 0 ? slides[index - 1]?.section : undefined\n const showSectionHeader = slideConfig.section && slideConfig.section !== prevSection\n\n return (\n <div key={index} className={showSectionHeader ? \"col-span-full\" : undefined}>\n {showSectionHeader && (\n <h3 className=\"mt-4 mb-3 text-xs font-bold tracking-[0.2em] text-neutral-500 uppercase first:mt-0\">\n {slideConfig.section}\n </h3>\n )}\n <button\n onClick={() => {\n goToSlide(index)\n setViewMode(\"slide\")\n }}\n className=\"group relative aspect-video w-full overflow-hidden rounded-lg border border-neutral-800 bg-black shadow-sm transition-all hover:border-primary hover:shadow-lg hover:shadow-primary/10\"\n >\n <div\n className=\"h-full w-full origin-top-left scale-[0.25]\"\n style={{ width: \"400%\", height: \"400%\" }}\n >\n <AnimationProvider\n currentStep={slideConfig.steps}\n totalSteps={slideConfig.steps}\n showAllAnimations={true}\n >\n <SlideErrorBoundary slideIndex={index} slideTitle={slideConfig.title}>\n <SlideComponent slideNumber={index + 1} totalSlides={slides.length} />\n </SlideErrorBoundary>\n </AnimationProvider>\n </div>\n <div className=\"absolute inset-0 bg-black/0 transition-colors group-hover:bg-black/20\" />\n <div className=\"absolute bottom-2 left-2 rounded bg-black/70 px-2 py-1 text-xs font-medium text-white\">\n {slideConfig.title ? `${index + 1}. ${slideConfig.title}` : index + 1}\n </div>\n </button>\n </div>\n )\n })}\n </div>\n </div>\n )}\n\n {/* List View */}\n <div\n className={cn(\n \"mx-auto max-w-7xl p-8 pt-16\",\n \"print:m-0 print:block print:max-w-none print:p-0\",\n viewMode === \"list\" ? \"block\" : \"hidden print:block\"\n )}\n >\n <div className=\"grid grid-cols-1 gap-8 print:block\">\n {slides.map((slideConfig, index) => {\n const SlideComponent = slideConfig.component\n return (\n <div\n key={index}\n className=\"aspect-video w-full overflow-hidden rounded-xl border border-neutral-800 bg-black shadow-sm print:relative print:m-0 print:h-[1080px] print:w-[1920px] print:break-after-page print:overflow-hidden print:rounded-none print:border-0 print:shadow-none\"\n >\n <div className=\"h-full w-full print:h-[720px] print:w-[1280px] print:origin-top-left print:scale-[1.5]\">\n <AnimationProvider\n currentStep={slideConfig.steps}\n totalSteps={slideConfig.steps}\n showAllAnimations={true}\n >\n <SlideErrorBoundary slideIndex={index} slideTitle={slideConfig.title}>\n <SlideComponent slideNumber={index + 1} totalSlides={slides.length} />\n </SlideErrorBoundary>\n </AnimationProvider>\n </div>\n </div>\n )\n })}\n </div>\n </div>\n </div>\n )\n}\n","import { useCallback, useEffect, useRef, useState } from \"react\"\nimport type { SlideConfig } from \"../types\"\nimport { AnnotationForm } from \"./annotation-form\"\nimport { AnnotationPin } from \"./annotation-pin\"\nimport { buildElementTarget, resolveTarget } from \"./selectors\"\nimport type { Annotation, AnnotationTarget } from \"./types\"\n\ninterface AnnotationOverlayProps {\n slides: SlideConfig[]\n currentSlide: number\n /** Ref to the slide container element (the div wrapping SlideRenderer) */\n slideContainerRef: React.RefObject<HTMLDivElement | null>\n selectedId: string | null\n onSelectId: (id: string | null) => void\n onShowPanel: () => void\n slideAnnotations: Annotation[]\n addAnnotation: (slideIndex: number, slideTitle: string, target: AnnotationTarget, body: string) => void\n}\n\ninterface PendingAnnotation {\n target: AnnotationTarget\n xPercent: number\n yPercent: number\n}\n\nexport function AnnotationOverlay({ slides, currentSlide, slideContainerRef, selectedId, onSelectId, onShowPanel, slideAnnotations, addAnnotation }: AnnotationOverlayProps) {\n const [pending, setPending] = useState<PendingAnnotation | null>(null)\n const [hoveredElement, setHoveredElement] = useState<DOMRect | null>(null)\n const overlayRef = useRef<HTMLDivElement>(null)\n\n const slideTitle = slides[currentSlide]?.title || `Slide ${currentSlide + 1}`\n\n // Resolve annotation positions — use the element if found, otherwise fallback coordinates\n const resolvedAnnotations = slideAnnotations.map((a, i) => {\n const container = slideContainerRef.current\n if (!container) {\n return { annotation: a, xPercent: a.target.position.xPercent, yPercent: a.target.position.yPercent, number: i + 1 }\n }\n\n const { element } = resolveTarget(a.target, container)\n if (element) {\n const rect = element.getBoundingClientRect()\n const containerRect = container.getBoundingClientRect()\n const xPercent = ((rect.left + rect.width / 2 - containerRect.left) / containerRect.width) * 100\n const yPercent = ((rect.top + rect.height / 2 - containerRect.top) / containerRect.height) * 100\n return { annotation: a, xPercent, yPercent, number: i + 1 }\n }\n\n return { annotation: a, xPercent: a.target.position.xPercent, yPercent: a.target.position.yPercent, number: i + 1 }\n })\n\n const handleOverlayClick = useCallback(\n (e: React.MouseEvent) => {\n const container = slideContainerRef.current\n if (!container) return\n\n // Get the element under the click by temporarily hiding the overlay\n const overlay = overlayRef.current\n if (overlay) overlay.style.pointerEvents = \"none\"\n const elementUnder = document.elementFromPoint(e.clientX, e.clientY) as HTMLElement | null\n if (overlay) overlay.style.pointerEvents = \"\"\n\n if (!elementUnder || !container.contains(elementUnder)) {\n setPending(null)\n onSelectId(null)\n return\n }\n\n // Pick the most specific meaningful element (skip tiny text nodes, pick their parent)\n let target = elementUnder\n if (target.tagName === \"SPAN\" && target.parentElement && container.contains(target.parentElement)) {\n // For inline spans, prefer their parent for a more meaningful target\n const parent = target.parentElement\n if (parent.tagName !== \"DIV\" || parent.children.length <= 3) {\n target = parent\n }\n }\n\n const annotationTarget = buildElementTarget(target, container)\n const containerRect = container.getBoundingClientRect()\n const xPercent = ((e.clientX - containerRect.left) / containerRect.width) * 100\n const yPercent = ((e.clientY - containerRect.top) / containerRect.height) * 100\n\n setPending({ target: annotationTarget, xPercent, yPercent })\n onSelectId(null)\n },\n [slideContainerRef, onSelectId]\n )\n\n const handleSubmit = useCallback(\n (text: string) => {\n if (!pending) return\n addAnnotation(currentSlide, slideTitle, pending.target, text)\n setPending(null)\n onShowPanel()\n },\n [pending, currentSlide, slideTitle, addAnnotation, onShowPanel]\n )\n\n // Track hover for element highlighting\n const handleMouseMove = useCallback(\n (e: React.MouseEvent) => {\n if (pending) {\n setHoveredElement(null)\n return\n }\n\n const container = slideContainerRef.current\n if (!container) return\n\n const overlay = overlayRef.current\n if (overlay) overlay.style.pointerEvents = \"none\"\n const elementUnder = document.elementFromPoint(e.clientX, e.clientY) as HTMLElement | null\n if (overlay) overlay.style.pointerEvents = \"\"\n\n if (elementUnder && container.contains(elementUnder) && elementUnder !== container) {\n const containerRect = container.getBoundingClientRect()\n const elRect = elementUnder.getBoundingClientRect()\n setHoveredElement(\n new DOMRect(\n elRect.left - containerRect.left,\n elRect.top - containerRect.top,\n elRect.width,\n elRect.height\n )\n )\n } else {\n setHoveredElement(null)\n }\n },\n [slideContainerRef, pending]\n )\n\n // Clear pending when slide changes\n useEffect(() => {\n setPending(null)\n onSelectId(null)\n setHoveredElement(null)\n }, [currentSlide, onSelectId])\n\n return (\n <>\n {/* Hover highlight */}\n {hoveredElement && (\n <div\n className=\"pointer-events-none absolute z-20 rounded-lg border-2 border-dashed border-[#FF6B35]/50 bg-[#FF6B35]/5\"\n style={{\n left: hoveredElement.x,\n top: hoveredElement.y,\n width: hoveredElement.width,\n height: hoveredElement.height\n }}\n />\n )}\n\n {/* Click capture overlay */}\n <div\n ref={overlayRef}\n role=\"button\"\n tabIndex={0}\n className=\"absolute inset-0 z-20\"\n style={{ cursor: `url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none'%3E%3Ccircle cx='12' cy='12' r='8' stroke='%23FF6B35' stroke-width='2' opacity='0.8'/%3E%3Ccircle cx='12' cy='12' r='2' fill='%23FF6B35'/%3E%3C/svg%3E\") 12 12, crosshair` }}\n onClick={handleOverlayClick}\n onKeyDown={e => { if (e.key === \"Escape\") { setPending(null); onSelectId(null) } }}\n onMouseMove={handleMouseMove}\n onMouseLeave={() => setHoveredElement(null)}\n />\n\n {/* Annotation pins */}\n {resolvedAnnotations.map(({ annotation, xPercent, yPercent, number }) => (\n <AnnotationPin\n key={annotation.id}\n number={number}\n status={annotation.status}\n xPercent={xPercent}\n yPercent={yPercent}\n isSelected={annotation.id === selectedId}\n onClick={() => {\n onSelectId(annotation.id === selectedId ? null : annotation.id)\n onShowPanel()\n setPending(null)\n }}\n />\n ))}\n\n {/* New annotation form */}\n {pending && (\n <AnnotationForm\n xPercent={pending.xPercent}\n yPercent={pending.yPercent}\n onSubmit={handleSubmit}\n onCancel={() => setPending(null)}\n />\n )}\n\n </>\n )\n}\n","import { useEffect, useRef, useState } from \"react\"\nimport { ArrowUp, X } from \"lucide-react\"\n\ninterface AnnotationFormProps {\n xPercent: number\n yPercent: number\n onSubmit: (text: string) => void\n onCancel: () => void\n}\n\nexport function AnnotationForm({ xPercent, yPercent, onSubmit, onCancel }: AnnotationFormProps) {\n const [text, setText] = useState(\"\")\n const textareaRef = useRef<HTMLTextAreaElement>(null)\n\n useEffect(() => {\n textareaRef.current?.focus()\n }, [])\n\n const handleSubmit = () => {\n const trimmed = text.trim()\n if (!trimmed) return\n onSubmit(trimmed)\n }\n\n const handleKeyDown = (e: React.KeyboardEvent) => {\n if (e.key === \"Enter\" && !e.shiftKey) {\n e.preventDefault()\n handleSubmit()\n }\n if (e.key === \"Escape\") {\n onCancel()\n }\n e.stopPropagation()\n }\n\n // Position the form, flipping if near edges\n const left = xPercent > 70 ? undefined : `${xPercent}%`\n const right = xPercent > 70 ? `${100 - xPercent}%` : undefined\n const top = yPercent > 70 ? undefined : `${yPercent}%`\n const bottom = yPercent > 70 ? `${100 - yPercent}%` : undefined\n\n return (\n <div\n role=\"dialog\"\n className=\"absolute z-40 w-72 overflow-hidden rounded-xl border border-white/[0.08] bg-neutral-900/95 shadow-2xl backdrop-blur-2xl\"\n style={{ left, right, top, bottom }}\n onClick={e => e.stopPropagation()}\n onKeyDown={e => e.stopPropagation()}\n >\n <div className=\"flex items-center justify-between border-b border-white/[0.06] px-3.5 py-2.5\">\n <span className=\"text-xs font-medium tracking-wide text-neutral-400\">Add annotation</span>\n <button\n onClick={onCancel}\n className=\"rounded-lg p-1 text-neutral-500 transition-colors hover:bg-white/[0.06] hover:text-neutral-300\"\n >\n <X className=\"h-3.5 w-3.5\" />\n </button>\n </div>\n <div className=\"p-3\">\n <textarea\n ref={textareaRef}\n value={text}\n onChange={e => setText(e.target.value)}\n onKeyDown={handleKeyDown}\n placeholder=\"Describe the change you want...\"\n className=\"w-full resize-none rounded-lg border border-white/[0.08] bg-white/[0.04] px-3 py-2 text-sm text-white placeholder-neutral-500 outline-none transition-colors focus:border-[#FF6B35]/50 focus:bg-white/[0.06]\"\n rows={3}\n />\n <div className=\"mt-2.5 flex items-center justify-between\">\n <span className=\"text-[11px] text-neutral-600\">Enter to send</span>\n <button\n onClick={handleSubmit}\n disabled={!text.trim()}\n className=\"flex h-7 w-7 items-center justify-center rounded-lg bg-[#FF6B35] text-white shadow-lg shadow-[#FF6B35]/20 transition-all hover:bg-[#FF7A4A] hover:shadow-[#FF6B35]/30 disabled:opacity-30 disabled:shadow-none disabled:hover:bg-[#FF6B35]\"\n >\n <ArrowUp className=\"h-3.5 w-3.5\" strokeWidth={2.5} />\n </button>\n </div>\n </div>\n </div>\n )\n}\n","interface AnnotationPinProps {\n number: number\n status: \"open\" | \"resolved\"\n xPercent: number\n yPercent: number\n isSelected: boolean\n onClick: () => void\n}\n\nexport function AnnotationPin({ number, status, xPercent, yPercent, isSelected, onClick }: AnnotationPinProps) {\n const isResolved = status === \"resolved\"\n\n return (\n <button\n onClick={e => {\n e.stopPropagation()\n onClick()\n }}\n className=\"absolute z-30 -translate-x-1/2 -translate-y-1/2 transition-all duration-200 hover:scale-110\"\n style={{ left: `${xPercent}%`, top: `${yPercent}%` }}\n title={`Annotation #${number}`}\n >\n {/* Glow ring */}\n {isSelected && !isResolved && (\n <div className=\"absolute inset-[-4px] animate-pulse rounded-full bg-[#FF6B35]/25 blur-sm\" />\n )}\n <div\n className={`relative flex h-7 w-7 items-center justify-center rounded-full text-[11px] font-semibold shadow-lg backdrop-blur-sm transition-all duration-200 ${\n isSelected\n ? isResolved\n ? \"bg-neutral-500/90 text-white ring-2 ring-neutral-400/50\"\n : \"bg-[#FF6B35] text-white ring-2 ring-[#FF6B35]/40 ring-offset-1 ring-offset-black/50\"\n : isResolved\n ? \"bg-neutral-700/80 text-neutral-400\"\n : \"bg-[#FF6B35]/90 text-white hover:bg-[#FF6B35]\"\n }`}\n >\n {number}\n </div>\n </button>\n )\n}\n","import type { AnnotationTarget } from \"./types\"\n\n/**\n * Build a composite target descriptor from a clicked DOM element.\n */\nexport function buildElementTarget(\n element: HTMLElement,\n slideRoot: HTMLElement\n): AnnotationTarget {\n const rect = element.getBoundingClientRect()\n const rootRect = slideRoot.getBoundingClientRect()\n\n const xPercent = ((rect.left + rect.width / 2 - rootRect.left) / rootRect.width) * 100\n const yPercent = ((rect.top + rect.height / 2 - rootRect.top) / rootRect.height) * 100\n\n return {\n dataAnnotate: element.getAttribute(\"data-annotate\") || undefined,\n contentNearPin: getTextFingerprint(element),\n position: { xPercent, yPercent }\n }\n}\n\n/**\n * Resolve a stored target back to a DOM element, trying strategies in priority order.\n */\nexport function resolveTarget(\n target: AnnotationTarget,\n slideRoot: HTMLElement\n): { element: HTMLElement | null; method: \"dataAnnotate\" | \"contentNearPin\" | \"position\" } {\n // 1. Try data-annotate attribute\n if (target.dataAnnotate) {\n const el = slideRoot.querySelector<HTMLElement>(`[data-annotate=\"${target.dataAnnotate}\"]`)\n if (el) return { element: el, method: \"dataAnnotate\" }\n }\n\n // 2. Try text content match\n if (target.contentNearPin) {\n const match = findByTextContent(slideRoot, target.contentNearPin)\n if (match) return { element: match, method: \"contentNearPin\" }\n }\n\n // 3. Fallback to coordinates (no element found)\n return { element: null, method: \"position\" }\n}\n\n/**\n * Extract a text fingerprint from an element (first 100 chars, trimmed).\n */\nfunction getTextFingerprint(element: HTMLElement): string | undefined {\n const text = element.textContent?.trim()\n if (!text) return undefined\n return text.slice(0, 100)\n}\n\n/**\n * Find an element by matching its text content.\n */\nfunction findByTextContent(root: HTMLElement, text: string): HTMLElement | null {\n const walker = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT)\n let best: HTMLElement | null = null\n let bestLength = Infinity\n\n while (walker.nextNode()) {\n const el = walker.currentNode as HTMLElement\n const elText = el.textContent?.trim()\n if (!elText) continue\n\n const elFingerprint = elText.slice(0, 100)\n if (elFingerprint === text && elText.length < bestLength) {\n best = el\n bestLength = elText.length\n }\n }\n\n return best\n}\n","import { MessageCircle, Trash2, X } from \"lucide-react\"\nimport type { Annotation } from \"./types\"\n\ninterface AnnotationPanelProps {\n annotations: Annotation[]\n selectedId: string | null\n onSelect: (id: string) => void\n onDelete: (id: string) => void\n onClose: () => void\n}\n\nexport function AnnotationPanel({ annotations, selectedId, onSelect, onDelete, onClose }: AnnotationPanelProps) {\n const open = annotations.filter(a => a.status === \"open\")\n const resolved = annotations.filter(a => a.status === \"resolved\")\n\n return (\n <div className=\"flex h-full w-80 flex-shrink-0 flex-col border-l border-white/[0.06] bg-neutral-950/95 backdrop-blur-2xl\">\n <div className=\"flex items-center justify-between px-4 py-3.5\">\n <div className=\"flex items-center gap-2.5\">\n <div className=\"flex h-6 w-6 items-center justify-center rounded-lg bg-[#FF6B35]/15\">\n <MessageCircle className=\"h-3.5 w-3.5 text-[#FF6B35]\" />\n </div>\n <span className=\"text-sm font-medium text-white\">Annotations</span>\n {open.length > 0 && (\n <span className=\"flex h-5 min-w-5 items-center justify-center rounded-full bg-[#FF6B35]/15 px-1.5 text-[11px] font-semibold text-[#FF6B35]\">\n {open.length}\n </span>\n )}\n </div>\n <button\n onClick={onClose}\n className=\"rounded-lg p-1.5 text-neutral-500 transition-colors hover:bg-white/[0.06] hover:text-neutral-300\"\n >\n <X className=\"h-4 w-4\" />\n </button>\n </div>\n\n <div className=\"h-px bg-gradient-to-r from-transparent via-white/[0.06] to-transparent\" />\n\n <div className=\"flex-1 overflow-y-auto p-2\">\n {annotations.length === 0 && (\n <div className=\"flex flex-col items-center gap-2 px-4 py-8 text-center\">\n <div className=\"flex h-10 w-10 items-center justify-center rounded-xl bg-white/[0.04]\">\n <MessageCircle className=\"h-5 w-5 text-neutral-600\" />\n </div>\n <p className=\"text-sm text-neutral-500\">Click on slide elements to add annotations</p>\n </div>\n )}\n\n {open.length > 0 && (\n <div>\n <div className=\"mb-1.5 px-2 pt-1 text-[11px] font-medium tracking-wider text-neutral-500 uppercase\">\n Open\n </div>\n {open.map((a, i) => (\n <AnnotationItem\n key={a.id}\n annotation={a}\n number={i + 1}\n isSelected={a.id === selectedId}\n onSelect={() => onSelect(a.id)}\n onDelete={() => onDelete(a.id)}\n />\n ))}\n </div>\n )}\n\n {resolved.length > 0 && (\n <div className={open.length > 0 ? \"mt-3\" : \"\"}>\n <div className=\"mb-1.5 px-2 pt-1 text-[11px] font-medium tracking-wider text-neutral-500 uppercase\">\n Resolved\n </div>\n {resolved.map((a, i) => (\n <AnnotationItem\n key={a.id}\n annotation={a}\n number={open.length + i + 1}\n isSelected={a.id === selectedId}\n onSelect={() => onSelect(a.id)}\n onDelete={() => onDelete(a.id)}\n />\n ))}\n </div>\n )}\n </div>\n </div>\n )\n}\n\nfunction AnnotationItem({\n annotation,\n number,\n isSelected,\n onSelect,\n onDelete\n}: {\n annotation: Annotation\n number: number\n isSelected: boolean\n onSelect: () => void\n onDelete: () => void\n}) {\n return (\n <div\n role=\"button\"\n tabIndex={0}\n onClick={onSelect}\n onKeyDown={e => { if (e.key === \"Enter\" || e.key === \" \") onSelect() }}\n className={`group relative mb-0.5 cursor-pointer rounded-xl p-2.5 transition-all duration-150 ${\n isSelected\n ? \"bg-[#FF6B35]/10 ring-1 ring-[#FF6B35]/20\"\n : \"hover:bg-white/[0.04]\"\n }`}\n >\n <button\n onClick={e => {\n e.stopPropagation()\n onDelete()\n }}\n className=\"absolute top-2 right-2 rounded-lg p-1 text-neutral-600 opacity-0 transition-all hover:bg-white/[0.08] hover:text-neutral-300 group-hover:opacity-100\"\n >\n <Trash2 className=\"h-3 w-3\" />\n </button>\n <div className=\"flex items-start gap-2.5\">\n <div\n className={`mt-0.5 flex h-5 w-5 flex-shrink-0 items-center justify-center rounded-full text-[11px] font-semibold ${\n annotation.status === \"open\"\n ? \"bg-[#FF6B35] text-white\"\n : \"bg-neutral-700 text-neutral-400\"\n }`}\n >\n {number}\n </div>\n <div className=\"min-w-0 pr-4\">\n <p className=\"text-[13px] leading-relaxed text-neutral-200\">{annotation.body}</p>\n {annotation.target.contentNearPin && (\n <p className=\"mt-1 truncate text-[11px] text-neutral-600\">\n {annotation.target.contentNearPin}\n </p>\n )}\n {annotation.resolution && (\n <p className=\"mt-1.5 text-[11px] text-emerald-400/80 italic\">\n {annotation.resolution}\n </p>\n )}\n </div>\n </div>\n </div>\n )\n}\n","import { useCallback, useEffect, useMemo, useRef, useState } from \"react\"\nimport { createHttpAdapter } from \"./adapters/http\"\nimport type { Annotation, AnnotationStorageAdapter, AnnotationTarget } from \"./types\"\n\nexport function useAnnotations(adapter?: AnnotationStorageAdapter) {\n const adapterRef = useRef(adapter ?? createHttpAdapter())\n const [annotations, setAnnotations] = useState<Annotation[]>([])\n\n // Load on mount and subscribe to external updates\n useEffect(() => {\n adapterRef.current.load().then(setAnnotations)\n return adapterRef.current.subscribe?.(setAnnotations)\n }, [])\n\n const addAnnotation = useCallback(\n (slideIndex: number, slideTitle: string, target: AnnotationTarget, body: string) => {\n const annotation: Annotation = {\n id: crypto.randomUUID(),\n slideIndex,\n slideTitle,\n target,\n body,\n createdAt: new Date().toISOString(),\n status: \"open\"\n }\n setAnnotations(prev => [...prev, annotation])\n adapterRef.current.add(annotation)\n },\n []\n )\n\n const deleteAnnotation = useCallback((id: string) => {\n setAnnotations(prev => prev.filter(a => a.id !== id))\n adapterRef.current.remove(id)\n }, [])\n\n const getSlideAnnotations = useCallback(\n (slideIndex: number) => annotations.filter(a => a.slideIndex === slideIndex),\n [annotations]\n )\n\n const openCount = useMemo(() => annotations.filter(a => a.status === \"open\").length, [annotations])\n\n // Allow external state updates (e.g. from postMessage adapter)\n const updateAnnotations = useCallback((updated: Annotation[]) => {\n setAnnotations(updated)\n }, [])\n\n return { annotations, addAnnotation, deleteAnnotation, getSlideAnnotations, openCount, updateAnnotations }\n}\n","import type { Annotation, AnnotationsFile, AnnotationStorageAdapter } from \"../types\"\n\nconst ENDPOINT = \"/__promptslide_annotations\"\n\nasync function loadAll(): Promise<Annotation[]> {\n try {\n const res = await fetch(ENDPOINT)\n if (!res.ok) return []\n const data: AnnotationsFile = await res.json()\n return data.annotations || []\n } catch {\n return []\n }\n}\n\nasync function saveAll(annotations: Annotation[]): Promise<void> {\n const data: AnnotationsFile = { version: 1, annotations }\n await fetch(ENDPOINT, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(data)\n })\n}\n\n/** Storage adapter for local Vite dev server (reads/writes annotations.json via middleware) */\nexport function createHttpAdapter(): AnnotationStorageAdapter {\n let cache: Annotation[] = []\n\n return {\n async load() {\n cache = await loadAll()\n return cache\n },\n async add(annotation) {\n cache = [...cache, annotation]\n await saveAll(cache)\n },\n async remove(id) {\n cache = cache.filter(a => a.id !== id)\n await saveAll(cache)\n }\n }\n}\n","import type { ClassValue } from \"clsx\"\n\nimport { clsx } from \"clsx\"\nimport { twMerge } from \"tailwind-merge\"\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs))\n}\n"],"mappings":"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","names":["jsx","motion","jsx","motion","createContext","useContext","useMemo","jsx","motion","jsx","jsx","motion","useCallback","useEffect","useState","jsx","useState","useEffect","useCallback","MessageCircle","useCallback","useEffect","useMemo","useRef","useState","useCallback","useEffect","useRef","useState","useEffect","useState","jsx","jsxs","jsx","jsxs","jsx","jsxs","useState","useRef","useCallback","useEffect","X","jsx","jsxs","useCallback","useEffect","useMemo","useRef","useState","useRef","useState","useEffect","useCallback","useMemo","jsx","jsxs","useState","useEffect","useMemo","useCallback","useRef","MessageCircle"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "promptslide",
3
- "version": "0.3.9",
3
+ "version": "0.3.10",
4
4
  "description": "CLI and slide engine for PromptSlide presentations",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -102,10 +102,12 @@ export function SlideEmbed({ slides, transition, directionalTransition }: SlideE
102
102
  return () => window.removeEventListener("message", handleMessage)
103
103
  }, [handleMessage])
104
104
 
105
- // Scale to fill viewport
105
+ // Scale to cover viewport (fills completely, may crop overflow)
106
106
  useEffect(() => {
107
107
  const calculateScale = () => {
108
- setScale(window.innerWidth / SLIDE_DIMENSIONS.width)
108
+ const scaleX = window.innerWidth / SLIDE_DIMENSIONS.width
109
+ const scaleY = window.innerHeight / SLIDE_DIMENSIONS.height
110
+ setScale(Math.max(scaleX, scaleY))
109
111
  }
110
112
 
111
113
  calculateScale()