promptslide 0.2.5 → 0.2.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -658,9 +658,7 @@ function SlideEmbed({ slides, transition, directionalTransition }) {
658
658
  }, [handleMessage]);
659
659
  useEffect2(() => {
660
660
  const calculateScale = () => {
661
- const scaleX = window.innerWidth / SLIDE_DIMENSIONS.width;
662
- const scaleY = window.innerHeight / SLIDE_DIMENSIONS.height;
663
- setScale(Math.min(scaleX, scaleY));
661
+ setScale(window.innerWidth / SLIDE_DIMENSIONS.width);
664
662
  };
665
663
  calculateScale();
666
664
  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/layouts/shared-footer.tsx","../src/core/slide-renderer.tsx","../src/core/slide-error-boundary.tsx","../src/core/slide-embed.tsx","../src/core/slide-deck.tsx","../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 { useTheme } from \"../theme-context\"\n\ninterface SlideFooterProps {\n slideNumber: number\n totalSlides: number\n /** Use light text/logo for dark slide backgrounds */\n variant?: \"default\" | \"light\"\n}\n\nexport function SlideFooter({ slideNumber, totalSlides, variant = \"default\" }: SlideFooterProps) {\n const theme = useTheme()\n if (!theme) return null\n\n const logoUrl = variant === \"light\"\n ? (theme.logo?.fullLight ?? theme.logo?.full)\n : theme.logo?.full\n\n const textClass = variant === \"light\"\n ? \"text-white/70\"\n : \"text-muted-foreground\"\n\n const nameClass = variant === \"light\"\n ? \"text-white font-semibold\"\n : \"text-foreground font-semibold\"\n\n return (\n <div className={`mt-4 flex shrink-0 items-center justify-between text-sm ${textClass}`}>\n <div className={`flex items-center gap-3 tracking-tight ${nameClass}`}>\n {logoUrl && (\n <img\n src={logoUrl}\n alt={`${theme.name} Logo`}\n className=\"h-8 w-auto\"\n />\n )}\n <span className=\"text-lg\">{theme.name}</span>\n </div>\n <div className=\"font-mono\">\n {slideNumber} / {totalSlides}\n </div>\n </div>\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 const scaleX = window.innerWidth / SLIDE_DIMENSIONS.width\n const scaleY = window.innerHeight / 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 }, [])\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, Monitor } from \"lucide-react\"\nimport { useCallback, useEffect, 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 { 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}\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 }: 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 const [viewMode, setViewMode] = useState<ViewMode>(\"slide\")\n const [isPresentationMode, setIsPresentationMode] = useState(false)\n const [scale, setScale] = useState(1)\n const containerRef = 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\") 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])\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 right-4 z-50 flex gap-1 rounded-lg border border-neutral-800 bg-neutral-950/90 p-1 backdrop-blur-sm print:hidden\",\n isPresentationMode && \"hidden\"\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={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 ref={containerRef}\n role=\"presentation\"\n tabIndex={isPresentationMode ? 0 : undefined}\n className={cn(\n \"flex h-screen w-full flex-col items-center justify-center overflow-hidden print: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 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 </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\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 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","jsx","motion","jsx","jsxs","jsx","motion","useCallback","useEffect","useState","jsx","useState","useEffect","useCallback","useCallback","useEffect","useState","jsx","jsxs","useState","useEffect","useCallback"]}
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/layouts/shared-footer.tsx","../src/core/slide-renderer.tsx","../src/core/slide-error-boundary.tsx","../src/core/slide-embed.tsx","../src/core/slide-deck.tsx","../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 { useTheme } from \"../theme-context\"\n\ninterface SlideFooterProps {\n slideNumber: number\n totalSlides: number\n /** Use light text/logo for dark slide backgrounds */\n variant?: \"default\" | \"light\"\n}\n\nexport function SlideFooter({ slideNumber, totalSlides, variant = \"default\" }: SlideFooterProps) {\n const theme = useTheme()\n if (!theme) return null\n\n const logoUrl = variant === \"light\"\n ? (theme.logo?.fullLight ?? theme.logo?.full)\n : theme.logo?.full\n\n const textClass = variant === \"light\"\n ? \"text-white/70\"\n : \"text-muted-foreground\"\n\n const nameClass = variant === \"light\"\n ? \"text-white font-semibold\"\n : \"text-foreground font-semibold\"\n\n return (\n <div className={`mt-4 flex shrink-0 items-center justify-between text-sm ${textClass}`}>\n <div className={`flex items-center gap-3 tracking-tight ${nameClass}`}>\n {logoUrl && (\n <img\n src={logoUrl}\n alt={`${theme.name} Logo`}\n className=\"h-8 w-auto\"\n />\n )}\n <span className=\"text-lg\">{theme.name}</span>\n </div>\n <div className=\"font-mono\">\n {slideNumber} / {totalSlides}\n </div>\n </div>\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, Monitor } from \"lucide-react\"\nimport { useCallback, useEffect, 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 { 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}\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 }: 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 const [viewMode, setViewMode] = useState<ViewMode>(\"slide\")\n const [isPresentationMode, setIsPresentationMode] = useState(false)\n const [scale, setScale] = useState(1)\n const containerRef = 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\") 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])\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 right-4 z-50 flex gap-1 rounded-lg border border-neutral-800 bg-neutral-950/90 p-1 backdrop-blur-sm print:hidden\",\n isPresentationMode && \"hidden\"\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={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 ref={containerRef}\n role=\"presentation\"\n tabIndex={isPresentationMode ? 0 : undefined}\n className={cn(\n \"flex h-screen w-full flex-col items-center justify-center overflow-hidden print: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 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 </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\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 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","jsx","motion","jsx","jsxs","jsx","motion","useCallback","useEffect","useState","jsx","useState","useEffect","useCallback","useCallback","useEffect","useState","jsx","jsxs","useState","useEffect","useCallback"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "promptslide",
3
- "version": "0.2.5",
3
+ "version": "0.2.6",
4
4
  "description": "CLI and slide engine for PromptSlide presentations",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -10,6 +10,7 @@ import {
10
10
  detectPackageManager,
11
11
  getInstallCommand,
12
12
  updateLockfileItem,
13
+ updateLockfilePublishConfig,
13
14
  hashContent,
14
15
  hashFile
15
16
  } from "../utils/registry.mjs"
