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 +1 -3
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/commands/add.mjs +7 -0
- package/src/commands/create.mjs +5 -1
- package/src/commands/login.mjs +6 -1
- package/src/commands/org.mjs +2 -2
- package/src/commands/publish.mjs +54 -17
- package/src/commands/pull.mjs +228 -0
- package/src/commands/studio.mjs +1 -1
- package/src/core/slide-embed.tsx +1 -3
- package/src/index.mjs +6 -0
- package/src/utils/auth.mjs +5 -3
- package/src/utils/prompts.mjs +70 -0
- package/src/utils/registry.mjs +12 -0
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
|
-
|
|
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
package/src/commands/add.mjs
CHANGED
|
@@ -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"))) {
|
package/src/commands/create.mjs
CHANGED
|
@@ -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
|
|
package/src/commands/login.mjs
CHANGED
|
@@ -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) {
|
package/src/commands/org.mjs
CHANGED
|
@@ -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
|
|
package/src/commands/publish.mjs
CHANGED
|
@@ -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("
|
|
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
|
|
414
|
-
|
|
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
|
-
|
|
436
|
-
const
|
|
437
|
-
const
|
|
438
|
-
|
|
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
|
+
}
|
package/src/commands/studio.mjs
CHANGED
|
@@ -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
|
|
package/src/core/slide-embed.tsx
CHANGED
|
@@ -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
|
-
|
|
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)
|
package/src/utils/auth.mjs
CHANGED
|
@@ -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
|
}
|
package/src/utils/prompts.mjs
CHANGED
|
@@ -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
|
+
}
|
package/src/utils/registry.mjs
CHANGED
|
@@ -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
|