promptslide 0.3.13 → 0.3.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,18 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.3.14](https://github.com/prompticeu/promptslide/compare/promptslide-v0.3.13...promptslide-v0.3.14) (2026-04-01)
4
+
5
+
6
+ ### Features
7
+
8
+ * add optional white glow PNG for slide backgrounds ([#94](https://github.com/prompticeu/promptslide/issues/94)) ([cbd500e](https://github.com/prompticeu/promptslide/commit/cbd500e8bdb1f3125bdbad6668d924394d6245a2))
9
+ * add workflow hint to annotation sidebar ([#92](https://github.com/prompticeu/promptslide/issues/92)) ([0d898d6](https://github.com/prompticeu/promptslide/commit/0d898d66e90a767bf6187103d3fb7a24dfc7d828))
10
+
11
+
12
+ ### Bug Fixes
13
+
14
+ * allow arrow key navigation in fullscreen when annotation mode is active ([#95](https://github.com/prompticeu/promptslide/issues/95)) ([b2f8d31](https://github.com/prompticeu/promptslide/commit/b2f8d3150d24b919303de8126f6460c0123bfd29))
15
+
3
16
  ## [0.3.13](https://github.com/prompticeu/promptslide/compare/promptslide-v0.3.12...promptslide-v0.3.13) (2026-03-29)
4
17
 
5
18
 
package/dist/index.js CHANGED
@@ -983,7 +983,7 @@ function AnnotationOverlay({ slides, currentSlide, slideContainerRef, selectedId
983
983
 
984
984
  // src/core/annotations/annotation-panel.tsx
985
985
  import { MessageCircle, Trash2, X as X2 } from "lucide-react";
986
- import { jsx as jsx11, jsxs as jsxs5 } from "react/jsx-runtime";
986
+ import { Fragment as Fragment2, jsx as jsx11, jsxs as jsxs5 } from "react/jsx-runtime";
987
987
  function AnnotationPanel({ annotations, selectedId, onSelect, onDelete, onClose }) {
988
988
  const open = annotations.filter((a) => a.status === "open");
989
989
  const resolved = annotations.filter((a) => a.status === "resolved");
@@ -1005,10 +1005,7 @@ function AnnotationPanel({ annotations, selectedId, onSelect, onDelete, onClose
1005
1005
  ] }),
1006
1006
  /* @__PURE__ */ jsx11("div", { className: "h-px bg-gradient-to-r from-transparent via-white/[0.06] to-transparent" }),
1007
1007
  /* @__PURE__ */ jsxs5("div", { className: "flex-1 overflow-y-auto p-2", children: [
1008
- annotations.length === 0 && /* @__PURE__ */ jsxs5("div", { className: "flex flex-col items-center gap-2 px-4 py-8 text-center", children: [
1009
- /* @__PURE__ */ jsx11("div", { className: "flex h-10 w-10 items-center justify-center rounded-xl bg-white/[0.04]", children: /* @__PURE__ */ jsx11(MessageCircle, { className: "h-5 w-5 text-neutral-600" }) }),
1010
- /* @__PURE__ */ jsx11("p", { className: "text-sm text-neutral-500", children: "Click on slide elements to add annotations" })
1011
- ] }),
1008
+ annotations.length === 0 && /* @__PURE__ */ jsx11("div", { className: "flex flex-col gap-4 px-3 py-6", children: /* @__PURE__ */ jsx11(WorkflowHint, {}) }),
1012
1009
  open.length > 0 && /* @__PURE__ */ jsxs5("div", { children: [
1013
1010
  /* @__PURE__ */ jsx11("div", { className: "mb-1.5 px-2 pt-1 text-[11px] font-medium tracking-wider text-neutral-500 uppercase", children: "Open" }),
1014
1011
  open.map((a, i) => /* @__PURE__ */ jsx11(
@@ -1037,6 +1034,27 @@ function AnnotationPanel({ annotations, selectedId, onSelect, onDelete, onClose
1037
1034
  a.id
1038
1035
  ))
1039
1036
  ] })
1037
+ ] }),
1038
+ annotations.length > 0 && /* @__PURE__ */ jsxs5(Fragment2, { children: [
1039
+ /* @__PURE__ */ jsx11("div", { className: "h-px bg-gradient-to-r from-transparent via-white/[0.06] to-transparent" }),
1040
+ /* @__PURE__ */ jsx11("div", { className: "px-3 py-3", children: /* @__PURE__ */ jsx11(WorkflowHint, {}) })
1041
+ ] })
1042
+ ] });
1043
+ }
1044
+ function WorkflowHint() {
1045
+ return /* @__PURE__ */ jsxs5("div", { className: "flex flex-col gap-2", children: [
1046
+ /* @__PURE__ */ jsx11("p", { className: "text-[11px] font-medium tracking-wider text-neutral-500 uppercase", children: "Workflow" }),
1047
+ /* @__PURE__ */ jsxs5("div", { className: "flex items-start gap-2.5", children: [
1048
+ /* @__PURE__ */ jsx11("div", { className: "mt-0.5 flex h-4 w-4 flex-shrink-0 items-center justify-center rounded-full bg-[#FF6B35]/15 text-[10px] font-semibold text-[#FF6B35]", children: "1" }),
1049
+ /* @__PURE__ */ jsx11("p", { className: "text-[12px] leading-snug text-neutral-400", children: "Annotate everything you want to fix" })
1050
+ ] }),
1051
+ /* @__PURE__ */ jsxs5("div", { className: "flex items-start gap-2.5", children: [
1052
+ /* @__PURE__ */ jsx11("div", { className: "mt-0.5 flex h-4 w-4 flex-shrink-0 items-center justify-center rounded-full bg-[#FF6B35]/15 text-[10px] font-semibold text-[#FF6B35]", children: "2" }),
1053
+ /* @__PURE__ */ jsx11("p", { className: "text-[12px] leading-snug text-neutral-400", children: "Switch to your coding agent" })
1054
+ ] }),
1055
+ /* @__PURE__ */ jsxs5("div", { className: "flex items-start gap-2.5", children: [
1056
+ /* @__PURE__ */ jsx11("div", { className: "mt-0.5 flex h-4 w-4 flex-shrink-0 items-center justify-center rounded-full bg-[#FF6B35]/15 text-[10px] font-semibold text-[#FF6B35]", children: "3" }),
1057
+ /* @__PURE__ */ jsx11("p", { className: "text-[12px] leading-snug text-neutral-400", children: '"Fix open annotations"' })
1040
1058
  ] })
1041
1059
  ] });
1042
1060
  }
@@ -1301,7 +1319,7 @@ function SlideDeck({ slides, transition, directionalTransition, annotations, onA
1301
1319
  setViewMode((prev) => prev === "grid" ? "slide" : "grid");
1302
1320
  return;
1303
1321
  }
1304
- if (viewMode !== "slide" || isAnnotationMode) return;
1322
+ if (viewMode !== "slide" || isAnnotationMode && !isPresentationMode) return;
1305
1323
  if (e.key === "ArrowRight" || e.key === " ") {
1306
1324
  e.preventDefault();
1307
1325
  advance();
@@ -1312,7 +1330,7 @@ function SlideDeck({ slides, transition, directionalTransition, annotations, onA
1312
1330
  };
1313
1331
  window.addEventListener("keydown", handleKeyDown);
1314
1332
  return () => window.removeEventListener("keydown", handleKeyDown);
1315
- }, [advance, goBack, viewMode, togglePresentationMode, isAnnotationMode]);
1333
+ }, [advance, goBack, viewMode, togglePresentationMode, isAnnotationMode, isPresentationMode]);
1316
1334
  return /* @__PURE__ */ jsxs6("div", { className: "min-h-screen w-full bg-neutral-950 text-foreground", children: [
1317
1335
  /* @__PURE__ */ jsx12("style", { children: `
1318
1336
  @media print {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/core/animation-config.ts","../src/core/animation-context.tsx","../src/core/animated.tsx","../src/core/transitions.ts","../src/core/morph.tsx","../src/core/use-slide-navigation.ts","../src/core/theme-context.tsx","../src/core/slide-renderer.tsx","../src/core/slide-error-boundary.tsx","../src/core/slide-embed.tsx","../src/core/slide-deck.tsx","../src/core/annotations/annotation-overlay.tsx","../src/core/annotations/annotation-form.tsx","../src/core/annotations/annotation-pin.tsx","../src/core/annotations/selectors.ts","../src/core/annotations/annotation-panel.tsx","../src/core/annotations/use-annotations.ts","../src/core/annotations/adapters/http.ts","../src/core/utils.ts"],"sourcesContent":["/**\n * Centralized animation configuration for the slide deck framework.\n * All animation timings, easings, and spring configs are defined here.\n */\n\n// =============================================================================\n// TIMING CONSTANTS\n// =============================================================================\n\n/** Duration for slide-to-slide transitions (seconds) */\nexport const SLIDE_TRANSITION_DURATION = 0.3\n\n/** Duration for morph/layout animations between slides (seconds) */\nexport const MORPH_DURATION = 0.8\n\n/** Duration for within-slide step animations (seconds) */\nexport const STEP_ANIMATION_DURATION = 0.4\n\n/** Default stagger delay for grouped animations (seconds) */\nexport const STAGGER_DELAY = 0.1\n\n// =============================================================================\n// EASING PRESETS\n// =============================================================================\n\nexport const EASE_DEFAULT = \"easeInOut\" as const\nexport const EASE_OUT = \"easeOut\" as const\nexport const EASE_IN = \"easeIn\" as const\n\n/** Smooth ease-in-out curve for morph animations (cubic bezier) */\nexport const EASE_MORPH = [0.4, 0, 0.2, 1] as const\n\n// =============================================================================\n// SPRING CONFIGURATIONS\n// =============================================================================\n\n/** Spring config for snappy, responsive animations */\nexport const SPRING_SNAPPY = {\n type: \"spring\" as const,\n stiffness: 300,\n damping: 30\n}\n\n/** Spring config for smooth, gentle animations */\nexport const SPRING_SMOOTH = {\n type: \"spring\" as const,\n stiffness: 200,\n damping: 25\n}\n\n/** Spring config for bouncy animations */\nexport const SPRING_BOUNCY = {\n type: \"spring\" as const,\n stiffness: 400,\n damping: 20\n}\n\n// =============================================================================\n// TRANSITION PRESETS\n// =============================================================================\n\n/** Standard transition for slide transitions */\nexport const SLIDE_TRANSITION = {\n duration: SLIDE_TRANSITION_DURATION,\n ease: EASE_DEFAULT\n} as const\n\n/** Standard transition for morph animations (smooth ease-in-out) */\nexport const MORPH_TRANSITION = {\n duration: MORPH_DURATION,\n ease: EASE_MORPH\n}\n\n/** Standard transition for step animations (spring-based, duration computed from stiffness/damping) */\nexport const STEP_TRANSITION = {\n ...SPRING_SNAPPY\n}\n\n// =============================================================================\n// DISTANCE CONSTANTS (pixels)\n// =============================================================================\n\n/** Distance for slide animations */\nexport const SLIDE_DISTANCE = 100\n\n/** Distance for within-slide element animations */\nexport const ELEMENT_SLIDE_DISTANCE = 30\n\n// =============================================================================\n// SLIDE DIMENSIONS\n// =============================================================================\n\n/** Standard slide dimensions (16:9 aspect ratio) */\nexport const SLIDE_DIMENSIONS = {\n width: 1280,\n height: 720,\n aspectRatio: 16 / 9\n} as const\n","import { createContext, useContext, useMemo } from \"react\"\n\ninterface AnimationContextValue {\n /** Current animation step (0 = no animations shown yet) */\n currentStep: number\n /** Total animation steps in this slide (declared in slide config) */\n totalSteps: number\n /** When true, all animation steps should be visible (used for backward navigation) */\n showAllAnimations: boolean\n}\n\nconst AnimationContext = createContext<AnimationContextValue>({\n currentStep: 0,\n totalSteps: 0,\n showAllAnimations: false\n})\n\ninterface AnimationProviderProps {\n children: React.ReactNode\n /** Current animation step (0 = no animations shown yet) */\n currentStep: number\n /** Total animation steps declared in slide config */\n totalSteps: number\n /** When true, show all animations regardless of currentStep (for backward navigation) */\n showAllAnimations?: boolean\n}\n\n/**\n * Provides animation context to child components.\n *\n * The totalSteps is now passed from parent (declared in slide config)\n * rather than discovered at runtime, eliminating race conditions.\n */\nexport function AnimationProvider({\n children,\n currentStep,\n totalSteps,\n showAllAnimations = false\n}: AnimationProviderProps) {\n const value = useMemo(\n () => ({\n currentStep,\n totalSteps,\n showAllAnimations\n }),\n [currentStep, totalSteps, showAllAnimations]\n )\n\n return <AnimationContext.Provider value={value}>{children}</AnimationContext.Provider>\n}\n\nexport function useAnimationContext() {\n return useContext(AnimationContext)\n}\n","import { motion, Variants } from \"framer-motion\"\n\nimport {\n ELEMENT_SLIDE_DISTANCE,\n SPRING_SNAPPY,\n STAGGER_DELAY,\n STEP_ANIMATION_DURATION\n} from \"./animation-config\"\nimport { useAnimationContext } from \"./animation-context\"\n\n// =============================================================================\n// ANIMATION TYPES & VARIANTS\n// =============================================================================\n\nexport type AnimationType =\n | \"fade\"\n | \"slide-up\"\n | \"slide-down\"\n | \"slide-left\"\n | \"slide-right\"\n | \"scale\"\n\nconst animationVariants: Record<AnimationType, Variants> = {\n fade: {\n hidden: { opacity: 0 },\n visible: { opacity: 1 }\n },\n \"slide-up\": {\n hidden: { opacity: 0, y: ELEMENT_SLIDE_DISTANCE },\n visible: { opacity: 1, y: 0 }\n },\n \"slide-down\": {\n hidden: { opacity: 0, y: -ELEMENT_SLIDE_DISTANCE },\n visible: { opacity: 1, y: 0 }\n },\n \"slide-left\": {\n hidden: { opacity: 0, x: ELEMENT_SLIDE_DISTANCE },\n visible: { opacity: 1, x: 0 }\n },\n \"slide-right\": {\n hidden: { opacity: 0, x: -ELEMENT_SLIDE_DISTANCE },\n visible: { opacity: 1, x: 0 }\n },\n scale: {\n hidden: { opacity: 0, scale: 0.8 },\n visible: { opacity: 1, scale: 1 }\n }\n}\n\ninterface AnimatedProps {\n /** Which step reveals this content (1-indexed) */\n step: number\n /** Animation type */\n animation?: AnimationType\n /** Animation duration in seconds */\n duration?: number\n /** Delay after trigger in seconds */\n delay?: number\n /** Custom className */\n className?: string\n children: React.ReactNode\n}\n\n/**\n * Animated element that appears at a specific animation step.\n *\n * The step count is now declared in slide config rather than discovered\n * at runtime, so this component simply consumes the context without\n * needing to register itself.\n */\nexport function Animated({\n step,\n animation = \"slide-up\",\n duration = STEP_ANIMATION_DURATION,\n delay = 0,\n className,\n children\n}: AnimatedProps) {\n const { currentStep, showAllAnimations } = useAnimationContext()\n\n // Show all animations when navigating backward, otherwise check step\n const isVisible = showAllAnimations || currentStep >= step\n\n return (\n <motion.div\n initial=\"hidden\"\n animate={isVisible ? \"visible\" : \"hidden\"}\n variants={animationVariants[animation]}\n transition={{\n ...SPRING_SNAPPY,\n duration,\n delay: isVisible ? delay : 0\n }}\n className={className}\n >\n {children}\n </motion.div>\n )\n}\n\n/**\n * Wrapper for staggering multiple children.\n * Each direct child will be animated in sequence.\n */\ninterface AnimatedGroupProps {\n /** Starting step for the first child */\n startStep: number\n /** Animation type for all children */\n animation?: AnimationType\n /** Delay between each child in seconds */\n staggerDelay?: number\n className?: string\n children: React.ReactNode\n}\n\nexport function AnimatedGroup({\n startStep,\n animation = \"slide-up\",\n staggerDelay = STAGGER_DELAY,\n className,\n children\n}: AnimatedGroupProps) {\n const { currentStep, showAllAnimations } = useAnimationContext()\n\n const childArray = Array.isArray(children) ? children : [children]\n\n // Show all animations when navigating backward, otherwise check step\n const isVisible = showAllAnimations || currentStep >= startStep\n\n const containerVariants: Variants = {\n hidden: {},\n visible: {\n transition: {\n staggerChildren: staggerDelay\n }\n }\n }\n\n return (\n <motion.div\n initial=\"hidden\"\n animate={isVisible ? \"visible\" : \"hidden\"}\n variants={containerVariants}\n className={className}\n >\n {childArray.map((child, index) => (\n <motion.div key={index} variants={animationVariants[animation]}>\n {child}\n </motion.div>\n ))}\n </motion.div>\n )\n}\n","/**\n * Slide transition variants for the slide deck framework.\n * These define how slides enter and exit during navigation.\n */\n\nimport type { Variants } from \"framer-motion\"\n\nimport {\n EASE_MORPH,\n MORPH_DURATION,\n SLIDE_DISTANCE,\n SLIDE_TRANSITION,\n SLIDE_TRANSITION_DURATION\n} from \"./animation-config\"\n\n// =============================================================================\n// TYPES\n// =============================================================================\n\nexport type SlideTransitionType =\n | \"fade\"\n | \"slide-left\"\n | \"slide-right\"\n | \"slide-up\"\n | \"slide-down\"\n | \"zoom\"\n | \"zoom-fade\"\n | \"morph\"\n | \"none\"\n\nexport interface SlideTransitionConfig {\n /** The transition type */\n type: SlideTransitionType\n /** Optional custom duration (overrides default) */\n duration?: number\n /** Whether to use directional transitions based on navigation direction */\n directional?: boolean\n}\n\n// =============================================================================\n// STATIC VARIANTS (non-directional)\n// =============================================================================\n\nconst fadeVariants: Variants = {\n enter: { opacity: 0 },\n center: { opacity: 1 },\n exit: { opacity: 0 }\n}\n\nconst slideLeftVariants: Variants = {\n enter: { x: SLIDE_DISTANCE, opacity: 0 },\n center: { x: 0, opacity: 1 },\n exit: { x: -SLIDE_DISTANCE, opacity: 0 }\n}\n\nconst slideRightVariants: Variants = {\n enter: { x: -SLIDE_DISTANCE, opacity: 0 },\n center: { x: 0, opacity: 1 },\n exit: { x: SLIDE_DISTANCE, opacity: 0 }\n}\n\nconst slideUpVariants: Variants = {\n enter: { y: SLIDE_DISTANCE, opacity: 0 },\n center: { y: 0, opacity: 1 },\n exit: { y: -SLIDE_DISTANCE, opacity: 0 }\n}\n\nconst slideDownVariants: Variants = {\n enter: { y: -SLIDE_DISTANCE, opacity: 0 },\n center: { y: 0, opacity: 1 },\n exit: { y: SLIDE_DISTANCE, opacity: 0 }\n}\n\nconst zoomVariants: Variants = {\n enter: { scale: 0.8, opacity: 0 },\n center: { scale: 1, opacity: 1 },\n exit: { scale: 1.2, opacity: 0 }\n}\n\nconst zoomFadeVariants: Variants = {\n enter: { scale: 0.95, opacity: 0 },\n center: { scale: 1, opacity: 1 },\n exit: { scale: 1.05, opacity: 0 }\n}\n\nconst morphVariants: Variants = {\n enter: {\n opacity: 0,\n zIndex: 1\n },\n center: {\n opacity: 1,\n zIndex: 1,\n transition: {\n opacity: { delay: 0.05, duration: 0.25 }\n }\n },\n exit: {\n opacity: 0,\n zIndex: 0,\n transition: {\n opacity: { duration: MORPH_DURATION, ease: EASE_MORPH }\n }\n }\n}\n\nconst noneVariants: Variants = {\n enter: {},\n center: {},\n exit: {}\n}\n\n// =============================================================================\n// VARIANT REGISTRY\n// =============================================================================\n\nexport const SLIDE_VARIANTS: Record<SlideTransitionType, Variants> = {\n fade: fadeVariants,\n \"slide-left\": slideLeftVariants,\n \"slide-right\": slideRightVariants,\n \"slide-up\": slideUpVariants,\n \"slide-down\": slideDownVariants,\n zoom: zoomVariants,\n \"zoom-fade\": zoomFadeVariants,\n morph: morphVariants,\n none: noneVariants\n}\n\n// =============================================================================\n// DIRECTIONAL VARIANTS (based on navigation direction)\n// =============================================================================\n\nexport function createDirectionalVariants(axis: \"x\" | \"y\" = \"x\"): (direction: number) => Variants {\n return (direction: number) => ({\n enter: {\n [axis]: direction > 0 ? SLIDE_DISTANCE : -SLIDE_DISTANCE,\n opacity: 0\n },\n center: {\n [axis]: 0,\n opacity: 1\n },\n exit: {\n [axis]: direction < 0 ? SLIDE_DISTANCE : -SLIDE_DISTANCE,\n opacity: 0\n }\n })\n}\n\n/** Horizontal directional slide (left/right based on direction) */\nexport const directionalSlideX = createDirectionalVariants(\"x\")\n\n/** Vertical directional slide (up/down based on direction) */\nexport const directionalSlideY = createDirectionalVariants(\"y\")\n\n// =============================================================================\n// HELPER FUNCTIONS\n// =============================================================================\n\nexport function getSlideVariants(\n config: SlideTransitionConfig | SlideTransitionType,\n direction: number = 1\n): Variants {\n const type = typeof config === \"string\" ? config : config.type\n const directional = typeof config === \"object\" ? config.directional : false\n\n if (directional && (type === \"slide-left\" || type === \"slide-right\")) {\n return directionalSlideX(direction)\n }\n\n if (directional && (type === \"slide-up\" || type === \"slide-down\")) {\n return directionalSlideY(direction)\n }\n\n return SLIDE_VARIANTS[type]\n}\n\nexport function getSlideTransition(config?: SlideTransitionConfig | SlideTransitionType): {\n duration: number\n ease: typeof SLIDE_TRANSITION.ease\n} {\n if (!config) return SLIDE_TRANSITION\n\n const type = typeof config === \"string\" ? config : config.type\n\n const defaultDuration = type === \"morph\" ? MORPH_DURATION : SLIDE_TRANSITION_DURATION\n\n const duration = typeof config === \"object\" && config.duration ? config.duration : defaultDuration\n\n return {\n ...SLIDE_TRANSITION,\n duration\n }\n}\n\n// =============================================================================\n// DEFAULT EXPORT\n// =============================================================================\n\nexport const DEFAULT_SLIDE_TRANSITION: SlideTransitionType = \"fade\"\n","import type { Transition } from \"framer-motion\"\n\nimport { motion } from \"framer-motion\"\n\nimport { MORPH_TRANSITION } from \"./animation-config\"\n\n// =============================================================================\n// TYPES\n// =============================================================================\n\ninterface MorphProps {\n layoutId: string\n transition?: Transition\n className?: string\n children: React.ReactNode\n}\n\ninterface MorphGroupProps {\n groupId: string\n transition?: Transition\n className?: string\n children: React.ReactNode\n}\n\n// =============================================================================\n// MORPH COMPONENT\n// =============================================================================\n\n/**\n * Wrapper component that enables morph/shared-layout animations between slides.\n *\n * Usage:\n * ```tsx\n * // Slide 1 - Large version\n * <Morph layoutId=\"hero-title\">\n * <h1 className=\"text-6xl\">Title</h1>\n * </Morph>\n *\n * // Slide 2 - Small version (same layoutId = morphs between them)\n * <Morph layoutId=\"hero-title\">\n * <h1 className=\"text-2xl\">Title</h1>\n * </Morph>\n * ```\n */\nexport function Morph({\n layoutId,\n transition = MORPH_TRANSITION,\n className,\n children\n}: MorphProps) {\n return (\n <motion.div\n layout\n layoutId={layoutId}\n initial={false}\n transition={transition}\n className={className}\n >\n {children}\n </motion.div>\n )\n}\n\n// =============================================================================\n// MORPH GROUP COMPONENT\n// =============================================================================\n\nexport function MorphGroup({\n groupId,\n transition = MORPH_TRANSITION,\n className,\n children\n}: MorphGroupProps) {\n return (\n <motion.div\n layout\n layoutId={groupId}\n initial={false}\n transition={transition}\n className={className}\n >\n {children}\n </motion.div>\n )\n}\n\n// =============================================================================\n// MORPH ITEM (for use within MorphGroup pattern)\n// =============================================================================\n\ninterface MorphItemProps {\n id: string\n prefix?: string\n transition?: Transition\n className?: string\n children: React.ReactNode\n}\n\nexport function MorphItem({\n id,\n prefix,\n transition = MORPH_TRANSITION,\n className,\n children\n}: MorphItemProps) {\n const layoutId = prefix ? `${prefix}-${id}` : id\n\n return (\n <motion.div\n layout\n layoutId={layoutId}\n initial={false}\n transition={transition}\n className={className}\n >\n {children}\n </motion.div>\n )\n}\n\n// =============================================================================\n// MORPH TEXT (specialized for text that changes size)\n// =============================================================================\n\ninterface MorphTextProps {\n layoutId: string\n as?: \"h1\" | \"h2\" | \"h3\" | \"h4\" | \"p\" | \"span\"\n transition?: Transition\n className?: string\n children: React.ReactNode\n}\n\nexport function MorphText({\n layoutId,\n as: Component = \"span\",\n transition = MORPH_TRANSITION,\n className,\n children\n}: MorphTextProps) {\n const MotionComponent = motion[Component]\n\n return (\n <MotionComponent\n layout\n layoutId={layoutId}\n initial={false}\n transition={transition}\n className={className}\n >\n {children}\n </MotionComponent>\n )\n}\n","import { useCallback, useEffect, useState } from \"react\"\n\nimport type { NavigationDirection, SlideConfig } from \"./types\"\n\n// =============================================================================\n// TYPES\n// =============================================================================\n\ntype NavigationStatus = \"idle\" | \"transitioning\"\n\ntype QueuedAction = \"advance\" | \"goBack\" | null\n\ninterface NavigationState {\n status: NavigationStatus\n direction: NavigationDirection\n}\n\nexport interface UseSlideNavigationOptions {\n slides: SlideConfig[]\n initialSlide?: number\n onSlideChange?: (slideIndex: number) => void\n}\n\nexport interface UseSlideNavigationReturn {\n currentSlide: number\n animationStep: number\n totalSteps: number\n direction: NavigationDirection\n isTransitioning: boolean\n showAllAnimations: boolean\n advance: () => void\n goBack: () => void\n goToSlide: (index: number) => void\n onTransitionComplete: () => void\n}\n\n// =============================================================================\n// HOOK\n// =============================================================================\n\nexport function useSlideNavigation({\n slides,\n initialSlide = 0,\n onSlideChange\n}: UseSlideNavigationOptions): UseSlideNavigationReturn {\n const [currentSlide, setCurrentSlide] = useState(initialSlide)\n const [animationStep, setAnimationStep] = useState(0)\n\n const [navState, setNavState] = useState<NavigationState>({\n status: \"idle\",\n direction: 0\n })\n\n const [queuedAction, setQueuedAction] = useState<QueuedAction>(null)\n\n const totalSteps = slides[currentSlide]?.steps ?? 0\n\n const onTransitionComplete = useCallback(() => {\n setNavState(prev => {\n if (prev.status === \"transitioning\") {\n return { status: \"idle\", direction: 0 }\n }\n return prev\n })\n }, [])\n\n const advance = useCallback(() => {\n if (navState.status === \"transitioning\") {\n setQueuedAction(\"advance\")\n return\n }\n\n const currentTotalSteps = slides[currentSlide]?.steps ?? 0\n\n if (animationStep >= currentTotalSteps) {\n const nextSlide = (currentSlide + 1) % slides.length\n setNavState({ status: \"transitioning\", direction: 1 })\n setAnimationStep(0)\n setCurrentSlide(nextSlide)\n onSlideChange?.(nextSlide)\n } else {\n setAnimationStep(prev => prev + 1)\n }\n }, [navState.status, animationStep, currentSlide, slides, onSlideChange])\n\n const goBack = useCallback(() => {\n if (navState.status === \"transitioning\") {\n setQueuedAction(\"goBack\")\n return\n }\n\n if (animationStep <= 0) {\n const prevSlide = (currentSlide - 1 + slides.length) % slides.length\n const prevSlideSteps = slides[prevSlide]?.steps ?? 0\n setNavState({ status: \"transitioning\", direction: -1 })\n setAnimationStep(prevSlideSteps)\n setCurrentSlide(prevSlide)\n onSlideChange?.(prevSlide)\n } else {\n setAnimationStep(prev => prev - 1)\n }\n }, [navState.status, animationStep, currentSlide, slides, onSlideChange])\n\n const goToSlide = useCallback(\n (index: number) => {\n if (index < 0 || index >= slides.length || index === currentSlide) {\n return\n }\n\n const direction = index > currentSlide ? 1 : -1\n setNavState({ status: \"transitioning\", direction })\n setAnimationStep(0)\n setCurrentSlide(index)\n onSlideChange?.(index)\n },\n [currentSlide, slides.length, onSlideChange]\n )\n\n useEffect(() => {\n if (navState.status === \"idle\" && queuedAction !== null) {\n setQueuedAction(null)\n if (queuedAction === \"advance\") {\n advance()\n } else if (queuedAction === \"goBack\") {\n goBack()\n }\n }\n }, [navState.status, queuedAction, advance, goBack])\n\n return {\n currentSlide,\n animationStep,\n totalSteps,\n direction: navState.direction,\n isTransitioning: navState.status !== \"idle\",\n showAllAnimations: navState.direction === -1 && navState.status === \"transitioning\",\n advance,\n goBack,\n goToSlide,\n onTransitionComplete\n }\n}\n","import { createContext, useContext, useMemo } from \"react\"\nimport type { ThemeConfig } from \"./types\"\n\nconst ThemeContext = createContext<ThemeConfig | null>(null)\n\n/**\n * Access the full theme config. Returns null outside SlideThemeProvider.\n */\nexport function useTheme(): ThemeConfig | null {\n return useContext(ThemeContext)\n}\n\nfunction buildCssOverrides(theme: ThemeConfig): React.CSSProperties {\n const style: Record<string, string> = {}\n\n if (theme.colors?.primary) style[\"--primary\"] = theme.colors.primary\n if (theme.colors?.primaryForeground) style[\"--primary-foreground\"] = theme.colors.primaryForeground\n if (theme.colors?.secondary) style[\"--secondary\"] = theme.colors.secondary\n if (theme.colors?.secondaryForeground) style[\"--secondary-foreground\"] = theme.colors.secondaryForeground\n if (theme.colors?.accent) style[\"--accent\"] = theme.colors.accent\n if (theme.colors?.accentForeground) style[\"--accent-foreground\"] = theme.colors.accentForeground\n\n if (theme.fonts?.heading) style[\"--font-heading\"] = theme.fonts.heading\n if (theme.fonts?.body) style[\"--font-body\"] = theme.fonts.body\n\n return style as React.CSSProperties\n}\n\ninterface SlideThemeProviderProps {\n theme: ThemeConfig\n children: React.ReactNode\n}\n\n/**\n * Provides the full theme to all descendants.\n * Injects CSS variable overrides via inline style.\n */\nexport function SlideThemeProvider({ theme, children }: SlideThemeProviderProps) {\n const cssOverrides = useMemo(() => buildCssOverrides(theme), [theme])\n\n return (\n <ThemeContext.Provider value={theme}>\n <div style={cssOverrides} className=\"contents\">\n {children}\n </div>\n </ThemeContext.Provider>\n )\n}\n","import { AnimatePresence, motion } from \"framer-motion\"\n\nimport type { SlideTransitionType } from \"./transitions\"\nimport type { NavigationDirection, SlideConfig } from \"./types\"\n\nimport { SLIDE_TRANSITION } from \"./animation-config\"\nimport { AnimationProvider } from \"./animation-context\"\nimport { SlideErrorBoundary } from \"./slide-error-boundary\"\nimport { DEFAULT_SLIDE_TRANSITION, getSlideVariants } from \"./transitions\"\n\n// =============================================================================\n// TYPES\n// =============================================================================\n\nexport interface SlideRendererProps {\n slides: SlideConfig[]\n currentSlide: number\n animationStep: number\n totalSteps: number\n direction: NavigationDirection\n showAllAnimations: boolean\n transition?: SlideTransitionType\n directionalTransition?: boolean\n onTransitionComplete: () => void\n}\n\n// =============================================================================\n// COMPONENT\n// =============================================================================\n\n/**\n * Renders a single slide with animated transitions.\n * Extracted from SlideDeck so it can be reused in SlideEmbed and other contexts.\n */\nexport function SlideRenderer({\n slides,\n currentSlide,\n animationStep,\n totalSteps,\n direction,\n showAllAnimations,\n transition,\n directionalTransition,\n onTransitionComplete\n}: SlideRendererProps) {\n const currentSlideTransition = slides[currentSlide]?.transition\n const transitionType = currentSlideTransition ?? transition ?? DEFAULT_SLIDE_TRANSITION\n const isDirectional = directionalTransition ?? false\n\n const slideVariants = getSlideVariants(\n { type: transitionType, directional: isDirectional },\n direction\n )\n\n const CurrentSlideComponent = slides[currentSlide]!.component\n\n return (\n <AnimatePresence initial={false}>\n <motion.div\n key={currentSlide}\n variants={slideVariants}\n initial=\"enter\"\n animate=\"center\"\n exit=\"exit\"\n transition={SLIDE_TRANSITION}\n onAnimationComplete={definition => {\n if (definition === \"center\") {\n onTransitionComplete()\n }\n }}\n className=\"absolute inset-0 h-full w-full\"\n >\n <AnimationProvider\n currentStep={animationStep}\n totalSteps={totalSteps}\n showAllAnimations={showAllAnimations}\n >\n <SlideErrorBoundary\n slideIndex={currentSlide}\n slideTitle={slides[currentSlide]?.title}\n >\n <CurrentSlideComponent\n slideNumber={currentSlide + 1}\n totalSlides={slides.length}\n />\n </SlideErrorBoundary>\n </AnimationProvider>\n </motion.div>\n </AnimatePresence>\n )\n}\n","import React from \"react\"\n\ninterface SlideErrorBoundaryProps {\n slideIndex: number\n slideTitle?: string\n children: React.ReactNode\n}\n\ninterface SlideErrorBoundaryState {\n hasError: boolean\n error: Error | null\n}\n\nexport class SlideErrorBoundary extends React.Component<\n SlideErrorBoundaryProps,\n SlideErrorBoundaryState\n> {\n state: SlideErrorBoundaryState = { hasError: false, error: null }\n\n static getDerivedStateFromError(error: Error) {\n return { hasError: true, error }\n }\n\n componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {\n console.error(\n `[PromptSlide] Slide ${this.props.slideIndex + 1}${this.props.slideTitle ? ` (\"${this.props.slideTitle}\")` : \"\"} crashed:`,\n error,\n errorInfo\n )\n }\n\n render() {\n if (this.state.hasError) {\n return (\n <div className=\"flex h-full w-full flex-col items-center justify-center bg-red-950/20 p-12\">\n <div className=\"mb-4 text-lg font-semibold text-red-400\">\n Slide {this.props.slideIndex + 1} Error\n {this.props.slideTitle && (\n <span className=\"ml-2 font-normal text-red-400/70\">({this.props.slideTitle})</span>\n )}\n </div>\n <div className=\"max-w-2xl text-center font-mono text-sm break-words text-red-300/80\">\n {this.state.error?.message ?? \"Unknown error\"}\n </div>\n </div>\n )\n }\n return this.props.children\n }\n}\n","import { useCallback, useEffect, useState } from \"react\"\n\nimport type { SlideTransitionType } from \"./transitions\"\nimport type { SlideConfig } from \"./types\"\n\nimport { SLIDE_DIMENSIONS } from \"./animation-config\"\nimport { SlideRenderer } from \"./slide-renderer\"\nimport { useSlideNavigation } from \"./use-slide-navigation\"\n\n// =============================================================================\n// TYPES\n// =============================================================================\n\ninterface SlideEmbedProps {\n slides: SlideConfig[]\n transition?: SlideTransitionType\n directionalTransition?: boolean\n}\n\n// =============================================================================\n// COMPONENT\n// =============================================================================\n\n/**\n * Headless slide viewer controlled via window.postMessage.\n * Designed for embedding in an iframe (e.g. the registry editor preview).\n *\n * Inbound messages (parent → embed):\n * { type: \"navigate\", data: { slide: number } }\n * { type: \"advance\" }\n * { type: \"goBack\" }\n *\n * Outbound messages (embed → parent):\n * { type: \"slideReady\" }\n * { type: \"slideState\", data: { currentSlide, totalSlides, animationStep, totalSteps, titles } }\n * { type: \"hmrUpdate\" }\n */\nexport function SlideEmbed({ slides, transition, directionalTransition }: SlideEmbedProps) {\n const [scale, setScale] = useState(1)\n\n const {\n currentSlide,\n animationStep,\n totalSteps,\n direction,\n showAllAnimations,\n advance,\n goBack,\n goToSlide,\n onTransitionComplete\n } = useSlideNavigation({ slides })\n\n // Post slide state to parent whenever it changes\n useEffect(() => {\n const state = {\n currentSlide,\n totalSlides: slides.length,\n animationStep,\n totalSteps,\n titles: slides.map(s => s.title || \"\")\n }\n window.parent.postMessage({ type: \"slideState\", data: state }, \"*\")\n }, [currentSlide, animationStep, totalSteps, slides])\n\n // Signal readiness on mount\n useEffect(() => {\n window.parent.postMessage({ type: \"slideReady\" }, \"*\")\n }, [])\n\n // Listen for Vite HMR updates\n useEffect(() => {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const hot = (import.meta as any).hot as { on: (event: string, cb: () => void) => void } | undefined\n if (hot) {\n hot.on(\"vite:afterUpdate\", () => {\n window.parent.postMessage({ type: \"hmrUpdate\" }, \"*\")\n })\n }\n }, [])\n\n // Listen for inbound messages from parent\n const handleMessage = useCallback(\n (event: MessageEvent) => {\n const { type, data } = event.data || {}\n switch (type) {\n case \"navigate\":\n if (typeof data?.slide === \"number\") goToSlide(data.slide)\n break\n case \"advance\":\n advance()\n break\n case \"goBack\":\n goBack()\n break\n }\n },\n [advance, goBack, goToSlide]\n )\n\n useEffect(() => {\n window.addEventListener(\"message\", handleMessage)\n return () => window.removeEventListener(\"message\", handleMessage)\n }, [handleMessage])\n\n // Scale to fit viewport while preserving aspect ratio\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=\"h-screen w-screen overflow-hidden bg-black\">\n <div\n className=\"absolute left-1/2 top-1/2 overflow-hidden\"\n style={{\n width: SLIDE_DIMENSIONS.width,\n height: SLIDE_DIMENSIONS.height,\n transform: `translate(-50%, -50%) scale(${scale})`,\n transformOrigin: \"center center\"\n }}\n >\n <SlideRenderer\n slides={slides}\n currentSlide={currentSlide}\n animationStep={animationStep}\n totalSteps={totalSteps}\n direction={direction}\n showAllAnimations={showAllAnimations}\n transition={transition}\n directionalTransition={directionalTransition}\n onTransitionComplete={onTransitionComplete}\n />\n </div>\n </div>\n )\n}\n","import { LayoutGroup } from \"framer-motion\"\nimport { ChevronLeft, ChevronRight, Download, Grid3X3, List, Maximize, MessageCircle, Monitor } from \"lucide-react\"\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\"\n\nimport type { SlideTransitionType } from \"./transitions\"\nimport type { SlideConfig } from \"./types\"\n\nimport { SLIDE_DIMENSIONS } from \"./animation-config\"\nimport { AnimationProvider } from \"./animation-context\"\nimport { AnnotationOverlay, AnnotationPanel, useAnnotations } from \"./annotations\"\nimport type { Annotation, AnnotationTarget } from \"./annotations\"\nimport { SlideErrorBoundary } from \"./slide-error-boundary\"\nimport { SlideRenderer } from \"./slide-renderer\"\nimport { useSlideNavigation } from \"./use-slide-navigation\"\nimport { cn } from \"./utils\"\n\n// =============================================================================\n// TYPES\n// =============================================================================\n\ntype ViewMode = \"slide\" | \"list\" | \"grid\"\n\ninterface SlideDeckProps {\n slides: SlideConfig[]\n transition?: SlideTransitionType\n directionalTransition?: boolean\n /** Annotation data to display. When provided (even empty array), annotation UI is enabled. When undefined, annotation UI is hidden. */\n annotations?: Annotation[]\n /** Called when the user creates an annotation */\n onAnnotationAdd?: (slideIndex: number, slideTitle: string, target: AnnotationTarget, body: string) => void\n /** Called when the user deletes an annotation */\n onAnnotationDelete?: (id: string) => void\n}\n\n// =============================================================================\n// EXPORT VIEW (for Playwright screenshot capture)\n// =============================================================================\n\nfunction SlideExportView({ slides, slideIndex }: { slides: SlideConfig[]; slideIndex: number }) {\n const [ready, setReady] = useState(false)\n const clampedIndex = Math.max(0, Math.min(slideIndex, slides.length - 1))\n const slideConfig = slides[clampedIndex]!\n const SlideComponent = slideConfig.component\n\n useEffect(() => {\n setReady(true)\n }, [])\n\n return (\n <div\n data-export-ready={ready ? \"true\" : undefined}\n style={{\n width: SLIDE_DIMENSIONS.width,\n height: SLIDE_DIMENSIONS.height,\n overflow: \"hidden\",\n position: \"relative\",\n background: \"black\"\n }}\n >\n <AnimationProvider\n currentStep={slideConfig.steps}\n totalSteps={slideConfig.steps}\n showAllAnimations={true}\n >\n <SlideErrorBoundary slideIndex={clampedIndex} slideTitle={slideConfig.title}>\n <SlideComponent slideNumber={clampedIndex + 1} totalSlides={slides.length} />\n </SlideErrorBoundary>\n </AnimationProvider>\n </div>\n )\n}\n\n// =============================================================================\n// COMPONENT\n// =============================================================================\n\nexport function SlideDeck({ slides, transition, directionalTransition, annotations, onAnnotationAdd, onAnnotationDelete }: SlideDeckProps) {\n // Check for export mode via URL params\n const [exportParams] = useState(() => {\n if (typeof window === \"undefined\") return null\n const params = new URLSearchParams(window.location.search)\n if (params.get(\"export\") !== \"true\") return null\n return { slideIndex: parseInt(params.get(\"slide\") || \"0\", 10) }\n })\n\n if (exportParams) {\n return <SlideExportView slides={slides} slideIndex={exportParams.slideIndex} />\n }\n\n // Use internal useAnnotations as fallback when no external annotations prop is provided\n const internal = useAnnotations()\n const isExternallyManaged = annotations !== undefined\n const effectiveAnnotations = isExternallyManaged ? annotations : internal.annotations\n const effectiveAdd = isExternallyManaged ? onAnnotationAdd : internal.addAnnotation\n const effectiveDelete = isExternallyManaged ? onAnnotationDelete : internal.deleteAnnotation\n\n const openCount = useMemo(() => effectiveAnnotations.filter(a => a.status === \"open\").length, [effectiveAnnotations])\n const getSlideAnnotations = useCallback(\n (slideIndex: number) => effectiveAnnotations.filter(a => a.slideIndex === slideIndex),\n [effectiveAnnotations]\n )\n\n const [viewMode, setViewMode] = useState<ViewMode>(\"slide\")\n const [isPresentationMode, setIsPresentationMode] = useState(false)\n const [isAnnotationMode, setIsAnnotationMode] = useState(false)\n const [showAnnotationPanel, setShowAnnotationPanel] = useState(false)\n const [selectedAnnotationId, setSelectedAnnotationId] = useState<string | null>(null)\n const [scale, setScale] = useState(1)\n const containerRef = useRef<HTMLDivElement>(null)\n const slideContainerRef = useRef<HTMLDivElement>(null)\n\n const {\n currentSlide,\n animationStep,\n totalSteps,\n direction,\n showAllAnimations,\n advance,\n goBack,\n goToSlide,\n onTransitionComplete\n } = useSlideNavigation({\n slides\n })\n\n const togglePresentationMode = useCallback(async () => {\n if (!document.fullscreenElement) {\n await document.documentElement.requestFullscreen()\n } else {\n await document.exitFullscreen()\n }\n }, [])\n\n // Listen for fullscreen changes\n useEffect(() => {\n const handleFullscreenChange = () => {\n setIsPresentationMode(!!document.fullscreenElement)\n }\n document.addEventListener(\"fullscreenchange\", handleFullscreenChange)\n return () => document.removeEventListener(\"fullscreenchange\", handleFullscreenChange)\n }, [])\n\n // Calculate scale factor for presentation mode\n useEffect(() => {\n const calculateScale = () => {\n if (!isPresentationMode) {\n setScale(1)\n return\n }\n const viewportWidth = window.innerWidth\n const viewportHeight = window.innerHeight\n const scaleX = viewportWidth / SLIDE_DIMENSIONS.width\n const scaleY = viewportHeight / SLIDE_DIMENSIONS.height\n setScale(Math.min(scaleX, scaleY))\n }\n\n calculateScale()\n window.addEventListener(\"resize\", calculateScale)\n return () => window.removeEventListener(\"resize\", calculateScale)\n }, [isPresentationMode])\n\n const handleExportPdf = () => {\n const previousMode = viewMode\n setViewMode(\"list\")\n\n setTimeout(() => {\n const handleAfterPrint = () => {\n setViewMode(previousMode)\n window.removeEventListener(\"afterprint\", handleAfterPrint)\n }\n window.addEventListener(\"afterprint\", handleAfterPrint)\n window.print()\n }, 100)\n }\n\n // Keyboard navigation\n useEffect(() => {\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.key === \"f\" || e.key === \"F\") {\n togglePresentationMode()\n return\n }\n\n // G for grid view toggle\n if (e.key === \"g\" || e.key === \"G\") {\n setViewMode(prev => (prev === \"grid\" ? \"slide\" : \"grid\"))\n return\n }\n\n if (viewMode !== \"slide\" || isAnnotationMode) return\n\n if (e.key === \"ArrowRight\" || e.key === \" \") {\n e.preventDefault()\n advance()\n } else if (e.key === \"ArrowLeft\") {\n e.preventDefault()\n goBack()\n }\n }\n\n window.addEventListener(\"keydown\", handleKeyDown)\n return () => window.removeEventListener(\"keydown\", handleKeyDown)\n }, [advance, goBack, viewMode, togglePresentationMode, isAnnotationMode])\n\n return (\n <div className=\"min-h-screen w-full bg-neutral-950 text-foreground\">\n <style>{`\n @media print {\n @page {\n size: 1920px 1080px;\n margin: 0;\n }\n html,\n body {\n width: 100%;\n height: 100%;\n margin: 0 !important;\n padding: 0 !important;\n overflow: visible !important;\n }\n body {\n print-color-adjust: exact;\n -webkit-print-color-adjust: exact;\n background: transparent !important;\n }\n }\n `}</style>\n\n {/* Toolbar */}\n <div\n className={cn(\n \"fixed top-4 z-50 flex gap-1 rounded-lg border border-neutral-800 bg-neutral-950/90 p-1 backdrop-blur-sm transition-[right] print:hidden\",\n isPresentationMode && \"hidden\",\n isAnnotationMode && showAnnotationPanel ? \"right-[19.5rem]\" : \"right-4\"\n )}\n >\n <button\n onClick={() => setViewMode(\"slide\")}\n className={cn(\n \"rounded-md p-2 text-neutral-400 transition-colors hover:bg-neutral-800 hover:text-white\",\n viewMode === \"slide\" && \"bg-neutral-800 text-white\"\n )}\n title=\"Presentation View\"\n >\n <Monitor className=\"h-4 w-4\" />\n </button>\n <button\n onClick={() => setViewMode(\"list\")}\n className={cn(\n \"rounded-md p-2 text-neutral-400 transition-colors hover:bg-neutral-800 hover:text-white\",\n viewMode === \"list\" && \"bg-neutral-800 text-white\"\n )}\n title=\"List View\"\n >\n <List className=\"h-4 w-4\" />\n </button>\n <button\n onClick={() => setViewMode(\"grid\")}\n className={cn(\n \"rounded-md p-2 text-neutral-400 transition-colors hover:bg-neutral-800 hover:text-white\",\n viewMode === \"grid\" && \"bg-neutral-800 text-white\"\n )}\n title=\"Grid View\"\n >\n <Grid3X3 className=\"h-4 w-4\" />\n </button>\n\n <div className=\"mx-1 w-px bg-neutral-800\" />\n\n <button\n onClick={() => {\n setIsAnnotationMode(prev => {\n const next = !prev\n setShowAnnotationPanel(next)\n if (!next) setSelectedAnnotationId(null)\n return next\n })\n }}\n className={cn(\n \"relative rounded-md p-2 text-neutral-400 transition-colors hover:bg-neutral-800 hover:text-white\",\n isAnnotationMode && \"bg-[#FF6B35] text-white hover:bg-[#FF7A4A]\"\n )}\n title=\"Annotate slides\"\n >\n <MessageCircle className=\"h-4 w-4\" />\n {openCount > 0 && (\n <span className=\"absolute -top-1 -right-1 flex h-4 w-4 items-center justify-center rounded-full bg-[#FF6B35] text-[10px] font-bold text-white\">\n {openCount}\n </span>\n )}\n </button>\n\n <div className=\"mx-1 w-px bg-neutral-800\" />\n\n <button\n onClick={handleExportPdf}\n className=\"rounded-md p-2 text-neutral-400 transition-colors hover:bg-neutral-800 hover:text-white\"\n title=\"Download PDF\"\n >\n <Download className=\"h-4 w-4\" />\n </button>\n <button\n onClick={togglePresentationMode}\n className=\"rounded-md p-2 text-neutral-400 transition-colors hover:bg-neutral-800 hover:text-white\"\n title=\"Present (F)\"\n >\n <Maximize className=\"h-4 w-4\" />\n </button>\n </div>\n\n {/* Slide View */}\n {viewMode === \"slide\" && (\n <div\n className={cn(\n \"flex h-screen w-full print:hidden\",\n isPresentationMode ? \"bg-black\" : \"\"\n )}\n >\n <div\n ref={containerRef}\n role=\"presentation\"\n tabIndex={isPresentationMode ? 0 : undefined}\n className={cn(\n \"flex flex-1 flex-col items-center justify-center overflow-hidden\",\n isPresentationMode ? \"bg-black p-0\" : \"p-4 md:p-8\"\n )}\n onClick={isPresentationMode ? advance : undefined}\n onKeyDown={\n isPresentationMode\n ? e => {\n if (e.key === \"Enter\" || e.key === \" \") advance()\n }\n : undefined\n }\n >\n <LayoutGroup id=\"slide-deck\">\n {isPresentationMode ? (\n <div\n className=\"pointer-events-none relative overflow-hidden bg-black\"\n style={{\n width: SLIDE_DIMENSIONS.width,\n height: SLIDE_DIMENSIONS.height,\n transform: `scale(${scale})`,\n transformOrigin: \"center center\"\n }}\n >\n <SlideRenderer\n slides={slides}\n currentSlide={currentSlide}\n animationStep={animationStep}\n totalSteps={totalSteps}\n direction={direction}\n showAllAnimations={showAllAnimations}\n transition={transition}\n directionalTransition={directionalTransition}\n onTransitionComplete={onTransitionComplete}\n />\n </div>\n ) : (\n <div ref={slideContainerRef} className=\"relative aspect-video w-full max-w-7xl overflow-hidden rounded-xl border border-neutral-800 bg-black shadow-2xl\">\n <SlideRenderer\n slides={slides}\n currentSlide={currentSlide}\n animationStep={animationStep}\n totalSteps={totalSteps}\n direction={direction}\n showAllAnimations={showAllAnimations}\n transition={transition}\n directionalTransition={directionalTransition}\n onTransitionComplete={onTransitionComplete}\n />\n {isAnnotationMode && (\n <AnnotationOverlay\n slides={slides}\n currentSlide={currentSlide}\n slideContainerRef={slideContainerRef}\n selectedId={selectedAnnotationId}\n onSelectId={setSelectedAnnotationId}\n onShowPanel={() => setShowAnnotationPanel(true)}\n slideAnnotations={getSlideAnnotations(currentSlide)}\n addAnnotation={effectiveAdd ?? (() => {})}\n\n />\n )}\n </div>\n )}\n </LayoutGroup>\n\n {/* Navigation Controls */}\n {!isPresentationMode && (\n <div className=\"mt-6 flex items-center gap-4\">\n <button\n onClick={goBack}\n className=\"rounded-full border border-neutral-800 bg-black/50 p-2 text-neutral-400 backdrop-blur-sm transition-colors hover:bg-neutral-900 hover:text-white\"\n >\n <ChevronLeft className=\"h-5 w-5\" />\n </button>\n <div className=\"flex min-w-[4rem] flex-col items-center\">\n <span className=\"font-mono text-sm text-neutral-500\">\n {currentSlide + 1} / {slides.length}\n </span>\n {slides[currentSlide]?.title && (\n <span className=\"mt-0.5 text-xs text-neutral-600\">\n {slides[currentSlide].title}\n </span>\n )}\n </div>\n <button\n onClick={advance}\n className=\"rounded-full border border-neutral-800 bg-black/50 p-2 text-neutral-400 backdrop-blur-sm transition-colors hover:bg-neutral-900 hover:text-white\"\n >\n <ChevronRight className=\"h-5 w-5\" />\n </button>\n </div>\n )}\n </div>\n\n {/* Annotation Panel — beside the slide */}\n {isAnnotationMode && showAnnotationPanel && !isPresentationMode && (\n <AnnotationPanel\n annotations={getSlideAnnotations(currentSlide)}\n selectedId={selectedAnnotationId}\n onSelect={setSelectedAnnotationId}\n onDelete={effectiveDelete ?? (() => {})}\n onClose={() => {\n setShowAnnotationPanel(false)\n setSelectedAnnotationId(null)\n }}\n />\n )}\n </div>\n )}\n\n {/* Grid View */}\n {viewMode === \"grid\" && (\n <div className=\"mx-auto max-w-7xl p-8 pt-16 print:hidden\">\n <div className=\"grid grid-cols-2 gap-4 md:grid-cols-3 lg:grid-cols-4\">\n {slides.map((slideConfig, index) => {\n const SlideComponent = slideConfig.component\n const prevSection = index > 0 ? slides[index - 1]?.section : undefined\n const showSectionHeader = slideConfig.section && slideConfig.section !== prevSection\n\n return (\n <div key={index} className={showSectionHeader ? \"col-span-full\" : undefined}>\n {showSectionHeader && (\n <h3 className=\"mt-4 mb-3 text-xs font-bold tracking-[0.2em] text-neutral-500 uppercase first:mt-0\">\n {slideConfig.section}\n </h3>\n )}\n <button\n onClick={() => {\n goToSlide(index)\n setViewMode(\"slide\")\n }}\n className=\"group relative aspect-video w-full overflow-hidden rounded-lg border border-neutral-800 bg-black shadow-sm transition-all hover:border-primary hover:shadow-lg hover:shadow-primary/10\"\n >\n <div\n className=\"h-full w-full origin-top-left scale-[0.25]\"\n style={{ width: \"400%\", height: \"400%\" }}\n >\n <AnimationProvider\n currentStep={slideConfig.steps}\n totalSteps={slideConfig.steps}\n showAllAnimations={true}\n >\n <SlideErrorBoundary slideIndex={index} slideTitle={slideConfig.title}>\n <SlideComponent slideNumber={index + 1} totalSlides={slides.length} />\n </SlideErrorBoundary>\n </AnimationProvider>\n </div>\n <div className=\"absolute inset-0 bg-black/0 transition-colors group-hover:bg-black/20\" />\n <div className=\"absolute bottom-2 left-2 rounded bg-black/70 px-2 py-1 text-xs font-medium text-white\">\n {slideConfig.title ? `${index + 1}. ${slideConfig.title}` : index + 1}\n </div>\n </button>\n </div>\n )\n })}\n </div>\n </div>\n )}\n\n {/* List View */}\n <div\n className={cn(\n \"mx-auto max-w-7xl p-8 pt-16\",\n \"print:m-0 print:block print:max-w-none print:p-0\",\n viewMode === \"list\" ? \"block\" : \"hidden print:block\"\n )}\n >\n <div className=\"grid grid-cols-1 gap-8 print:block\">\n {slides.map((slideConfig, index) => {\n const SlideComponent = slideConfig.component\n return (\n <div\n key={index}\n className=\"aspect-video w-full overflow-hidden rounded-xl border border-neutral-800 bg-black shadow-sm print:relative print:m-0 print:h-[1080px] print:w-[1920px] print:break-after-page print:overflow-hidden print:rounded-none print:border-0 print:shadow-none\"\n >\n <div className=\"h-full w-full print:h-[720px] print:w-[1280px] print:origin-top-left print:scale-[1.5]\">\n <AnimationProvider\n currentStep={slideConfig.steps}\n totalSteps={slideConfig.steps}\n showAllAnimations={true}\n >\n <SlideErrorBoundary slideIndex={index} slideTitle={slideConfig.title}>\n <SlideComponent slideNumber={index + 1} totalSlides={slides.length} />\n </SlideErrorBoundary>\n </AnimationProvider>\n </div>\n </div>\n )\n })}\n </div>\n </div>\n </div>\n )\n}\n","import { useCallback, useEffect, useRef, useState } from \"react\"\nimport type { SlideConfig } from \"../types\"\nimport { AnnotationForm } from \"./annotation-form\"\nimport { AnnotationPin } from \"./annotation-pin\"\nimport { buildElementTarget, resolveTarget } from \"./selectors\"\nimport type { Annotation, AnnotationTarget } from \"./types\"\n\ninterface AnnotationOverlayProps {\n slides: SlideConfig[]\n currentSlide: number\n /** Ref to the slide container element (the div wrapping SlideRenderer) */\n slideContainerRef: React.RefObject<HTMLDivElement | null>\n selectedId: string | null\n onSelectId: (id: string | null) => void\n onShowPanel: () => void\n slideAnnotations: Annotation[]\n addAnnotation: (slideIndex: number, slideTitle: string, target: AnnotationTarget, body: string) => void\n}\n\ninterface PendingAnnotation {\n target: AnnotationTarget\n xPercent: number\n yPercent: number\n}\n\nexport function AnnotationOverlay({ slides, currentSlide, slideContainerRef, selectedId, onSelectId, onShowPanel, slideAnnotations, addAnnotation }: AnnotationOverlayProps) {\n const [pending, setPending] = useState<PendingAnnotation | null>(null)\n const [hoveredElement, setHoveredElement] = useState<DOMRect | null>(null)\n const overlayRef = useRef<HTMLDivElement>(null)\n\n const slideTitle = slides[currentSlide]?.title || `Slide ${currentSlide + 1}`\n\n // Resolve annotation positions — use the element if found, otherwise fallback coordinates\n const resolvedAnnotations = slideAnnotations.map((a, i) => {\n const container = slideContainerRef.current\n if (!container) {\n return { annotation: a, xPercent: a.target.position.xPercent, yPercent: a.target.position.yPercent, number: i + 1 }\n }\n\n const { element } = resolveTarget(a.target, container)\n if (element) {\n const rect = element.getBoundingClientRect()\n const containerRect = container.getBoundingClientRect()\n const xPercent = ((rect.left + rect.width / 2 - containerRect.left) / containerRect.width) * 100\n const yPercent = ((rect.top + rect.height / 2 - containerRect.top) / containerRect.height) * 100\n return { annotation: a, xPercent, yPercent, number: i + 1 }\n }\n\n return { annotation: a, xPercent: a.target.position.xPercent, yPercent: a.target.position.yPercent, number: i + 1 }\n })\n\n const handleOverlayClick = useCallback(\n (e: React.MouseEvent) => {\n const container = slideContainerRef.current\n if (!container) return\n\n // Get the element under the click by temporarily hiding the overlay\n const overlay = overlayRef.current\n if (overlay) overlay.style.pointerEvents = \"none\"\n const elementUnder = document.elementFromPoint(e.clientX, e.clientY) as HTMLElement | null\n if (overlay) overlay.style.pointerEvents = \"\"\n\n if (!elementUnder || !container.contains(elementUnder)) {\n setPending(null)\n onSelectId(null)\n return\n }\n\n // Pick the most specific meaningful element (skip tiny text nodes, pick their parent)\n let target = elementUnder\n if (target.tagName === \"SPAN\" && target.parentElement && container.contains(target.parentElement)) {\n // For inline spans, prefer their parent for a more meaningful target\n const parent = target.parentElement\n if (parent.tagName !== \"DIV\" || parent.children.length <= 3) {\n target = parent\n }\n }\n\n const annotationTarget = buildElementTarget(target, container)\n const containerRect = container.getBoundingClientRect()\n const xPercent = ((e.clientX - containerRect.left) / containerRect.width) * 100\n const yPercent = ((e.clientY - containerRect.top) / containerRect.height) * 100\n\n setPending({ target: annotationTarget, xPercent, yPercent })\n onSelectId(null)\n },\n [slideContainerRef, onSelectId]\n )\n\n const handleSubmit = useCallback(\n (text: string) => {\n if (!pending) return\n addAnnotation(currentSlide, slideTitle, pending.target, text)\n setPending(null)\n onShowPanel()\n },\n [pending, currentSlide, slideTitle, addAnnotation, onShowPanel]\n )\n\n // Track hover for element highlighting\n const handleMouseMove = useCallback(\n (e: React.MouseEvent) => {\n if (pending) {\n setHoveredElement(null)\n return\n }\n\n const container = slideContainerRef.current\n if (!container) return\n\n const overlay = overlayRef.current\n if (overlay) overlay.style.pointerEvents = \"none\"\n const elementUnder = document.elementFromPoint(e.clientX, e.clientY) as HTMLElement | null\n if (overlay) overlay.style.pointerEvents = \"\"\n\n if (elementUnder && container.contains(elementUnder) && elementUnder !== container) {\n const containerRect = container.getBoundingClientRect()\n const elRect = elementUnder.getBoundingClientRect()\n setHoveredElement(\n new DOMRect(\n elRect.left - containerRect.left,\n elRect.top - containerRect.top,\n elRect.width,\n elRect.height\n )\n )\n } else {\n setHoveredElement(null)\n }\n },\n [slideContainerRef, pending]\n )\n\n // Clear pending when slide changes\n useEffect(() => {\n setPending(null)\n onSelectId(null)\n setHoveredElement(null)\n }, [currentSlide, onSelectId])\n\n return (\n <>\n {/* Hover highlight */}\n {hoveredElement && (\n <div\n className=\"pointer-events-none absolute z-20 rounded-lg border-2 border-dashed border-[#FF6B35]/50 bg-[#FF6B35]/5\"\n style={{\n left: hoveredElement.x,\n top: hoveredElement.y,\n width: hoveredElement.width,\n height: hoveredElement.height\n }}\n />\n )}\n\n {/* Click capture overlay */}\n <div\n ref={overlayRef}\n role=\"button\"\n tabIndex={0}\n className=\"absolute inset-0 z-20\"\n style={{ cursor: `url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none'%3E%3Ccircle cx='12' cy='12' r='8' stroke='%23FF6B35' stroke-width='2' opacity='0.8'/%3E%3Ccircle cx='12' cy='12' r='2' fill='%23FF6B35'/%3E%3C/svg%3E\") 12 12, crosshair` }}\n onClick={handleOverlayClick}\n onKeyDown={e => { if (e.key === \"Escape\") { setPending(null); onSelectId(null) } }}\n onMouseMove={handleMouseMove}\n onMouseLeave={() => setHoveredElement(null)}\n />\n\n {/* Annotation pins */}\n {resolvedAnnotations.map(({ annotation, xPercent, yPercent, number }) => (\n <AnnotationPin\n key={annotation.id}\n number={number}\n status={annotation.status}\n xPercent={xPercent}\n yPercent={yPercent}\n isSelected={annotation.id === selectedId}\n onClick={() => {\n onSelectId(annotation.id === selectedId ? null : annotation.id)\n onShowPanel()\n setPending(null)\n }}\n />\n ))}\n\n {/* New annotation form */}\n {pending && (\n <AnnotationForm\n xPercent={pending.xPercent}\n yPercent={pending.yPercent}\n onSubmit={handleSubmit}\n onCancel={() => setPending(null)}\n />\n )}\n\n </>\n )\n}\n","import { useEffect, useRef, useState } from \"react\"\nimport { ArrowUp, X } from \"lucide-react\"\n\ninterface AnnotationFormProps {\n xPercent: number\n yPercent: number\n onSubmit: (text: string) => void\n onCancel: () => void\n}\n\nexport function AnnotationForm({ xPercent, yPercent, onSubmit, onCancel }: AnnotationFormProps) {\n const [text, setText] = useState(\"\")\n const textareaRef = useRef<HTMLTextAreaElement>(null)\n\n useEffect(() => {\n textareaRef.current?.focus()\n }, [])\n\n const handleSubmit = () => {\n const trimmed = text.trim()\n if (!trimmed) return\n onSubmit(trimmed)\n }\n\n const handleKeyDown = (e: React.KeyboardEvent) => {\n if (e.key === \"Enter\" && !e.shiftKey) {\n e.preventDefault()\n handleSubmit()\n }\n if (e.key === \"Escape\") {\n onCancel()\n }\n e.stopPropagation()\n }\n\n // Position the form, flipping if near edges\n const left = xPercent > 70 ? undefined : `${xPercent}%`\n const right = xPercent > 70 ? `${100 - xPercent}%` : undefined\n const top = yPercent > 70 ? undefined : `${yPercent}%`\n const bottom = yPercent > 70 ? `${100 - yPercent}%` : undefined\n\n return (\n <div\n role=\"dialog\"\n className=\"absolute z-40 w-72 overflow-hidden rounded-xl border border-white/[0.08] bg-neutral-900/95 shadow-2xl backdrop-blur-2xl\"\n style={{ left, right, top, bottom }}\n onClick={e => e.stopPropagation()}\n onKeyDown={e => e.stopPropagation()}\n >\n <div className=\"flex items-center justify-between border-b border-white/[0.06] px-3.5 py-2.5\">\n <span className=\"text-xs font-medium tracking-wide text-neutral-400\">Add annotation</span>\n <button\n onClick={onCancel}\n className=\"rounded-lg p-1 text-neutral-500 transition-colors hover:bg-white/[0.06] hover:text-neutral-300\"\n >\n <X className=\"h-3.5 w-3.5\" />\n </button>\n </div>\n <div className=\"p-3\">\n <textarea\n ref={textareaRef}\n value={text}\n onChange={e => setText(e.target.value)}\n onKeyDown={handleKeyDown}\n placeholder=\"Describe the change you want...\"\n className=\"w-full resize-none rounded-lg border border-white/[0.08] bg-white/[0.04] px-3 py-2 text-sm text-white placeholder-neutral-500 outline-none transition-colors focus:border-[#FF6B35]/50 focus:bg-white/[0.06]\"\n rows={3}\n />\n <div className=\"mt-2.5 flex items-center justify-between\">\n <span className=\"text-[11px] text-neutral-600\">Enter to send</span>\n <button\n onClick={handleSubmit}\n disabled={!text.trim()}\n className=\"flex h-7 w-7 items-center justify-center rounded-lg bg-[#FF6B35] text-white shadow-lg shadow-[#FF6B35]/20 transition-all hover:bg-[#FF7A4A] hover:shadow-[#FF6B35]/30 disabled:opacity-30 disabled:shadow-none disabled:hover:bg-[#FF6B35]\"\n >\n <ArrowUp className=\"h-3.5 w-3.5\" strokeWidth={2.5} />\n </button>\n </div>\n </div>\n </div>\n )\n}\n","interface AnnotationPinProps {\n number: number\n status: \"open\" | \"resolved\"\n xPercent: number\n yPercent: number\n isSelected: boolean\n onClick: () => void\n}\n\nexport function AnnotationPin({ number, status, xPercent, yPercent, isSelected, onClick }: AnnotationPinProps) {\n const isResolved = status === \"resolved\"\n\n return (\n <button\n onClick={e => {\n e.stopPropagation()\n onClick()\n }}\n className=\"absolute z-30 -translate-x-1/2 -translate-y-1/2 transition-all duration-200 hover:scale-110\"\n style={{ left: `${xPercent}%`, top: `${yPercent}%` }}\n title={`Annotation #${number}`}\n >\n {/* Glow ring */}\n {isSelected && !isResolved && (\n <div className=\"absolute inset-[-4px] animate-pulse rounded-full bg-[#FF6B35]/25 blur-sm\" />\n )}\n <div\n className={`relative flex h-7 w-7 items-center justify-center rounded-full text-[11px] font-semibold shadow-lg backdrop-blur-sm transition-all duration-200 ${\n isSelected\n ? isResolved\n ? \"bg-neutral-500/90 text-white ring-2 ring-neutral-400/50\"\n : \"bg-[#FF6B35] text-white ring-2 ring-[#FF6B35]/40 ring-offset-1 ring-offset-black/50\"\n : isResolved\n ? \"bg-neutral-700/80 text-neutral-400\"\n : \"bg-[#FF6B35]/90 text-white hover:bg-[#FF6B35]\"\n }`}\n >\n {number}\n </div>\n </button>\n )\n}\n","import type { AnnotationTarget } from \"./types\"\n\n/**\n * Build a composite target descriptor from a clicked DOM element.\n */\nexport function buildElementTarget(\n element: HTMLElement,\n slideRoot: HTMLElement\n): AnnotationTarget {\n const rect = element.getBoundingClientRect()\n const rootRect = slideRoot.getBoundingClientRect()\n\n const xPercent = ((rect.left + rect.width / 2 - rootRect.left) / rootRect.width) * 100\n const yPercent = ((rect.top + rect.height / 2 - rootRect.top) / rootRect.height) * 100\n\n return {\n dataAnnotate: element.getAttribute(\"data-annotate\") || undefined,\n contentNearPin: getTextFingerprint(element),\n position: { xPercent, yPercent }\n }\n}\n\n/**\n * Resolve a stored target back to a DOM element, trying strategies in priority order.\n */\nexport function resolveTarget(\n target: AnnotationTarget,\n slideRoot: HTMLElement\n): { element: HTMLElement | null; method: \"dataAnnotate\" | \"contentNearPin\" | \"position\" } {\n // 1. Try data-annotate attribute\n if (target.dataAnnotate) {\n const el = slideRoot.querySelector<HTMLElement>(`[data-annotate=\"${target.dataAnnotate}\"]`)\n if (el) return { element: el, method: \"dataAnnotate\" }\n }\n\n // 2. Try text content match\n if (target.contentNearPin) {\n const match = findByTextContent(slideRoot, target.contentNearPin)\n if (match) return { element: match, method: \"contentNearPin\" }\n }\n\n // 3. Fallback to coordinates (no element found)\n return { element: null, method: \"position\" }\n}\n\n/**\n * Extract a text fingerprint from an element (first 100 chars, trimmed).\n */\nfunction getTextFingerprint(element: HTMLElement): string | undefined {\n const text = element.textContent?.trim()\n if (!text) return undefined\n return text.slice(0, 100)\n}\n\n/**\n * Find an element by matching its text content.\n */\nfunction findByTextContent(root: HTMLElement, text: string): HTMLElement | null {\n const walker = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT)\n let best: HTMLElement | null = null\n let bestLength = Infinity\n\n while (walker.nextNode()) {\n const el = walker.currentNode as HTMLElement\n const elText = el.textContent?.trim()\n if (!elText) continue\n\n const elFingerprint = elText.slice(0, 100)\n if (elFingerprint === text && elText.length < bestLength) {\n best = el\n bestLength = elText.length\n }\n }\n\n return best\n}\n","import { MessageCircle, Trash2, X } from \"lucide-react\"\nimport type { Annotation } from \"./types\"\n\ninterface AnnotationPanelProps {\n annotations: Annotation[]\n selectedId: string | null\n onSelect: (id: string) => void\n onDelete: (id: string) => void\n onClose: () => void\n}\n\nexport function AnnotationPanel({ annotations, selectedId, onSelect, onDelete, onClose }: AnnotationPanelProps) {\n const open = annotations.filter(a => a.status === \"open\")\n const resolved = annotations.filter(a => a.status === \"resolved\")\n\n return (\n <div className=\"flex h-full w-80 flex-shrink-0 flex-col border-l border-white/[0.06] bg-neutral-950/95 backdrop-blur-2xl\">\n <div className=\"flex items-center justify-between px-4 py-3.5\">\n <div className=\"flex items-center gap-2.5\">\n <div className=\"flex h-6 w-6 items-center justify-center rounded-lg bg-[#FF6B35]/15\">\n <MessageCircle className=\"h-3.5 w-3.5 text-[#FF6B35]\" />\n </div>\n <span className=\"text-sm font-medium text-white\">Annotations</span>\n {open.length > 0 && (\n <span className=\"flex h-5 min-w-5 items-center justify-center rounded-full bg-[#FF6B35]/15 px-1.5 text-[11px] font-semibold text-[#FF6B35]\">\n {open.length}\n </span>\n )}\n </div>\n <button\n onClick={onClose}\n className=\"rounded-lg p-1.5 text-neutral-500 transition-colors hover:bg-white/[0.06] hover:text-neutral-300\"\n >\n <X className=\"h-4 w-4\" />\n </button>\n </div>\n\n <div className=\"h-px bg-gradient-to-r from-transparent via-white/[0.06] to-transparent\" />\n\n <div className=\"flex-1 overflow-y-auto p-2\">\n {annotations.length === 0 && (\n <div className=\"flex flex-col items-center gap-2 px-4 py-8 text-center\">\n <div className=\"flex h-10 w-10 items-center justify-center rounded-xl bg-white/[0.04]\">\n <MessageCircle className=\"h-5 w-5 text-neutral-600\" />\n </div>\n <p className=\"text-sm text-neutral-500\">Click on slide elements to add annotations</p>\n </div>\n )}\n\n {open.length > 0 && (\n <div>\n <div className=\"mb-1.5 px-2 pt-1 text-[11px] font-medium tracking-wider text-neutral-500 uppercase\">\n Open\n </div>\n {open.map((a, i) => (\n <AnnotationItem\n key={a.id}\n annotation={a}\n number={i + 1}\n isSelected={a.id === selectedId}\n onSelect={() => onSelect(a.id)}\n onDelete={() => onDelete(a.id)}\n />\n ))}\n </div>\n )}\n\n {resolved.length > 0 && (\n <div className={open.length > 0 ? \"mt-3\" : \"\"}>\n <div className=\"mb-1.5 px-2 pt-1 text-[11px] font-medium tracking-wider text-neutral-500 uppercase\">\n Resolved\n </div>\n {resolved.map((a, i) => (\n <AnnotationItem\n key={a.id}\n annotation={a}\n number={open.length + i + 1}\n isSelected={a.id === selectedId}\n onSelect={() => onSelect(a.id)}\n onDelete={() => onDelete(a.id)}\n />\n ))}\n </div>\n )}\n </div>\n </div>\n )\n}\n\nfunction AnnotationItem({\n annotation,\n number,\n isSelected,\n onSelect,\n onDelete\n}: {\n annotation: Annotation\n number: number\n isSelected: boolean\n onSelect: () => void\n onDelete: () => void\n}) {\n return (\n <div\n role=\"button\"\n tabIndex={0}\n onClick={onSelect}\n onKeyDown={e => { if (e.key === \"Enter\" || e.key === \" \") onSelect() }}\n className={`group relative mb-0.5 cursor-pointer rounded-xl p-2.5 transition-all duration-150 ${\n isSelected\n ? \"bg-[#FF6B35]/10 ring-1 ring-[#FF6B35]/20\"\n : \"hover:bg-white/[0.04]\"\n }`}\n >\n <button\n onClick={e => {\n e.stopPropagation()\n onDelete()\n }}\n className=\"absolute top-2 right-2 rounded-lg p-1 text-neutral-600 opacity-0 transition-all hover:bg-white/[0.08] hover:text-neutral-300 group-hover:opacity-100\"\n >\n <Trash2 className=\"h-3 w-3\" />\n </button>\n <div className=\"flex items-start gap-2.5\">\n <div\n className={`mt-0.5 flex h-5 w-5 flex-shrink-0 items-center justify-center rounded-full text-[11px] font-semibold ${\n annotation.status === \"open\"\n ? \"bg-[#FF6B35] text-white\"\n : \"bg-neutral-700 text-neutral-400\"\n }`}\n >\n {number}\n </div>\n <div className=\"min-w-0 pr-4\">\n <p className=\"text-[13px] leading-relaxed text-neutral-200\">{annotation.body}</p>\n {annotation.target.contentNearPin && (\n <p className=\"mt-1 truncate text-[11px] text-neutral-600\">\n {annotation.target.contentNearPin}\n </p>\n )}\n {annotation.resolution && (\n <p className=\"mt-1.5 text-[11px] text-emerald-400/80 italic\">\n {annotation.resolution}\n </p>\n )}\n </div>\n </div>\n </div>\n )\n}\n","import { useCallback, useEffect, useMemo, useRef, useState } from \"react\"\nimport { createHttpAdapter } from \"./adapters/http\"\nimport type { Annotation, AnnotationStorageAdapter, AnnotationTarget } from \"./types\"\n\nexport function useAnnotations(adapter?: AnnotationStorageAdapter) {\n const adapterRef = useRef(adapter ?? createHttpAdapter())\n const [annotations, setAnnotations] = useState<Annotation[]>([])\n\n // Load on mount and subscribe to external updates\n useEffect(() => {\n adapterRef.current.load().then(setAnnotations)\n return adapterRef.current.subscribe?.(setAnnotations)\n }, [])\n\n const addAnnotation = useCallback(\n (slideIndex: number, slideTitle: string, target: AnnotationTarget, body: string) => {\n const annotation: Annotation = {\n id: crypto.randomUUID(),\n slideIndex,\n slideTitle,\n target,\n body,\n createdAt: new Date().toISOString(),\n status: \"open\"\n }\n setAnnotations(prev => [...prev, annotation])\n adapterRef.current.add(annotation)\n },\n []\n )\n\n const deleteAnnotation = useCallback((id: string) => {\n setAnnotations(prev => prev.filter(a => a.id !== id))\n adapterRef.current.remove(id)\n }, [])\n\n const getSlideAnnotations = useCallback(\n (slideIndex: number) => annotations.filter(a => a.slideIndex === slideIndex),\n [annotations]\n )\n\n const openCount = useMemo(() => annotations.filter(a => a.status === \"open\").length, [annotations])\n\n // Allow external state updates (e.g. from postMessage adapter)\n const updateAnnotations = useCallback((updated: Annotation[]) => {\n setAnnotations(updated)\n }, [])\n\n return { annotations, addAnnotation, deleteAnnotation, getSlideAnnotations, openCount, updateAnnotations }\n}\n","import type { Annotation, AnnotationsFile, AnnotationStorageAdapter } from \"../types\"\n\nconst ENDPOINT = \"/__promptslide_annotations\"\n\nasync function loadAll(): Promise<Annotation[]> {\n try {\n const res = await fetch(ENDPOINT)\n if (!res.ok) return []\n const data: AnnotationsFile = await res.json()\n return data.annotations || []\n } catch {\n return []\n }\n}\n\nasync function saveAll(annotations: Annotation[]): Promise<void> {\n const data: AnnotationsFile = { version: 1, annotations }\n await fetch(ENDPOINT, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(data)\n })\n}\n\n/** Storage adapter for local Vite dev server (reads/writes annotations.json via middleware) */\nexport function createHttpAdapter(): AnnotationStorageAdapter {\n let cache: Annotation[] = []\n\n return {\n async load() {\n cache = await loadAll()\n return cache\n },\n async add(annotation) {\n cache = [...cache, annotation]\n await saveAll(cache)\n },\n async remove(id) {\n cache = cache.filter(a => a.id !== id)\n await saveAll(cache)\n }\n }\n}\n","import type { ClassValue } from \"clsx\"\n\nimport { clsx } from \"clsx\"\nimport { twMerge } from \"tailwind-merge\"\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs))\n}\n"],"mappings":"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","names":["jsx","motion","jsx","motion","createContext","useContext","useMemo","jsx","motion","jsx","jsx","motion","useCallback","useEffect","useState","jsx","useState","useEffect","useCallback","MessageCircle","useCallback","useEffect","useMemo","useRef","useState","useCallback","useEffect","useRef","useState","useEffect","useState","jsx","jsxs","jsx","jsxs","jsx","jsxs","useState","useRef","useCallback","useEffect","X","jsx","jsxs","useCallback","useEffect","useMemo","useRef","useState","useRef","useState","useEffect","useCallback","useMemo","jsx","jsxs","useState","useEffect","useMemo","useCallback","useRef","MessageCircle"]}
1
+ {"version":3,"sources":["../src/core/animation-config.ts","../src/core/animation-context.tsx","../src/core/animated.tsx","../src/core/transitions.ts","../src/core/morph.tsx","../src/core/use-slide-navigation.ts","../src/core/theme-context.tsx","../src/core/slide-renderer.tsx","../src/core/slide-error-boundary.tsx","../src/core/slide-embed.tsx","../src/core/slide-deck.tsx","../src/core/annotations/annotation-overlay.tsx","../src/core/annotations/annotation-form.tsx","../src/core/annotations/annotation-pin.tsx","../src/core/annotations/selectors.ts","../src/core/annotations/annotation-panel.tsx","../src/core/annotations/use-annotations.ts","../src/core/annotations/adapters/http.ts","../src/core/utils.ts"],"sourcesContent":["/**\n * Centralized animation configuration for the slide deck framework.\n * All animation timings, easings, and spring configs are defined here.\n */\n\n// =============================================================================\n// TIMING CONSTANTS\n// =============================================================================\n\n/** Duration for slide-to-slide transitions (seconds) */\nexport const SLIDE_TRANSITION_DURATION = 0.3\n\n/** Duration for morph/layout animations between slides (seconds) */\nexport const MORPH_DURATION = 0.8\n\n/** Duration for within-slide step animations (seconds) */\nexport const STEP_ANIMATION_DURATION = 0.4\n\n/** Default stagger delay for grouped animations (seconds) */\nexport const STAGGER_DELAY = 0.1\n\n// =============================================================================\n// EASING PRESETS\n// =============================================================================\n\nexport const EASE_DEFAULT = \"easeInOut\" as const\nexport const EASE_OUT = \"easeOut\" as const\nexport const EASE_IN = \"easeIn\" as const\n\n/** Smooth ease-in-out curve for morph animations (cubic bezier) */\nexport const EASE_MORPH = [0.4, 0, 0.2, 1] as const\n\n// =============================================================================\n// SPRING CONFIGURATIONS\n// =============================================================================\n\n/** Spring config for snappy, responsive animations */\nexport const SPRING_SNAPPY = {\n type: \"spring\" as const,\n stiffness: 300,\n damping: 30\n}\n\n/** Spring config for smooth, gentle animations */\nexport const SPRING_SMOOTH = {\n type: \"spring\" as const,\n stiffness: 200,\n damping: 25\n}\n\n/** Spring config for bouncy animations */\nexport const SPRING_BOUNCY = {\n type: \"spring\" as const,\n stiffness: 400,\n damping: 20\n}\n\n// =============================================================================\n// TRANSITION PRESETS\n// =============================================================================\n\n/** Standard transition for slide transitions */\nexport const SLIDE_TRANSITION = {\n duration: SLIDE_TRANSITION_DURATION,\n ease: EASE_DEFAULT\n} as const\n\n/** Standard transition for morph animations (smooth ease-in-out) */\nexport const MORPH_TRANSITION = {\n duration: MORPH_DURATION,\n ease: EASE_MORPH\n}\n\n/** Standard transition for step animations (spring-based, duration computed from stiffness/damping) */\nexport const STEP_TRANSITION = {\n ...SPRING_SNAPPY\n}\n\n// =============================================================================\n// DISTANCE CONSTANTS (pixels)\n// =============================================================================\n\n/** Distance for slide animations */\nexport const SLIDE_DISTANCE = 100\n\n/** Distance for within-slide element animations */\nexport const ELEMENT_SLIDE_DISTANCE = 30\n\n// =============================================================================\n// SLIDE DIMENSIONS\n// =============================================================================\n\n/** Standard slide dimensions (16:9 aspect ratio) */\nexport const SLIDE_DIMENSIONS = {\n width: 1280,\n height: 720,\n aspectRatio: 16 / 9\n} as const\n","import { createContext, useContext, useMemo } from \"react\"\n\ninterface AnimationContextValue {\n /** Current animation step (0 = no animations shown yet) */\n currentStep: number\n /** Total animation steps in this slide (declared in slide config) */\n totalSteps: number\n /** When true, all animation steps should be visible (used for backward navigation) */\n showAllAnimations: boolean\n}\n\nconst AnimationContext = createContext<AnimationContextValue>({\n currentStep: 0,\n totalSteps: 0,\n showAllAnimations: false\n})\n\ninterface AnimationProviderProps {\n children: React.ReactNode\n /** Current animation step (0 = no animations shown yet) */\n currentStep: number\n /** Total animation steps declared in slide config */\n totalSteps: number\n /** When true, show all animations regardless of currentStep (for backward navigation) */\n showAllAnimations?: boolean\n}\n\n/**\n * Provides animation context to child components.\n *\n * The totalSteps is now passed from parent (declared in slide config)\n * rather than discovered at runtime, eliminating race conditions.\n */\nexport function AnimationProvider({\n children,\n currentStep,\n totalSteps,\n showAllAnimations = false\n}: AnimationProviderProps) {\n const value = useMemo(\n () => ({\n currentStep,\n totalSteps,\n showAllAnimations\n }),\n [currentStep, totalSteps, showAllAnimations]\n )\n\n return <AnimationContext.Provider value={value}>{children}</AnimationContext.Provider>\n}\n\nexport function useAnimationContext() {\n return useContext(AnimationContext)\n}\n","import { motion, Variants } from \"framer-motion\"\n\nimport {\n ELEMENT_SLIDE_DISTANCE,\n SPRING_SNAPPY,\n STAGGER_DELAY,\n STEP_ANIMATION_DURATION\n} from \"./animation-config\"\nimport { useAnimationContext } from \"./animation-context\"\n\n// =============================================================================\n// ANIMATION TYPES & VARIANTS\n// =============================================================================\n\nexport type AnimationType =\n | \"fade\"\n | \"slide-up\"\n | \"slide-down\"\n | \"slide-left\"\n | \"slide-right\"\n | \"scale\"\n\nconst animationVariants: Record<AnimationType, Variants> = {\n fade: {\n hidden: { opacity: 0 },\n visible: { opacity: 1 }\n },\n \"slide-up\": {\n hidden: { opacity: 0, y: ELEMENT_SLIDE_DISTANCE },\n visible: { opacity: 1, y: 0 }\n },\n \"slide-down\": {\n hidden: { opacity: 0, y: -ELEMENT_SLIDE_DISTANCE },\n visible: { opacity: 1, y: 0 }\n },\n \"slide-left\": {\n hidden: { opacity: 0, x: ELEMENT_SLIDE_DISTANCE },\n visible: { opacity: 1, x: 0 }\n },\n \"slide-right\": {\n hidden: { opacity: 0, x: -ELEMENT_SLIDE_DISTANCE },\n visible: { opacity: 1, x: 0 }\n },\n scale: {\n hidden: { opacity: 0, scale: 0.8 },\n visible: { opacity: 1, scale: 1 }\n }\n}\n\ninterface AnimatedProps {\n /** Which step reveals this content (1-indexed) */\n step: number\n /** Animation type */\n animation?: AnimationType\n /** Animation duration in seconds */\n duration?: number\n /** Delay after trigger in seconds */\n delay?: number\n /** Custom className */\n className?: string\n children: React.ReactNode\n}\n\n/**\n * Animated element that appears at a specific animation step.\n *\n * The step count is now declared in slide config rather than discovered\n * at runtime, so this component simply consumes the context without\n * needing to register itself.\n */\nexport function Animated({\n step,\n animation = \"slide-up\",\n duration = STEP_ANIMATION_DURATION,\n delay = 0,\n className,\n children\n}: AnimatedProps) {\n const { currentStep, showAllAnimations } = useAnimationContext()\n\n // Show all animations when navigating backward, otherwise check step\n const isVisible = showAllAnimations || currentStep >= step\n\n return (\n <motion.div\n initial=\"hidden\"\n animate={isVisible ? \"visible\" : \"hidden\"}\n variants={animationVariants[animation]}\n transition={{\n ...SPRING_SNAPPY,\n duration,\n delay: isVisible ? delay : 0\n }}\n className={className}\n >\n {children}\n </motion.div>\n )\n}\n\n/**\n * Wrapper for staggering multiple children.\n * Each direct child will be animated in sequence.\n */\ninterface AnimatedGroupProps {\n /** Starting step for the first child */\n startStep: number\n /** Animation type for all children */\n animation?: AnimationType\n /** Delay between each child in seconds */\n staggerDelay?: number\n className?: string\n children: React.ReactNode\n}\n\nexport function AnimatedGroup({\n startStep,\n animation = \"slide-up\",\n staggerDelay = STAGGER_DELAY,\n className,\n children\n}: AnimatedGroupProps) {\n const { currentStep, showAllAnimations } = useAnimationContext()\n\n const childArray = Array.isArray(children) ? children : [children]\n\n // Show all animations when navigating backward, otherwise check step\n const isVisible = showAllAnimations || currentStep >= startStep\n\n const containerVariants: Variants = {\n hidden: {},\n visible: {\n transition: {\n staggerChildren: staggerDelay\n }\n }\n }\n\n return (\n <motion.div\n initial=\"hidden\"\n animate={isVisible ? \"visible\" : \"hidden\"}\n variants={containerVariants}\n className={className}\n >\n {childArray.map((child, index) => (\n <motion.div key={index} variants={animationVariants[animation]}>\n {child}\n </motion.div>\n ))}\n </motion.div>\n )\n}\n","/**\n * Slide transition variants for the slide deck framework.\n * These define how slides enter and exit during navigation.\n */\n\nimport type { Variants } from \"framer-motion\"\n\nimport {\n EASE_MORPH,\n MORPH_DURATION,\n SLIDE_DISTANCE,\n SLIDE_TRANSITION,\n SLIDE_TRANSITION_DURATION\n} from \"./animation-config\"\n\n// =============================================================================\n// TYPES\n// =============================================================================\n\nexport type SlideTransitionType =\n | \"fade\"\n | \"slide-left\"\n | \"slide-right\"\n | \"slide-up\"\n | \"slide-down\"\n | \"zoom\"\n | \"zoom-fade\"\n | \"morph\"\n | \"none\"\n\nexport interface SlideTransitionConfig {\n /** The transition type */\n type: SlideTransitionType\n /** Optional custom duration (overrides default) */\n duration?: number\n /** Whether to use directional transitions based on navigation direction */\n directional?: boolean\n}\n\n// =============================================================================\n// STATIC VARIANTS (non-directional)\n// =============================================================================\n\nconst fadeVariants: Variants = {\n enter: { opacity: 0 },\n center: { opacity: 1 },\n exit: { opacity: 0 }\n}\n\nconst slideLeftVariants: Variants = {\n enter: { x: SLIDE_DISTANCE, opacity: 0 },\n center: { x: 0, opacity: 1 },\n exit: { x: -SLIDE_DISTANCE, opacity: 0 }\n}\n\nconst slideRightVariants: Variants = {\n enter: { x: -SLIDE_DISTANCE, opacity: 0 },\n center: { x: 0, opacity: 1 },\n exit: { x: SLIDE_DISTANCE, opacity: 0 }\n}\n\nconst slideUpVariants: Variants = {\n enter: { y: SLIDE_DISTANCE, opacity: 0 },\n center: { y: 0, opacity: 1 },\n exit: { y: -SLIDE_DISTANCE, opacity: 0 }\n}\n\nconst slideDownVariants: Variants = {\n enter: { y: -SLIDE_DISTANCE, opacity: 0 },\n center: { y: 0, opacity: 1 },\n exit: { y: SLIDE_DISTANCE, opacity: 0 }\n}\n\nconst zoomVariants: Variants = {\n enter: { scale: 0.8, opacity: 0 },\n center: { scale: 1, opacity: 1 },\n exit: { scale: 1.2, opacity: 0 }\n}\n\nconst zoomFadeVariants: Variants = {\n enter: { scale: 0.95, opacity: 0 },\n center: { scale: 1, opacity: 1 },\n exit: { scale: 1.05, opacity: 0 }\n}\n\nconst morphVariants: Variants = {\n enter: {\n opacity: 0,\n zIndex: 1\n },\n center: {\n opacity: 1,\n zIndex: 1,\n transition: {\n opacity: { delay: 0.05, duration: 0.25 }\n }\n },\n exit: {\n opacity: 0,\n zIndex: 0,\n transition: {\n opacity: { duration: MORPH_DURATION, ease: EASE_MORPH }\n }\n }\n}\n\nconst noneVariants: Variants = {\n enter: {},\n center: {},\n exit: {}\n}\n\n// =============================================================================\n// VARIANT REGISTRY\n// =============================================================================\n\nexport const SLIDE_VARIANTS: Record<SlideTransitionType, Variants> = {\n fade: fadeVariants,\n \"slide-left\": slideLeftVariants,\n \"slide-right\": slideRightVariants,\n \"slide-up\": slideUpVariants,\n \"slide-down\": slideDownVariants,\n zoom: zoomVariants,\n \"zoom-fade\": zoomFadeVariants,\n morph: morphVariants,\n none: noneVariants\n}\n\n// =============================================================================\n// DIRECTIONAL VARIANTS (based on navigation direction)\n// =============================================================================\n\nexport function createDirectionalVariants(axis: \"x\" | \"y\" = \"x\"): (direction: number) => Variants {\n return (direction: number) => ({\n enter: {\n [axis]: direction > 0 ? SLIDE_DISTANCE : -SLIDE_DISTANCE,\n opacity: 0\n },\n center: {\n [axis]: 0,\n opacity: 1\n },\n exit: {\n [axis]: direction < 0 ? SLIDE_DISTANCE : -SLIDE_DISTANCE,\n opacity: 0\n }\n })\n}\n\n/** Horizontal directional slide (left/right based on direction) */\nexport const directionalSlideX = createDirectionalVariants(\"x\")\n\n/** Vertical directional slide (up/down based on direction) */\nexport const directionalSlideY = createDirectionalVariants(\"y\")\n\n// =============================================================================\n// HELPER FUNCTIONS\n// =============================================================================\n\nexport function getSlideVariants(\n config: SlideTransitionConfig | SlideTransitionType,\n direction: number = 1\n): Variants {\n const type = typeof config === \"string\" ? config : config.type\n const directional = typeof config === \"object\" ? config.directional : false\n\n if (directional && (type === \"slide-left\" || type === \"slide-right\")) {\n return directionalSlideX(direction)\n }\n\n if (directional && (type === \"slide-up\" || type === \"slide-down\")) {\n return directionalSlideY(direction)\n }\n\n return SLIDE_VARIANTS[type]\n}\n\nexport function getSlideTransition(config?: SlideTransitionConfig | SlideTransitionType): {\n duration: number\n ease: typeof SLIDE_TRANSITION.ease\n} {\n if (!config) return SLIDE_TRANSITION\n\n const type = typeof config === \"string\" ? config : config.type\n\n const defaultDuration = type === \"morph\" ? MORPH_DURATION : SLIDE_TRANSITION_DURATION\n\n const duration = typeof config === \"object\" && config.duration ? config.duration : defaultDuration\n\n return {\n ...SLIDE_TRANSITION,\n duration\n }\n}\n\n// =============================================================================\n// DEFAULT EXPORT\n// =============================================================================\n\nexport const DEFAULT_SLIDE_TRANSITION: SlideTransitionType = \"fade\"\n","import type { Transition } from \"framer-motion\"\n\nimport { motion } from \"framer-motion\"\n\nimport { MORPH_TRANSITION } from \"./animation-config\"\n\n// =============================================================================\n// TYPES\n// =============================================================================\n\ninterface MorphProps {\n layoutId: string\n transition?: Transition\n className?: string\n children: React.ReactNode\n}\n\ninterface MorphGroupProps {\n groupId: string\n transition?: Transition\n className?: string\n children: React.ReactNode\n}\n\n// =============================================================================\n// MORPH COMPONENT\n// =============================================================================\n\n/**\n * Wrapper component that enables morph/shared-layout animations between slides.\n *\n * Usage:\n * ```tsx\n * // Slide 1 - Large version\n * <Morph layoutId=\"hero-title\">\n * <h1 className=\"text-6xl\">Title</h1>\n * </Morph>\n *\n * // Slide 2 - Small version (same layoutId = morphs between them)\n * <Morph layoutId=\"hero-title\">\n * <h1 className=\"text-2xl\">Title</h1>\n * </Morph>\n * ```\n */\nexport function Morph({\n layoutId,\n transition = MORPH_TRANSITION,\n className,\n children\n}: MorphProps) {\n return (\n <motion.div\n layout\n layoutId={layoutId}\n initial={false}\n transition={transition}\n className={className}\n >\n {children}\n </motion.div>\n )\n}\n\n// =============================================================================\n// MORPH GROUP COMPONENT\n// =============================================================================\n\nexport function MorphGroup({\n groupId,\n transition = MORPH_TRANSITION,\n className,\n children\n}: MorphGroupProps) {\n return (\n <motion.div\n layout\n layoutId={groupId}\n initial={false}\n transition={transition}\n className={className}\n >\n {children}\n </motion.div>\n )\n}\n\n// =============================================================================\n// MORPH ITEM (for use within MorphGroup pattern)\n// =============================================================================\n\ninterface MorphItemProps {\n id: string\n prefix?: string\n transition?: Transition\n className?: string\n children: React.ReactNode\n}\n\nexport function MorphItem({\n id,\n prefix,\n transition = MORPH_TRANSITION,\n className,\n children\n}: MorphItemProps) {\n const layoutId = prefix ? `${prefix}-${id}` : id\n\n return (\n <motion.div\n layout\n layoutId={layoutId}\n initial={false}\n transition={transition}\n className={className}\n >\n {children}\n </motion.div>\n )\n}\n\n// =============================================================================\n// MORPH TEXT (specialized for text that changes size)\n// =============================================================================\n\ninterface MorphTextProps {\n layoutId: string\n as?: \"h1\" | \"h2\" | \"h3\" | \"h4\" | \"p\" | \"span\"\n transition?: Transition\n className?: string\n children: React.ReactNode\n}\n\nexport function MorphText({\n layoutId,\n as: Component = \"span\",\n transition = MORPH_TRANSITION,\n className,\n children\n}: MorphTextProps) {\n const MotionComponent = motion[Component]\n\n return (\n <MotionComponent\n layout\n layoutId={layoutId}\n initial={false}\n transition={transition}\n className={className}\n >\n {children}\n </MotionComponent>\n )\n}\n","import { useCallback, useEffect, useState } from \"react\"\n\nimport type { NavigationDirection, SlideConfig } from \"./types\"\n\n// =============================================================================\n// TYPES\n// =============================================================================\n\ntype NavigationStatus = \"idle\" | \"transitioning\"\n\ntype QueuedAction = \"advance\" | \"goBack\" | null\n\ninterface NavigationState {\n status: NavigationStatus\n direction: NavigationDirection\n}\n\nexport interface UseSlideNavigationOptions {\n slides: SlideConfig[]\n initialSlide?: number\n onSlideChange?: (slideIndex: number) => void\n}\n\nexport interface UseSlideNavigationReturn {\n currentSlide: number\n animationStep: number\n totalSteps: number\n direction: NavigationDirection\n isTransitioning: boolean\n showAllAnimations: boolean\n advance: () => void\n goBack: () => void\n goToSlide: (index: number) => void\n onTransitionComplete: () => void\n}\n\n// =============================================================================\n// HOOK\n// =============================================================================\n\nexport function useSlideNavigation({\n slides,\n initialSlide = 0,\n onSlideChange\n}: UseSlideNavigationOptions): UseSlideNavigationReturn {\n const [currentSlide, setCurrentSlide] = useState(initialSlide)\n const [animationStep, setAnimationStep] = useState(0)\n\n const [navState, setNavState] = useState<NavigationState>({\n status: \"idle\",\n direction: 0\n })\n\n const [queuedAction, setQueuedAction] = useState<QueuedAction>(null)\n\n const totalSteps = slides[currentSlide]?.steps ?? 0\n\n const onTransitionComplete = useCallback(() => {\n setNavState(prev => {\n if (prev.status === \"transitioning\") {\n return { status: \"idle\", direction: 0 }\n }\n return prev\n })\n }, [])\n\n const advance = useCallback(() => {\n if (navState.status === \"transitioning\") {\n setQueuedAction(\"advance\")\n return\n }\n\n const currentTotalSteps = slides[currentSlide]?.steps ?? 0\n\n if (animationStep >= currentTotalSteps) {\n const nextSlide = (currentSlide + 1) % slides.length\n setNavState({ status: \"transitioning\", direction: 1 })\n setAnimationStep(0)\n setCurrentSlide(nextSlide)\n onSlideChange?.(nextSlide)\n } else {\n setAnimationStep(prev => prev + 1)\n }\n }, [navState.status, animationStep, currentSlide, slides, onSlideChange])\n\n const goBack = useCallback(() => {\n if (navState.status === \"transitioning\") {\n setQueuedAction(\"goBack\")\n return\n }\n\n if (animationStep <= 0) {\n const prevSlide = (currentSlide - 1 + slides.length) % slides.length\n const prevSlideSteps = slides[prevSlide]?.steps ?? 0\n setNavState({ status: \"transitioning\", direction: -1 })\n setAnimationStep(prevSlideSteps)\n setCurrentSlide(prevSlide)\n onSlideChange?.(prevSlide)\n } else {\n setAnimationStep(prev => prev - 1)\n }\n }, [navState.status, animationStep, currentSlide, slides, onSlideChange])\n\n const goToSlide = useCallback(\n (index: number) => {\n if (index < 0 || index >= slides.length || index === currentSlide) {\n return\n }\n\n const direction = index > currentSlide ? 1 : -1\n setNavState({ status: \"transitioning\", direction })\n setAnimationStep(0)\n setCurrentSlide(index)\n onSlideChange?.(index)\n },\n [currentSlide, slides.length, onSlideChange]\n )\n\n useEffect(() => {\n if (navState.status === \"idle\" && queuedAction !== null) {\n setQueuedAction(null)\n if (queuedAction === \"advance\") {\n advance()\n } else if (queuedAction === \"goBack\") {\n goBack()\n }\n }\n }, [navState.status, queuedAction, advance, goBack])\n\n return {\n currentSlide,\n animationStep,\n totalSteps,\n direction: navState.direction,\n isTransitioning: navState.status !== \"idle\",\n showAllAnimations: navState.direction === -1 && navState.status === \"transitioning\",\n advance,\n goBack,\n goToSlide,\n onTransitionComplete\n }\n}\n","import { createContext, useContext, useMemo } from \"react\"\nimport type { ThemeConfig } from \"./types\"\n\nconst ThemeContext = createContext<ThemeConfig | null>(null)\n\n/**\n * Access the full theme config. Returns null outside SlideThemeProvider.\n */\nexport function useTheme(): ThemeConfig | null {\n return useContext(ThemeContext)\n}\n\nfunction buildCssOverrides(theme: ThemeConfig): React.CSSProperties {\n const style: Record<string, string> = {}\n\n if (theme.colors?.primary) style[\"--primary\"] = theme.colors.primary\n if (theme.colors?.primaryForeground) style[\"--primary-foreground\"] = theme.colors.primaryForeground\n if (theme.colors?.secondary) style[\"--secondary\"] = theme.colors.secondary\n if (theme.colors?.secondaryForeground) style[\"--secondary-foreground\"] = theme.colors.secondaryForeground\n if (theme.colors?.accent) style[\"--accent\"] = theme.colors.accent\n if (theme.colors?.accentForeground) style[\"--accent-foreground\"] = theme.colors.accentForeground\n\n if (theme.fonts?.heading) style[\"--font-heading\"] = theme.fonts.heading\n if (theme.fonts?.body) style[\"--font-body\"] = theme.fonts.body\n\n return style as React.CSSProperties\n}\n\ninterface SlideThemeProviderProps {\n theme: ThemeConfig\n children: React.ReactNode\n}\n\n/**\n * Provides the full theme to all descendants.\n * Injects CSS variable overrides via inline style.\n */\nexport function SlideThemeProvider({ theme, children }: SlideThemeProviderProps) {\n const cssOverrides = useMemo(() => buildCssOverrides(theme), [theme])\n\n return (\n <ThemeContext.Provider value={theme}>\n <div style={cssOverrides} className=\"contents\">\n {children}\n </div>\n </ThemeContext.Provider>\n )\n}\n","import { AnimatePresence, motion } from \"framer-motion\"\n\nimport type { SlideTransitionType } from \"./transitions\"\nimport type { NavigationDirection, SlideConfig } from \"./types\"\n\nimport { SLIDE_TRANSITION } from \"./animation-config\"\nimport { AnimationProvider } from \"./animation-context\"\nimport { SlideErrorBoundary } from \"./slide-error-boundary\"\nimport { DEFAULT_SLIDE_TRANSITION, getSlideVariants } from \"./transitions\"\n\n// =============================================================================\n// TYPES\n// =============================================================================\n\nexport interface SlideRendererProps {\n slides: SlideConfig[]\n currentSlide: number\n animationStep: number\n totalSteps: number\n direction: NavigationDirection\n showAllAnimations: boolean\n transition?: SlideTransitionType\n directionalTransition?: boolean\n onTransitionComplete: () => void\n}\n\n// =============================================================================\n// COMPONENT\n// =============================================================================\n\n/**\n * Renders a single slide with animated transitions.\n * Extracted from SlideDeck so it can be reused in SlideEmbed and other contexts.\n */\nexport function SlideRenderer({\n slides,\n currentSlide,\n animationStep,\n totalSteps,\n direction,\n showAllAnimations,\n transition,\n directionalTransition,\n onTransitionComplete\n}: SlideRendererProps) {\n const currentSlideTransition = slides[currentSlide]?.transition\n const transitionType = currentSlideTransition ?? transition ?? DEFAULT_SLIDE_TRANSITION\n const isDirectional = directionalTransition ?? false\n\n const slideVariants = getSlideVariants(\n { type: transitionType, directional: isDirectional },\n direction\n )\n\n const CurrentSlideComponent = slides[currentSlide]!.component\n\n return (\n <AnimatePresence initial={false}>\n <motion.div\n key={currentSlide}\n variants={slideVariants}\n initial=\"enter\"\n animate=\"center\"\n exit=\"exit\"\n transition={SLIDE_TRANSITION}\n onAnimationComplete={definition => {\n if (definition === \"center\") {\n onTransitionComplete()\n }\n }}\n className=\"absolute inset-0 h-full w-full\"\n >\n <AnimationProvider\n currentStep={animationStep}\n totalSteps={totalSteps}\n showAllAnimations={showAllAnimations}\n >\n <SlideErrorBoundary\n slideIndex={currentSlide}\n slideTitle={slides[currentSlide]?.title}\n >\n <CurrentSlideComponent\n slideNumber={currentSlide + 1}\n totalSlides={slides.length}\n />\n </SlideErrorBoundary>\n </AnimationProvider>\n </motion.div>\n </AnimatePresence>\n )\n}\n","import React from \"react\"\n\ninterface SlideErrorBoundaryProps {\n slideIndex: number\n slideTitle?: string\n children: React.ReactNode\n}\n\ninterface SlideErrorBoundaryState {\n hasError: boolean\n error: Error | null\n}\n\nexport class SlideErrorBoundary extends React.Component<\n SlideErrorBoundaryProps,\n SlideErrorBoundaryState\n> {\n state: SlideErrorBoundaryState = { hasError: false, error: null }\n\n static getDerivedStateFromError(error: Error) {\n return { hasError: true, error }\n }\n\n componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {\n console.error(\n `[PromptSlide] Slide ${this.props.slideIndex + 1}${this.props.slideTitle ? ` (\"${this.props.slideTitle}\")` : \"\"} crashed:`,\n error,\n errorInfo\n )\n }\n\n render() {\n if (this.state.hasError) {\n return (\n <div className=\"flex h-full w-full flex-col items-center justify-center bg-red-950/20 p-12\">\n <div className=\"mb-4 text-lg font-semibold text-red-400\">\n Slide {this.props.slideIndex + 1} Error\n {this.props.slideTitle && (\n <span className=\"ml-2 font-normal text-red-400/70\">({this.props.slideTitle})</span>\n )}\n </div>\n <div className=\"max-w-2xl text-center font-mono text-sm break-words text-red-300/80\">\n {this.state.error?.message ?? \"Unknown error\"}\n </div>\n </div>\n )\n }\n return this.props.children\n }\n}\n","import { useCallback, useEffect, useState } from \"react\"\n\nimport type { SlideTransitionType } from \"./transitions\"\nimport type { SlideConfig } from \"./types\"\n\nimport { SLIDE_DIMENSIONS } from \"./animation-config\"\nimport { SlideRenderer } from \"./slide-renderer\"\nimport { useSlideNavigation } from \"./use-slide-navigation\"\n\n// =============================================================================\n// TYPES\n// =============================================================================\n\ninterface SlideEmbedProps {\n slides: SlideConfig[]\n transition?: SlideTransitionType\n directionalTransition?: boolean\n}\n\n// =============================================================================\n// COMPONENT\n// =============================================================================\n\n/**\n * Headless slide viewer controlled via window.postMessage.\n * Designed for embedding in an iframe (e.g. the registry editor preview).\n *\n * Inbound messages (parent → embed):\n * { type: \"navigate\", data: { slide: number } }\n * { type: \"advance\" }\n * { type: \"goBack\" }\n *\n * Outbound messages (embed → parent):\n * { type: \"slideReady\" }\n * { type: \"slideState\", data: { currentSlide, totalSlides, animationStep, totalSteps, titles } }\n * { type: \"hmrUpdate\" }\n */\nexport function SlideEmbed({ slides, transition, directionalTransition }: SlideEmbedProps) {\n const [scale, setScale] = useState(1)\n\n const {\n currentSlide,\n animationStep,\n totalSteps,\n direction,\n showAllAnimations,\n advance,\n goBack,\n goToSlide,\n onTransitionComplete\n } = useSlideNavigation({ slides })\n\n // Post slide state to parent whenever it changes\n useEffect(() => {\n const state = {\n currentSlide,\n totalSlides: slides.length,\n animationStep,\n totalSteps,\n titles: slides.map(s => s.title || \"\")\n }\n window.parent.postMessage({ type: \"slideState\", data: state }, \"*\")\n }, [currentSlide, animationStep, totalSteps, slides])\n\n // Signal readiness on mount\n useEffect(() => {\n window.parent.postMessage({ type: \"slideReady\" }, \"*\")\n }, [])\n\n // Listen for Vite HMR updates\n useEffect(() => {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const hot = (import.meta as any).hot as { on: (event: string, cb: () => void) => void } | undefined\n if (hot) {\n hot.on(\"vite:afterUpdate\", () => {\n window.parent.postMessage({ type: \"hmrUpdate\" }, \"*\")\n })\n }\n }, [])\n\n // Listen for inbound messages from parent\n const handleMessage = useCallback(\n (event: MessageEvent) => {\n const { type, data } = event.data || {}\n switch (type) {\n case \"navigate\":\n if (typeof data?.slide === \"number\") goToSlide(data.slide)\n break\n case \"advance\":\n advance()\n break\n case \"goBack\":\n goBack()\n break\n }\n },\n [advance, goBack, goToSlide]\n )\n\n useEffect(() => {\n window.addEventListener(\"message\", handleMessage)\n return () => window.removeEventListener(\"message\", handleMessage)\n }, [handleMessage])\n\n // Scale to fit viewport while preserving aspect ratio\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=\"h-screen w-screen overflow-hidden bg-black\">\n <div\n className=\"absolute left-1/2 top-1/2 overflow-hidden\"\n style={{\n width: SLIDE_DIMENSIONS.width,\n height: SLIDE_DIMENSIONS.height,\n transform: `translate(-50%, -50%) scale(${scale})`,\n transformOrigin: \"center center\"\n }}\n >\n <SlideRenderer\n slides={slides}\n currentSlide={currentSlide}\n animationStep={animationStep}\n totalSteps={totalSteps}\n direction={direction}\n showAllAnimations={showAllAnimations}\n transition={transition}\n directionalTransition={directionalTransition}\n onTransitionComplete={onTransitionComplete}\n />\n </div>\n </div>\n )\n}\n","import { LayoutGroup } from \"framer-motion\"\nimport { ChevronLeft, ChevronRight, Download, Grid3X3, List, Maximize, MessageCircle, Monitor } from \"lucide-react\"\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\"\n\nimport type { SlideTransitionType } from \"./transitions\"\nimport type { SlideConfig } from \"./types\"\n\nimport { SLIDE_DIMENSIONS } from \"./animation-config\"\nimport { AnimationProvider } from \"./animation-context\"\nimport { AnnotationOverlay, AnnotationPanel, useAnnotations } from \"./annotations\"\nimport type { Annotation, AnnotationTarget } from \"./annotations\"\nimport { SlideErrorBoundary } from \"./slide-error-boundary\"\nimport { SlideRenderer } from \"./slide-renderer\"\nimport { useSlideNavigation } from \"./use-slide-navigation\"\nimport { cn } from \"./utils\"\n\n// =============================================================================\n// TYPES\n// =============================================================================\n\ntype ViewMode = \"slide\" | \"list\" | \"grid\"\n\ninterface SlideDeckProps {\n slides: SlideConfig[]\n transition?: SlideTransitionType\n directionalTransition?: boolean\n /** Annotation data to display. When provided (even empty array), annotation UI is enabled. When undefined, annotation UI is hidden. */\n annotations?: Annotation[]\n /** Called when the user creates an annotation */\n onAnnotationAdd?: (slideIndex: number, slideTitle: string, target: AnnotationTarget, body: string) => void\n /** Called when the user deletes an annotation */\n onAnnotationDelete?: (id: string) => void\n}\n\n// =============================================================================\n// EXPORT VIEW (for Playwright screenshot capture)\n// =============================================================================\n\nfunction SlideExportView({ slides, slideIndex }: { slides: SlideConfig[]; slideIndex: number }) {\n const [ready, setReady] = useState(false)\n const clampedIndex = Math.max(0, Math.min(slideIndex, slides.length - 1))\n const slideConfig = slides[clampedIndex]!\n const SlideComponent = slideConfig.component\n\n useEffect(() => {\n setReady(true)\n }, [])\n\n return (\n <div\n data-export-ready={ready ? \"true\" : undefined}\n style={{\n width: SLIDE_DIMENSIONS.width,\n height: SLIDE_DIMENSIONS.height,\n overflow: \"hidden\",\n position: \"relative\",\n background: \"black\"\n }}\n >\n <AnimationProvider\n currentStep={slideConfig.steps}\n totalSteps={slideConfig.steps}\n showAllAnimations={true}\n >\n <SlideErrorBoundary slideIndex={clampedIndex} slideTitle={slideConfig.title}>\n <SlideComponent slideNumber={clampedIndex + 1} totalSlides={slides.length} />\n </SlideErrorBoundary>\n </AnimationProvider>\n </div>\n )\n}\n\n// =============================================================================\n// COMPONENT\n// =============================================================================\n\nexport function SlideDeck({ slides, transition, directionalTransition, annotations, onAnnotationAdd, onAnnotationDelete }: SlideDeckProps) {\n // Check for export mode via URL params\n const [exportParams] = useState(() => {\n if (typeof window === \"undefined\") return null\n const params = new URLSearchParams(window.location.search)\n if (params.get(\"export\") !== \"true\") return null\n return { slideIndex: parseInt(params.get(\"slide\") || \"0\", 10) }\n })\n\n if (exportParams) {\n return <SlideExportView slides={slides} slideIndex={exportParams.slideIndex} />\n }\n\n // Use internal useAnnotations as fallback when no external annotations prop is provided\n const internal = useAnnotations()\n const isExternallyManaged = annotations !== undefined\n const effectiveAnnotations = isExternallyManaged ? annotations : internal.annotations\n const effectiveAdd = isExternallyManaged ? onAnnotationAdd : internal.addAnnotation\n const effectiveDelete = isExternallyManaged ? onAnnotationDelete : internal.deleteAnnotation\n\n const openCount = useMemo(() => effectiveAnnotations.filter(a => a.status === \"open\").length, [effectiveAnnotations])\n const getSlideAnnotations = useCallback(\n (slideIndex: number) => effectiveAnnotations.filter(a => a.slideIndex === slideIndex),\n [effectiveAnnotations]\n )\n\n const [viewMode, setViewMode] = useState<ViewMode>(\"slide\")\n const [isPresentationMode, setIsPresentationMode] = useState(false)\n const [isAnnotationMode, setIsAnnotationMode] = useState(false)\n const [showAnnotationPanel, setShowAnnotationPanel] = useState(false)\n const [selectedAnnotationId, setSelectedAnnotationId] = useState<string | null>(null)\n const [scale, setScale] = useState(1)\n const containerRef = useRef<HTMLDivElement>(null)\n const slideContainerRef = useRef<HTMLDivElement>(null)\n\n const {\n currentSlide,\n animationStep,\n totalSteps,\n direction,\n showAllAnimations,\n advance,\n goBack,\n goToSlide,\n onTransitionComplete\n } = useSlideNavigation({\n slides\n })\n\n const togglePresentationMode = useCallback(async () => {\n if (!document.fullscreenElement) {\n await document.documentElement.requestFullscreen()\n } else {\n await document.exitFullscreen()\n }\n }, [])\n\n // Listen for fullscreen changes\n useEffect(() => {\n const handleFullscreenChange = () => {\n setIsPresentationMode(!!document.fullscreenElement)\n }\n document.addEventListener(\"fullscreenchange\", handleFullscreenChange)\n return () => document.removeEventListener(\"fullscreenchange\", handleFullscreenChange)\n }, [])\n\n // Calculate scale factor for presentation mode\n useEffect(() => {\n const calculateScale = () => {\n if (!isPresentationMode) {\n setScale(1)\n return\n }\n const viewportWidth = window.innerWidth\n const viewportHeight = window.innerHeight\n const scaleX = viewportWidth / SLIDE_DIMENSIONS.width\n const scaleY = viewportHeight / SLIDE_DIMENSIONS.height\n setScale(Math.min(scaleX, scaleY))\n }\n\n calculateScale()\n window.addEventListener(\"resize\", calculateScale)\n return () => window.removeEventListener(\"resize\", calculateScale)\n }, [isPresentationMode])\n\n const handleExportPdf = () => {\n const previousMode = viewMode\n setViewMode(\"list\")\n\n setTimeout(() => {\n const handleAfterPrint = () => {\n setViewMode(previousMode)\n window.removeEventListener(\"afterprint\", handleAfterPrint)\n }\n window.addEventListener(\"afterprint\", handleAfterPrint)\n window.print()\n }, 100)\n }\n\n // Keyboard navigation\n useEffect(() => {\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.key === \"f\" || e.key === \"F\") {\n togglePresentationMode()\n return\n }\n\n // G for grid view toggle\n if (e.key === \"g\" || e.key === \"G\") {\n setViewMode(prev => (prev === \"grid\" ? \"slide\" : \"grid\"))\n return\n }\n\n if (viewMode !== \"slide\" || (isAnnotationMode && !isPresentationMode)) return\n\n if (e.key === \"ArrowRight\" || e.key === \" \") {\n e.preventDefault()\n advance()\n } else if (e.key === \"ArrowLeft\") {\n e.preventDefault()\n goBack()\n }\n }\n\n window.addEventListener(\"keydown\", handleKeyDown)\n return () => window.removeEventListener(\"keydown\", handleKeyDown)\n }, [advance, goBack, viewMode, togglePresentationMode, isAnnotationMode, isPresentationMode])\n\n return (\n <div className=\"min-h-screen w-full bg-neutral-950 text-foreground\">\n <style>{`\n @media print {\n @page {\n size: 1920px 1080px;\n margin: 0;\n }\n html,\n body {\n width: 100%;\n height: 100%;\n margin: 0 !important;\n padding: 0 !important;\n overflow: visible !important;\n }\n body {\n print-color-adjust: exact;\n -webkit-print-color-adjust: exact;\n background: transparent !important;\n }\n }\n `}</style>\n\n {/* Toolbar */}\n <div\n className={cn(\n \"fixed top-4 z-50 flex gap-1 rounded-lg border border-neutral-800 bg-neutral-950/90 p-1 backdrop-blur-sm transition-[right] print:hidden\",\n isPresentationMode && \"hidden\",\n isAnnotationMode && showAnnotationPanel ? \"right-[19.5rem]\" : \"right-4\"\n )}\n >\n <button\n onClick={() => setViewMode(\"slide\")}\n className={cn(\n \"rounded-md p-2 text-neutral-400 transition-colors hover:bg-neutral-800 hover:text-white\",\n viewMode === \"slide\" && \"bg-neutral-800 text-white\"\n )}\n title=\"Presentation View\"\n >\n <Monitor className=\"h-4 w-4\" />\n </button>\n <button\n onClick={() => setViewMode(\"list\")}\n className={cn(\n \"rounded-md p-2 text-neutral-400 transition-colors hover:bg-neutral-800 hover:text-white\",\n viewMode === \"list\" && \"bg-neutral-800 text-white\"\n )}\n title=\"List View\"\n >\n <List className=\"h-4 w-4\" />\n </button>\n <button\n onClick={() => setViewMode(\"grid\")}\n className={cn(\n \"rounded-md p-2 text-neutral-400 transition-colors hover:bg-neutral-800 hover:text-white\",\n viewMode === \"grid\" && \"bg-neutral-800 text-white\"\n )}\n title=\"Grid View\"\n >\n <Grid3X3 className=\"h-4 w-4\" />\n </button>\n\n <div className=\"mx-1 w-px bg-neutral-800\" />\n\n <button\n onClick={() => {\n setIsAnnotationMode(prev => {\n const next = !prev\n setShowAnnotationPanel(next)\n if (!next) setSelectedAnnotationId(null)\n return next\n })\n }}\n className={cn(\n \"relative rounded-md p-2 text-neutral-400 transition-colors hover:bg-neutral-800 hover:text-white\",\n isAnnotationMode && \"bg-[#FF6B35] text-white hover:bg-[#FF7A4A]\"\n )}\n title=\"Annotate slides\"\n >\n <MessageCircle className=\"h-4 w-4\" />\n {openCount > 0 && (\n <span className=\"absolute -top-1 -right-1 flex h-4 w-4 items-center justify-center rounded-full bg-[#FF6B35] text-[10px] font-bold text-white\">\n {openCount}\n </span>\n )}\n </button>\n\n <div className=\"mx-1 w-px bg-neutral-800\" />\n\n <button\n onClick={handleExportPdf}\n className=\"rounded-md p-2 text-neutral-400 transition-colors hover:bg-neutral-800 hover:text-white\"\n title=\"Download PDF\"\n >\n <Download className=\"h-4 w-4\" />\n </button>\n <button\n onClick={togglePresentationMode}\n className=\"rounded-md p-2 text-neutral-400 transition-colors hover:bg-neutral-800 hover:text-white\"\n title=\"Present (F)\"\n >\n <Maximize className=\"h-4 w-4\" />\n </button>\n </div>\n\n {/* Slide View */}\n {viewMode === \"slide\" && (\n <div\n className={cn(\n \"flex h-screen w-full print:hidden\",\n isPresentationMode ? \"bg-black\" : \"\"\n )}\n >\n <div\n ref={containerRef}\n role=\"presentation\"\n tabIndex={isPresentationMode ? 0 : undefined}\n className={cn(\n \"flex flex-1 flex-col items-center justify-center overflow-hidden\",\n isPresentationMode ? \"bg-black p-0\" : \"p-4 md:p-8\"\n )}\n onClick={isPresentationMode ? advance : undefined}\n onKeyDown={\n isPresentationMode\n ? e => {\n if (e.key === \"Enter\" || e.key === \" \") advance()\n }\n : undefined\n }\n >\n <LayoutGroup id=\"slide-deck\">\n {isPresentationMode ? (\n <div\n className=\"pointer-events-none relative overflow-hidden bg-black\"\n style={{\n width: SLIDE_DIMENSIONS.width,\n height: SLIDE_DIMENSIONS.height,\n transform: `scale(${scale})`,\n transformOrigin: \"center center\"\n }}\n >\n <SlideRenderer\n slides={slides}\n currentSlide={currentSlide}\n animationStep={animationStep}\n totalSteps={totalSteps}\n direction={direction}\n showAllAnimations={showAllAnimations}\n transition={transition}\n directionalTransition={directionalTransition}\n onTransitionComplete={onTransitionComplete}\n />\n </div>\n ) : (\n <div ref={slideContainerRef} className=\"relative aspect-video w-full max-w-7xl overflow-hidden rounded-xl border border-neutral-800 bg-black shadow-2xl\">\n <SlideRenderer\n slides={slides}\n currentSlide={currentSlide}\n animationStep={animationStep}\n totalSteps={totalSteps}\n direction={direction}\n showAllAnimations={showAllAnimations}\n transition={transition}\n directionalTransition={directionalTransition}\n onTransitionComplete={onTransitionComplete}\n />\n {isAnnotationMode && (\n <AnnotationOverlay\n slides={slides}\n currentSlide={currentSlide}\n slideContainerRef={slideContainerRef}\n selectedId={selectedAnnotationId}\n onSelectId={setSelectedAnnotationId}\n onShowPanel={() => setShowAnnotationPanel(true)}\n slideAnnotations={getSlideAnnotations(currentSlide)}\n addAnnotation={effectiveAdd ?? (() => {})}\n\n />\n )}\n </div>\n )}\n </LayoutGroup>\n\n {/* Navigation Controls */}\n {!isPresentationMode && (\n <div className=\"mt-6 flex items-center gap-4\">\n <button\n onClick={goBack}\n className=\"rounded-full border border-neutral-800 bg-black/50 p-2 text-neutral-400 backdrop-blur-sm transition-colors hover:bg-neutral-900 hover:text-white\"\n >\n <ChevronLeft className=\"h-5 w-5\" />\n </button>\n <div className=\"flex min-w-[4rem] flex-col items-center\">\n <span className=\"font-mono text-sm text-neutral-500\">\n {currentSlide + 1} / {slides.length}\n </span>\n {slides[currentSlide]?.title && (\n <span className=\"mt-0.5 text-xs text-neutral-600\">\n {slides[currentSlide].title}\n </span>\n )}\n </div>\n <button\n onClick={advance}\n className=\"rounded-full border border-neutral-800 bg-black/50 p-2 text-neutral-400 backdrop-blur-sm transition-colors hover:bg-neutral-900 hover:text-white\"\n >\n <ChevronRight className=\"h-5 w-5\" />\n </button>\n </div>\n )}\n </div>\n\n {/* Annotation Panel — beside the slide */}\n {isAnnotationMode && showAnnotationPanel && !isPresentationMode && (\n <AnnotationPanel\n annotations={getSlideAnnotations(currentSlide)}\n selectedId={selectedAnnotationId}\n onSelect={setSelectedAnnotationId}\n onDelete={effectiveDelete ?? (() => {})}\n onClose={() => {\n setShowAnnotationPanel(false)\n setSelectedAnnotationId(null)\n }}\n />\n )}\n </div>\n )}\n\n {/* Grid View */}\n {viewMode === \"grid\" && (\n <div className=\"mx-auto max-w-7xl p-8 pt-16 print:hidden\">\n <div className=\"grid grid-cols-2 gap-4 md:grid-cols-3 lg:grid-cols-4\">\n {slides.map((slideConfig, index) => {\n const SlideComponent = slideConfig.component\n const prevSection = index > 0 ? slides[index - 1]?.section : undefined\n const showSectionHeader = slideConfig.section && slideConfig.section !== prevSection\n\n return (\n <div key={index} className={showSectionHeader ? \"col-span-full\" : undefined}>\n {showSectionHeader && (\n <h3 className=\"mt-4 mb-3 text-xs font-bold tracking-[0.2em] text-neutral-500 uppercase first:mt-0\">\n {slideConfig.section}\n </h3>\n )}\n <button\n onClick={() => {\n goToSlide(index)\n setViewMode(\"slide\")\n }}\n className=\"group relative aspect-video w-full overflow-hidden rounded-lg border border-neutral-800 bg-black shadow-sm transition-all hover:border-primary hover:shadow-lg hover:shadow-primary/10\"\n >\n <div\n className=\"h-full w-full origin-top-left scale-[0.25]\"\n style={{ width: \"400%\", height: \"400%\" }}\n >\n <AnimationProvider\n currentStep={slideConfig.steps}\n totalSteps={slideConfig.steps}\n showAllAnimations={true}\n >\n <SlideErrorBoundary slideIndex={index} slideTitle={slideConfig.title}>\n <SlideComponent slideNumber={index + 1} totalSlides={slides.length} />\n </SlideErrorBoundary>\n </AnimationProvider>\n </div>\n <div className=\"absolute inset-0 bg-black/0 transition-colors group-hover:bg-black/20\" />\n <div className=\"absolute bottom-2 left-2 rounded bg-black/70 px-2 py-1 text-xs font-medium text-white\">\n {slideConfig.title ? `${index + 1}. ${slideConfig.title}` : index + 1}\n </div>\n </button>\n </div>\n )\n })}\n </div>\n </div>\n )}\n\n {/* List View */}\n <div\n className={cn(\n \"mx-auto max-w-7xl p-8 pt-16\",\n \"print:m-0 print:block print:max-w-none print:p-0\",\n viewMode === \"list\" ? \"block\" : \"hidden print:block\"\n )}\n >\n <div className=\"grid grid-cols-1 gap-8 print:block\">\n {slides.map((slideConfig, index) => {\n const SlideComponent = slideConfig.component\n return (\n <div\n key={index}\n className=\"aspect-video w-full overflow-hidden rounded-xl border border-neutral-800 bg-black shadow-sm print:relative print:m-0 print:h-[1080px] print:w-[1920px] print:break-after-page print:overflow-hidden print:rounded-none print:border-0 print:shadow-none\"\n >\n <div className=\"h-full w-full print:h-[720px] print:w-[1280px] print:origin-top-left print:scale-[1.5]\">\n <AnimationProvider\n currentStep={slideConfig.steps}\n totalSteps={slideConfig.steps}\n showAllAnimations={true}\n >\n <SlideErrorBoundary slideIndex={index} slideTitle={slideConfig.title}>\n <SlideComponent slideNumber={index + 1} totalSlides={slides.length} />\n </SlideErrorBoundary>\n </AnimationProvider>\n </div>\n </div>\n )\n })}\n </div>\n </div>\n </div>\n )\n}\n","import { useCallback, useEffect, useRef, useState } from \"react\"\nimport type { SlideConfig } from \"../types\"\nimport { AnnotationForm } from \"./annotation-form\"\nimport { AnnotationPin } from \"./annotation-pin\"\nimport { buildElementTarget, resolveTarget } from \"./selectors\"\nimport type { Annotation, AnnotationTarget } from \"./types\"\n\ninterface AnnotationOverlayProps {\n slides: SlideConfig[]\n currentSlide: number\n /** Ref to the slide container element (the div wrapping SlideRenderer) */\n slideContainerRef: React.RefObject<HTMLDivElement | null>\n selectedId: string | null\n onSelectId: (id: string | null) => void\n onShowPanel: () => void\n slideAnnotations: Annotation[]\n addAnnotation: (slideIndex: number, slideTitle: string, target: AnnotationTarget, body: string) => void\n}\n\ninterface PendingAnnotation {\n target: AnnotationTarget\n xPercent: number\n yPercent: number\n}\n\nexport function AnnotationOverlay({ slides, currentSlide, slideContainerRef, selectedId, onSelectId, onShowPanel, slideAnnotations, addAnnotation }: AnnotationOverlayProps) {\n const [pending, setPending] = useState<PendingAnnotation | null>(null)\n const [hoveredElement, setHoveredElement] = useState<DOMRect | null>(null)\n const overlayRef = useRef<HTMLDivElement>(null)\n\n const slideTitle = slides[currentSlide]?.title || `Slide ${currentSlide + 1}`\n\n // Resolve annotation positions — use the element if found, otherwise fallback coordinates\n const resolvedAnnotations = slideAnnotations.map((a, i) => {\n const container = slideContainerRef.current\n if (!container) {\n return { annotation: a, xPercent: a.target.position.xPercent, yPercent: a.target.position.yPercent, number: i + 1 }\n }\n\n const { element } = resolveTarget(a.target, container)\n if (element) {\n const rect = element.getBoundingClientRect()\n const containerRect = container.getBoundingClientRect()\n const xPercent = ((rect.left + rect.width / 2 - containerRect.left) / containerRect.width) * 100\n const yPercent = ((rect.top + rect.height / 2 - containerRect.top) / containerRect.height) * 100\n return { annotation: a, xPercent, yPercent, number: i + 1 }\n }\n\n return { annotation: a, xPercent: a.target.position.xPercent, yPercent: a.target.position.yPercent, number: i + 1 }\n })\n\n const handleOverlayClick = useCallback(\n (e: React.MouseEvent) => {\n const container = slideContainerRef.current\n if (!container) return\n\n // Get the element under the click by temporarily hiding the overlay\n const overlay = overlayRef.current\n if (overlay) overlay.style.pointerEvents = \"none\"\n const elementUnder = document.elementFromPoint(e.clientX, e.clientY) as HTMLElement | null\n if (overlay) overlay.style.pointerEvents = \"\"\n\n if (!elementUnder || !container.contains(elementUnder)) {\n setPending(null)\n onSelectId(null)\n return\n }\n\n // Pick the most specific meaningful element (skip tiny text nodes, pick their parent)\n let target = elementUnder\n if (target.tagName === \"SPAN\" && target.parentElement && container.contains(target.parentElement)) {\n // For inline spans, prefer their parent for a more meaningful target\n const parent = target.parentElement\n if (parent.tagName !== \"DIV\" || parent.children.length <= 3) {\n target = parent\n }\n }\n\n const annotationTarget = buildElementTarget(target, container)\n const containerRect = container.getBoundingClientRect()\n const xPercent = ((e.clientX - containerRect.left) / containerRect.width) * 100\n const yPercent = ((e.clientY - containerRect.top) / containerRect.height) * 100\n\n setPending({ target: annotationTarget, xPercent, yPercent })\n onSelectId(null)\n },\n [slideContainerRef, onSelectId]\n )\n\n const handleSubmit = useCallback(\n (text: string) => {\n if (!pending) return\n addAnnotation(currentSlide, slideTitle, pending.target, text)\n setPending(null)\n onShowPanel()\n },\n [pending, currentSlide, slideTitle, addAnnotation, onShowPanel]\n )\n\n // Track hover for element highlighting\n const handleMouseMove = useCallback(\n (e: React.MouseEvent) => {\n if (pending) {\n setHoveredElement(null)\n return\n }\n\n const container = slideContainerRef.current\n if (!container) return\n\n const overlay = overlayRef.current\n if (overlay) overlay.style.pointerEvents = \"none\"\n const elementUnder = document.elementFromPoint(e.clientX, e.clientY) as HTMLElement | null\n if (overlay) overlay.style.pointerEvents = \"\"\n\n if (elementUnder && container.contains(elementUnder) && elementUnder !== container) {\n const containerRect = container.getBoundingClientRect()\n const elRect = elementUnder.getBoundingClientRect()\n setHoveredElement(\n new DOMRect(\n elRect.left - containerRect.left,\n elRect.top - containerRect.top,\n elRect.width,\n elRect.height\n )\n )\n } else {\n setHoveredElement(null)\n }\n },\n [slideContainerRef, pending]\n )\n\n // Clear pending when slide changes\n useEffect(() => {\n setPending(null)\n onSelectId(null)\n setHoveredElement(null)\n }, [currentSlide, onSelectId])\n\n return (\n <>\n {/* Hover highlight */}\n {hoveredElement && (\n <div\n className=\"pointer-events-none absolute z-20 rounded-lg border-2 border-dashed border-[#FF6B35]/50 bg-[#FF6B35]/5\"\n style={{\n left: hoveredElement.x,\n top: hoveredElement.y,\n width: hoveredElement.width,\n height: hoveredElement.height\n }}\n />\n )}\n\n {/* Click capture overlay */}\n <div\n ref={overlayRef}\n role=\"button\"\n tabIndex={0}\n className=\"absolute inset-0 z-20\"\n style={{ cursor: `url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none'%3E%3Ccircle cx='12' cy='12' r='8' stroke='%23FF6B35' stroke-width='2' opacity='0.8'/%3E%3Ccircle cx='12' cy='12' r='2' fill='%23FF6B35'/%3E%3C/svg%3E\") 12 12, crosshair` }}\n onClick={handleOverlayClick}\n onKeyDown={e => { if (e.key === \"Escape\") { setPending(null); onSelectId(null) } }}\n onMouseMove={handleMouseMove}\n onMouseLeave={() => setHoveredElement(null)}\n />\n\n {/* Annotation pins */}\n {resolvedAnnotations.map(({ annotation, xPercent, yPercent, number }) => (\n <AnnotationPin\n key={annotation.id}\n number={number}\n status={annotation.status}\n xPercent={xPercent}\n yPercent={yPercent}\n isSelected={annotation.id === selectedId}\n onClick={() => {\n onSelectId(annotation.id === selectedId ? null : annotation.id)\n onShowPanel()\n setPending(null)\n }}\n />\n ))}\n\n {/* New annotation form */}\n {pending && (\n <AnnotationForm\n xPercent={pending.xPercent}\n yPercent={pending.yPercent}\n onSubmit={handleSubmit}\n onCancel={() => setPending(null)}\n />\n )}\n\n </>\n )\n}\n","import { useEffect, useRef, useState } from \"react\"\nimport { ArrowUp, X } from \"lucide-react\"\n\ninterface AnnotationFormProps {\n xPercent: number\n yPercent: number\n onSubmit: (text: string) => void\n onCancel: () => void\n}\n\nexport function AnnotationForm({ xPercent, yPercent, onSubmit, onCancel }: AnnotationFormProps) {\n const [text, setText] = useState(\"\")\n const textareaRef = useRef<HTMLTextAreaElement>(null)\n\n useEffect(() => {\n textareaRef.current?.focus()\n }, [])\n\n const handleSubmit = () => {\n const trimmed = text.trim()\n if (!trimmed) return\n onSubmit(trimmed)\n }\n\n const handleKeyDown = (e: React.KeyboardEvent) => {\n if (e.key === \"Enter\" && !e.shiftKey) {\n e.preventDefault()\n handleSubmit()\n }\n if (e.key === \"Escape\") {\n onCancel()\n }\n e.stopPropagation()\n }\n\n // Position the form, flipping if near edges\n const left = xPercent > 70 ? undefined : `${xPercent}%`\n const right = xPercent > 70 ? `${100 - xPercent}%` : undefined\n const top = yPercent > 70 ? undefined : `${yPercent}%`\n const bottom = yPercent > 70 ? `${100 - yPercent}%` : undefined\n\n return (\n <div\n role=\"dialog\"\n className=\"absolute z-40 w-72 overflow-hidden rounded-xl border border-white/[0.08] bg-neutral-900/95 shadow-2xl backdrop-blur-2xl\"\n style={{ left, right, top, bottom }}\n onClick={e => e.stopPropagation()}\n onKeyDown={e => e.stopPropagation()}\n >\n <div className=\"flex items-center justify-between border-b border-white/[0.06] px-3.5 py-2.5\">\n <span className=\"text-xs font-medium tracking-wide text-neutral-400\">Add annotation</span>\n <button\n onClick={onCancel}\n className=\"rounded-lg p-1 text-neutral-500 transition-colors hover:bg-white/[0.06] hover:text-neutral-300\"\n >\n <X className=\"h-3.5 w-3.5\" />\n </button>\n </div>\n <div className=\"p-3\">\n <textarea\n ref={textareaRef}\n value={text}\n onChange={e => setText(e.target.value)}\n onKeyDown={handleKeyDown}\n placeholder=\"Describe the change you want...\"\n className=\"w-full resize-none rounded-lg border border-white/[0.08] bg-white/[0.04] px-3 py-2 text-sm text-white placeholder-neutral-500 outline-none transition-colors focus:border-[#FF6B35]/50 focus:bg-white/[0.06]\"\n rows={3}\n />\n <div className=\"mt-2.5 flex items-center justify-between\">\n <span className=\"text-[11px] text-neutral-600\">Enter to send</span>\n <button\n onClick={handleSubmit}\n disabled={!text.trim()}\n className=\"flex h-7 w-7 items-center justify-center rounded-lg bg-[#FF6B35] text-white shadow-lg shadow-[#FF6B35]/20 transition-all hover:bg-[#FF7A4A] hover:shadow-[#FF6B35]/30 disabled:opacity-30 disabled:shadow-none disabled:hover:bg-[#FF6B35]\"\n >\n <ArrowUp className=\"h-3.5 w-3.5\" strokeWidth={2.5} />\n </button>\n </div>\n </div>\n </div>\n )\n}\n","interface AnnotationPinProps {\n number: number\n status: \"open\" | \"resolved\"\n xPercent: number\n yPercent: number\n isSelected: boolean\n onClick: () => void\n}\n\nexport function AnnotationPin({ number, status, xPercent, yPercent, isSelected, onClick }: AnnotationPinProps) {\n const isResolved = status === \"resolved\"\n\n return (\n <button\n onClick={e => {\n e.stopPropagation()\n onClick()\n }}\n className=\"absolute z-30 -translate-x-1/2 -translate-y-1/2 transition-all duration-200 hover:scale-110\"\n style={{ left: `${xPercent}%`, top: `${yPercent}%` }}\n title={`Annotation #${number}`}\n >\n {/* Glow ring */}\n {isSelected && !isResolved && (\n <div className=\"absolute inset-[-4px] animate-pulse rounded-full bg-[#FF6B35]/25 blur-sm\" />\n )}\n <div\n className={`relative flex h-7 w-7 items-center justify-center rounded-full text-[11px] font-semibold shadow-lg backdrop-blur-sm transition-all duration-200 ${\n isSelected\n ? isResolved\n ? \"bg-neutral-500/90 text-white ring-2 ring-neutral-400/50\"\n : \"bg-[#FF6B35] text-white ring-2 ring-[#FF6B35]/40 ring-offset-1 ring-offset-black/50\"\n : isResolved\n ? \"bg-neutral-700/80 text-neutral-400\"\n : \"bg-[#FF6B35]/90 text-white hover:bg-[#FF6B35]\"\n }`}\n >\n {number}\n </div>\n </button>\n )\n}\n","import type { AnnotationTarget } from \"./types\"\n\n/**\n * Build a composite target descriptor from a clicked DOM element.\n */\nexport function buildElementTarget(\n element: HTMLElement,\n slideRoot: HTMLElement\n): AnnotationTarget {\n const rect = element.getBoundingClientRect()\n const rootRect = slideRoot.getBoundingClientRect()\n\n const xPercent = ((rect.left + rect.width / 2 - rootRect.left) / rootRect.width) * 100\n const yPercent = ((rect.top + rect.height / 2 - rootRect.top) / rootRect.height) * 100\n\n return {\n dataAnnotate: element.getAttribute(\"data-annotate\") || undefined,\n contentNearPin: getTextFingerprint(element),\n position: { xPercent, yPercent }\n }\n}\n\n/**\n * Resolve a stored target back to a DOM element, trying strategies in priority order.\n */\nexport function resolveTarget(\n target: AnnotationTarget,\n slideRoot: HTMLElement\n): { element: HTMLElement | null; method: \"dataAnnotate\" | \"contentNearPin\" | \"position\" } {\n // 1. Try data-annotate attribute\n if (target.dataAnnotate) {\n const el = slideRoot.querySelector<HTMLElement>(`[data-annotate=\"${target.dataAnnotate}\"]`)\n if (el) return { element: el, method: \"dataAnnotate\" }\n }\n\n // 2. Try text content match\n if (target.contentNearPin) {\n const match = findByTextContent(slideRoot, target.contentNearPin)\n if (match) return { element: match, method: \"contentNearPin\" }\n }\n\n // 3. Fallback to coordinates (no element found)\n return { element: null, method: \"position\" }\n}\n\n/**\n * Extract a text fingerprint from an element (first 100 chars, trimmed).\n */\nfunction getTextFingerprint(element: HTMLElement): string | undefined {\n const text = element.textContent?.trim()\n if (!text) return undefined\n return text.slice(0, 100)\n}\n\n/**\n * Find an element by matching its text content.\n */\nfunction findByTextContent(root: HTMLElement, text: string): HTMLElement | null {\n const walker = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT)\n let best: HTMLElement | null = null\n let bestLength = Infinity\n\n while (walker.nextNode()) {\n const el = walker.currentNode as HTMLElement\n const elText = el.textContent?.trim()\n if (!elText) continue\n\n const elFingerprint = elText.slice(0, 100)\n if (elFingerprint === text && elText.length < bestLength) {\n best = el\n bestLength = elText.length\n }\n }\n\n return best\n}\n","import { MessageCircle, Trash2, X } from \"lucide-react\"\nimport type { Annotation } from \"./types\"\n\ninterface AnnotationPanelProps {\n annotations: Annotation[]\n selectedId: string | null\n onSelect: (id: string) => void\n onDelete: (id: string) => void\n onClose: () => void\n}\n\nexport function AnnotationPanel({ annotations, selectedId, onSelect, onDelete, onClose }: AnnotationPanelProps) {\n const open = annotations.filter(a => a.status === \"open\")\n const resolved = annotations.filter(a => a.status === \"resolved\")\n\n return (\n <div className=\"flex h-full w-80 flex-shrink-0 flex-col border-l border-white/[0.06] bg-neutral-950/95 backdrop-blur-2xl\">\n <div className=\"flex items-center justify-between px-4 py-3.5\">\n <div className=\"flex items-center gap-2.5\">\n <div className=\"flex h-6 w-6 items-center justify-center rounded-lg bg-[#FF6B35]/15\">\n <MessageCircle className=\"h-3.5 w-3.5 text-[#FF6B35]\" />\n </div>\n <span className=\"text-sm font-medium text-white\">Annotations</span>\n {open.length > 0 && (\n <span className=\"flex h-5 min-w-5 items-center justify-center rounded-full bg-[#FF6B35]/15 px-1.5 text-[11px] font-semibold text-[#FF6B35]\">\n {open.length}\n </span>\n )}\n </div>\n <button\n onClick={onClose}\n className=\"rounded-lg p-1.5 text-neutral-500 transition-colors hover:bg-white/[0.06] hover:text-neutral-300\"\n >\n <X className=\"h-4 w-4\" />\n </button>\n </div>\n\n <div className=\"h-px bg-gradient-to-r from-transparent via-white/[0.06] to-transparent\" />\n\n <div className=\"flex-1 overflow-y-auto p-2\">\n {annotations.length === 0 && (\n <div className=\"flex flex-col gap-4 px-3 py-6\">\n <WorkflowHint />\n </div>\n )}\n\n {open.length > 0 && (\n <div>\n <div className=\"mb-1.5 px-2 pt-1 text-[11px] font-medium tracking-wider text-neutral-500 uppercase\">\n Open\n </div>\n {open.map((a, i) => (\n <AnnotationItem\n key={a.id}\n annotation={a}\n number={i + 1}\n isSelected={a.id === selectedId}\n onSelect={() => onSelect(a.id)}\n onDelete={() => onDelete(a.id)}\n />\n ))}\n </div>\n )}\n\n {resolved.length > 0 && (\n <div className={open.length > 0 ? \"mt-3\" : \"\"}>\n <div className=\"mb-1.5 px-2 pt-1 text-[11px] font-medium tracking-wider text-neutral-500 uppercase\">\n Resolved\n </div>\n {resolved.map((a, i) => (\n <AnnotationItem\n key={a.id}\n annotation={a}\n number={open.length + i + 1}\n isSelected={a.id === selectedId}\n onSelect={() => onSelect(a.id)}\n onDelete={() => onDelete(a.id)}\n />\n ))}\n </div>\n )}\n </div>\n\n {annotations.length > 0 && (\n <>\n <div className=\"h-px bg-gradient-to-r from-transparent via-white/[0.06] to-transparent\" />\n <div className=\"px-3 py-3\">\n <WorkflowHint />\n </div>\n </>\n )}\n </div>\n )\n}\n\nfunction WorkflowHint() {\n return (\n <div className=\"flex flex-col gap-2\">\n <p className=\"text-[11px] font-medium tracking-wider text-neutral-500 uppercase\">Workflow</p>\n <div className=\"flex items-start gap-2.5\">\n <div className=\"mt-0.5 flex h-4 w-4 flex-shrink-0 items-center justify-center rounded-full bg-[#FF6B35]/15 text-[10px] font-semibold text-[#FF6B35]\">1</div>\n <p className=\"text-[12px] leading-snug text-neutral-400\">Annotate everything you want to fix</p>\n </div>\n <div className=\"flex items-start gap-2.5\">\n <div className=\"mt-0.5 flex h-4 w-4 flex-shrink-0 items-center justify-center rounded-full bg-[#FF6B35]/15 text-[10px] font-semibold text-[#FF6B35]\">2</div>\n <p className=\"text-[12px] leading-snug text-neutral-400\">Switch to your coding agent</p>\n </div>\n <div className=\"flex items-start gap-2.5\">\n <div className=\"mt-0.5 flex h-4 w-4 flex-shrink-0 items-center justify-center rounded-full bg-[#FF6B35]/15 text-[10px] font-semibold text-[#FF6B35]\">3</div>\n <p className=\"text-[12px] leading-snug text-neutral-400\">\"Fix open annotations\"</p>\n </div>\n </div>\n )\n}\n\nfunction AnnotationItem({\n annotation,\n number,\n isSelected,\n onSelect,\n onDelete\n}: {\n annotation: Annotation\n number: number\n isSelected: boolean\n onSelect: () => void\n onDelete: () => void\n}) {\n return (\n <div\n role=\"button\"\n tabIndex={0}\n onClick={onSelect}\n onKeyDown={e => { if (e.key === \"Enter\" || e.key === \" \") onSelect() }}\n className={`group relative mb-0.5 cursor-pointer rounded-xl p-2.5 transition-all duration-150 ${\n isSelected\n ? \"bg-[#FF6B35]/10 ring-1 ring-[#FF6B35]/20\"\n : \"hover:bg-white/[0.04]\"\n }`}\n >\n <button\n onClick={e => {\n e.stopPropagation()\n onDelete()\n }}\n className=\"absolute top-2 right-2 rounded-lg p-1 text-neutral-600 opacity-0 transition-all hover:bg-white/[0.08] hover:text-neutral-300 group-hover:opacity-100\"\n >\n <Trash2 className=\"h-3 w-3\" />\n </button>\n <div className=\"flex items-start gap-2.5\">\n <div\n className={`mt-0.5 flex h-5 w-5 flex-shrink-0 items-center justify-center rounded-full text-[11px] font-semibold ${\n annotation.status === \"open\"\n ? \"bg-[#FF6B35] text-white\"\n : \"bg-neutral-700 text-neutral-400\"\n }`}\n >\n {number}\n </div>\n <div className=\"min-w-0 pr-4\">\n <p className=\"text-[13px] leading-relaxed text-neutral-200\">{annotation.body}</p>\n {annotation.target.contentNearPin && (\n <p className=\"mt-1 truncate text-[11px] text-neutral-600\">\n {annotation.target.contentNearPin}\n </p>\n )}\n {annotation.resolution && (\n <p className=\"mt-1.5 text-[11px] text-emerald-400/80 italic\">\n {annotation.resolution}\n </p>\n )}\n </div>\n </div>\n </div>\n )\n}\n","import { useCallback, useEffect, useMemo, useRef, useState } from \"react\"\nimport { createHttpAdapter } from \"./adapters/http\"\nimport type { Annotation, AnnotationStorageAdapter, AnnotationTarget } from \"./types\"\n\nexport function useAnnotations(adapter?: AnnotationStorageAdapter) {\n const adapterRef = useRef(adapter ?? createHttpAdapter())\n const [annotations, setAnnotations] = useState<Annotation[]>([])\n\n // Load on mount and subscribe to external updates\n useEffect(() => {\n adapterRef.current.load().then(setAnnotations)\n return adapterRef.current.subscribe?.(setAnnotations)\n }, [])\n\n const addAnnotation = useCallback(\n (slideIndex: number, slideTitle: string, target: AnnotationTarget, body: string) => {\n const annotation: Annotation = {\n id: crypto.randomUUID(),\n slideIndex,\n slideTitle,\n target,\n body,\n createdAt: new Date().toISOString(),\n status: \"open\"\n }\n setAnnotations(prev => [...prev, annotation])\n adapterRef.current.add(annotation)\n },\n []\n )\n\n const deleteAnnotation = useCallback((id: string) => {\n setAnnotations(prev => prev.filter(a => a.id !== id))\n adapterRef.current.remove(id)\n }, [])\n\n const getSlideAnnotations = useCallback(\n (slideIndex: number) => annotations.filter(a => a.slideIndex === slideIndex),\n [annotations]\n )\n\n const openCount = useMemo(() => annotations.filter(a => a.status === \"open\").length, [annotations])\n\n // Allow external state updates (e.g. from postMessage adapter)\n const updateAnnotations = useCallback((updated: Annotation[]) => {\n setAnnotations(updated)\n }, [])\n\n return { annotations, addAnnotation, deleteAnnotation, getSlideAnnotations, openCount, updateAnnotations }\n}\n","import type { Annotation, AnnotationsFile, AnnotationStorageAdapter } from \"../types\"\n\nconst ENDPOINT = \"/__promptslide_annotations\"\n\nasync function loadAll(): Promise<Annotation[]> {\n try {\n const res = await fetch(ENDPOINT)\n if (!res.ok) return []\n const data: AnnotationsFile = await res.json()\n return data.annotations || []\n } catch {\n return []\n }\n}\n\nasync function saveAll(annotations: Annotation[]): Promise<void> {\n const data: AnnotationsFile = { version: 1, annotations }\n await fetch(ENDPOINT, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(data)\n })\n}\n\n/** Storage adapter for local Vite dev server (reads/writes annotations.json via middleware) */\nexport function createHttpAdapter(): AnnotationStorageAdapter {\n let cache: Annotation[] = []\n\n return {\n async load() {\n cache = await loadAll()\n return cache\n },\n async add(annotation) {\n cache = [...cache, annotation]\n await saveAll(cache)\n },\n async remove(id) {\n cache = cache.filter(a => a.id !== id)\n await saveAll(cache)\n }\n }\n}\n","import type { ClassValue } from \"clsx\"\n\nimport { clsx } from \"clsx\"\nimport { twMerge } from \"tailwind-merge\"\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs))\n}\n"],"mappings":";;;;;AAUO,IAAM,4BAA4B;AAGlC,IAAM,iBAAiB;AAGvB,IAAM,0BAA0B;AAGhC,IAAM,gBAAgB;AAMtB,IAAM,eAAe;AACrB,IAAM,WAAW;AACjB,IAAM,UAAU;AAGhB,IAAM,aAAa,CAAC,KAAK,GAAG,KAAK,CAAC;AAOlC,IAAM,gBAAgB;AAAA,EAC3B,MAAM;AAAA,EACN,WAAW;AAAA,EACX,SAAS;AACX;AAGO,IAAM,gBAAgB;AAAA,EAC3B,MAAM;AAAA,EACN,WAAW;AAAA,EACX,SAAS;AACX;AAGO,IAAM,gBAAgB;AAAA,EAC3B,MAAM;AAAA,EACN,WAAW;AAAA,EACX,SAAS;AACX;AAOO,IAAM,mBAAmB;AAAA,EAC9B,UAAU;AAAA,EACV,MAAM;AACR;AAGO,IAAM,mBAAmB;AAAA,EAC9B,UAAU;AAAA,EACV,MAAM;AACR;AAGO,IAAM,kBAAkB;AAAA,EAC7B,GAAG;AACL;AAOO,IAAM,iBAAiB;AAGvB,IAAM,yBAAyB;AAO/B,IAAM,mBAAmB;AAAA,EAC9B,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,aAAa,KAAK;AACpB;;;ACjGA,SAAS,eAAe,YAAY,eAAe;AAgD1C;AArCT,IAAM,mBAAmB,cAAqC;AAAA,EAC5D,aAAa;AAAA,EACb,YAAY;AAAA,EACZ,mBAAmB;AACrB,CAAC;AAkBM,SAAS,kBAAkB;AAAA,EAChC;AAAA,EACA;AAAA,EACA;AAAA,EACA,oBAAoB;AACtB,GAA2B;AACzB,QAAM,QAAQ;AAAA,IACZ,OAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,CAAC,aAAa,YAAY,iBAAiB;AAAA,EAC7C;AAEA,SAAO,oBAAC,iBAAiB,UAAjB,EAA0B,OAAe,UAAS;AAC5D;AAEO,SAAS,sBAAsB;AACpC,SAAO,WAAW,gBAAgB;AACpC;;;ACrDA,SAAS,cAAwB;AAoF7B,gBAAAA,YAAA;AA9DJ,IAAM,oBAAqD;AAAA,EACzD,MAAM;AAAA,IACJ,QAAQ,EAAE,SAAS,EAAE;AAAA,IACrB,SAAS,EAAE,SAAS,EAAE;AAAA,EACxB;AAAA,EACA,YAAY;AAAA,IACV,QAAQ,EAAE,SAAS,GAAG,GAAG,uBAAuB;AAAA,IAChD,SAAS,EAAE,SAAS,GAAG,GAAG,EAAE;AAAA,EAC9B;AAAA,EACA,cAAc;AAAA,IACZ,QAAQ,EAAE,SAAS,GAAG,GAAG,CAAC,uBAAuB;AAAA,IACjD,SAAS,EAAE,SAAS,GAAG,GAAG,EAAE;AAAA,EAC9B;AAAA,EACA,cAAc;AAAA,IACZ,QAAQ,EAAE,SAAS,GAAG,GAAG,uBAAuB;AAAA,IAChD,SAAS,EAAE,SAAS,GAAG,GAAG,EAAE;AAAA,EAC9B;AAAA,EACA,eAAe;AAAA,IACb,QAAQ,EAAE,SAAS,GAAG,GAAG,CAAC,uBAAuB;AAAA,IACjD,SAAS,EAAE,SAAS,GAAG,GAAG,EAAE;AAAA,EAC9B;AAAA,EACA,OAAO;AAAA,IACL,QAAQ,EAAE,SAAS,GAAG,OAAO,IAAI;AAAA,IACjC,SAAS,EAAE,SAAS,GAAG,OAAO,EAAE;AAAA,EAClC;AACF;AAuBO,SAAS,SAAS;AAAA,EACvB;AAAA,EACA,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,QAAQ;AAAA,EACR;AAAA,EACA;AACF,GAAkB;AAChB,QAAM,EAAE,aAAa,kBAAkB,IAAI,oBAAoB;AAG/D,QAAM,YAAY,qBAAqB,eAAe;AAEtD,SACE,gBAAAA;AAAA,IAAC,OAAO;AAAA,IAAP;AAAA,MACC,SAAQ;AAAA,MACR,SAAS,YAAY,YAAY;AAAA,MACjC,UAAU,kBAAkB,SAAS;AAAA,MACrC,YAAY;AAAA,QACV,GAAG;AAAA,QACH;AAAA,QACA,OAAO,YAAY,QAAQ;AAAA,MAC7B;AAAA,MACA;AAAA,MAEC;AAAA;AAAA,EACH;AAEJ;AAiBO,SAAS,cAAc;AAAA,EAC5B;AAAA,EACA,YAAY;AAAA,EACZ,eAAe;AAAA,EACf;AAAA,EACA;AACF,GAAuB;AACrB,QAAM,EAAE,aAAa,kBAAkB,IAAI,oBAAoB;AAE/D,QAAM,aAAa,MAAM,QAAQ,QAAQ,IAAI,WAAW,CAAC,QAAQ;AAGjE,QAAM,YAAY,qBAAqB,eAAe;AAEtD,QAAM,oBAA8B;AAAA,IAClC,QAAQ,CAAC;AAAA,IACT,SAAS;AAAA,MACP,YAAY;AAAA,QACV,iBAAiB;AAAA,MACnB;AAAA,IACF;AAAA,EACF;AAEA,SACE,gBAAAA;AAAA,IAAC,OAAO;AAAA,IAAP;AAAA,MACC,SAAQ;AAAA,MACR,SAAS,YAAY,YAAY;AAAA,MACjC,UAAU;AAAA,MACV;AAAA,MAEC,qBAAW,IAAI,CAAC,OAAO,UACtB,gBAAAA,KAAC,OAAO,KAAP,EAAuB,UAAU,kBAAkB,SAAS,GAC1D,mBADc,KAEjB,CACD;AAAA;AAAA,EACH;AAEJ;;;AC7GA,IAAM,eAAyB;AAAA,EAC7B,OAAO,EAAE,SAAS,EAAE;AAAA,EACpB,QAAQ,EAAE,SAAS,EAAE;AAAA,EACrB,MAAM,EAAE,SAAS,EAAE;AACrB;AAEA,IAAM,oBAA8B;AAAA,EAClC,OAAO,EAAE,GAAG,gBAAgB,SAAS,EAAE;AAAA,EACvC,QAAQ,EAAE,GAAG,GAAG,SAAS,EAAE;AAAA,EAC3B,MAAM,EAAE,GAAG,CAAC,gBAAgB,SAAS,EAAE;AACzC;AAEA,IAAM,qBAA+B;AAAA,EACnC,OAAO,EAAE,GAAG,CAAC,gBAAgB,SAAS,EAAE;AAAA,EACxC,QAAQ,EAAE,GAAG,GAAG,SAAS,EAAE;AAAA,EAC3B,MAAM,EAAE,GAAG,gBAAgB,SAAS,EAAE;AACxC;AAEA,IAAM,kBAA4B;AAAA,EAChC,OAAO,EAAE,GAAG,gBAAgB,SAAS,EAAE;AAAA,EACvC,QAAQ,EAAE,GAAG,GAAG,SAAS,EAAE;AAAA,EAC3B,MAAM,EAAE,GAAG,CAAC,gBAAgB,SAAS,EAAE;AACzC;AAEA,IAAM,oBAA8B;AAAA,EAClC,OAAO,EAAE,GAAG,CAAC,gBAAgB,SAAS,EAAE;AAAA,EACxC,QAAQ,EAAE,GAAG,GAAG,SAAS,EAAE;AAAA,EAC3B,MAAM,EAAE,GAAG,gBAAgB,SAAS,EAAE;AACxC;AAEA,IAAM,eAAyB;AAAA,EAC7B,OAAO,EAAE,OAAO,KAAK,SAAS,EAAE;AAAA,EAChC,QAAQ,EAAE,OAAO,GAAG,SAAS,EAAE;AAAA,EAC/B,MAAM,EAAE,OAAO,KAAK,SAAS,EAAE;AACjC;AAEA,IAAM,mBAA6B;AAAA,EACjC,OAAO,EAAE,OAAO,MAAM,SAAS,EAAE;AAAA,EACjC,QAAQ,EAAE,OAAO,GAAG,SAAS,EAAE;AAAA,EAC/B,MAAM,EAAE,OAAO,MAAM,SAAS,EAAE;AAClC;AAEA,IAAM,gBAA0B;AAAA,EAC9B,OAAO;AAAA,IACL,SAAS;AAAA,IACT,QAAQ;AAAA,EACV;AAAA,EACA,QAAQ;AAAA,IACN,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,YAAY;AAAA,MACV,SAAS,EAAE,OAAO,MAAM,UAAU,KAAK;AAAA,IACzC;AAAA,EACF;AAAA,EACA,MAAM;AAAA,IACJ,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,YAAY;AAAA,MACV,SAAS,EAAE,UAAU,gBAAgB,MAAM,WAAW;AAAA,IACxD;AAAA,EACF;AACF;AAEA,IAAM,eAAyB;AAAA,EAC7B,OAAO,CAAC;AAAA,EACR,QAAQ,CAAC;AAAA,EACT,MAAM,CAAC;AACT;AAMO,IAAM,iBAAwD;AAAA,EACnE,MAAM;AAAA,EACN,cAAc;AAAA,EACd,eAAe;AAAA,EACf,YAAY;AAAA,EACZ,cAAc;AAAA,EACd,MAAM;AAAA,EACN,aAAa;AAAA,EACb,OAAO;AAAA,EACP,MAAM;AACR;AAMO,SAAS,0BAA0B,OAAkB,KAAsC;AAChG,SAAO,CAAC,eAAuB;AAAA,IAC7B,OAAO;AAAA,MACL,CAAC,IAAI,GAAG,YAAY,IAAI,iBAAiB,CAAC;AAAA,MAC1C,SAAS;AAAA,IACX;AAAA,IACA,QAAQ;AAAA,MACN,CAAC,IAAI,GAAG;AAAA,MACR,SAAS;AAAA,IACX;AAAA,IACA,MAAM;AAAA,MACJ,CAAC,IAAI,GAAG,YAAY,IAAI,iBAAiB,CAAC;AAAA,MAC1C,SAAS;AAAA,IACX;AAAA,EACF;AACF;AAGO,IAAM,oBAAoB,0BAA0B,GAAG;AAGvD,IAAM,oBAAoB,0BAA0B,GAAG;AAMvD,SAAS,iBACd,QACA,YAAoB,GACV;AACV,QAAM,OAAO,OAAO,WAAW,WAAW,SAAS,OAAO;AAC1D,QAAM,cAAc,OAAO,WAAW,WAAW,OAAO,cAAc;AAEtE,MAAI,gBAAgB,SAAS,gBAAgB,SAAS,gBAAgB;AACpE,WAAO,kBAAkB,SAAS;AAAA,EACpC;AAEA,MAAI,gBAAgB,SAAS,cAAc,SAAS,eAAe;AACjE,WAAO,kBAAkB,SAAS;AAAA,EACpC;AAEA,SAAO,eAAe,IAAI;AAC5B;AAEO,SAAS,mBAAmB,QAGjC;AACA,MAAI,CAAC,OAAQ,QAAO;AAEpB,QAAM,OAAO,OAAO,WAAW,WAAW,SAAS,OAAO;AAE1D,QAAM,kBAAkB,SAAS,UAAU,iBAAiB;AAE5D,QAAM,WAAW,OAAO,WAAW,YAAY,OAAO,WAAW,OAAO,WAAW;AAEnF,SAAO;AAAA,IACL,GAAG;AAAA,IACH;AAAA,EACF;AACF;AAMO,IAAM,2BAAgD;;;ACrM7D,SAAS,UAAAC,eAAc;AAiDnB,gBAAAC,YAAA;AAPG,SAAS,MAAM;AAAA,EACpB;AAAA,EACA,aAAa;AAAA,EACb;AAAA,EACA;AACF,GAAe;AACb,SACE,gBAAAA;AAAA,IAACC,QAAO;AAAA,IAAP;AAAA,MACC,QAAM;AAAA,MACN;AAAA,MACA,SAAS;AAAA,MACT;AAAA,MACA;AAAA,MAEC;AAAA;AAAA,EACH;AAEJ;AAMO,SAAS,WAAW;AAAA,EACzB;AAAA,EACA,aAAa;AAAA,EACb;AAAA,EACA;AACF,GAAoB;AAClB,SACE,gBAAAD;AAAA,IAACC,QAAO;AAAA,IAAP;AAAA,MACC,QAAM;AAAA,MACN,UAAU;AAAA,MACV,SAAS;AAAA,MACT;AAAA,MACA;AAAA,MAEC;AAAA;AAAA,EACH;AAEJ;AAcO,SAAS,UAAU;AAAA,EACxB;AAAA,EACA;AAAA,EACA,aAAa;AAAA,EACb;AAAA,EACA;AACF,GAAmB;AACjB,QAAM,WAAW,SAAS,GAAG,MAAM,IAAI,EAAE,KAAK;AAE9C,SACE,gBAAAD;AAAA,IAACC,QAAO;AAAA,IAAP;AAAA,MACC,QAAM;AAAA,MACN;AAAA,MACA,SAAS;AAAA,MACT;AAAA,MACA;AAAA,MAEC;AAAA;AAAA,EACH;AAEJ;AAcO,SAAS,UAAU;AAAA,EACxB;AAAA,EACA,IAAI,YAAY;AAAA,EAChB,aAAa;AAAA,EACb;AAAA,EACA;AACF,GAAmB;AACjB,QAAM,kBAAkBA,QAAO,SAAS;AAExC,SACE,gBAAAD;AAAA,IAAC;AAAA;AAAA,MACC,QAAM;AAAA,MACN;AAAA,MACA,SAAS;AAAA,MACT;AAAA,MACA;AAAA,MAEC;AAAA;AAAA,EACH;AAEJ;;;ACxJA,SAAS,aAAa,WAAW,gBAAgB;AAwC1C,SAAS,mBAAmB;AAAA,EACjC;AAAA,EACA,eAAe;AAAA,EACf;AACF,GAAwD;AACtD,QAAM,CAAC,cAAc,eAAe,IAAI,SAAS,YAAY;AAC7D,QAAM,CAAC,eAAe,gBAAgB,IAAI,SAAS,CAAC;AAEpD,QAAM,CAAC,UAAU,WAAW,IAAI,SAA0B;AAAA,IACxD,QAAQ;AAAA,IACR,WAAW;AAAA,EACb,CAAC;AAED,QAAM,CAAC,cAAc,eAAe,IAAI,SAAuB,IAAI;AAEnE,QAAM,aAAa,OAAO,YAAY,GAAG,SAAS;AAElD,QAAM,uBAAuB,YAAY,MAAM;AAC7C,gBAAY,UAAQ;AAClB,UAAI,KAAK,WAAW,iBAAiB;AACnC,eAAO,EAAE,QAAQ,QAAQ,WAAW,EAAE;AAAA,MACxC;AACA,aAAO;AAAA,IACT,CAAC;AAAA,EACH,GAAG,CAAC,CAAC;AAEL,QAAM,UAAU,YAAY,MAAM;AAChC,QAAI,SAAS,WAAW,iBAAiB;AACvC,sBAAgB,SAAS;AACzB;AAAA,IACF;AAEA,UAAM,oBAAoB,OAAO,YAAY,GAAG,SAAS;AAEzD,QAAI,iBAAiB,mBAAmB;AACtC,YAAM,aAAa,eAAe,KAAK,OAAO;AAC9C,kBAAY,EAAE,QAAQ,iBAAiB,WAAW,EAAE,CAAC;AACrD,uBAAiB,CAAC;AAClB,sBAAgB,SAAS;AACzB,sBAAgB,SAAS;AAAA,IAC3B,OAAO;AACL,uBAAiB,UAAQ,OAAO,CAAC;AAAA,IACnC;AAAA,EACF,GAAG,CAAC,SAAS,QAAQ,eAAe,cAAc,QAAQ,aAAa,CAAC;AAExE,QAAM,SAAS,YAAY,MAAM;AAC/B,QAAI,SAAS,WAAW,iBAAiB;AACvC,sBAAgB,QAAQ;AACxB;AAAA,IACF;AAEA,QAAI,iBAAiB,GAAG;AACtB,YAAM,aAAa,eAAe,IAAI,OAAO,UAAU,OAAO;AAC9D,YAAM,iBAAiB,OAAO,SAAS,GAAG,SAAS;AACnD,kBAAY,EAAE,QAAQ,iBAAiB,WAAW,GAAG,CAAC;AACtD,uBAAiB,cAAc;AAC/B,sBAAgB,SAAS;AACzB,sBAAgB,SAAS;AAAA,IAC3B,OAAO;AACL,uBAAiB,UAAQ,OAAO,CAAC;AAAA,IACnC;AAAA,EACF,GAAG,CAAC,SAAS,QAAQ,eAAe,cAAc,QAAQ,aAAa,CAAC;AAExE,QAAM,YAAY;AAAA,IAChB,CAAC,UAAkB;AACjB,UAAI,QAAQ,KAAK,SAAS,OAAO,UAAU,UAAU,cAAc;AACjE;AAAA,MACF;AAEA,YAAM,YAAY,QAAQ,eAAe,IAAI;AAC7C,kBAAY,EAAE,QAAQ,iBAAiB,UAAU,CAAC;AAClD,uBAAiB,CAAC;AAClB,sBAAgB,KAAK;AACrB,sBAAgB,KAAK;AAAA,IACvB;AAAA,IACA,CAAC,cAAc,OAAO,QAAQ,aAAa;AAAA,EAC7C;AAEA,YAAU,MAAM;AACd,QAAI,SAAS,WAAW,UAAU,iBAAiB,MAAM;AACvD,sBAAgB,IAAI;AACpB,UAAI,iBAAiB,WAAW;AAC9B,gBAAQ;AAAA,MACV,WAAW,iBAAiB,UAAU;AACpC,eAAO;AAAA,MACT;AAAA,IACF;AAAA,EACF,GAAG,CAAC,SAAS,QAAQ,cAAc,SAAS,MAAM,CAAC;AAEnD,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA,WAAW,SAAS;AAAA,IACpB,iBAAiB,SAAS,WAAW;AAAA,IACrC,mBAAmB,SAAS,cAAc,MAAM,SAAS,WAAW;AAAA,IACpE;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;AC7IA,SAAS,iBAAAE,gBAAe,cAAAC,aAAY,WAAAC,gBAAe;AA0C7C,gBAAAC,YAAA;AAvCN,IAAM,eAAeH,eAAkC,IAAI;AAKpD,SAAS,WAA+B;AAC7C,SAAOC,YAAW,YAAY;AAChC;AAEA,SAAS,kBAAkB,OAAyC;AAClE,QAAM,QAAgC,CAAC;AAEvC,MAAI,MAAM,QAAQ,QAAS,OAAM,WAAW,IAAI,MAAM,OAAO;AAC7D,MAAI,MAAM,QAAQ,kBAAmB,OAAM,sBAAsB,IAAI,MAAM,OAAO;AAClF,MAAI,MAAM,QAAQ,UAAW,OAAM,aAAa,IAAI,MAAM,OAAO;AACjE,MAAI,MAAM,QAAQ,oBAAqB,OAAM,wBAAwB,IAAI,MAAM,OAAO;AACtF,MAAI,MAAM,QAAQ,OAAQ,OAAM,UAAU,IAAI,MAAM,OAAO;AAC3D,MAAI,MAAM,QAAQ,iBAAkB,OAAM,qBAAqB,IAAI,MAAM,OAAO;AAEhF,MAAI,MAAM,OAAO,QAAS,OAAM,gBAAgB,IAAI,MAAM,MAAM;AAChE,MAAI,MAAM,OAAO,KAAM,OAAM,aAAa,IAAI,MAAM,MAAM;AAE1D,SAAO;AACT;AAWO,SAAS,mBAAmB,EAAE,OAAO,SAAS,GAA4B;AAC/E,QAAM,eAAeC,SAAQ,MAAM,kBAAkB,KAAK,GAAG,CAAC,KAAK,CAAC;AAEpE,SACE,gBAAAC,KAAC,aAAa,UAAb,EAAsB,OAAO,OAC5B,0BAAAA,KAAC,SAAI,OAAO,cAAc,WAAU,YACjC,UACH,GACF;AAEJ;;;AC/CA,SAAS,iBAAiB,UAAAC,eAAc;;;ACAxC,OAAO,WAAW;AAsCJ,SAGJ,OAAAC,MAHI;AAzBP,IAAM,qBAAN,cAAiC,MAAM,UAG5C;AAAA,EAHK;AAAA;AAIL,iCAAiC,EAAE,UAAU,OAAO,OAAO,KAAK;AAAA;AAAA,EAEhE,OAAO,yBAAyB,OAAc;AAC5C,WAAO,EAAE,UAAU,MAAM,MAAM;AAAA,EACjC;AAAA,EAEA,kBAAkB,OAAc,WAA4B;AAC1D,YAAQ;AAAA,MACN,uBAAuB,KAAK,MAAM,aAAa,CAAC,GAAG,KAAK,MAAM,aAAa,MAAM,KAAK,MAAM,UAAU,OAAO,EAAE;AAAA,MAC/G;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEA,SAAS;AACP,QAAI,KAAK,MAAM,UAAU;AACvB,aACE,qBAAC,SAAI,WAAU,8EACb;AAAA,6BAAC,SAAI,WAAU,2CAA0C;AAAA;AAAA,UAChD,KAAK,MAAM,aAAa;AAAA,UAAE;AAAA,UAChC,KAAK,MAAM,cACV,qBAAC,UAAK,WAAU,oCAAmC;AAAA;AAAA,YAAE,KAAK,MAAM;AAAA,YAAW;AAAA,aAAC;AAAA,WAEhF;AAAA,QACA,gBAAAA,KAAC,SAAI,WAAU,uEACZ,eAAK,MAAM,OAAO,WAAW,iBAChC;AAAA,SACF;AAAA,IAEJ;AACA,WAAO,KAAK,MAAM;AAAA,EACpB;AACF;;;ADgCY,gBAAAC,YAAA;AA/CL,SAAS,cAAc;AAAA,EAC5B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAuB;AACrB,QAAM,yBAAyB,OAAO,YAAY,GAAG;AACrD,QAAM,iBAAiB,0BAA0B,cAAc;AAC/D,QAAM,gBAAgB,yBAAyB;AAE/C,QAAM,gBAAgB;AAAA,IACpB,EAAE,MAAM,gBAAgB,aAAa,cAAc;AAAA,IACnD;AAAA,EACF;AAEA,QAAM,wBAAwB,OAAO,YAAY,EAAG;AAEpD,SACE,gBAAAA,KAAC,mBAAgB,SAAS,OACxB,0BAAAA;AAAA,IAACC,QAAO;AAAA,IAAP;AAAA,MAEC,UAAU;AAAA,MACV,SAAQ;AAAA,MACR,SAAQ;AAAA,MACR,MAAK;AAAA,MACL,YAAY;AAAA,MACZ,qBAAqB,gBAAc;AACjC,YAAI,eAAe,UAAU;AAC3B,+BAAqB;AAAA,QACvB;AAAA,MACF;AAAA,MACA,WAAU;AAAA,MAEV,0BAAAD;AAAA,QAAC;AAAA;AAAA,UACC,aAAa;AAAA,UACb;AAAA,UACA;AAAA,UAEA,0BAAAA;AAAA,YAAC;AAAA;AAAA,cACC,YAAY;AAAA,cACZ,YAAY,OAAO,YAAY,GAAG;AAAA,cAElC,0BAAAA;AAAA,gBAAC;AAAA;AAAA,kBACC,aAAa,eAAe;AAAA,kBAC5B,aAAa,OAAO;AAAA;AAAA,cACtB;AAAA;AAAA,UACF;AAAA;AAAA,MACF;AAAA;AAAA,IA3BK;AAAA,EA4BP,GACF;AAEJ;;;AE1FA,SAAS,eAAAE,cAAa,aAAAC,YAAW,YAAAC,iBAAgB;AAgIzC,gBAAAC,YAAA;AA3FD,SAAS,WAAW,EAAE,QAAQ,YAAY,sBAAsB,GAAoB;AACzF,QAAM,CAAC,OAAO,QAAQ,IAAIC,UAAS,CAAC;AAEpC,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI,mBAAmB,EAAE,OAAO,CAAC;AAGjC,EAAAC,WAAU,MAAM;AACd,UAAM,QAAQ;AAAA,MACZ;AAAA,MACA,aAAa,OAAO;AAAA,MACpB;AAAA,MACA;AAAA,MACA,QAAQ,OAAO,IAAI,OAAK,EAAE,SAAS,EAAE;AAAA,IACvC;AACA,WAAO,OAAO,YAAY,EAAE,MAAM,cAAc,MAAM,MAAM,GAAG,GAAG;AAAA,EACpE,GAAG,CAAC,cAAc,eAAe,YAAY,MAAM,CAAC;AAGpD,EAAAA,WAAU,MAAM;AACd,WAAO,OAAO,YAAY,EAAE,MAAM,aAAa,GAAG,GAAG;AAAA,EACvD,GAAG,CAAC,CAAC;AAGL,EAAAA,WAAU,MAAM;AAEd,UAAM,MAAO,YAAoB;AACjC,QAAI,KAAK;AACP,UAAI,GAAG,oBAAoB,MAAM;AAC/B,eAAO,OAAO,YAAY,EAAE,MAAM,YAAY,GAAG,GAAG;AAAA,MACtD,CAAC;AAAA,IACH;AAAA,EACF,GAAG,CAAC,CAAC;AAGL,QAAM,gBAAgBC;AAAA,IACpB,CAAC,UAAwB;AACvB,YAAM,EAAE,MAAM,KAAK,IAAI,MAAM,QAAQ,CAAC;AACtC,cAAQ,MAAM;AAAA,QACZ,KAAK;AACH,cAAI,OAAO,MAAM,UAAU,SAAU,WAAU,KAAK,KAAK;AACzD;AAAA,QACF,KAAK;AACH,kBAAQ;AACR;AAAA,QACF,KAAK;AACH,iBAAO;AACP;AAAA,MACJ;AAAA,IACF;AAAA,IACA,CAAC,SAAS,QAAQ,SAAS;AAAA,EAC7B;AAEA,EAAAD,WAAU,MAAM;AACd,WAAO,iBAAiB,WAAW,aAAa;AAChD,WAAO,MAAM,OAAO,oBAAoB,WAAW,aAAa;AAAA,EAClE,GAAG,CAAC,aAAa,CAAC;AAGlB,EAAAA,WAAU,MAAM;AACd,UAAM,iBAAiB,MAAM;AAC3B,YAAM,SAAS,OAAO,aAAa,iBAAiB;AACpD,YAAM,SAAS,OAAO,cAAc,iBAAiB;AACrD,eAAS,KAAK,IAAI,QAAQ,MAAM,CAAC;AAAA,IACnC;AAEA,mBAAe;AACf,WAAO,iBAAiB,UAAU,cAAc;AAChD,WAAO,MAAM,OAAO,oBAAoB,UAAU,cAAc;AAAA,EAClE,GAAG,CAAC,CAAC;AAEL,SACE,gBAAAF,KAAC,SAAI,WAAU,8CACb,0BAAAA;AAAA,IAAC;AAAA;AAAA,MACC,WAAU;AAAA,MACV,OAAO;AAAA,QACL,OAAO,iBAAiB;AAAA,QACxB,QAAQ,iBAAiB;AAAA,QACzB,WAAW,+BAA+B,KAAK;AAAA,QAC/C,iBAAiB;AAAA,MACnB;AAAA,MAEA,0BAAAA;AAAA,QAAC;AAAA;AAAA,UACC;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA;AAAA,MACF;AAAA;AAAA,EACF,GACF;AAEJ;;;AC9IA,SAAS,mBAAmB;AAC5B,SAAS,aAAa,cAAc,UAAU,SAAS,MAAM,UAAU,iBAAAI,gBAAe,eAAe;AACrG,SAAS,eAAAC,cAAa,aAAAC,YAAW,WAAAC,UAAS,UAAAC,SAAQ,YAAAC,iBAAgB;;;ACFlE,SAAS,eAAAC,cAAa,aAAAC,YAAW,UAAAC,SAAQ,YAAAC,iBAAgB;;;ACAzD,SAAS,aAAAC,YAAW,QAAQ,YAAAC,iBAAgB;AAC5C,SAAS,SAAS,SAAS;AAgDrB,SACE,OAAAC,MADF,QAAAC,aAAA;AAvCC,SAAS,eAAe,EAAE,UAAU,UAAU,UAAU,SAAS,GAAwB;AAC9F,QAAM,CAAC,MAAM,OAAO,IAAIF,UAAS,EAAE;AACnC,QAAM,cAAc,OAA4B,IAAI;AAEpD,EAAAD,WAAU,MAAM;AACd,gBAAY,SAAS,MAAM;AAAA,EAC7B,GAAG,CAAC,CAAC;AAEL,QAAM,eAAe,MAAM;AACzB,UAAM,UAAU,KAAK,KAAK;AAC1B,QAAI,CAAC,QAAS;AACd,aAAS,OAAO;AAAA,EAClB;AAEA,QAAM,gBAAgB,CAAC,MAA2B;AAChD,QAAI,EAAE,QAAQ,WAAW,CAAC,EAAE,UAAU;AACpC,QAAE,eAAe;AACjB,mBAAa;AAAA,IACf;AACA,QAAI,EAAE,QAAQ,UAAU;AACtB,eAAS;AAAA,IACX;AACA,MAAE,gBAAgB;AAAA,EACpB;AAGA,QAAM,OAAO,WAAW,KAAK,SAAY,GAAG,QAAQ;AACpD,QAAM,QAAQ,WAAW,KAAK,GAAG,MAAM,QAAQ,MAAM;AACrD,QAAM,MAAM,WAAW,KAAK,SAAY,GAAG,QAAQ;AACnD,QAAM,SAAS,WAAW,KAAK,GAAG,MAAM,QAAQ,MAAM;AAEtD,SACE,gBAAAG;AAAA,IAAC;AAAA;AAAA,MACC,MAAK;AAAA,MACL,WAAU;AAAA,MACV,OAAO,EAAE,MAAM,OAAO,KAAK,OAAO;AAAA,MAClC,SAAS,OAAK,EAAE,gBAAgB;AAAA,MAChC,WAAW,OAAK,EAAE,gBAAgB;AAAA,MAElC;AAAA,wBAAAA,MAAC,SAAI,WAAU,gFACb;AAAA,0BAAAD,KAAC,UAAK,WAAU,sDAAqD,4BAAc;AAAA,UACnF,gBAAAA;AAAA,YAAC;AAAA;AAAA,cACC,SAAS;AAAA,cACT,WAAU;AAAA,cAEV,0BAAAA,KAAC,KAAE,WAAU,eAAc;AAAA;AAAA,UAC7B;AAAA,WACF;AAAA,QACA,gBAAAC,MAAC,SAAI,WAAU,OACb;AAAA,0BAAAD;AAAA,YAAC;AAAA;AAAA,cACC,KAAK;AAAA,cACL,OAAO;AAAA,cACP,UAAU,OAAK,QAAQ,EAAE,OAAO,KAAK;AAAA,cACrC,WAAW;AAAA,cACX,aAAY;AAAA,cACZ,WAAU;AAAA,cACV,MAAM;AAAA;AAAA,UACR;AAAA,UACA,gBAAAC,MAAC,SAAI,WAAU,4CACb;AAAA,4BAAAD,KAAC,UAAK,WAAU,gCAA+B,2BAAa;AAAA,YAC5D,gBAAAA;AAAA,cAAC;AAAA;AAAA,gBACC,SAAS;AAAA,gBACT,UAAU,CAAC,KAAK,KAAK;AAAA,gBACrB,WAAU;AAAA,gBAEV,0BAAAA,KAAC,WAAQ,WAAU,eAAc,aAAa,KAAK;AAAA;AAAA,YACrD;AAAA,aACF;AAAA,WACF;AAAA;AAAA;AAAA,EACF;AAEJ;;;ACpEI,SAWI,OAAAE,MAXJ,QAAAC,aAAA;AAJG,SAAS,cAAc,EAAE,QAAQ,QAAQ,UAAU,UAAU,YAAY,QAAQ,GAAuB;AAC7G,QAAM,aAAa,WAAW;AAE9B,SACE,gBAAAA;AAAA,IAAC;AAAA;AAAA,MACC,SAAS,OAAK;AACZ,UAAE,gBAAgB;AAClB,gBAAQ;AAAA,MACV;AAAA,MACA,WAAU;AAAA,MACV,OAAO,EAAE,MAAM,GAAG,QAAQ,KAAK,KAAK,GAAG,QAAQ,IAAI;AAAA,MACnD,OAAO,eAAe,MAAM;AAAA,MAG3B;AAAA,sBAAc,CAAC,cACd,gBAAAD,KAAC,SAAI,WAAU,4EAA2E;AAAA,QAE5F,gBAAAA;AAAA,UAAC;AAAA;AAAA,YACC,WAAW,mJACT,aACI,aACE,4DACA,wFACF,aACE,uCACA,+CACR;AAAA,YAEC;AAAA;AAAA,QACH;AAAA;AAAA;AAAA,EACF;AAEJ;;;ACpCO,SAAS,mBACd,SACA,WACkB;AAClB,QAAM,OAAO,QAAQ,sBAAsB;AAC3C,QAAM,WAAW,UAAU,sBAAsB;AAEjD,QAAM,YAAa,KAAK,OAAO,KAAK,QAAQ,IAAI,SAAS,QAAQ,SAAS,QAAS;AACnF,QAAM,YAAa,KAAK,MAAM,KAAK,SAAS,IAAI,SAAS,OAAO,SAAS,SAAU;AAEnF,SAAO;AAAA,IACL,cAAc,QAAQ,aAAa,eAAe,KAAK;AAAA,IACvD,gBAAgB,mBAAmB,OAAO;AAAA,IAC1C,UAAU,EAAE,UAAU,SAAS;AAAA,EACjC;AACF;AAKO,SAAS,cACd,QACA,WACyF;AAEzF,MAAI,OAAO,cAAc;AACvB,UAAM,KAAK,UAAU,cAA2B,mBAAmB,OAAO,YAAY,IAAI;AAC1F,QAAI,GAAI,QAAO,EAAE,SAAS,IAAI,QAAQ,eAAe;AAAA,EACvD;AAGA,MAAI,OAAO,gBAAgB;AACzB,UAAM,QAAQ,kBAAkB,WAAW,OAAO,cAAc;AAChE,QAAI,MAAO,QAAO,EAAE,SAAS,OAAO,QAAQ,iBAAiB;AAAA,EAC/D;AAGA,SAAO,EAAE,SAAS,MAAM,QAAQ,WAAW;AAC7C;AAKA,SAAS,mBAAmB,SAA0C;AACpE,QAAM,OAAO,QAAQ,aAAa,KAAK;AACvC,MAAI,CAAC,KAAM,QAAO;AAClB,SAAO,KAAK,MAAM,GAAG,GAAG;AAC1B;AAKA,SAAS,kBAAkB,MAAmB,MAAkC;AAC9E,QAAM,SAAS,SAAS,iBAAiB,MAAM,WAAW,YAAY;AACtE,MAAI,OAA2B;AAC/B,MAAI,aAAa;AAEjB,SAAO,OAAO,SAAS,GAAG;AACxB,UAAM,KAAK,OAAO;AAClB,UAAM,SAAS,GAAG,aAAa,KAAK;AACpC,QAAI,CAAC,OAAQ;AAEb,UAAM,gBAAgB,OAAO,MAAM,GAAG,GAAG;AACzC,QAAI,kBAAkB,QAAQ,OAAO,SAAS,YAAY;AACxD,aAAO;AACP,mBAAa,OAAO;AAAA,IACtB;AAAA,EACF;AAEA,SAAO;AACT;;;AHkEI,mBAGI,OAAAE,OAHJ,QAAAC,aAAA;AApHG,SAAS,kBAAkB,EAAE,QAAQ,cAAc,mBAAmB,YAAY,YAAY,aAAa,kBAAkB,cAAc,GAA2B;AAC3K,QAAM,CAAC,SAAS,UAAU,IAAIC,UAAmC,IAAI;AACrE,QAAM,CAAC,gBAAgB,iBAAiB,IAAIA,UAAyB,IAAI;AACzE,QAAM,aAAaC,QAAuB,IAAI;AAE9C,QAAM,aAAa,OAAO,YAAY,GAAG,SAAS,SAAS,eAAe,CAAC;AAG3E,QAAM,sBAAsB,iBAAiB,IAAI,CAAC,GAAG,MAAM;AACzD,UAAM,YAAY,kBAAkB;AACpC,QAAI,CAAC,WAAW;AACd,aAAO,EAAE,YAAY,GAAG,UAAU,EAAE,OAAO,SAAS,UAAU,UAAU,EAAE,OAAO,SAAS,UAAU,QAAQ,IAAI,EAAE;AAAA,IACpH;AAEA,UAAM,EAAE,QAAQ,IAAI,cAAc,EAAE,QAAQ,SAAS;AACrD,QAAI,SAAS;AACX,YAAM,OAAO,QAAQ,sBAAsB;AAC3C,YAAM,gBAAgB,UAAU,sBAAsB;AACtD,YAAM,YAAa,KAAK,OAAO,KAAK,QAAQ,IAAI,cAAc,QAAQ,cAAc,QAAS;AAC7F,YAAM,YAAa,KAAK,MAAM,KAAK,SAAS,IAAI,cAAc,OAAO,cAAc,SAAU;AAC7F,aAAO,EAAE,YAAY,GAAG,UAAU,UAAU,QAAQ,IAAI,EAAE;AAAA,IAC5D;AAEA,WAAO,EAAE,YAAY,GAAG,UAAU,EAAE,OAAO,SAAS,UAAU,UAAU,EAAE,OAAO,SAAS,UAAU,QAAQ,IAAI,EAAE;AAAA,EACpH,CAAC;AAED,QAAM,qBAAqBC;AAAA,IACzB,CAAC,MAAwB;AACvB,YAAM,YAAY,kBAAkB;AACpC,UAAI,CAAC,UAAW;AAGhB,YAAM,UAAU,WAAW;AAC3B,UAAI,QAAS,SAAQ,MAAM,gBAAgB;AAC3C,YAAM,eAAe,SAAS,iBAAiB,EAAE,SAAS,EAAE,OAAO;AACnE,UAAI,QAAS,SAAQ,MAAM,gBAAgB;AAE3C,UAAI,CAAC,gBAAgB,CAAC,UAAU,SAAS,YAAY,GAAG;AACtD,mBAAW,IAAI;AACf,mBAAW,IAAI;AACf;AAAA,MACF;AAGA,UAAI,SAAS;AACb,UAAI,OAAO,YAAY,UAAU,OAAO,iBAAiB,UAAU,SAAS,OAAO,aAAa,GAAG;AAEjG,cAAM,SAAS,OAAO;AACtB,YAAI,OAAO,YAAY,SAAS,OAAO,SAAS,UAAU,GAAG;AAC3D,mBAAS;AAAA,QACX;AAAA,MACF;AAEA,YAAM,mBAAmB,mBAAmB,QAAQ,SAAS;AAC7D,YAAM,gBAAgB,UAAU,sBAAsB;AACtD,YAAM,YAAa,EAAE,UAAU,cAAc,QAAQ,cAAc,QAAS;AAC5E,YAAM,YAAa,EAAE,UAAU,cAAc,OAAO,cAAc,SAAU;AAE5E,iBAAW,EAAE,QAAQ,kBAAkB,UAAU,SAAS,CAAC;AAC3D,iBAAW,IAAI;AAAA,IACjB;AAAA,IACA,CAAC,mBAAmB,UAAU;AAAA,EAChC;AAEA,QAAM,eAAeA;AAAA,IACnB,CAAC,SAAiB;AAChB,UAAI,CAAC,QAAS;AACd,oBAAc,cAAc,YAAY,QAAQ,QAAQ,IAAI;AAC5D,iBAAW,IAAI;AACf,kBAAY;AAAA,IACd;AAAA,IACA,CAAC,SAAS,cAAc,YAAY,eAAe,WAAW;AAAA,EAChE;AAGA,QAAM,kBAAkBA;AAAA,IACtB,CAAC,MAAwB;AACvB,UAAI,SAAS;AACX,0BAAkB,IAAI;AACtB;AAAA,MACF;AAEA,YAAM,YAAY,kBAAkB;AACpC,UAAI,CAAC,UAAW;AAEhB,YAAM,UAAU,WAAW;AAC3B,UAAI,QAAS,SAAQ,MAAM,gBAAgB;AAC3C,YAAM,eAAe,SAAS,iBAAiB,EAAE,SAAS,EAAE,OAAO;AACnE,UAAI,QAAS,SAAQ,MAAM,gBAAgB;AAE3C,UAAI,gBAAgB,UAAU,SAAS,YAAY,KAAK,iBAAiB,WAAW;AAClF,cAAM,gBAAgB,UAAU,sBAAsB;AACtD,cAAM,SAAS,aAAa,sBAAsB;AAClD;AAAA,UACE,IAAI;AAAA,YACF,OAAO,OAAO,cAAc;AAAA,YAC5B,OAAO,MAAM,cAAc;AAAA,YAC3B,OAAO;AAAA,YACP,OAAO;AAAA,UACT;AAAA,QACF;AAAA,MACF,OAAO;AACL,0BAAkB,IAAI;AAAA,MACxB;AAAA,IACF;AAAA,IACA,CAAC,mBAAmB,OAAO;AAAA,EAC7B;AAGA,EAAAC,WAAU,MAAM;AACd,eAAW,IAAI;AACf,eAAW,IAAI;AACf,sBAAkB,IAAI;AAAA,EACxB,GAAG,CAAC,cAAc,UAAU,CAAC;AAE7B,SACE,gBAAAJ,MAAA,YAEG;AAAA,sBACC,gBAAAD;AAAA,MAAC;AAAA;AAAA,QACC,WAAU;AAAA,QACV,OAAO;AAAA,UACL,MAAM,eAAe;AAAA,UACrB,KAAK,eAAe;AAAA,UACpB,OAAO,eAAe;AAAA,UACtB,QAAQ,eAAe;AAAA,QACzB;AAAA;AAAA,IACF;AAAA,IAIF,gBAAAA;AAAA,MAAC;AAAA;AAAA,QACC,KAAK;AAAA,QACL,MAAK;AAAA,QACL,UAAU;AAAA,QACV,WAAU;AAAA,QACV,OAAO,EAAE,QAAQ,gRAAgR;AAAA,QACjS,SAAS;AAAA,QACT,WAAW,OAAK;AAAE,cAAI,EAAE,QAAQ,UAAU;AAAE,uBAAW,IAAI;AAAG,uBAAW,IAAI;AAAA,UAAE;AAAA,QAAE;AAAA,QACjF,aAAa;AAAA,QACb,cAAc,MAAM,kBAAkB,IAAI;AAAA;AAAA,IAC5C;AAAA,IAGC,oBAAoB,IAAI,CAAC,EAAE,YAAY,UAAU,UAAU,OAAO,MACjE,gBAAAA;AAAA,MAAC;AAAA;AAAA,QAEC;AAAA,QACA,QAAQ,WAAW;AAAA,QACnB;AAAA,QACA;AAAA,QACA,YAAY,WAAW,OAAO;AAAA,QAC9B,SAAS,MAAM;AACb,qBAAW,WAAW,OAAO,aAAa,OAAO,WAAW,EAAE;AAC9D,sBAAY;AACZ,qBAAW,IAAI;AAAA,QACjB;AAAA;AAAA,MAVK,WAAW;AAAA,IAWlB,CACD;AAAA,IAGA,WACC,gBAAAA;AAAA,MAAC;AAAA;AAAA,QACC,UAAU,QAAQ;AAAA,QAClB,UAAU,QAAQ;AAAA,QAClB,UAAU;AAAA,QACV,UAAU,MAAM,WAAW,IAAI;AAAA;AAAA,IACjC;AAAA,KAGJ;AAEJ;;;AIrMA,SAAS,eAAe,QAAQ,KAAAM,UAAS;AAkBjC,SAkEA,YAAAC,WAhEI,OAAAC,OAFJ,QAAAC,aAAA;AAPD,SAAS,gBAAgB,EAAE,aAAa,YAAY,UAAU,UAAU,QAAQ,GAAyB;AAC9G,QAAM,OAAO,YAAY,OAAO,OAAK,EAAE,WAAW,MAAM;AACxD,QAAM,WAAW,YAAY,OAAO,OAAK,EAAE,WAAW,UAAU;AAEhE,SACE,gBAAAA,MAAC,SAAI,WAAU,4GACb;AAAA,oBAAAA,MAAC,SAAI,WAAU,iDACb;AAAA,sBAAAA,MAAC,SAAI,WAAU,6BACb;AAAA,wBAAAD,MAAC,SAAI,WAAU,uEACb,0BAAAA,MAAC,iBAAc,WAAU,8BAA6B,GACxD;AAAA,QACA,gBAAAA,MAAC,UAAK,WAAU,kCAAiC,yBAAW;AAAA,QAC3D,KAAK,SAAS,KACb,gBAAAA,MAAC,UAAK,WAAU,6HACb,eAAK,QACR;AAAA,SAEJ;AAAA,MACA,gBAAAA;AAAA,QAAC;AAAA;AAAA,UACC,SAAS;AAAA,UACT,WAAU;AAAA,UAEV,0BAAAA,MAACF,IAAA,EAAE,WAAU,WAAU;AAAA;AAAA,MACzB;AAAA,OACF;AAAA,IAEA,gBAAAE,MAAC,SAAI,WAAU,0EAAyE;AAAA,IAExF,gBAAAC,MAAC,SAAI,WAAU,8BACZ;AAAA,kBAAY,WAAW,KACtB,gBAAAD,MAAC,SAAI,WAAU,iCACb,0BAAAA,MAAC,gBAAa,GAChB;AAAA,MAGD,KAAK,SAAS,KACb,gBAAAC,MAAC,SACC;AAAA,wBAAAD,MAAC,SAAI,WAAU,sFAAqF,kBAEpG;AAAA,QACC,KAAK,IAAI,CAAC,GAAG,MACZ,gBAAAA;AAAA,UAAC;AAAA;AAAA,YAEC,YAAY;AAAA,YACZ,QAAQ,IAAI;AAAA,YACZ,YAAY,EAAE,OAAO;AAAA,YACrB,UAAU,MAAM,SAAS,EAAE,EAAE;AAAA,YAC7B,UAAU,MAAM,SAAS,EAAE,EAAE;AAAA;AAAA,UALxB,EAAE;AAAA,QAMT,CACD;AAAA,SACH;AAAA,MAGD,SAAS,SAAS,KACjB,gBAAAC,MAAC,SAAI,WAAW,KAAK,SAAS,IAAI,SAAS,IACzC;AAAA,wBAAAD,MAAC,SAAI,WAAU,sFAAqF,sBAEpG;AAAA,QACC,SAAS,IAAI,CAAC,GAAG,MAChB,gBAAAA;AAAA,UAAC;AAAA;AAAA,YAEC,YAAY;AAAA,YACZ,QAAQ,KAAK,SAAS,IAAI;AAAA,YAC1B,YAAY,EAAE,OAAO;AAAA,YACrB,UAAU,MAAM,SAAS,EAAE,EAAE;AAAA,YAC7B,UAAU,MAAM,SAAS,EAAE,EAAE;AAAA;AAAA,UALxB,EAAE;AAAA,QAMT,CACD;AAAA,SACH;AAAA,OAEJ;AAAA,IAEC,YAAY,SAAS,KACpB,gBAAAC,MAAAF,WAAA,EACE;AAAA,sBAAAC,MAAC,SAAI,WAAU,0EAAyE;AAAA,MACxF,gBAAAA,MAAC,SAAI,WAAU,aACb,0BAAAA,MAAC,gBAAa,GAChB;AAAA,OACF;AAAA,KAEJ;AAEJ;AAEA,SAAS,eAAe;AACtB,SACE,gBAAAC,MAAC,SAAI,WAAU,uBACb;AAAA,oBAAAD,MAAC,OAAE,WAAU,qEAAoE,sBAAQ;AAAA,IACzF,gBAAAC,MAAC,SAAI,WAAU,4BACb;AAAA,sBAAAD,MAAC,SAAI,WAAU,uIAAsI,eAAC;AAAA,MACtJ,gBAAAA,MAAC,OAAE,WAAU,6CAA4C,iDAAmC;AAAA,OAC9F;AAAA,IACA,gBAAAC,MAAC,SAAI,WAAU,4BACb;AAAA,sBAAAD,MAAC,SAAI,WAAU,uIAAsI,eAAC;AAAA,MACtJ,gBAAAA,MAAC,OAAE,WAAU,6CAA4C,yCAA2B;AAAA,OACtF;AAAA,IACA,gBAAAC,MAAC,SAAI,WAAU,4BACb;AAAA,sBAAAD,MAAC,SAAI,WAAU,uIAAsI,eAAC;AAAA,MACtJ,gBAAAA,MAAC,OAAE,WAAU,6CAA4C,oCAAsB;AAAA,OACjF;AAAA,KACF;AAEJ;AAEA,SAAS,eAAe;AAAA,EACtB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAMG;AACD,SACE,gBAAAC;AAAA,IAAC;AAAA;AAAA,MACC,MAAK;AAAA,MACL,UAAU;AAAA,MACV,SAAS;AAAA,MACT,WAAW,OAAK;AAAE,YAAI,EAAE,QAAQ,WAAW,EAAE,QAAQ,IAAK,UAAS;AAAA,MAAE;AAAA,MACrE,WAAW,qFACT,aACI,6CACA,uBACN;AAAA,MAEA;AAAA,wBAAAD;AAAA,UAAC;AAAA;AAAA,YACC,SAAS,OAAK;AACZ,gBAAE,gBAAgB;AAClB,uBAAS;AAAA,YACX;AAAA,YACA,WAAU;AAAA,YAEV,0BAAAA,MAAC,UAAO,WAAU,WAAU;AAAA;AAAA,QAC9B;AAAA,QACA,gBAAAC,MAAC,SAAI,WAAU,4BACb;AAAA,0BAAAD;AAAA,YAAC;AAAA;AAAA,cACC,WAAW,wGACT,WAAW,WAAW,SAClB,4BACA,iCACN;AAAA,cAEC;AAAA;AAAA,UACH;AAAA,UACA,gBAAAC,MAAC,SAAI,WAAU,gBACb;AAAA,4BAAAD,MAAC,OAAE,WAAU,gDAAgD,qBAAW,MAAK;AAAA,YAC5E,WAAW,OAAO,kBACjB,gBAAAA,MAAC,OAAE,WAAU,8CACV,qBAAW,OAAO,gBACrB;AAAA,YAED,WAAW,cACV,gBAAAA,MAAC,OAAE,WAAU,iDACV,qBAAW,YACd;AAAA,aAEJ;AAAA,WACF;AAAA;AAAA;AAAA,EACF;AAEJ;;;AC/KA,SAAS,eAAAE,cAAa,aAAAC,YAAW,WAAAC,UAAS,UAAAC,SAAQ,YAAAC,iBAAgB;;;ACElE,IAAM,WAAW;AAEjB,eAAe,UAAiC;AAC9C,MAAI;AACF,UAAM,MAAM,MAAM,MAAM,QAAQ;AAChC,QAAI,CAAC,IAAI,GAAI,QAAO,CAAC;AACrB,UAAM,OAAwB,MAAM,IAAI,KAAK;AAC7C,WAAO,KAAK,eAAe,CAAC;AAAA,EAC9B,QAAQ;AACN,WAAO,CAAC;AAAA,EACV;AACF;AAEA,eAAe,QAAQ,aAA0C;AAC/D,QAAM,OAAwB,EAAE,SAAS,GAAG,YAAY;AACxD,QAAM,MAAM,UAAU;AAAA,IACpB,QAAQ;AAAA,IACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,IAC9C,MAAM,KAAK,UAAU,IAAI;AAAA,EAC3B,CAAC;AACH;AAGO,SAAS,oBAA8C;AAC5D,MAAI,QAAsB,CAAC;AAE3B,SAAO;AAAA,IACL,MAAM,OAAO;AACX,cAAQ,MAAM,QAAQ;AACtB,aAAO;AAAA,IACT;AAAA,IACA,MAAM,IAAI,YAAY;AACpB,cAAQ,CAAC,GAAG,OAAO,UAAU;AAC7B,YAAM,QAAQ,KAAK;AAAA,IACrB;AAAA,IACA,MAAM,OAAO,IAAI;AACf,cAAQ,MAAM,OAAO,OAAK,EAAE,OAAO,EAAE;AACrC,YAAM,QAAQ,KAAK;AAAA,IACrB;AAAA,EACF;AACF;;;ADtCO,SAAS,eAAe,SAAoC;AACjE,QAAM,aAAaC,QAAO,WAAW,kBAAkB,CAAC;AACxD,QAAM,CAAC,aAAa,cAAc,IAAIC,UAAuB,CAAC,CAAC;AAG/D,EAAAC,WAAU,MAAM;AACd,eAAW,QAAQ,KAAK,EAAE,KAAK,cAAc;AAC7C,WAAO,WAAW,QAAQ,YAAY,cAAc;AAAA,EACtD,GAAG,CAAC,CAAC;AAEL,QAAM,gBAAgBC;AAAA,IACpB,CAAC,YAAoB,YAAoB,QAA0B,SAAiB;AAClF,YAAM,aAAyB;AAAA,QAC7B,IAAI,OAAO,WAAW;AAAA,QACtB;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,QAClC,QAAQ;AAAA,MACV;AACA,qBAAe,UAAQ,CAAC,GAAG,MAAM,UAAU,CAAC;AAC5C,iBAAW,QAAQ,IAAI,UAAU;AAAA,IACnC;AAAA,IACA,CAAC;AAAA,EACH;AAEA,QAAM,mBAAmBA,aAAY,CAAC,OAAe;AACnD,mBAAe,UAAQ,KAAK,OAAO,OAAK,EAAE,OAAO,EAAE,CAAC;AACpD,eAAW,QAAQ,OAAO,EAAE;AAAA,EAC9B,GAAG,CAAC,CAAC;AAEL,QAAM,sBAAsBA;AAAA,IAC1B,CAAC,eAAuB,YAAY,OAAO,OAAK,EAAE,eAAe,UAAU;AAAA,IAC3E,CAAC,WAAW;AAAA,EACd;AAEA,QAAM,YAAYC,SAAQ,MAAM,YAAY,OAAO,OAAK,EAAE,WAAW,MAAM,EAAE,QAAQ,CAAC,WAAW,CAAC;AAGlG,QAAM,oBAAoBD,aAAY,CAAC,YAA0B;AAC/D,mBAAe,OAAO;AAAA,EACxB,GAAG,CAAC,CAAC;AAEL,SAAO,EAAE,aAAa,eAAe,kBAAkB,qBAAqB,WAAW,kBAAkB;AAC3G;;;AE/CA,SAAS,YAAY;AACrB,SAAS,eAAe;AAEjB,SAAS,MAAM,QAAsB;AAC1C,SAAO,QAAQ,KAAK,MAAM,CAAC;AAC7B;;;AR0DU,gBAAAE,OA4MF,QAAAC,aA5ME;AA3BV,SAAS,gBAAgB,EAAE,QAAQ,WAAW,GAAkD;AAC9F,QAAM,CAAC,OAAO,QAAQ,IAAIC,UAAS,KAAK;AACxC,QAAM,eAAe,KAAK,IAAI,GAAG,KAAK,IAAI,YAAY,OAAO,SAAS,CAAC,CAAC;AACxE,QAAM,cAAc,OAAO,YAAY;AACvC,QAAM,iBAAiB,YAAY;AAEnC,EAAAC,WAAU,MAAM;AACd,aAAS,IAAI;AAAA,EACf,GAAG,CAAC,CAAC;AAEL,SACE,gBAAAH;AAAA,IAAC;AAAA;AAAA,MACC,qBAAmB,QAAQ,SAAS;AAAA,MACpC,OAAO;AAAA,QACL,OAAO,iBAAiB;AAAA,QACxB,QAAQ,iBAAiB;AAAA,QACzB,UAAU;AAAA,QACV,UAAU;AAAA,QACV,YAAY;AAAA,MACd;AAAA,MAEA,0BAAAA;AAAA,QAAC;AAAA;AAAA,UACC,aAAa,YAAY;AAAA,UACzB,YAAY,YAAY;AAAA,UACxB,mBAAmB;AAAA,UAEnB,0BAAAA,MAAC,sBAAmB,YAAY,cAAc,YAAY,YAAY,OACpE,0BAAAA,MAAC,kBAAe,aAAa,eAAe,GAAG,aAAa,OAAO,QAAQ,GAC7E;AAAA;AAAA,MACF;AAAA;AAAA,EACF;AAEJ;AAMO,SAAS,UAAU,EAAE,QAAQ,YAAY,uBAAuB,aAAa,iBAAiB,mBAAmB,GAAmB;AAEzI,QAAM,CAAC,YAAY,IAAIE,UAAS,MAAM;AACpC,QAAI,OAAO,WAAW,YAAa,QAAO;AAC1C,UAAM,SAAS,IAAI,gBAAgB,OAAO,SAAS,MAAM;AACzD,QAAI,OAAO,IAAI,QAAQ,MAAM,OAAQ,QAAO;AAC5C,WAAO,EAAE,YAAY,SAAS,OAAO,IAAI,OAAO,KAAK,KAAK,EAAE,EAAE;AAAA,EAChE,CAAC;AAED,MAAI,cAAc;AAChB,WAAO,gBAAAF,MAAC,mBAAgB,QAAgB,YAAY,aAAa,YAAY;AAAA,EAC/E;AAGA,QAAM,WAAW,eAAe;AAChC,QAAM,sBAAsB,gBAAgB;AAC5C,QAAM,uBAAuB,sBAAsB,cAAc,SAAS;AAC1E,QAAM,eAAe,sBAAsB,kBAAkB,SAAS;AACtE,QAAM,kBAAkB,sBAAsB,qBAAqB,SAAS;AAE5E,QAAM,YAAYI,SAAQ,MAAM,qBAAqB,OAAO,OAAK,EAAE,WAAW,MAAM,EAAE,QAAQ,CAAC,oBAAoB,CAAC;AACpH,QAAM,sBAAsBC;AAAA,IAC1B,CAAC,eAAuB,qBAAqB,OAAO,OAAK,EAAE,eAAe,UAAU;AAAA,IACpF,CAAC,oBAAoB;AAAA,EACvB;AAEA,QAAM,CAAC,UAAU,WAAW,IAAIH,UAAmB,OAAO;AAC1D,QAAM,CAAC,oBAAoB,qBAAqB,IAAIA,UAAS,KAAK;AAClE,QAAM,CAAC,kBAAkB,mBAAmB,IAAIA,UAAS,KAAK;AAC9D,QAAM,CAAC,qBAAqB,sBAAsB,IAAIA,UAAS,KAAK;AACpE,QAAM,CAAC,sBAAsB,uBAAuB,IAAIA,UAAwB,IAAI;AACpF,QAAM,CAAC,OAAO,QAAQ,IAAIA,UAAS,CAAC;AACpC,QAAM,eAAeI,QAAuB,IAAI;AAChD,QAAM,oBAAoBA,QAAuB,IAAI;AAErD,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI,mBAAmB;AAAA,IACrB;AAAA,EACF,CAAC;AAED,QAAM,yBAAyBD,aAAY,YAAY;AACrD,QAAI,CAAC,SAAS,mBAAmB;AAC/B,YAAM,SAAS,gBAAgB,kBAAkB;AAAA,IACnD,OAAO;AACL,YAAM,SAAS,eAAe;AAAA,IAChC;AAAA,EACF,GAAG,CAAC,CAAC;AAGL,EAAAF,WAAU,MAAM;AACd,UAAM,yBAAyB,MAAM;AACnC,4BAAsB,CAAC,CAAC,SAAS,iBAAiB;AAAA,IACpD;AACA,aAAS,iBAAiB,oBAAoB,sBAAsB;AACpE,WAAO,MAAM,SAAS,oBAAoB,oBAAoB,sBAAsB;AAAA,EACtF,GAAG,CAAC,CAAC;AAGL,EAAAA,WAAU,MAAM;AACd,UAAM,iBAAiB,MAAM;AAC3B,UAAI,CAAC,oBAAoB;AACvB,iBAAS,CAAC;AACV;AAAA,MACF;AACA,YAAM,gBAAgB,OAAO;AAC7B,YAAM,iBAAiB,OAAO;AAC9B,YAAM,SAAS,gBAAgB,iBAAiB;AAChD,YAAM,SAAS,iBAAiB,iBAAiB;AACjD,eAAS,KAAK,IAAI,QAAQ,MAAM,CAAC;AAAA,IACnC;AAEA,mBAAe;AACf,WAAO,iBAAiB,UAAU,cAAc;AAChD,WAAO,MAAM,OAAO,oBAAoB,UAAU,cAAc;AAAA,EAClE,GAAG,CAAC,kBAAkB,CAAC;AAEvB,QAAM,kBAAkB,MAAM;AAC5B,UAAM,eAAe;AACrB,gBAAY,MAAM;AAElB,eAAW,MAAM;AACf,YAAM,mBAAmB,MAAM;AAC7B,oBAAY,YAAY;AACxB,eAAO,oBAAoB,cAAc,gBAAgB;AAAA,MAC3D;AACA,aAAO,iBAAiB,cAAc,gBAAgB;AACtD,aAAO,MAAM;AAAA,IACf,GAAG,GAAG;AAAA,EACR;AAGA,EAAAA,WAAU,MAAM;AACd,UAAM,gBAAgB,CAAC,MAAqB;AAC1C,UAAI,EAAE,QAAQ,OAAO,EAAE,QAAQ,KAAK;AAClC,+BAAuB;AACvB;AAAA,MACF;AAGA,UAAI,EAAE,QAAQ,OAAO,EAAE,QAAQ,KAAK;AAClC,oBAAY,UAAS,SAAS,SAAS,UAAU,MAAO;AACxD;AAAA,MACF;AAEA,UAAI,aAAa,WAAY,oBAAoB,CAAC,mBAAqB;AAEvE,UAAI,EAAE,QAAQ,gBAAgB,EAAE,QAAQ,KAAK;AAC3C,UAAE,eAAe;AACjB,gBAAQ;AAAA,MACV,WAAW,EAAE,QAAQ,aAAa;AAChC,UAAE,eAAe;AACjB,eAAO;AAAA,MACT;AAAA,IACF;AAEA,WAAO,iBAAiB,WAAW,aAAa;AAChD,WAAO,MAAM,OAAO,oBAAoB,WAAW,aAAa;AAAA,EAClE,GAAG,CAAC,SAAS,QAAQ,UAAU,wBAAwB,kBAAkB,kBAAkB,CAAC;AAE5F,SACE,gBAAAF,MAAC,SAAI,WAAU,sDACb;AAAA,oBAAAD,MAAC,WAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAoBN;AAAA,IAGF,gBAAAC;AAAA,MAAC;AAAA;AAAA,QACC,WAAW;AAAA,UACT;AAAA,UACA,sBAAsB;AAAA,UACtB,oBAAoB,sBAAsB,oBAAoB;AAAA,QAChE;AAAA,QAEA;AAAA,0BAAAD;AAAA,YAAC;AAAA;AAAA,cACC,SAAS,MAAM,YAAY,OAAO;AAAA,cAClC,WAAW;AAAA,gBACT;AAAA,gBACA,aAAa,WAAW;AAAA,cAC1B;AAAA,cACA,OAAM;AAAA,cAEN,0BAAAA,MAAC,WAAQ,WAAU,WAAU;AAAA;AAAA,UAC/B;AAAA,UACA,gBAAAA;AAAA,YAAC;AAAA;AAAA,cACC,SAAS,MAAM,YAAY,MAAM;AAAA,cACjC,WAAW;AAAA,gBACT;AAAA,gBACA,aAAa,UAAU;AAAA,cACzB;AAAA,cACA,OAAM;AAAA,cAEN,0BAAAA,MAAC,QAAK,WAAU,WAAU;AAAA;AAAA,UAC5B;AAAA,UACA,gBAAAA;AAAA,YAAC;AAAA;AAAA,cACC,SAAS,MAAM,YAAY,MAAM;AAAA,cACjC,WAAW;AAAA,gBACT;AAAA,gBACA,aAAa,UAAU;AAAA,cACzB;AAAA,cACA,OAAM;AAAA,cAEN,0BAAAA,MAAC,WAAQ,WAAU,WAAU;AAAA;AAAA,UAC/B;AAAA,UAEA,gBAAAA,MAAC,SAAI,WAAU,4BAA2B;AAAA,UAE1C,gBAAAC;AAAA,YAAC;AAAA;AAAA,cACC,SAAS,MAAM;AACb,oCAAoB,UAAQ;AAC1B,wBAAM,OAAO,CAAC;AACd,yCAAuB,IAAI;AAC3B,sBAAI,CAAC,KAAM,yBAAwB,IAAI;AACvC,yBAAO;AAAA,gBACT,CAAC;AAAA,cACH;AAAA,cACA,WAAW;AAAA,gBACT;AAAA,gBACA,oBAAoB;AAAA,cACtB;AAAA,cACA,OAAM;AAAA,cAEN;AAAA,gCAAAD,MAACO,gBAAA,EAAc,WAAU,WAAU;AAAA,gBAClC,YAAY,KACX,gBAAAP,MAAC,UAAK,WAAU,gIACb,qBACH;AAAA;AAAA;AAAA,UAEJ;AAAA,UAEA,gBAAAA,MAAC,SAAI,WAAU,4BAA2B;AAAA,UAE1C,gBAAAA;AAAA,YAAC;AAAA;AAAA,cACC,SAAS;AAAA,cACT,WAAU;AAAA,cACV,OAAM;AAAA,cAEN,0BAAAA,MAAC,YAAS,WAAU,WAAU;AAAA;AAAA,UAChC;AAAA,UACA,gBAAAA;AAAA,YAAC;AAAA;AAAA,cACC,SAAS;AAAA,cACT,WAAU;AAAA,cACV,OAAM;AAAA,cAEN,0BAAAA,MAAC,YAAS,WAAU,WAAU;AAAA;AAAA,UAChC;AAAA;AAAA;AAAA,IACF;AAAA,IAGC,aAAa,WACZ,gBAAAC;AAAA,MAAC;AAAA;AAAA,QACC,WAAW;AAAA,UACT;AAAA,UACA,qBAAqB,aAAa;AAAA,QACpC;AAAA,QAEA;AAAA,0BAAAA;AAAA,YAAC;AAAA;AAAA,cACC,KAAK;AAAA,cACL,MAAK;AAAA,cACL,UAAU,qBAAqB,IAAI;AAAA,cACnC,WAAW;AAAA,gBACT;AAAA,gBACA,qBAAqB,iBAAiB;AAAA,cACxC;AAAA,cACA,SAAS,qBAAqB,UAAU;AAAA,cACxC,WACE,qBACI,OAAK;AACH,oBAAI,EAAE,QAAQ,WAAW,EAAE,QAAQ,IAAK,SAAQ;AAAA,cAClD,IACA;AAAA,cAGN;AAAA,gCAAAD,MAAC,eAAY,IAAG,cACb,+BACC,gBAAAA;AAAA,kBAAC;AAAA;AAAA,oBACC,WAAU;AAAA,oBACV,OAAO;AAAA,sBACL,OAAO,iBAAiB;AAAA,sBACxB,QAAQ,iBAAiB;AAAA,sBACzB,WAAW,SAAS,KAAK;AAAA,sBACzB,iBAAiB;AAAA,oBACnB;AAAA,oBAEA,0BAAAA;AAAA,sBAAC;AAAA;AAAA,wBACC;AAAA,wBACA;AAAA,wBACA;AAAA,wBACA;AAAA,wBACA;AAAA,wBACA;AAAA,wBACA;AAAA,wBACA;AAAA,wBACA;AAAA;AAAA,oBACF;AAAA;AAAA,gBACF,IAEA,gBAAAC,MAAC,SAAI,KAAK,mBAAmB,WAAU,mHACrC;AAAA,kCAAAD;AAAA,oBAAC;AAAA;AAAA,sBACC;AAAA,sBACA;AAAA,sBACA;AAAA,sBACA;AAAA,sBACA;AAAA,sBACA;AAAA,sBACA;AAAA,sBACA;AAAA,sBACA;AAAA;AAAA,kBACF;AAAA,kBACC,oBACC,gBAAAA;AAAA,oBAAC;AAAA;AAAA,sBACC;AAAA,sBACA;AAAA,sBACA;AAAA,sBACA,YAAY;AAAA,sBACZ,YAAY;AAAA,sBACZ,aAAa,MAAM,uBAAuB,IAAI;AAAA,sBAC9C,kBAAkB,oBAAoB,YAAY;AAAA,sBAClD,eAAe,iBAAiB,MAAM;AAAA,sBAAC;AAAA;AAAA,kBAEzC;AAAA,mBAEJ,GAEJ;AAAA,gBAGC,CAAC,sBACA,gBAAAC,MAAC,SAAI,WAAU,gCACb;AAAA,kCAAAD;AAAA,oBAAC;AAAA;AAAA,sBACC,SAAS;AAAA,sBACT,WAAU;AAAA,sBAEV,0BAAAA,MAAC,eAAY,WAAU,WAAU;AAAA;AAAA,kBACnC;AAAA,kBACA,gBAAAC,MAAC,SAAI,WAAU,2CACb;AAAA,oCAAAA,MAAC,UAAK,WAAU,sCACb;AAAA,qCAAe;AAAA,sBAAE;AAAA,sBAAI,OAAO;AAAA,uBAC/B;AAAA,oBACC,OAAO,YAAY,GAAG,SACrB,gBAAAD,MAAC,UAAK,WAAU,mCACb,iBAAO,YAAY,EAAE,OACxB;AAAA,qBAEJ;AAAA,kBACA,gBAAAA;AAAA,oBAAC;AAAA;AAAA,sBACC,SAAS;AAAA,sBACT,WAAU;AAAA,sBAEV,0BAAAA,MAAC,gBAAa,WAAU,WAAU;AAAA;AAAA,kBACpC;AAAA,mBACF;AAAA;AAAA;AAAA,UAEJ;AAAA,UAGC,oBAAoB,uBAAuB,CAAC,sBAC3C,gBAAAA;AAAA,YAAC;AAAA;AAAA,cACC,aAAa,oBAAoB,YAAY;AAAA,cAC7C,YAAY;AAAA,cACZ,UAAU;AAAA,cACV,UAAU,oBAAoB,MAAM;AAAA,cAAC;AAAA,cACrC,SAAS,MAAM;AACb,uCAAuB,KAAK;AAC5B,wCAAwB,IAAI;AAAA,cAC9B;AAAA;AAAA,UACF;AAAA;AAAA;AAAA,IAEJ;AAAA,IAID,aAAa,UACZ,gBAAAA,MAAC,SAAI,WAAU,4CACb,0BAAAA,MAAC,SAAI,WAAU,wDACZ,iBAAO,IAAI,CAAC,aAAa,UAAU;AAClC,YAAM,iBAAiB,YAAY;AACnC,YAAM,cAAc,QAAQ,IAAI,OAAO,QAAQ,CAAC,GAAG,UAAU;AAC7D,YAAM,oBAAoB,YAAY,WAAW,YAAY,YAAY;AAEzE,aACE,gBAAAC,MAAC,SAAgB,WAAW,oBAAoB,kBAAkB,QAC/D;AAAA,6BACC,gBAAAD,MAAC,QAAG,WAAU,sFACX,sBAAY,SACf;AAAA,QAEF,gBAAAC;AAAA,UAAC;AAAA;AAAA,YACC,SAAS,MAAM;AACb,wBAAU,KAAK;AACf,0BAAY,OAAO;AAAA,YACrB;AAAA,YACA,WAAU;AAAA,YAEV;AAAA,8BAAAD;AAAA,gBAAC;AAAA;AAAA,kBACC,WAAU;AAAA,kBACV,OAAO,EAAE,OAAO,QAAQ,QAAQ,OAAO;AAAA,kBAEvC,0BAAAA;AAAA,oBAAC;AAAA;AAAA,sBACC,aAAa,YAAY;AAAA,sBACzB,YAAY,YAAY;AAAA,sBACxB,mBAAmB;AAAA,sBAEnB,0BAAAA,MAAC,sBAAmB,YAAY,OAAO,YAAY,YAAY,OAC7D,0BAAAA,MAAC,kBAAe,aAAa,QAAQ,GAAG,aAAa,OAAO,QAAQ,GACtE;AAAA;AAAA,kBACF;AAAA;AAAA,cACF;AAAA,cACA,gBAAAA,MAAC,SAAI,WAAU,yEAAwE;AAAA,cACvF,gBAAAA,MAAC,SAAI,WAAU,yFACZ,sBAAY,QAAQ,GAAG,QAAQ,CAAC,KAAK,YAAY,KAAK,KAAK,QAAQ,GACtE;AAAA;AAAA;AAAA,QACF;AAAA,WA/BQ,KAgCV;AAAA,IAEJ,CAAC,GACH,GACF;AAAA,IAIF,gBAAAA;AAAA,MAAC;AAAA;AAAA,QACC,WAAW;AAAA,UACT;AAAA,UACA;AAAA,UACA,aAAa,SAAS,UAAU;AAAA,QAClC;AAAA,QAEA,0BAAAA,MAAC,SAAI,WAAU,sCACZ,iBAAO,IAAI,CAAC,aAAa,UAAU;AAClC,gBAAM,iBAAiB,YAAY;AACnC,iBACE,gBAAAA;AAAA,YAAC;AAAA;AAAA,cAEC,WAAU;AAAA,cAEV,0BAAAA,MAAC,SAAI,WAAU,0FACb,0BAAAA;AAAA,gBAAC;AAAA;AAAA,kBACC,aAAa,YAAY;AAAA,kBACzB,YAAY,YAAY;AAAA,kBACxB,mBAAmB;AAAA,kBAEnB,0BAAAA,MAAC,sBAAmB,YAAY,OAAO,YAAY,YAAY,OAC7D,0BAAAA,MAAC,kBAAe,aAAa,QAAQ,GAAG,aAAa,OAAO,QAAQ,GACtE;AAAA;AAAA,cACF,GACF;AAAA;AAAA,YAbK;AAAA,UAcP;AAAA,QAEJ,CAAC,GACH;AAAA;AAAA,IACF;AAAA,KACF;AAEJ;","names":["jsx","motion","jsx","motion","createContext","useContext","useMemo","jsx","motion","jsx","jsx","motion","useCallback","useEffect","useState","jsx","useState","useEffect","useCallback","MessageCircle","useCallback","useEffect","useMemo","useRef","useState","useCallback","useEffect","useRef","useState","useEffect","useState","jsx","jsxs","jsx","jsxs","jsx","jsxs","useState","useRef","useCallback","useEffect","X","Fragment","jsx","jsxs","useCallback","useEffect","useMemo","useRef","useState","useRef","useState","useEffect","useCallback","useMemo","jsx","jsxs","useState","useEffect","useMemo","useCallback","useRef","MessageCircle"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "promptslide",
3
- "version": "0.3.13",
3
+ "version": "0.3.14",
4
4
  "description": "CLI and slide engine for PromptSlide presentations",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -39,11 +39,8 @@ export function AnnotationPanel({ annotations, selectedId, onSelect, onDelete, o
39
39
 
40
40
  <div className="flex-1 overflow-y-auto p-2">
41
41
  {annotations.length === 0 && (
42
- <div className="flex flex-col items-center gap-2 px-4 py-8 text-center">
43
- <div className="flex h-10 w-10 items-center justify-center rounded-xl bg-white/[0.04]">
44
- <MessageCircle className="h-5 w-5 text-neutral-600" />
45
- </div>
46
- <p className="text-sm text-neutral-500">Click on slide elements to add annotations</p>
42
+ <div className="flex flex-col gap-4 px-3 py-6">
43
+ <WorkflowHint />
47
44
  </div>
48
45
  )}
49
46
 
@@ -83,6 +80,35 @@ export function AnnotationPanel({ annotations, selectedId, onSelect, onDelete, o
83
80
  </div>
84
81
  )}
85
82
  </div>
83
+
84
+ {annotations.length > 0 && (
85
+ <>
86
+ <div className="h-px bg-gradient-to-r from-transparent via-white/[0.06] to-transparent" />
87
+ <div className="px-3 py-3">
88
+ <WorkflowHint />
89
+ </div>
90
+ </>
91
+ )}
92
+ </div>
93
+ )
94
+ }
95
+
96
+ function WorkflowHint() {
97
+ return (
98
+ <div className="flex flex-col gap-2">
99
+ <p className="text-[11px] font-medium tracking-wider text-neutral-500 uppercase">Workflow</p>
100
+ <div className="flex items-start gap-2.5">
101
+ <div className="mt-0.5 flex h-4 w-4 flex-shrink-0 items-center justify-center rounded-full bg-[#FF6B35]/15 text-[10px] font-semibold text-[#FF6B35]">1</div>
102
+ <p className="text-[12px] leading-snug text-neutral-400">Annotate everything you want to fix</p>
103
+ </div>
104
+ <div className="flex items-start gap-2.5">
105
+ <div className="mt-0.5 flex h-4 w-4 flex-shrink-0 items-center justify-center rounded-full bg-[#FF6B35]/15 text-[10px] font-semibold text-[#FF6B35]">2</div>
106
+ <p className="text-[12px] leading-snug text-neutral-400">Switch to your coding agent</p>
107
+ </div>
108
+ <div className="flex items-start gap-2.5">
109
+ <div className="mt-0.5 flex h-4 w-4 flex-shrink-0 items-center justify-center rounded-full bg-[#FF6B35]/15 text-[10px] font-semibold text-[#FF6B35]">3</div>
110
+ <p className="text-[12px] leading-snug text-neutral-400">"Fix open annotations"</p>
111
+ </div>
86
112
  </div>
87
113
  )
88
114
  }
@@ -187,7 +187,7 @@ export function SlideDeck({ slides, transition, directionalTransition, annotatio
187
187
  return
188
188
  }
189
189
 
190
- if (viewMode !== "slide" || isAnnotationMode) return
190
+ if (viewMode !== "slide" || (isAnnotationMode && !isPresentationMode)) return
191
191
 
192
192
  if (e.key === "ArrowRight" || e.key === " ") {
193
193
  e.preventDefault()
@@ -200,7 +200,7 @@ export function SlideDeck({ slides, transition, directionalTransition, annotatio
200
200
 
201
201
  window.addEventListener("keydown", handleKeyDown)
202
202
  return () => window.removeEventListener("keydown", handleKeyDown)
203
- }, [advance, goBack, viewMode, togglePresentationMode, isAnnotationMode])
203
+ }, [advance, goBack, viewMode, togglePresentationMode, isAnnotationMode, isPresentationMode])
204
204
 
205
205
  return (
206
206
  <div className="min-h-screen w-full bg-neutral-950 text-foreground">
@@ -8,7 +8,7 @@ Slide deck framework: Vite + React 19 + Tailwind v4 + Framer Motion. Each slide
8
8
 
9
9
  Do not jump straight to writing slides. First confirm the visual direction with the user — theme colors, fonts, and overall style. Then, for each slide, think about what design approach fits the content before coding. Not everything needs cards or grids — let the content shape the layout.
10
10
 
11
- If the PromptSlide skill is installed, follow its workflow — it includes design planning steps that should happen before writing any slides.
11
+ If the `promptslide` skill is installed, follow its workflow and **always consult the skill before writing slide code** — it documents framework-specific behavior and constraints that aren't obvious from the component APIs alone.
12
12
 
13
13
  ---
14
14
 
@@ -87,6 +87,6 @@ Layouts in `src/layouts/` and theme colors in `src/globals.css` are yours to cus
87
87
  - **Slide dimensions**: 1280×720 (16:9). Content scales automatically in presentation mode.
88
88
  - **Semantic colors**: Use `text-foreground`, `text-muted-foreground`, `text-primary`, `bg-background`, `bg-card`, `border-border`.
89
89
  - **Icons**: Import from `lucide-react` (e.g., `import { ArrowRight } from "lucide-react"`).
90
- - **Animations**: Use `<Animated step={n}>` for click-to-reveal. The `steps` value in `deck-config.ts` must equal the highest step number used. Available: `fade`, `slide-up`, `slide-down`, `slide-left`, `slide-right`, `scale`.
90
+ - **Animations**: Use `<Animated step={n}>` for click-to-reveal. The `steps` value in `deck-config.ts` must equal the highest step number used. Available: `fade`, `slide-up`, `slide-down`, `slide-left`, `slide-right`, `scale`. **Important:** `<Animated>` renders a wrapper div — when inside a grid/flex container, pass layout classes (`h-full`, `col-span-*`, etc.) via `className` on the `<Animated>`, not only on the inner child.
91
91
  - **PDF compatibility**: No `blur()` or `backdrop-filter` (dropped by Chromium). No gradients (use solid colors with opacity). No `box-shadow` (doesn't export correctly) — use borders or background tints instead.
92
92
  - **Brand color**: Edit `--primary` in `src/globals.css`. Configure logo and fonts in `src/theme.ts`.