@@ -136,6 +137,12 @@ export async function add(args) {
136
137
  updateLockfileItem(cwd, name, regItem.version ?? 0, fileHashes)
137
138
  }
138
139
 
140
+ // Persist deck slug for future pull/publish if this is a deck
141
+ if (item.type === "deck") {
142
+ const prefix = item.name.split("/")[0]
143
+ updateLockfilePublishConfig(cwd, { deckSlug: item.name, deckPrefix: prefix })
144
+ }
145
+
139
146
  // Auto-update deck-config.ts
140
147
  if (item.type === "slide") {
141
148
  for (const { file } of written.filter(w => w.file.target.includes("slides"))) {
@@ -7,7 +7,7 @@ import { bold, green, cyan, red, dim } from "../utils/ansi.mjs"
7
7
  import { requireAuth } from "../utils/auth.mjs"
8
8
  import { hexToOklch, isValidHex } from "../utils/colors.mjs"
9
9
  import { prompt, confirm, closePrompts } from "../utils/prompts.mjs"
10
- import { fetchRegistryItem, resolveRegistryDependencies } from "../utils/registry.mjs"
10
+ import { fetchRegistryItem, resolveRegistryDependencies, updateLockfilePublishConfig } from "../utils/registry.mjs"
11
11
  import { toPascalCase, replaceDeckConfig } from "../utils/deck-config.mjs"
12
12
  import { ensureTsConfig } from "../utils/tsconfig.mjs"
13
13
 
@@ -224,6 +224,10 @@ export async function create(args) {
224
224
  console.log(` ${green("✓")} Added ${dim(pkgList.join(", "))} to package.json`)
225
225
  }
226
226
 
227
+ // Persist deck slug for future pull/publish in the new project
228
+ const prefix = fromSlug.split("/")[0]
229
+ updateLockfilePublishConfig(targetDir, { deckSlug: fromSlug, deckPrefix: prefix })
230
+
227
231
  console.log()
228
232
  }
229
233
 
@@ -126,6 +126,7 @@ export async function login(args) {
126
126
  // Step 4: Fetch user's organizations and let them pick
127
127
  let organizationId = null
128
128
  let organizationName = null
129
+ let organizationSlug = null
129
130
 
130
131
  try {
131
132
  const orgs = await fetchOrganizations({ registry, token: accessToken })
@@ -135,6 +136,7 @@ export async function login(args) {
135
136
  } else if (orgs.length === 1) {
136
137
  organizationId = orgs[0].id
137
138
  organizationName = orgs[0].name
139
+ organizationSlug = orgs[0].slug
138
140
  } else {
139
141
  console.log()
140
142
  console.log(` ${bold("Select organization:")}`)
@@ -148,10 +150,12 @@ export async function login(args) {
148
150
  if (idx >= 0 && idx < orgs.length) {
149
151
  organizationId = orgs[idx].id
150
152
  organizationName = orgs[idx].name
153
+ organizationSlug = orgs[idx].slug
151
154
  } else {
152
155
  console.error(` ${red("Error:")} Invalid selection. Using first organization.`)
153
156
  organizationId = orgs[0].id
154
157
  organizationName = orgs[0].name
158
+ organizationSlug = orgs[0].slug
155
159
  }
156
160
  }
157
161
  } catch (err) {
@@ -163,7 +167,8 @@ export async function login(args) {
163
167
  registry,
164
168
  token: accessToken,
165
169
  organizationId,
166
- organizationName
170
+ organizationName,
171
+ organizationSlug
167
172
  })
168
173
 
169
174
  if (organizationName) {
@@ -34,7 +34,7 @@ export async function org(args) {
34
34
 
35
35
  if (orgs.length === 1) {
36
36
  if (auth.organizationId !== orgs[0].id) {
37
- saveAuth({ ...auth, organizationId: orgs[0].id, organizationName: orgs[0].name })
37
+ saveAuth({ ...auth, organizationId: orgs[0].id, organizationName: orgs[0].name, organizationSlug: orgs[0].slug })
38
38
  console.log(` ${green("✓")} Switched to ${bold(orgs[0].name)}`)
39
39
  } else {
40
40
  console.log(` Already using ${bold(orgs[0].name)}.`)
@@ -60,7 +60,7 @@ export async function org(args) {
60
60
  }
61
61
 
62
62
  const selected = orgs[idx]
63
- saveAuth({ ...auth, organizationId: selected.id, organizationName: selected.name })
63
+ saveAuth({ ...auth, organizationId: selected.id, organizationName: selected.name, organizationSlug: selected.slug })
64
64
  console.log(` ${green("✓")} Switched to ${bold(selected.name)}`)
65
65
  console.log()
66
66
 
@@ -4,11 +4,16 @@ import { join, basename, relative, extname } from "node:path"
4
4
  import { bold, green, cyan, red, dim } from "../utils/ansi.mjs"
5
5
  import { requireAuth } from "../utils/auth.mjs"
6
6
  import { captureSlideAsDataUri, isPlaywrightAvailable } from "../utils/export.mjs"
7
- import { publishToRegistry, registryItemExists, searchRegistry, updateLockfileItem, readLockfile, hashContent, detectPackageManager, requestUploadTokens, uploadBinaryToBlob, assetFileToSlug, detectAssetDepsInContent } from "../utils/registry.mjs"
8
- import { prompt, confirm, closePrompts } from "../utils/prompts.mjs"
7
+ import { publishToRegistry, registryItemExists, searchRegistry, updateLockfileItem, updateLockfilePublishConfig, readLockfile, hashContent, detectPackageManager, requestUploadTokens, uploadBinaryToBlob, assetFileToSlug, detectAssetDepsInContent } from "../utils/registry.mjs"
8
+ import { prompt, confirm, select, closePrompts } from "../utils/prompts.mjs"
9
9
  import { parseDeckConfig } from "../utils/deck-config.mjs"
10
10
 
11
11
  function readDeckPrefix(cwd) {
12
+ // Prefer stored prefix from lockfile (user's previous choice)
13
+ const lock = readLockfile(cwd)
14
+ if (lock.deckPrefix) return lock.deckPrefix
15
+
16
+ // Fall back to package.json name
12
17
  try {
13
18
  const pkg = JSON.parse(readFileSync(join(cwd, "package.json"), "utf-8"))
14
19
  return (pkg.name || "").toLowerCase()
@@ -402,22 +407,17 @@ export async function publish(args) {
402
407
  process.exit(1)
403
408
  }
404
409
 
405
- console.log(` ${bold("Available files:")}`)
406
- available.forEach((f, i) => {
407
- console.log(` ${dim(`${i + 1}.`)} ${f.target}${f.path}`)
408
- })
409
- console.log(` ${dim("─".repeat(30))}`)
410
- console.log(` ${dim(`${available.length + 1}.`)} ${bold("Entire deck")}`)
410
+ console.log(` ${bold("What do you want to publish?")}`)
411
411
  console.log()
412
412
 
413
- const choice = await prompt("Select file number:", "1")
414
- const idx = parseInt(choice, 10) - 1
413
+ const options = [
414
+ ...available.map(f => `${f.target}${f.path}`),
415
+ "Entire deck"
416
+ ]
417
+ const idx = await select(options, options.length - 1)
415
418
 
416
419
  if (idx === available.length) {
417
420
  typeOverride = "deck"
418
- } else if (idx < 0 || idx >= available.length) {
419
- console.error(` ${red("Error:")} Invalid selection.`)
420
- process.exit(1)
421
421
  } else {
422
422
  filePath = relative(cwd, available[idx].fullPath)
423
423
  }
@@ -432,10 +432,34 @@ export async function publish(args) {
432
432
  process.exit(1)
433
433
  }
434
434
 
435
- const deckPrefix = await promptDeckPrefix(cwd, true)
436
- const dirName = basename(cwd)
437
- const deckBaseSlug = dirName.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "")
438
- const deckSlug = `${deckPrefix}/${deckBaseSlug}`
435
+ // Check if a deck slug already exists in the lockfile
436
+ const existingLock = readLockfile(cwd)
437
+ const existingSlug = existingLock.deckSlug
438
+ let deckPrefix, deckSlug
439
+
440
+ if (existingSlug) {
441
+ console.log(` ${dim("Previously published as")} ${cyan(existingSlug)}`)
442
+ console.log()
443
+ const reuse = await confirm(` Publish to ${bold(existingSlug)}?`)
444
+
445
+ if (reuse) {
446
+ deckSlug = existingSlug
447
+ deckPrefix = existingSlug.split("/")[0]
448
+ } else {
449
+ deckPrefix = await promptDeckPrefix(cwd, true)
450
+ const dirName = basename(cwd)
451
+ const deckBaseSlug = dirName.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "")
452
+ deckSlug = `${deckPrefix}/${deckBaseSlug}`
453
+ }
454
+ } else {
455
+ deckPrefix = await promptDeckPrefix(cwd, true)
456
+ const dirName = basename(cwd)
457
+ const deckBaseSlug = dirName.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "")
458
+ deckSlug = `${deckPrefix}/${deckBaseSlug}`
459
+ }
460
+
461
+ // Persist prefix for next time (slug is saved after successful publish)
462
+ updateLockfilePublishConfig(cwd, { deckPrefix })
439
463
 
440
464
  // Walk public/ to collect assets and build reference set
441
465
  const publicDir = join(cwd, "public")
@@ -721,6 +745,7 @@ export async function publish(args) {
721
745
  const assetSlugs = publicAssets.map(a => assetFileToSlug(deckPrefix, a.relativePath))
722
746
  const allDeckDeps = [...slideSlugs, ...assetSlugs]
723
747
 
748
+ let deckItemId = null
724
749
  try {
725
750
  const result = await publishToRegistry({
726
751
  type: "deck",
@@ -736,6 +761,8 @@ export async function publish(args) {
736
761
  }, auth)
737
762
  console.log(` [${itemIndex}/${totalItems}] ${green("✓")} deck ${cyan(deckSlug)} ${dim(`v${result.version}`)}`)
738
763
  updateLockfileItem(cwd, deckSlug, result.version ?? 0, {})
764
+ updateLockfilePublishConfig(cwd, { deckSlug })
765
+ deckItemId = result.id
739
766
  published++
740
767
  } catch (err) {
741
768
  console.log(` [${itemIndex}/${totalItems}] ${red("✗")} deck ${dim(deckSlug)}: ${err.message}`)
@@ -744,6 +771,9 @@ export async function publish(args) {
744
771
 
745
772
  console.log()
746
773
  console.log(` ${bold("Done:")} ${green(`${published} published`)}${skipped ? `, ${skipped} unchanged` : ""}${failed ? `, ${red(`${failed} failed`)}` : ""}`)
774
+ if (auth.organizationSlug && deckItemId) {
775
+ console.log(` View: ${cyan(`${auth.registry}/${auth.organizationSlug}/items/${deckItemId}`)}`)
776
+ }
747
777
  console.log(` Install: ${cyan(`promptslide add ${deckSlug}`)}`)
748
778
  console.log()
749
779
  closePrompts()
@@ -782,6 +812,10 @@ export async function publish(args) {
782
812
  // Prompt for deck prefix (required)
783
813
  const deckPrefix = await promptDeckPrefix(cwd, true)
784
814
  const slug = `${deckPrefix}/${baseSlug}`
815
+
816
+ // Persist prefix for next time
817
+ updateLockfilePublishConfig(cwd, { deckPrefix })
818
+
785
819
  console.log(` Slug: ${cyan(slug)}`)
786
820
  console.log()
787
821
 
@@ -919,6 +953,9 @@ export async function publish(args) {
919
953
  const verTag = result.version ? ` v${result.version}` : ""
920
954
  console.log(` ${green("✓")} Published ${bold(slug)}${verTag} to ${auth.organizationName || "registry"}`)
921
955
  console.log(` Status: ${result.status || "published"}`)
956
+ if (auth.organizationSlug && result.id) {
957
+ console.log(` View: ${cyan(`${auth.registry}/${auth.organizationSlug}/items/${result.id}`)}`)
958
+ }
922
959
  console.log(` Install: ${cyan(`promptslide add ${slug}`)}`)
923
960
 
924
961
  // Track in lockfile
@@ -0,0 +1,228 @@
1
+ import { existsSync, readFileSync, writeFileSync, mkdirSync } from "node:fs"
2
+ import { execFileSync } from "node:child_process"
3
+ import { join, dirname, resolve, sep } from "node:path"
4
+
5
+ import { bold, green, cyan, red, yellow, dim } from "../utils/ansi.mjs"
6
+ import { requireAuth } from "../utils/auth.mjs"
7
+ import {
8
+ fetchRegistryItem,
9
+ resolveRegistryDependencies,
10
+ detectPackageManager,
11
+ getInstallCommand,
12
+ readLockfile,
13
+ updateLockfileItem,
14
+ hashContent,
15
+ hashFile,
16
+ isFileDirty
17
+ } from "../utils/registry.mjs"
18
+ import {
19
+ toPascalCase,
20
+ addSlideToDeckConfig,
21
+ replaceDeckConfig
22
+ } from "../utils/deck-config.mjs"
23
+ import { confirm, closePrompts } from "../utils/prompts.mjs"
24
+
25
+ export async function pull(args) {
26
+ const cwd = process.cwd()
27
+
28
+ console.log()
29
+ console.log(` ${bold("promptslide")} ${dim("pull")}`)
30
+ console.log()
31
+
32
+ if (args[0] === "--help" || args[0] === "-h") {
33
+ console.log(` ${bold("Usage:")} promptslide pull ${dim("[--force]")}`)
34
+ console.log()
35
+ console.log(` Pull the latest version of your deck from the registry.`)
36
+ console.log(` Reads the deck slug from the lockfile (set during publish).`)
37
+ console.log()
38
+ console.log(` ${bold("Options:")}`)
39
+ console.log(` --force Overwrite locally modified files without prompting`)
40
+ console.log()
41
+ process.exit(0)
42
+ }
43
+
44
+ const force = args.includes("--force")
45
+ const auth = requireAuth()
46
+
47
+ // Read deckSlug from lockfile
48
+ const lock = readLockfile(cwd)
49
+ const deckSlug = lock.deckSlug
50
+
51
+ if (!deckSlug) {
52
+ console.error(` ${red("Error:")} No deck slug found in lockfile.`)
53
+ console.error(` ${dim("Run")} ${cyan("promptslide publish --type deck")} ${dim("first to set it.")}`)
54
+ console.log()
55
+ process.exit(1)
56
+ }
57
+
58
+ console.log(` Pulling deck ${bold(deckSlug)}...`)
59
+ console.log()
60
+
61
+ // Fetch the deck manifest from the registry
62
+ let deckItem
63
+ try {
64
+ deckItem = await fetchRegistryItem(deckSlug, auth)
65
+ } catch (err) {
66
+ console.error(` ${red("Error:")} ${err.message}`)
67
+ process.exit(1)
68
+ }
69
+
70
+ const versionTag = deckItem.version ? ` ${dim(`v${deckItem.version}`)}` : ""
71
+ console.log(` Found ${bold(deckItem.title || deckItem.name)} ${dim(`(${deckItem.type})`)}${versionTag}`)
72
+
73
+ // Resolve all dependencies (slides, layouts, themes, assets)
74
+ let resolved
75
+ try {
76
+ resolved = await resolveRegistryDependencies(deckItem, auth, cwd)
77
+ } catch (err) {
78
+ console.error(` ${red("Error resolving dependencies:")} ${err.message}`)
79
+ process.exit(1)
80
+ }
81
+
82
+ const itemCount = resolved.items.length
83
+ const fileCount = resolved.items.reduce((sum, i) => sum + (i.files?.length || 0), 0)
84
+ console.log(` Resolved ${bold(String(itemCount))} items with ${bold(String(fileCount))} files`)
85
+ console.log()
86
+
87
+ // Write files
88
+ const written = []
89
+ const writtenByItem = new Map()
90
+
91
+ for (const regItem of resolved.items) {
92
+ if (!regItem.files?.length) continue
93
+
94
+ const fileHashes = {}
95
+
96
+ for (const file of regItem.files) {
97
+ const targetPath = resolve(cwd, file.target, file.path)
98
+ if (!targetPath.startsWith(cwd + sep)) {
99
+ console.log(` ${red("Error:")} Invalid file path: ${file.target}${file.path}`)
100
+ continue
101
+ }
102
+ const targetDir = dirname(targetPath)
103
+ const relativePath = file.target + file.path
104
+ const newHash = hashContent(file.content)
105
+
106
+ if (existsSync(targetPath)) {
107
+ // Check if content is identical
108
+ const dataUriMatch = file.content.match(/^data:[^;]+;base64,/)
109
+ let identical
110
+ if (dataUriMatch) {
111
+ const newBuf = Buffer.from(file.content.slice(dataUriMatch[0].length), "base64")
112
+ const existingBuf = readFileSync(targetPath)
113
+ identical = newBuf.equals(existingBuf)
114
+ } else {
115
+ identical = hashFile(targetPath) === newHash
116
+ }
117
+
118
+ if (identical) {
119
+ fileHashes[relativePath] = newHash
120
+ continue
121
+ }
122
+
123
+ // Check if file has local modifications
124
+ const lockEntry = lock.items[regItem.name]
125
+ const storedHash = lockEntry?.files?.[relativePath]
126
+ if (!force) {
127
+ if (storedHash && isFileDirty(cwd, relativePath, storedHash)) {
128
+ // File was tracked and has been locally modified
129
+ const overwrite = await confirm(
130
+ ` ${yellow("!")} ${relativePath} has local changes. Overwrite?`,
131
+ false
132
+ )
133
+ if (!overwrite) {
134
+ fileHashes[relativePath] = storedHash
135
+ console.log(` ${dim("Skipped")} ${relativePath}`)
136
+ continue
137
+ }
138
+ } else if (!storedHash) {
139
+ // File exists but not in lockfile (first pull or untracked)
140
+ const overwrite = await confirm(` Overwrite ${relativePath}? ${dim("(local changes will be lost)")}`, false)
141
+ if (!overwrite) {
142
+ console.log(` ${dim("Skipped")} ${relativePath}`)
143
+ continue
144
+ }
145
+ }
146
+ }
147
+ }
148
+
149
+ // Write the file
150
+ mkdirSync(targetDir, { recursive: true })
151
+ const dataUriPrefix = file.content.match(/^data:[^;]+;base64,/)
152
+ if (dataUriPrefix) {
153
+ writeFileSync(targetPath, Buffer.from(file.content.slice(dataUriPrefix[0].length), "base64"))
154
+ } else {
155
+ writeFileSync(targetPath, file.content, "utf-8")
156
+ }
157
+ fileHashes[relativePath] = newHash
158
+ written.push({ item: regItem, file })
159
+ console.log(` ${green("+")} ${cyan(relativePath)}`)
160
+ }
161
+
162
+ if (Object.keys(fileHashes).length > 0) {
163
+ writtenByItem.set(regItem.name, { regItem, fileHashes })
164
+ }
165
+ }
166
+
167
+ // Update lockfile for all resolved items
168
+ for (const [name, { regItem, fileHashes }] of writtenByItem) {
169
+ updateLockfileItem(cwd, name, regItem.version ?? 0, fileHashes)
170
+ }
171
+
172
+ // Also update the deck manifest entry itself (has no files)
173
+ updateLockfileItem(cwd, deckSlug, deckItem.version ?? 0, {})
174
+
175
+ // Update deck-config.ts
176
+ if (deckItem.type === "deck" && deckItem.meta?.slides) {
177
+ const shouldReplace = await confirm(" Replace deck-config.ts with pulled deck config?", true)
178
+ if (shouldReplace) {
179
+ const slides = deckItem.meta.slides.map(s => ({
180
+ componentName: toPascalCase(s.slug),
181
+ importPath: `@/slides/${s.slug}`,
182
+ steps: s.steps,
183
+ section: s.section
184
+ }))
185
+ replaceDeckConfig(cwd, slides, {
186
+ transition: deckItem.meta.transition,
187
+ directionalTransition: deckItem.meta.directionalTransition
188
+ })
189
+ console.log(` ${green("+")} Replaced ${cyan("deck-config.ts")} ${dim(`(${slides.length} slides)`)}`)
190
+ } else {
191
+ // Append individual slides
192
+ for (const s of deckItem.meta.slides) {
193
+ const componentName = toPascalCase(s.slug)
194
+ const importPath = `@/slides/${s.slug}`
195
+ const updated = addSlideToDeckConfig(cwd, { componentName, importPath, steps: s.steps, section: s.section })
196
+ if (updated) {
197
+ console.log(` ${green("+")} Added ${componentName} to ${cyan("deck-config.ts")}`)
198
+ }
199
+ }
200
+ }
201
+ }
202
+
203
+ // Install npm dependencies
204
+ if (Object.keys(resolved.npmDeps).length > 0 && existsSync(join(cwd, "package.json"))) {
205
+ const pm = detectPackageManager(cwd)
206
+ const pkgList = Object.entries(resolved.npmDeps).map(([name, ver]) => `${name}@${ver}`)
207
+ const { cmd, args: installArgs, display } = getInstallCommand(pm, pkgList)
208
+ console.log()
209
+ console.log(` ${dim(`Installing dependencies: ${display}`)}`)
210
+ try {
211
+ execFileSync(cmd, installArgs, { cwd, stdio: "inherit" })
212
+ console.log(` ${green("+")} Dependencies installed`)
213
+ } catch {
214
+ console.log(` ${red("!")} Dependency installation failed. Run manually:`)
215
+ console.log(` ${display}`)
216
+ }
217
+ }
218
+
219
+ // Summary
220
+ console.log()
221
+ if (written.length === 0) {
222
+ console.log(` ${green("+")} Everything is up to date.`)
223
+ } else {
224
+ console.log(` ${green("+")} Pulled ${bold(String(written.length))} file(s) from ${bold(deckSlug)}`)
225
+ }
226
+ console.log()
227
+ closePrompts()
228
+ }
@@ -10,7 +10,7 @@ export async function studio(args) {
10
10
  const port = portArg ? parseInt(portArg.split("=")[1], 10) : 5173
11
11
  const hasHost = args.includes("--host") || args.some(a => a.startsWith("--host="))
12
12
  const hostArg = args.find(a => a.startsWith("--host="))
13
- const host = hasHost ? (hostArg ? hostArg.split("=")[1] : "0.0.0.0") : undefined
13
+ const host = hasHost ? (hostArg ? hostArg.split("=")[1] || "0.0.0.0" : "0.0.0.0") : undefined
14
14
 
15
15
  ensureTsConfig(cwd)
16
16
 
@@ -105,9 +105,7 @@ export function SlideEmbed({ slides, transition, directionalTransition }: SlideE
105
105
  // Scale to fill viewport
106
106
  useEffect(() => {
107
107
  const calculateScale = () => {
108
- const scaleX = window.innerWidth / SLIDE_DIMENSIONS.width
109
- const scaleY = window.innerHeight / SLIDE_DIMENSIONS.height
110
- setScale(Math.min(scaleX, scaleY))
108
+ setScale(window.innerWidth / SLIDE_DIMENSIONS.width)
111
109
  }
112
110
 
113
111
  calculateScale()
package/src/index.mjs CHANGED
@@ -31,6 +31,7 @@ function printHelp() {
31
31
  console.log(` add ${dim("<name>")} Install a slide/deck from the registry`)
32
32
  console.log(` publish ${dim("[file]")} Publish a slide to the registry`)
33
33
  console.log(` update ${dim("[name]")} Check for and apply updates`)
34
+ console.log(` pull Pull the latest deck from the registry`)
34
35
  console.log(` remove ${dim("<name>")} Remove an installed item`)
35
36
  console.log(` info ${dim("<name>")} Show details about a registry item`)
36
37
  console.log(` search ${dim("<query>")} Search the registry`)
@@ -99,6 +100,11 @@ switch (command) {
99
100
  await update(args)
100
101
  break
101
102
  }
103
+ case "pull": {
104
+ const { pull } = await import("./commands/pull.mjs")
105
+ await pull(args)
106
+ break
107
+ }
102
108
  case "search": {
103
109
  const { search } = await import("./commands/search.mjs")
104
110
  await search(args)
@@ -20,7 +20,8 @@ export function loadAuth() {
20
20
  registry: data.registry || DEFAULT_REGISTRY,
21
21
  token: data.token,
22
22
  organizationId: data.organizationId || null,
23
- organizationName: data.organizationName || null
23
+ organizationName: data.organizationName || null,
24
+ organizationSlug: data.organizationSlug || null
24
25
  }
25
26
  } catch {
26
27
  return null
@@ -30,13 +31,14 @@ export function loadAuth() {
30
31
  /**
31
32
  * Save auth credentials to ~/.promptslide/auth.json.
32
33
  */
33
- export function saveAuth({ registry, token, organizationId, organizationName }) {
34
+ export function saveAuth({ registry, token, organizationId, organizationName, organizationSlug }) {
34
35
  mkdirSync(AUTH_DIR, { recursive: true })
35
36
  const data = {
36
37
  registry: registry || DEFAULT_REGISTRY,
37
38
  token,
38
39
  organizationId: organizationId || null,
39
- organizationName: organizationName || null
40
+ organizationName: organizationName || null,
41
+ organizationSlug: organizationSlug || null
40
42
  }
41
43
  writeFileSync(AUTH_FILE, JSON.stringify(data, null, 2) + "\n", { encoding: "utf-8", mode: 0o600 })
42
44
  }
@@ -52,3 +52,73 @@ export function confirm(question, defaultYes = true) {
52
52
  })
53
53
  })
54
54
  }
55
+
56
+ /**
57
+ * Arrow-key select prompt. Returns the index of the chosen option.
58
+ * @param {string[]} options - Display labels for each option
59
+ * @param {number} defaultIndex - Initially highlighted index
60
+ * @returns {Promise<number>}
61
+ */
62
+ export function select(options, defaultIndex = 0) {
63
+ if (!process.stdin.isTTY) return Promise.resolve(defaultIndex)
64
+
65
+ // Pause readline so we can use raw mode
66
+ if (_rl) { _rl.pause() }
67
+
68
+ return new Promise(resolve => {
69
+ let cursor = defaultIndex
70
+ const { stdin, stdout } = process
71
+
72
+ const render = () => {
73
+ // Move up to overwrite previous render (except first time)
74
+ if (render._drawn) stdout.write(`\x1b[${options.length}A`)
75
+ for (let i = 0; i < options.length; i++) {
76
+ const prefix = i === cursor ? " \x1b[36m❯\x1b[0m " : " "
77
+ const label = i === cursor ? `\x1b[1m${options[i]}\x1b[0m` : dim(options[i])
78
+ stdout.write(`\x1b[2K${prefix}${label}\n`)
79
+ }
80
+ render._drawn = true
81
+ }
82
+
83
+ stdin.setRawMode(true)
84
+ stdin.resume()
85
+ render()
86
+
87
+ const onData = (buf) => {
88
+ const key = buf.toString()
89
+
90
+ // Ctrl+C
91
+ if (key === "\x03") {
92
+ stdin.setRawMode(false)
93
+ stdin.removeListener("data", onData)
94
+ if (_rl) { _rl.resume() }
95
+ process.exit(0)
96
+ }
97
+
98
+ // Up arrow or k
99
+ if (key === "\x1b[A" || key === "k") {
100
+ cursor = (cursor - 1 + options.length) % options.length
101
+ render()
102
+ return
103
+ }
104
+
105
+ // Down arrow or j
106
+ if (key === "\x1b[B" || key === "j") {
107
+ cursor = (cursor + 1) % options.length
108
+ render()
109
+ return
110
+ }
111
+
112
+ // Enter
113
+ if (key === "\r" || key === "\n") {
114
+ stdin.setRawMode(false)
115
+ stdin.removeListener("data", onData)
116
+ stdin.pause()
117
+ if (_rl) { _rl.resume() }
118
+ resolve(cursor)
119
+ }
120
+ }
121
+
122
+ stdin.on("data", onData)
123
+ })
124
+ }
@@ -79,6 +79,18 @@ export function updateLockfileItem(cwd, slug, version, files) {
79
79
  writeLockfile(cwd, lock)
80
80
  }
81
81
 
82
+ /**
83
+ * Store publish configuration (deckPrefix, deckSlug) in the lockfile.
84
+ * @param {string} cwd
85
+ * @param {{ deckPrefix?: string, deckSlug?: string }} config
86
+ */
87
+ export function updateLockfilePublishConfig(cwd, config) {
88
+ const lock = readLockfile(cwd)
89
+ if (config.deckPrefix !== undefined) lock.deckPrefix = config.deckPrefix
90
+ if (config.deckSlug !== undefined) lock.deckSlug = config.deckSlug
91
+ writeLockfile(cwd, lock)
92
+ }
93
+
82
94
  /**
83
95
  * Remove a single item from the lockfile.
84
96
  * @param {string} cwd