@navieo/react 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/NavieoProvider.tsx","../src/ChatWidget.tsx","../src/useNavieo.ts","../src/TourRenderer.tsx","../src/routeUtils.ts","../src/constants.ts","../src/logger.ts"],"sourcesContent":["\"use client\";\n\nimport React, { Component, createContext, useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport type {\n NavieoContextValue,\n TourState,\n TourStep,\n ChatMessage,\n} from \"./types\";\nimport { ChatWidget } from \"./ChatWidget\";\nimport { useTourRenderer } from \"./TourRenderer\";\nimport { isDynamicRoute, routeMatches } from \"./routeUtils\";\nimport { CHAT_MESSAGES } from \"./constants\";\nimport { logger } from \"./logger\";\n\n/**\n * Error boundary that catches render errors in Navieo components\n * and prevents them from crashing the host application.\n */\nclass NavieoErrorBoundary extends Component<\n { children: React.ReactNode },\n { hasError: boolean }\n> {\n constructor(props: { children: React.ReactNode }) {\n super(props);\n this.state = { hasError: false };\n }\n\n static getDerivedStateFromError(): { hasError: boolean } {\n return { hasError: true };\n }\n\n componentDidCatch(error: Error, info: React.ErrorInfo) {\n logger.error(\"Navieo caught a render error:\", error, info.componentStack);\n }\n\n render() {\n if (this.state.hasError) {\n // Silently degrade — don't break the host app\n return this.props.children;\n }\n return this.props.children;\n }\n}\n\nexport const NavieoContext = createContext<NavieoContextValue | null>(null);\n\nconst CHAT_STORAGE_KEY = \"navieo_chat_history\";\nconst TOUR_STORAGE_KEY = \"navieo_active_tour\";\nconst MAX_STORED_MESSAGES = 50;\nconst CONTEXT_WINDOW = 6; // last N messages sent with each request\nconst NAV_TIMEOUT_MS = 30_000; // max time to wait for navigation before resetting\nconst MAX_TOUR_STEPS = 50; // safety limit on steps from LLM\nconst FETCH_TIMEOUT_MS = 30_000; // abort API calls after this many ms\nconst MIN_REQUEST_INTERVAL_MS = 2_000; // minimum time between API requests\n\n/** Strip control characters (U+0000–U+001F except \\t \\n \\r, plus U+007F) from user input. */\nfunction sanitizeInput(str: string): string {\n // eslint-disable-next-line no-control-regex\n return str.replace(/[\\x00-\\x08\\x0B\\x0C\\x0E-\\x1F\\x7F]/g, \"\");\n}\n\n/** Validate that an API endpoint is a safe relative or same-origin URL. */\nfunction isValidEndpoint(endpoint: string): boolean {\n // Relative paths are always ok\n if (endpoint.startsWith(\"/\")) return true;\n try {\n const url = new URL(endpoint);\n // Allow same origin, or http/https protocols only\n if (url.protocol !== \"http:\" && url.protocol !== \"https:\") return false;\n if (typeof window !== \"undefined\" && url.origin === window.location.origin) return true;\n // Allow explicit cross-origin (user explicitly passed a full URL)\n return true;\n } catch {\n return false;\n }\n}\n\n/** Persist active tour state to sessionStorage so it survives navigations. */\ninterface PersistedTourState {\n steps: TourStep[];\n pendingRoute: string | null;\n}\n\nfunction saveTourState(state: PersistedTourState | null) {\n if (typeof window === \"undefined\") return;\n try {\n if (state) {\n sessionStorage.setItem(TOUR_STORAGE_KEY, JSON.stringify(state));\n } else {\n sessionStorage.removeItem(TOUR_STORAGE_KEY);\n }\n } catch { /* ignore */ }\n}\n\nfunction loadTourState(): PersistedTourState | null {\n if (typeof window === \"undefined\") return null;\n try {\n const stored = sessionStorage.getItem(TOUR_STORAGE_KEY);\n if (!stored) return null;\n const parsed = JSON.parse(stored);\n // Validate structure: must have steps array with route + tooltipText on each\n if (\n !parsed ||\n !Array.isArray(parsed.steps) ||\n parsed.steps.length === 0 ||\n !parsed.steps.every(\n (s: unknown) =>\n s &&\n typeof s === \"object\" &&\n typeof (s as Record<string, unknown>).route === \"string\" &&\n typeof (s as Record<string, unknown>).tooltipText === \"string\"\n )\n ) {\n logger.warn(\"loadTourState: invalid persisted data — clearing\");\n sessionStorage.removeItem(TOUR_STORAGE_KEY);\n return null;\n }\n return parsed as PersistedTourState;\n } catch {\n // Corrupted JSON — clear it\n try { sessionStorage.removeItem(TOUR_STORAGE_KEY); } catch { /* ignore */ }\n }\n return null;\n}\n\nfunction loadChatHistory(): ChatMessage[] {\n if (typeof window === \"undefined\") return [];\n try {\n const stored = localStorage.getItem(CHAT_STORAGE_KEY);\n if (stored) {\n const parsed = JSON.parse(stored);\n if (Array.isArray(parsed)) {\n // Validate each item is a well-formed ChatMessage\n const valid = parsed.filter(\n (m: unknown): m is ChatMessage =>\n !!m &&\n typeof m === \"object\" &&\n ((m as Record<string, unknown>).role === \"user\" ||\n (m as Record<string, unknown>).role === \"assistant\") &&\n typeof (m as Record<string, unknown>).content === \"string\"\n );\n return valid.slice(-MAX_STORED_MESSAGES);\n }\n }\n } catch {\n try { localStorage.removeItem(CHAT_STORAGE_KEY); } catch { /* ignore */ }\n }\n return [];\n}\n\nfunction saveChatHistory(messages: ChatMessage[]) {\n if (typeof window === \"undefined\") return;\n try {\n localStorage.setItem(\n CHAT_STORAGE_KEY,\n JSON.stringify(messages.slice(-MAX_STORED_MESSAGES))\n );\n } catch { /* ignore quota errors */ }\n}\n\n/** Props for the {@link NavieoProvider} context provider. */\nexport interface NavieoProviderProps {\n children: React.ReactNode;\n /** Current pathname of the app (e.g., from usePathname, window.location.pathname, etc.) */\n currentRoute: string;\n /** Called when the tour needs to navigate to a different route */\n onNavigate: (route: string) => void;\n /** API endpoint for guide queries. Defaults to \"/api/guide\". */\n apiEndpoint?: string;\n /** Application identifier */\n appId?: string;\n /** Suggestion chips shown in empty chat state */\n suggestions?: Array<{ label: string; tag?: string }>;\n /** Whether to render the built-in ChatWidget. Default: true */\n renderChat?: boolean;\n}\n\n/**\n * Root context provider for the Navieo SDK.\n *\n * Manages tour state, chat history, API communication, and cross-page\n * navigation. Wrap your application (or a subtree) with this provider and\n * access the tour/chat API via the {@link useNavieo} hook.\n *\n * @example\n * ```tsx\n * <NavieoProvider currentRoute={pathname} onNavigate={router.push}>\n * <App />\n * </NavieoProvider>\n * ```\n */\nexport function NavieoProvider({\n children,\n currentRoute,\n onNavigate,\n apiEndpoint = \"/api/guide\",\n appId,\n suggestions,\n renderChat = true,\n}: NavieoProviderProps) {\n const apiKey =\n typeof process !== \"undefined\"\n ? process.env?.NEXT_PUBLIC_NAVIEO_PUBLISHABLE_KEY\n : undefined;\n const [isChatOpen, setIsChatOpen] = useState(false);\n const [tourState, setTourState] = useState<TourState>(\"idle\");\n const [steps, setSteps] = useState<TourStep[]>([]);\n const [currentStepIndex, setCurrentStepIndex] = useState(0);\n const [chatHistory, setChatHistory] = useState<ChatMessage[]>(loadChatHistory);\n\n // Diagnostic: detect mount/unmount + clean up dangling timers + destroy driver\n useEffect(() => {\n logger.info(\"NavieoProvider MOUNTED\");\n return () => {\n logger.warn(\"NavieoProvider UNMOUNTED — cleaning up\");\n tourRef.current.stopTour(); // Destroy Driver.js overlay if active\n if (navTimeoutRef.current) clearTimeout(navTimeoutRef.current);\n if (startTourDelayRef.current) clearTimeout(startTourDelayRef.current);\n if (errorRecoveryRef.current) clearTimeout(errorRecoveryRef.current);\n };\n }, []);\n\n // Persist chat history to localStorage whenever it changes\n useEffect(() => {\n saveChatHistory(chatHistory);\n }, [chatHistory]);\n\n // Warn user before closing tab/window during active tour\n useEffect(() => {\n if (tourState !== \"active\") return;\n const handler = (e: BeforeUnloadEvent) => {\n e.preventDefault();\n };\n window.addEventListener(\"beforeunload\", handler);\n return () => window.removeEventListener(\"beforeunload\", handler);\n }, [tourState]);\n\n // Keep ref copies so callbacks always have the latest values\n const stepsRef = useRef<TourStep[]>([]);\n stepsRef.current = steps;\n const chatHistoryRef = useRef<ChatMessage[]>(chatHistory);\n chatHistoryRef.current = chatHistory;\n\n // Cross-page navigation state\n const pendingRouteRef = useRef<string | null>(null);\n\n const resetTour = useCallback(() => {\n logger.info(\"resetTour: resetting tour state to idle\");\n setTourState(\"idle\");\n setSteps([]);\n setCurrentStepIndex(0);\n saveTourState(null);\n }, []);\n\n // Safety timeout ref\n const navTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n // Refs for miscellaneous timers so they can be cleaned on unmount\n const startTourDelayRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const errorRecoveryRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n const clearNavTimeout = useCallback(() => {\n if (navTimeoutRef.current) {\n clearTimeout(navTimeoutRef.current);\n navTimeoutRef.current = null;\n }\n }, []);\n\n const tour = useTourRenderer({\n onStepChange: (index) => {\n logger.debug(`Provider.onStepChange: index=${index}`);\n setCurrentStepIndex(index);\n },\n onComplete: () => {\n logger.info(\"Provider.onComplete: tour finished, resetting\");\n clearNavTimeout();\n pendingRouteRef.current = null;\n resetTour();\n },\n onClose: () => {\n logger.info(\"Provider.onClose: tour closed, resetting\");\n clearNavTimeout();\n pendingRouteRef.current = null;\n resetTour();\n },\n onError: (message) => {\n // Only fires on genuine Driver.js crash (driverRef already null).\n logger.error(`Provider.onError: ${message}`);\n pendingRouteRef.current = null;\n clearNavTimeout();\n resetTour();\n setChatHistory((prev) => [\n ...prev,\n {\n role: \"assistant\",\n content: CHAT_MESSAGES.tourError(message),\n },\n ]);\n setIsChatOpen(true);\n },\n onNavigationNeeded: (route) => {\n logger.info(`Provider.onNavigationNeeded: route=\"${route}\", currentRoute=\"${currentRoute}\"`);\n\n // Check if we've ALREADY arrived at the target route.\n if (routeMatches(currentRoute, route)) {\n logger.info(`Provider.onNavigationNeeded: ALREADY on target route — continuing in 500ms`);\n saveTourState(null);\n const timer = setTimeout(() => {\n logger.debug(`Provider.onNavigationNeeded: delayed continueAfterNavigation(\"${route}\")`);\n tourRef.current.continueAfterNavigation(route);\n }, 500);\n navTimeoutRef.current = timer;\n return;\n }\n\n pendingRouteRef.current = route;\n saveTourState({ steps: stepsRef.current, pendingRoute: route });\n\n // Start a safety timeout\n clearNavTimeout();\n navTimeoutRef.current = setTimeout(() => {\n if (pendingRouteRef.current) {\n logger.warn(`Provider: navigation timeout — route \"${route}\" not reached after ${NAV_TIMEOUT_MS / 1000}s, resetting`);\n pendingRouteRef.current = null;\n saveTourState(null);\n tourRef.current.stopTour();\n resetTour();\n setChatHistory((prev) => [\n ...prev,\n { role: \"assistant\", content: CHAT_MESSAGES.navigationTimeout },\n ]);\n setIsChatOpen(true);\n }\n }, NAV_TIMEOUT_MS);\n\n // Validate route is a relative path (reject protocol schemes like javascript: or //evil.com)\n if (!route.startsWith(\"/\") || route.startsWith(\"//\")) {\n logger.error(`Provider.onNavigationNeeded: rejected invalid route \"${route}\"`);\n return;\n }\n\n if (isDynamicRoute(route)) {\n logger.info(`Provider.onNavigationNeeded: dynamic route \"${route}\" — waiting for user navigation`);\n } else {\n logger.info(`Provider.onNavigationNeeded: static route — calling onNavigate(\"${route}\")`);\n onNavigate(route);\n }\n },\n });\n\n const tourRef = useRef(tour);\n tourRef.current = tour;\n\n // Restore persisted tour state on mount (e.g. after cross-page navigation).\n // StrictMode-safe: sessionStorage is only cleared inside the timer callback,\n // so if StrictMode cancels the timer the next mount can restore again.\n // pendingRouteRef is NOT set — restoreTour handles finding the right group.\n useEffect(() => {\n const persisted = loadTourState();\n if (persisted && persisted.steps.length > 0) {\n logger.info(`Provider: restoring persisted tour: ${persisted.steps.length} steps, pendingRoute=\"${persisted.pendingRoute}\"`);\n setSteps(persisted.steps);\n setTourState(\"active\");\n // Do NOT set pendingRouteRef — restoreTour will find the right group\n // Do NOT clear sessionStorage yet — survive StrictMode double-invoke\n const timer = setTimeout(() => {\n saveTourState(null); // Safe to clear now — timer survived StrictMode\n logger.info(\"Provider: calling restoreTour from persisted state\");\n tourRef.current.restoreTour(persisted.steps, currentRoute);\n }, 500);\n return () => clearTimeout(timer);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n // Watch pathname changes for cross-page tour continuation.\n useEffect(() => {\n // Unconditional diagnostic log — always fires when currentRoute changes\n logger.debug(\n `Route watcher fired: currentRoute=\"${currentRoute}\", ` +\n `tourState=\"${tourState}\", stepIndex=${currentStepIndex}, ` +\n `stepsCount=${stepsRef.current.length}, ` +\n `pendingRoute=${pendingRouteRef.current || \"null\"}`\n );\n\n // Case 1: Standard pending route match\n if (pendingRouteRef.current) {\n const matches = routeMatches(currentRoute, pendingRouteRef.current);\n logger.info(`Provider route watcher: currentRoute=\"${currentRoute}\", pending=\"${pendingRouteRef.current}\", matches=${matches}`);\n if (matches) {\n const pendingPattern = pendingRouteRef.current;\n pendingRouteRef.current = null;\n clearNavTimeout();\n saveTourState(null);\n const timer = setTimeout(() => {\n logger.info(`Provider route watcher: DOM ready, continuing tour for \"${pendingPattern}\"`);\n tourRef.current.continueAfterNavigation(pendingPattern);\n }, 500);\n return () => clearTimeout(timer);\n }\n return;\n }\n\n // Case 2: Tour active, no pending route — detect user-initiated navigation\n if (tourState === \"active\" && stepsRef.current.length > 0) {\n const currentStepRoute = stepsRef.current[currentStepIndex]?.route;\n if (currentStepRoute && !routeMatches(currentRoute, currentStepRoute)) {\n const futureStep = stepsRef.current.find(\n (s, i) => i > currentStepIndex && routeMatches(currentRoute, s.route)\n );\n if (futureStep) {\n logger.info(`Provider route watcher (Case 2): auto-detected navigation to future step route \"${futureStep.route}\"`);\n saveTourState(null);\n const timer = setTimeout(() => {\n tourRef.current.continueAfterNavigation(futureStep.route);\n }, 500);\n return () => clearTimeout(timer);\n }\n }\n }\n }, [currentRoute, clearNavTimeout, tourState, currentStepIndex]);\n\n const openChat = useCallback(() => setIsChatOpen(true), []);\n const closeChat = useCallback(() => setIsChatOpen(false), []);\n const toggleChat = useCallback(() => setIsChatOpen((v) => !v), []);\n\n const clearChatHistory = useCallback(() => {\n setChatHistory([]);\n saveChatHistory([]);\n }, []);\n\n // ─── Start Tour ───────────────────────────────────────────\n\n // AbortController ref for cancelling in-flight requests on double-submit\n const abortControllerRef = useRef<AbortController | null>(null);\n // Client-side rate limiting\n const lastRequestTimeRef = useRef(0);\n\n const startTour = useCallback(\n async (query: string) => {\n const trimmedQuery = sanitizeInput(query.slice(0, 500));\n logger.info(`Provider.startTour: query=\"${trimmedQuery}\", currentRoute=\"${currentRoute}\"`);\n\n // Client-side rate limiting\n const now = Date.now();\n if (now - lastRequestTimeRef.current < MIN_REQUEST_INTERVAL_MS) {\n logger.warn(\"Provider.startTour: request throttled (too fast)\");\n return;\n }\n lastRequestTimeRef.current = now;\n\n // Validate API endpoint before making any request\n if (!isValidEndpoint(apiEndpoint)) {\n logger.error(`Provider.startTour: invalid API endpoint \"${apiEndpoint}\"`);\n setChatHistory((prev) => [\n ...prev,\n { role: \"user\", content: trimmedQuery },\n { role: \"assistant\", content: CHAT_MESSAGES.genericError },\n ]);\n setTourState(\"error\");\n return;\n }\n\n // Cancel any in-flight request and pending timers from a previous tour\n if (abortControllerRef.current) {\n logger.info(\"Provider.startTour: aborting previous in-flight request\");\n abortControllerRef.current.abort();\n }\n if (startTourDelayRef.current) {\n clearTimeout(startTourDelayRef.current);\n startTourDelayRef.current = null;\n }\n if (errorRecoveryRef.current) {\n clearTimeout(errorRecoveryRef.current);\n errorRecoveryRef.current = null;\n }\n const controller = new AbortController();\n abortControllerRef.current = controller;\n\n // Compose abort signal: user cancellation OR fetch timeout\n const timeoutId = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);\n\n setTourState(\"loading\");\n setChatHistory((prev) => [...prev, { role: \"user\", content: trimmedQuery }]);\n\n try {\n const headers: Record<string, string> = { \"Content-Type\": \"application/json\" };\n if (apiKey) headers[\"x-api-key\"] = apiKey;\n\n const recentContext = chatHistoryRef.current\n .slice(-CONTEXT_WINDOW)\n .map(m => ({ role: m.role, content: m.content }));\n\n logger.debug(`Provider.startTour: fetching ${apiEndpoint} with ${recentContext.length} context messages`);\n\n const response = await fetch(apiEndpoint, {\n method: \"POST\",\n headers,\n body: JSON.stringify({\n query: trimmedQuery,\n currentRoute,\n appId,\n chatContext: recentContext,\n }),\n signal: controller.signal,\n });\n\n logger.debug(`Provider.startTour: API response status=${response.status}`);\n\n if (!response.ok) {\n const errorText = await response.text().catch(() => \"\");\n // Log the full error for debugging, but don't expose raw API details to the user\n logger.error(`Provider.startTour: API error ${response.status}: ${errorText.slice(0, 200)}`);\n throw new Error(\"The guide service returned an error. Please try again.\");\n }\n\n let data: unknown;\n try {\n data = await response.json();\n } catch {\n throw new Error(\"Invalid JSON response from API\");\n }\n\n const parsed = data as Record<string, unknown>;\n const steps = Array.isArray(parsed?.steps) ? parsed.steps as TourStep[] : [];\n const answer = typeof parsed?.answer === \"string\" ? parsed.answer : undefined;\n const error = typeof parsed?.error === \"string\" ? parsed.error : undefined;\n\n logger.info(`Provider.startTour: API returned ${steps.length} steps, answer=${!!answer}, error=${error || \"none\"}`);\n\n if (error) {\n logger.warn(`Provider.startTour: API returned error: ${error}`);\n setTourState(\"error\");\n // Show a generic message to the user; server error details stay in logs\n setChatHistory((prev) => [\n ...prev,\n { role: \"assistant\", content: CHAT_MESSAGES.genericError },\n ]);\n return;\n }\n\n if (steps.length === 0) {\n logger.info(\"Provider.startTour: 0 steps returned — showing answer text\");\n setTourState(\"idle\");\n setChatHistory((prev) => [\n ...prev,\n {\n role: \"assistant\",\n content:\n answer ||\n CHAT_MESSAGES.noStepsFound,\n },\n ]);\n return;\n }\n\n // Log all received steps\n logger.debugSteps(\"Provider.startTour: raw steps from API\", steps.map((s, i) => ({\n step: i + 1,\n route: s.route,\n title: s.tooltipTitle || \"(no title)\",\n text: (s.tooltipText || \"\").slice(0, 60) + \"...\",\n cssSelector: s.selector?.cssSelector || \"(none)\",\n elementId: s.elementId || \"(none)\",\n })));\n\n // Validate that each step has required fields, enforce max step limit\n const validSteps = steps\n .filter(\n (s) => s && typeof s.route === \"string\" && typeof s.tooltipText === \"string\"\n )\n .slice(0, MAX_TOUR_STEPS);\n\n if (steps.length > MAX_TOUR_STEPS) {\n logger.warn(`Provider.startTour: truncated ${steps.length} steps to ${MAX_TOUR_STEPS}`);\n }\n\n // Normalize: trim whitespace from routes and selectors (LLMs\n // sometimes return \"/ \" instead of \"/\", which breaks route matching).\n for (const s of validSteps) {\n s.route = s.route.trim();\n if (s.elementId) s.elementId = s.elementId.trim();\n if (s.selector) {\n if (s.selector.cssSelector) s.selector.cssSelector = s.selector.cssSelector.trim();\n if (s.selector.testId) s.selector.testId = s.selector.testId.trim();\n if (s.selector.ariaLabel) s.selector.ariaLabel = s.selector.ariaLabel.trim();\n }\n }\n\n logger.info(`Provider.startTour: ${validSteps.length}/${steps.length} steps passed validation`);\n\n if (validSteps.length === 0) {\n logger.warn(\"Provider.startTour: no valid steps after filtering\");\n setTourState(\"idle\");\n setChatHistory((prev) => [\n ...prev,\n { role: \"assistant\", content: answer || CHAT_MESSAGES.invalidSteps },\n ]);\n return;\n }\n\n setSteps(validSteps);\n setCurrentStepIndex(0);\n setTourState(\"active\");\n setChatHistory((prev) => [\n ...prev,\n {\n role: \"assistant\",\n content:\n answer || CHAT_MESSAGES.tourStarted(validSteps.length),\n },\n ]);\n\n // Close chat and start Driver.js tour after a brief delay\n logger.info(\"Provider.startTour: closing chat, scheduling tourRenderer.startTour in 300ms\");\n setIsChatOpen(false);\n if (startTourDelayRef.current) clearTimeout(startTourDelayRef.current);\n startTourDelayRef.current = setTimeout(() => {\n startTourDelayRef.current = null;\n logger.info(`Provider.startTour: 300ms elapsed, calling tourRef.current.startTour(${validSteps.length} steps, \"${currentRoute}\")`);\n tourRef.current.startTour(validSteps, currentRoute);\n }, 300);\n } catch (err) {\n // Ignore aborted requests — a new startTour call superseded this one\n if (err instanceof DOMException && err.name === \"AbortError\") {\n logger.debug(\"Provider.startTour: request aborted (superseded by newer request)\");\n return;\n }\n logger.error(\"Provider.startTour: caught exception\", err);\n setTourState(\"error\");\n setChatHistory((prev) => [\n ...prev,\n {\n role: \"assistant\",\n content: CHAT_MESSAGES.genericError,\n },\n ]);\n if (errorRecoveryRef.current) clearTimeout(errorRecoveryRef.current);\n errorRecoveryRef.current = setTimeout(() => {\n errorRecoveryRef.current = null;\n setTourState(\"idle\");\n }, 2000);\n } finally {\n clearTimeout(timeoutId);\n // Clear ref if this controller is still the active one\n if (abortControllerRef.current === controller) {\n abortControllerRef.current = null;\n }\n }\n },\n [apiEndpoint, currentRoute, appId, apiKey]\n );\n\n // ─── Tour Controls ──────────────────────────────────────────\n\n const nextStep = useCallback(() => tourRef.current.nextStep(), []);\n const prevStep = useCallback(() => tourRef.current.prevStep(), []);\n\n const endTour = useCallback(() => {\n logger.info(\"Provider.endTour: user explicitly stopped tour\");\n pendingRouteRef.current = null;\n clearNavTimeout();\n saveTourState(null);\n tourRef.current.stopTour();\n resetTour();\n }, [resetTour, clearNavTimeout]);\n\n const goToStep = useCallback(\n (index: number) => {\n if (index >= 0 && index < steps.length) tourRef.current.goToStep(index);\n },\n [steps.length]\n );\n\n const currentStep = steps[currentStepIndex] ?? null;\n\n // ─── Context Value ──────────────────────────────────────────\n\n const value = useMemo<NavieoContextValue>(\n () => ({\n isChatOpen,\n openChat,\n closeChat,\n toggleChat,\n tourState,\n steps,\n currentStepIndex,\n currentStep,\n startTour,\n nextStep,\n prevStep,\n endTour,\n goToStep,\n chatHistory,\n clearChatHistory,\n currentRoute,\n suggestions,\n }),\n [\n isChatOpen, openChat, closeChat, toggleChat,\n tourState, steps, currentStepIndex, currentStep,\n startTour, nextStep, prevStep, endTour, goToStep,\n chatHistory, clearChatHistory, currentRoute, suggestions,\n ]\n );\n\n return (\n <NavieoContext.Provider value={value}>\n {children}\n <NavieoErrorBoundary>\n {renderChat && <ChatWidget />}\n </NavieoErrorBoundary>\n </NavieoContext.Provider>\n );\n}\n","\"use client\";\n\nimport React, { useState, useRef, useEffect } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { useNavieo } from \"./useNavieo\";\n\n/**\n * Floating chat widget rendered by {@link NavieoProvider} (when `renderChat`\n * is `true`). Provides a text input for guide queries, displays chat history,\n * suggestion chips, and a stop-tour button during active tours.\n *\n * Rendered via `createPortal` into `document.body`.\n */\nexport function ChatWidget() {\n const {\n isChatOpen,\n toggleChat,\n startTour,\n tourState,\n chatHistory,\n clearChatHistory,\n suggestions,\n endTour,\n } = useNavieo();\n\n const [inputValue, setInputValue] = useState(\"\");\n const messagesEndRef = useRef<HTMLDivElement>(null);\n const [mounted, setMounted] = useState(false);\n\n useEffect(() => setMounted(true), []);\n\n useEffect(() => {\n messagesEndRef.current?.scrollIntoView({ behavior: \"smooth\" });\n }, [chatHistory]);\n\n const handleSubmit = (e: React.FormEvent) => {\n e.preventDefault();\n if (!inputValue.trim() || tourState === \"loading\") return;\n startTour(inputValue.trim());\n setInputValue(\"\");\n };\n\n if (!mounted) return null;\n\n const isTourActive = tourState === \"active\";\n\n const widget = (\n <>\n <div className={`fixed bottom-6 right-6 flex flex-col items-end gap-3 font-sans ${isTourActive ? \"z-[1100000000]\" : \"z-[40]\"}`}>\n {/* Chat Panel (hidden during tour) */}\n {!isTourActive && isChatOpen && (\n <div className=\"w-[380px] h-[520px] bg-white rounded-2xl shadow-2xl border border-gray-200 flex flex-col overflow-hidden\">\n {/* Header */}\n <div className=\"px-5 py-4 bg-gradient-to-r from-blue-600 to-blue-700 text-white flex justify-between items-center\">\n <div>\n <p className=\"font-semibold text-sm\">Navieo Assistant</p>\n <p className=\"text-blue-200 text-xs\">\n Ask me how to do anything\n </p>\n </div>\n <div className=\"flex items-center gap-1\">\n {chatHistory.length > 0 && (\n <button\n onClick={clearChatHistory}\n aria-label=\"Clear chat history\"\n title=\"Clear chat history\"\n className=\"hover:bg-white/10 rounded-lg p-1 transition-colors\"\n >\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n >\n <path d=\"M3 6h18M8 6V4a2 2 0 012-2h4a2 2 0 012 2v2m3 0v14a2 2 0 01-2 2H7a2 2 0 01-2-2V6h14\" />\n </svg>\n </button>\n )}\n <button\n onClick={toggleChat}\n aria-label=\"Close chat\"\n className=\"hover:bg-white/10 rounded-lg p-1 transition-colors\"\n >\n <svg\n width=\"18\"\n height=\"18\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n >\n <path d=\"M18 6L6 18M6 6l12 12\" />\n </svg>\n </button>\n </div>\n </div>\n\n {/* Messages */}\n <div className=\"flex-1 overflow-y-auto p-4 space-y-3\">\n {chatHistory.length === 0 && (\n <div className=\"text-center mt-6 px-4\">\n <div className=\"w-12 h-12 bg-blue-100 rounded-full flex items-center justify-center mx-auto mb-4\">\n <svg\n className=\"w-6 h-6 text-blue-600\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n viewBox=\"0 0 24 24\"\n >\n <path d=\"M9.663 17h4.673M12 3v1m6.364 1.636l-.707.707M21 12h-1M4 12H3m3.343-5.657l-.707-.707m2.828 9.9a5 5 0 117.072 0l-.548.547A3.374 3.374 0 0014 18.469V19a2 2 0 11-4 0v-.531c0-.895-.356-1.754-.988-2.386l-.548-.547z\" />\n </svg>\n </div>\n <p className=\"text-gray-900 font-medium text-sm mb-1\">\n How can I help?\n </p>\n <p className=\"text-gray-400 text-xs leading-relaxed mb-4\">\n Ask me how to do anything in this app and I&apos;ll guide\n you step by step.\n </p>\n\n {/* Suggestion chips */}\n {suggestions && suggestions.length > 0 && (\n <div className=\"space-y-1.5\">\n {suggestions.map((s) => (\n <button\n key={s.label}\n disabled={tourState === \"loading\"}\n onClick={() => {\n if (tourState === \"loading\") return;\n setInputValue(s.label);\n startTour(s.label);\n }}\n className=\"flex items-center gap-2 w-full text-left text-xs bg-gray-50 hover:bg-gray-100 text-gray-600 rounded-lg px-3 py-2 transition-colors disabled:opacity-50\"\n >\n <span className=\"flex-1\">{s.label}</span>\n {s.tag && (\n <span className=\"shrink-0 text-[10px] font-medium px-1.5 py-0.5 rounded bg-blue-100 text-blue-600\">\n {s.tag}\n </span>\n )}\n </button>\n ))}\n </div>\n )}\n </div>\n )}\n\n {/* Chat messages */}\n {chatHistory.map((msg, i) => (\n <div\n key={i}\n className={`flex ${msg.role === \"user\" ? \"justify-end\" : \"justify-start\"}`}\n >\n <div\n className={`max-w-[85%] rounded-2xl px-4 py-2.5 text-sm leading-relaxed whitespace-pre-line ${\n msg.role === \"user\"\n ? \"bg-blue-600 text-white rounded-br-md\"\n : \"bg-gray-100 text-gray-800 rounded-bl-md\"\n }`}\n >\n {msg.content}\n </div>\n </div>\n ))}\n\n {/* Loading indicator */}\n {tourState === \"loading\" && (\n <div className=\"flex justify-start\">\n <div className=\"bg-gray-100 rounded-2xl rounded-bl-md px-4 py-2.5 text-sm text-gray-500\">\n <span className=\"inline-flex gap-1\">\n <span className=\"w-1.5 h-1.5 bg-gray-400 rounded-full animate-bounce [animation-delay:0ms]\" />\n <span className=\"w-1.5 h-1.5 bg-gray-400 rounded-full animate-bounce [animation-delay:150ms]\" />\n <span className=\"w-1.5 h-1.5 bg-gray-400 rounded-full animate-bounce [animation-delay:300ms]\" />\n </span>\n </div>\n </div>\n )}\n <div ref={messagesEndRef} />\n </div>\n\n {/* Input */}\n <form\n onSubmit={handleSubmit}\n className=\"p-3 border-t border-gray-200 bg-white\"\n >\n <div className=\"flex gap-2\">\n <input\n type=\"text\"\n value={inputValue}\n onChange={(e) => setInputValue(e.target.value)}\n placeholder=\"How do I...\"\n className=\"flex-1 border border-gray-300 rounded-xl px-4 py-2.5 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent\"\n disabled={tourState === \"loading\"}\n />\n <button\n type=\"submit\"\n disabled={tourState === \"loading\" || !inputValue.trim()}\n className=\"bg-blue-600 text-white px-4 py-2.5 rounded-xl text-sm hover:bg-blue-700 disabled:opacity-50 transition-colors\"\n >\n <svg\n className=\"w-4 h-4\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n viewBox=\"0 0 24 24\"\n >\n <path d=\"M5 12h14M12 5l7 7-7 7\" />\n </svg>\n </button>\n </div>\n </form>\n </div>\n )}\n\n {/* Floating Action Button — visible during tours as a stop button */}\n <button\n onClick={isTourActive ? endTour : toggleChat}\n aria-label={isTourActive ? \"Stop tour\" : \"Open Navieo assistant\"}\n className={`w-14 h-14 rounded-full shadow-lg flex items-center justify-center transition-all hover:scale-105 ${\n isTourActive\n ? \"bg-red-500 hover:bg-red-600\"\n : isChatOpen\n ? \"bg-gray-700 hover:bg-gray-800\"\n : \"bg-blue-600 hover:bg-blue-700\"\n } text-white`}\n >\n {isTourActive ? (\n /* Stop icon */\n <svg\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"currentColor\"\n >\n <rect x=\"6\" y=\"6\" width=\"12\" height=\"12\" rx=\"2\" />\n </svg>\n ) : isChatOpen ? (\n <svg\n width=\"22\"\n height=\"22\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n >\n <path d=\"M18 6L6 18M6 6l12 12\" />\n </svg>\n ) : (\n <svg\n width=\"22\"\n height=\"22\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n >\n <path d=\"M21 15a2 2 0 01-2 2H7l-4 4V5a2 2 0 012-2h14a2 2 0 012 2z\" />\n </svg>\n )}\n </button>\n </div>\n </>\n );\n\n return createPortal(widget, document.body);\n}\n","\"use client\";\n\nimport { useContext } from \"react\";\nimport { NavieoContext } from \"./NavieoProvider\";\nimport type { NavieoContextValue } from \"./types\";\n\n/**\n * Access the Navieo tour and chat API from any component inside a\n * {@link NavieoProvider}.\n *\n * @throws {Error} If called outside of a `<NavieoProvider>`.\n *\n * @example\n * ```tsx\n * const { startTour, tourState, chatHistory } = useNavieo();\n * ```\n */\nexport function useNavieo(): NavieoContextValue {\n const context = useContext(NavieoContext);\n if (!context) {\n throw new Error(\"useNavieo must be used within a <NavieoProvider>\");\n }\n return context;\n}\n","\"use client\";\n\nimport { driver, type DriveStep, type Driver } from \"driver.js\";\nimport \"driver.js/dist/driver.css\";\nimport { useEffect, useRef, useCallback, useMemo } from \"react\";\nimport type { TourStep } from \"./types\";\nimport { routeMatches } from \"./routeUtils\";\nimport { TOUR_ERRORS } from \"./constants\";\nimport { logger } from \"./logger\";\n\n/** A consecutive group of steps that share the same route. */\ninterface RouteGroup {\n route: string;\n steps: TourStep[];\n globalStartIndex: number; // index of first step in the full tour\n}\n\n/**\n * Escape HTML entities in a string to prevent XSS.\n * LLM outputs go into Driver.js popover titles/descriptions which render HTML.\n */\nfunction escapeHtml(str: string): string {\n return str\n .replace(/&/g, \"&amp;\")\n .replace(/</g, \"&lt;\")\n .replace(/>/g, \"&gt;\")\n .replace(/\"/g, \"&quot;\")\n .replace(/'/g, \"&#39;\");\n}\n\nexport interface TourRendererOptions {\n onStepChange?: (stepIndex: number) => void;\n onComplete?: () => void;\n onClose?: () => void;\n /** Called when the tour needs to navigate to a different route. */\n onNavigationNeeded?: (route: string) => void;\n /** Called when the tour fails (e.g. elements not found after polling). */\n onError?: (message: string) => void;\n}\n\n/** Split steps into consecutive groups by route. */\nfunction groupByRoute(steps: TourStep[]): RouteGroup[] {\n const groups: RouteGroup[] = [];\n let currentGroup: RouteGroup | null = null;\n\n steps.forEach((step, i) => {\n if (!currentGroup || currentGroup.route !== step.route) {\n currentGroup = { route: step.route, steps: [], globalStartIndex: i };\n groups.push(currentGroup);\n }\n currentGroup.steps.push(step);\n });\n\n return groups;\n}\n\nexport function useTourRenderer(options: TourRendererOptions = {}) {\n const driverRef = useRef<Driver | null>(null);\n const optionsRef = useRef(options);\n optionsRef.current = options;\n\n // Cross-page tour state\n const allStepsRef = useRef<TourStep[]>([]);\n const groupsRef = useRef<RouteGroup[]>([]);\n const currentGroupIndexRef = useRef(0);\n\n // Guard flag: true while transitioning between route groups.\n // Prevents onClose/onComplete from firing during group transitions.\n const transitioningRef = useRef(false);\n\n // Ref for the 60s transition safety timeout so it can be cleaned up.\n const transitionTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n // Flag for programmatic destruction. When true, onDestroyStarted confirms\n // immediately instead of running transition/close/complete logic.\n const forceDestroyRef = useRef(false);\n\n // Track the last known active step index within the current group.\n const lastLocalIndexRef = useRef(0);\n\n /**\n * Try to find an element in the DOM using a fallback chain of selectors.\n * Returns the first selector that matches, or undefined if none match.\n */\n function resolveSelector(step: TourStep): string | undefined {\n const candidates: string[] = [];\n\n if (step.selector?.cssSelector) candidates.push(step.selector.cssSelector);\n if (step.elementId) candidates.push(`#${CSS.escape(step.elementId)}`);\n if (step.selector?.testId) candidates.push(`[data-testid=\"${CSS.escape(step.selector.testId)}\"]`);\n if (step.selector?.ariaLabel) candidates.push(`[aria-label=\"${CSS.escape(step.selector.ariaLabel)}\"]`);\n\n const stepLabel = step.tooltipTitle || step.elementId || \"unknown\";\n\n if (candidates.length === 0) {\n logger.warn(`resolveSelector(\"${stepLabel}\"): no selectors defined on step`);\n return undefined;\n }\n\n logger.debug(`resolveSelector(\"${stepLabel}\"): trying ${candidates.length} candidates: ${candidates.join(\", \")}`);\n\n for (const sel of candidates) {\n try {\n const el = document.querySelector(sel);\n if (el) {\n logger.debug(`resolveSelector(\"${stepLabel}\"): FOUND via \"${sel}\" → <${el.tagName.toLowerCase()}>`);\n return sel;\n }\n logger.debug(`resolveSelector(\"${stepLabel}\"): miss \"${sel}\"`);\n } catch {\n logger.warn(`resolveSelector(\"${stepLabel}\"): invalid selector syntax \"${sel}\"`);\n }\n }\n\n logger.warn(`resolveSelector(\"${stepLabel}\"): NO element found. Tried: ${candidates.join(\", \")}`);\n return undefined;\n }\n\n /** Build Driver.js steps from a route group, with global step counter. */\n function buildDriverSteps(\n group: RouteGroup,\n totalSteps: number,\n isLastGroup: boolean\n ): DriveStep[] {\n return group.steps.map((s, i) => {\n const globalIndex = group.globalStartIndex + i;\n const isLastStepInGroup = i === group.steps.length - 1;\n\n return {\n element: s.selector?.cssSelector || `#${s.elementId}`,\n popover: {\n title: escapeHtml(s.tooltipTitle || `Step ${globalIndex + 1} of ${totalSteps}`),\n description: escapeHtml(s.tooltipText),\n progressText: `${globalIndex + 1} of ${totalSteps}`,\n ...(isLastStepInGroup && !isLastGroup\n ? { doneBtnText: \"Next →\" }\n : {}),\n },\n };\n });\n }\n\n /**\n * Safely destroy the current driver and null the ref.\n */\n function destroyCurrentDriver() {\n const d = driverRef.current;\n if (!d) return;\n logger.debug(\"destroyCurrentDriver: destroying active driver instance\");\n forceDestroyRef.current = true;\n try { d.destroy(); } catch { /* already destroyed */ }\n forceDestroyRef.current = false;\n driverRef.current = null;\n }\n\n // Ref to track the element-polling interval\n const pollIntervalRef = useRef<ReturnType<typeof setInterval> | null>(null);\n\n function clearTransitionTimeout() {\n if (transitionTimeoutRef.current) {\n clearTimeout(transitionTimeoutRef.current);\n transitionTimeoutRef.current = null;\n }\n }\n\n function clearPollInterval() {\n if (pollIntervalRef.current) {\n clearInterval(pollIntervalRef.current);\n pollIntervalRef.current = null;\n }\n }\n\n /**\n * Check if at least one selector from any step matches a DOM element.\n */\n function anyElementExists(steps: TourStep[]): boolean {\n for (const step of steps) {\n const candidates: string[] = [];\n if (step.selector?.cssSelector) candidates.push(step.selector.cssSelector);\n if (step.elementId) candidates.push(`#${CSS.escape(step.elementId)}`);\n if (step.selector?.testId) candidates.push(`[data-testid=\"${CSS.escape(step.selector.testId)}\"]`);\n if (step.selector?.ariaLabel) candidates.push(`[aria-label=\"${CSS.escape(step.selector.ariaLabel)}\"]`);\n\n for (const sel of candidates) {\n try {\n if (document.querySelector(sel)) return true;\n } catch { /* invalid selector */ }\n }\n }\n return false;\n }\n\n /**\n * Start the Driver.js instance for a group.\n */\n function launchDriver(\n group: RouteGroup,\n driverSteps: DriveStep[]\n ) {\n logger.info(`launchDriver: group=\"${group.route}\", ${driverSteps.length} steps, globalStart=${group.globalStartIndex}`);\n\n // Resolve selectors with fallback chain\n const resolvedSummary: Array<{ step: string; selector: string | null }> = [];\n for (let idx = 0; idx < driverSteps.length; idx++) {\n const resolved = resolveSelector(group.steps[idx]);\n if (resolved) {\n driverSteps[idx].element = resolved;\n } else {\n driverSteps[idx].element = undefined as unknown as string;\n }\n resolvedSummary.push({\n step: group.steps[idx].tooltipTitle || `Step ${idx + 1}`,\n selector: resolved || null,\n });\n }\n\n logger.debugSteps(\"launchDriver: resolved selectors\", resolvedSummary);\n\n try {\n logger.debug(\"launchDriver: calling driver() constructor...\");\n driverRef.current = driver({\n showProgress: true,\n animate: true,\n overlayColor: \"rgba(0, 0, 0, 0.6)\",\n stagePadding: 8,\n stageRadius: 8,\n steps: driverSteps,\n onHighlightStarted: (_element, _step, opts) => {\n const localIndex = opts.state.activeIndex ?? 0;\n lastLocalIndexRef.current = localIndex;\n const globalIndex = group.globalStartIndex + localIndex;\n logger.debug(`onHighlightStarted: local=${localIndex}, global=${globalIndex}`);\n optionsRef.current.onStepChange?.(globalIndex);\n },\n onDestroyStarted: () => {\n const d = driverRef.current;\n if (!d) {\n logger.warn(\"onDestroyStarted: driverRef is null — skipping\");\n return;\n }\n\n // Programmatic destroy — just confirm it.\n if (forceDestroyRef.current) {\n logger.debug(\"onDestroyStarted: forceDestroy=true, confirming\");\n driverRef.current = null;\n d.destroy();\n return;\n }\n\n const activeIndex = lastLocalIndexRef.current;\n const isLastStep = activeIndex >= driverSteps.length - 1;\n const isLastGroupNow =\n currentGroupIndexRef.current >= groupsRef.current.length - 1;\n const hasMoreGroups = !isLastGroupNow;\n\n logger.info(\n `onDestroyStarted: step=${activeIndex}/${driverSteps.length - 1}, ` +\n `group=${currentGroupIndexRef.current}/${groupsRef.current.length - 1}, ` +\n `isLastStep=${isLastStep}, hasMoreGroups=${hasMoreGroups}`\n );\n\n if (isLastStep && hasMoreGroups) {\n transitioningRef.current = true;\n driverRef.current = null;\n d.destroy();\n const nextGroup =\n groupsRef.current[currentGroupIndexRef.current + 1];\n logger.info(`onDestroyStarted: transitioning to next group, route=\"${nextGroup.route}\"`);\n\n clearTransitionTimeout();\n transitionTimeoutRef.current = setTimeout(() => {\n if (transitioningRef.current) {\n logger.warn(\"Transition safety timeout (60s) — navigation never completed\");\n transitioningRef.current = false;\n optionsRef.current.onClose?.();\n }\n transitionTimeoutRef.current = null;\n }, 60_000);\n\n optionsRef.current.onNavigationNeeded?.(nextGroup.route);\n } else if (isLastStep && isLastGroupNow) {\n driverRef.current = null;\n d.destroy();\n logger.info(\"onDestroyStarted: tour COMPLETE (last step of last group)\");\n optionsRef.current.onComplete?.();\n } else {\n driverRef.current = null;\n d.destroy();\n logger.info(\"onDestroyStarted: tour CLOSED by user (early exit)\");\n optionsRef.current.onClose?.();\n }\n },\n onDestroyed: () => {\n if (transitioningRef.current) {\n logger.debug(\"onDestroyed: transitioning between groups, skipping\");\n return;\n }\n logger.debug(\"onDestroyed: driver fully destroyed\");\n },\n });\n\n logger.debug(\"launchDriver: driver() created, calling .drive()...\");\n driverRef.current.drive();\n logger.info(\"launchDriver: .drive() called — tour should now be visible\");\n } catch (err) {\n logger.error(\"launchDriver: Driver.js crashed!\", err);\n driverRef.current = null;\n optionsRef.current.onError?.(TOUR_ERRORS.driverCrash);\n }\n }\n\n /** Drive a specific route group. Polls for elements before starting. */\n const driveGroup = useCallback((groupIndex: number) => {\n logger.info(`driveGroup(${groupIndex}): entering`);\n transitioningRef.current = false;\n lastLocalIndexRef.current = 0;\n\n clearTransitionTimeout();\n clearPollInterval();\n destroyCurrentDriver();\n\n const groups = groupsRef.current;\n const totalSteps = allStepsRef.current.length;\n\n logger.debug(`driveGroup(${groupIndex}): totalGroups=${groups.length}, totalSteps=${totalSteps}`);\n\n if (groupIndex >= groups.length) {\n logger.warn(`driveGroup(${groupIndex}): index out of range (${groups.length} groups), calling onComplete`);\n optionsRef.current.onComplete?.();\n return;\n }\n\n currentGroupIndexRef.current = groupIndex;\n const group = groups[groupIndex];\n const isLastGroup = groupIndex >= groups.length - 1;\n const driverSteps = buildDriverSteps(group, totalSteps, isLastGroup);\n\n // Log step details for this group\n const stepDetails = group.steps.map((s, i) => ({\n index: group.globalStartIndex + i,\n route: s.route,\n title: s.tooltipTitle || \"(no title)\",\n cssSelector: s.selector?.cssSelector || \"(none)\",\n elementId: s.elementId || \"(none)\",\n testId: s.selector?.testId || \"(none)\",\n }));\n logger.info(`driveGroup(${groupIndex}): route=\"${group.route}\", ${driverSteps.length} steps, isLastGroup=${isLastGroup}`);\n logger.debugSteps(`driveGroup(${groupIndex}): step details`, stepDetails);\n\n // Poll for elements\n const POLL_INTERVAL_MS = 200;\n const POLL_TIMEOUT_MS = 5_000;\n const pollStartTime = Date.now();\n\n if (anyElementExists(group.steps)) {\n logger.info(`driveGroup(${groupIndex}): elements found immediately — launching`);\n launchDriver(group, driverSteps);\n return;\n }\n\n logger.info(`driveGroup(${groupIndex}): elements NOT found yet, starting poll (interval=${POLL_INTERVAL_MS}ms, timeout=${POLL_TIMEOUT_MS}ms)`);\n\n pollIntervalRef.current = setInterval(() => {\n const elapsed = Date.now() - pollStartTime;\n\n if (anyElementExists(group.steps)) {\n logger.info(`driveGroup(${groupIndex}): elements found after ${elapsed}ms — launching`);\n clearPollInterval();\n launchDriver(group, driverSteps);\n return;\n }\n\n if (elapsed >= POLL_TIMEOUT_MS) {\n clearPollInterval();\n logger.warn(`driveGroup(${groupIndex}): poll timed out after ${POLL_TIMEOUT_MS}ms — launching anyway (soft fallback)`);\n launchDriver(group, driverSteps);\n }\n }, POLL_INTERVAL_MS);\n }, []);\n\n /** Start a new multi-page tour. */\n const startTour = useCallback(\n (steps: TourStep[], currentRoute: string) => {\n logger.info(`startTour: ${steps.length} steps, currentRoute=\"${currentRoute}\"`);\n\n // Log all step routes and selectors\n const stepSummary = steps.map((s, i) => ({\n step: i + 1,\n route: s.route,\n title: s.tooltipTitle || \"(no title)\",\n cssSelector: s.selector?.cssSelector || \"(none)\",\n elementId: s.elementId || \"(none)\",\n }));\n logger.debugSteps(\"startTour: received steps\", stepSummary);\n\n allStepsRef.current = steps;\n groupsRef.current = groupByRoute(steps);\n currentGroupIndexRef.current = 0;\n transitioningRef.current = false;\n\n const groups = groupsRef.current;\n logger.info(`startTour: grouped into ${groups.length} route groups: ${groups.map(g => `\"${g.route}\"(${g.steps.length})`).join(\", \")}`);\n\n if (groups.length === 0) {\n logger.warn(\"startTour: no groups created — returning\");\n return;\n }\n\n if (!routeMatches(currentRoute, groups[0].route)) {\n logger.info(\n `startTour: first group route \"${groups[0].route}\" != currentRoute \"${currentRoute}\" — showing nav popover before redirect`\n );\n\n // Show a centered popover so the user knows navigation is happening\n // (driver.js renders a centered modal when no element is specified)\n destroyCurrentDriver();\n driverRef.current = driver({\n showProgress: false,\n animate: true,\n overlayColor: \"rgba(0, 0, 0, 0.6)\",\n steps: [\n {\n popover: {\n title: `Navigating to ${groups[0].route}`,\n description:\n \"This guide needs to take you to a different page. Click Next to continue.\",\n doneBtnText: \"Next →\",\n },\n },\n ],\n onDestroyStarted: () => {\n const d = driverRef.current;\n if (!d) return;\n driverRef.current = null;\n d.destroy();\n optionsRef.current.onNavigationNeeded?.(groups[0].route);\n },\n });\n driverRef.current.drive();\n } else {\n logger.info(`startTour: first group route matches currentRoute — calling driveGroup(0)`);\n driveGroup(0);\n }\n },\n [driveGroup]\n );\n\n /** Continue tour after navigation completed. */\n const continueAfterNavigation = useCallback(\n (arrivedRouteOrPattern: string) => {\n const groups = groupsRef.current;\n logger.info(\n `continueAfterNavigation: arrivedAt=\"${arrivedRouteOrPattern}\", ` +\n `currentGroup=${currentGroupIndexRef.current}, totalGroups=${groups.length}`\n );\n\n const nextIndex = groups.findIndex(\n (g, i) =>\n i > currentGroupIndexRef.current &&\n (g.route === arrivedRouteOrPattern ||\n routeMatches(arrivedRouteOrPattern, g.route))\n );\n\n if (nextIndex !== -1) {\n logger.info(`continueAfterNavigation: found next group ${nextIndex}, route=\"${groups[nextIndex].route}\"`);\n driveGroup(nextIndex);\n } else if (\n groups.length > 0 &&\n (groups[0].route === arrivedRouteOrPattern ||\n routeMatches(arrivedRouteOrPattern, groups[0].route)) &&\n currentGroupIndexRef.current === 0\n ) {\n logger.info(\"continueAfterNavigation: first group matches — driving group 0\");\n driveGroup(0);\n } else {\n const currentGroup = groups[currentGroupIndexRef.current];\n if (\n currentGroup &&\n (currentGroup.route === arrivedRouteOrPattern ||\n routeMatches(arrivedRouteOrPattern, currentGroup.route))\n ) {\n logger.debug(`continueAfterNavigation: current group already matches \"${arrivedRouteOrPattern}\" — duplicate, ignoring`);\n return;\n }\n\n logger.warn(`continueAfterNavigation: no matching group for \"${arrivedRouteOrPattern}\" — ignoring`);\n }\n },\n [driveGroup]\n );\n\n /**\n * Restore a tour after a page reload or React remount.\n * Unlike startTour (which always starts from group 0), this finds the\n * group matching the current route and drives it directly.\n */\n const restoreTour = useCallback(\n (steps: TourStep[], currentRoute: string) => {\n logger.info(`restoreTour: ${steps.length} steps, currentRoute=\"${currentRoute}\"`);\n\n allStepsRef.current = steps;\n groupsRef.current = groupByRoute(steps);\n currentGroupIndexRef.current = 0;\n transitioningRef.current = false;\n\n const groups = groupsRef.current;\n logger.info(`restoreTour: grouped into ${groups.length} route groups: ${groups.map(g => `\"${g.route}\"(${g.steps.length})`).join(\", \")}`);\n\n if (groups.length === 0) {\n logger.warn(\"restoreTour: no groups — aborting\");\n return;\n }\n\n // Find the group matching the current route (instead of starting from 0)\n const matchingIndex = groups.findIndex(g =>\n routeMatches(currentRoute, g.route)\n );\n\n if (matchingIndex !== -1) {\n logger.info(`restoreTour: found matching group ${matchingIndex}, route=\"${groups[matchingIndex].route}\" — driving`);\n driveGroup(matchingIndex);\n } else {\n // Current route doesn't match any group — fall back to startTour behavior\n logger.warn(`restoreTour: no group matches currentRoute \"${currentRoute}\" — falling back to startTour logic`);\n if (!routeMatches(currentRoute, groups[0].route)) {\n optionsRef.current.onNavigationNeeded?.(groups[0].route);\n } else {\n driveGroup(0);\n }\n }\n },\n [driveGroup]\n );\n\n const stopTour = useCallback(() => {\n logger.info(\"stopTour: stopping tour and clearing all state\");\n transitioningRef.current = false;\n clearTransitionTimeout();\n clearPollInterval();\n destroyCurrentDriver();\n allStepsRef.current = [];\n groupsRef.current = [];\n currentGroupIndexRef.current = 0;\n }, []);\n\n const nextStep = useCallback(() => {\n driverRef.current?.moveNext();\n }, []);\n\n const prevStep = useCallback(() => {\n driverRef.current?.movePrevious();\n }, []);\n\n const goToStep = useCallback((index: number) => {\n driverRef.current?.moveTo(index);\n }, []);\n\n useEffect(() => {\n return () => {\n clearTransitionTimeout();\n clearPollInterval();\n destroyCurrentDriver();\n };\n }, []);\n\n return useMemo(\n () => ({ startTour, restoreTour, stopTour, nextStep, prevStep, goToStep, continueAfterNavigation }),\n [startTour, restoreTour, stopTour, nextStep, prevStep, goToStep, continueAfterNavigation]\n );\n}\n","/**\n * Utilities for matching routes with dynamic segments.\n *\n * Supported Next.js patterns:\n * [param] — single dynamic segment\n * [...slug] — catch-all (matches 1+ segments)\n * [[...slug]] — optional catch-all (matches 0+ segments)\n */\n\n/**\n * Strip Next.js route groups from a path.\n * Route groups are parenthesized segments like `(auth)` or `(marketing)` that\n * exist in the filesystem but are NOT part of the URL path.\n *\n * Examples:\n * \"/(auth)/login\" → \"/login\"\n * \"/(marketing)/about\" → \"/about\"\n * \"/(group)\" → \"/\"\n * \"/dashboard\" → \"/dashboard\" (no change)\n */\nfunction stripRouteGroups(route: string): string {\n // Remove segments that are entirely wrapped in parentheses: /(groupName)\n return route.replace(/\\/\\([^)]+\\)/g, \"\") || \"/\";\n}\n\n/**\n * Normalize a route for comparison:\n * - Strip Next.js route groups like /(auth)\n * - Strip query string and hash fragment\n * - Remove trailing slash (except for root \"/\")\n * - Trim whitespace\n *\n * Examples:\n * \"/dashboard/\" → \"/dashboard\"\n * \"/dashboard?q=1\" → \"/dashboard\"\n * \"/docs#section\" → \"/docs\"\n * \"/\" → \"/\"\n * \"/ \" → \"/\"\n * \"/(auth)/login\" → \"/login\"\n */\nfunction normalizeRoute(route: string): string {\n let r = route.trim();\n // Strip route groups\n r = stripRouteGroups(r);\n // Strip query string\n const qIdx = r.indexOf(\"?\");\n if (qIdx !== -1) r = r.slice(0, qIdx);\n // Strip hash fragment\n const hIdx = r.indexOf(\"#\");\n if (hIdx !== -1) r = r.slice(0, hIdx);\n // Strip trailing slash (but keep root \"/\")\n if (r.length > 1 && r.endsWith(\"/\")) r = r.slice(0, -1);\n return r;\n}\n\n/**\n * Check if a route pattern contains dynamic segments like [param].\n */\nexport function isDynamicRoute(route: string): boolean {\n return /\\[.+?\\]/.test(route);\n}\n\n/**\n * Check if an actual pathname matches a route pattern.\n * Both sides are normalized (trailing slashes, query params, hash stripped).\n *\n * Examples:\n * routeMatches(\"/dashboard/abc123\", \"/dashboard/[appId]\") → true\n * routeMatches(\"/dashboard\", \"/dashboard\") → true\n * routeMatches(\"/dashboard/\", \"/dashboard\") → true\n * routeMatches(\"/dashboard?q=1\", \"/dashboard\") → true\n * routeMatches(\"/docs/a/b/c\", \"/docs/[...slug]\") → true\n * routeMatches(\"/docs\", \"/docs/[[...slug]]\") → true\n * routeMatches(\"/docs/a/b\", \"/docs/[[...slug]]\") → true\n * routeMatches(\"/docs/getting-started\", \"/dashboard/[appId]\") → false\n * routeMatches(\"/dashboard\", \"/dashboard/[appId]\") → false\n */\nexport function routeMatches(actual: string, pattern: string): boolean {\n const a = normalizeRoute(actual);\n const p = normalizeRoute(pattern);\n\n if (a === p) return true;\n\n const actualParts = a.split(\"/\");\n const patternParts = p.split(\"/\");\n\n // Check for catch-all and optional catch-all patterns\n const lastPart = patternParts[patternParts.length - 1];\n\n // Optional catch-all: [[...slug]] — matches 0 or more additional segments\n if (lastPart && lastPart.startsWith(\"[[...\") && lastPart.endsWith(\"]]\")) {\n const prefixParts = patternParts.slice(0, -1);\n // Actual must have at least as many parts as the prefix (catch-all can be empty)\n if (actualParts.length < prefixParts.length) return false;\n return prefixParts.every(\n (part, i) => (part.startsWith(\"[\") && part.endsWith(\"]\")) || part === actualParts[i]\n );\n }\n\n // Catch-all: [...slug] — matches 1 or more additional segments\n if (lastPart && lastPart.startsWith(\"[...\") && lastPart.endsWith(\"]\")) {\n const prefixParts = patternParts.slice(0, -1);\n // Actual must have MORE parts than the prefix (catch-all needs at least 1 segment)\n if (actualParts.length <= prefixParts.length) return false;\n return prefixParts.every(\n (part, i) => (part.startsWith(\"[\") && part.endsWith(\"]\")) || part === actualParts[i]\n );\n }\n\n // Standard: segment counts must match exactly\n if (actualParts.length !== patternParts.length) return false;\n\n return patternParts.every(\n (part, i) => (part.startsWith(\"[\") && part.endsWith(\"]\")) || part === actualParts[i]\n );\n}\n","/**\n * Centralized user-facing messages for the Navieo SDK.\n *\n * All strings shown to the end user (chat messages, error messages, etc.)\n * live here so they're easy to find, update, and eventually i18n.\n */\n\n// ─── Tour Error Messages (from TourRenderer → onError callback) ──────\n\nexport const TOUR_ERRORS = {\n /** Element polling timed out — page elements never appeared in the DOM. */\n elementsNotFound: (stepLabels: string) =>\n `Could not find the page elements needed for the next steps (${stepLabels}). The page may still be loading or the layout may have changed.`,\n\n /** Transition between route groups timed out (60s safety). */\n transitionTimeout:\n \"The tour couldn't continue because the next page didn't load in time.\",\n\n /** Driver.js threw an unexpected exception. */\n driverCrash:\n \"The tour encountered an unexpected error and had to stop.\",\n\n /** continueAfterNavigation couldn't find a matching route group. */\n noMatchingGroup:\n \"The tour couldn't find steps for the page you navigated to. The tour has been stopped.\",\n} as const;\n\n// ─── Chat Messages (shown in the ChatWidget) ─────────────────────────\n\nexport const CHAT_MESSAGES = {\n /** Wraps a tour error for display in chat. */\n tourError: (detail: string) =>\n `The tour ran into a problem: ${detail} Please try again or ask a different question.`,\n\n /** Navigation timeout — route never changed within NAV_TIMEOUT_MS. */\n navigationTimeout:\n \"The tour was stopped because the expected page navigation didn't complete in time. Please try again.\",\n\n /** API returned no steps and no answer text. */\n noStepsFound:\n \"I couldn't find specific steps for that. Try asking something else.\",\n\n /** API returned steps but none had the required fields. */\n invalidSteps:\n \"The response didn't contain valid steps. Try rephrasing your question.\",\n\n /** Generic API/network error. */\n genericError:\n \"Something went wrong. Please try again.\",\n\n /** Tour started successfully. */\n tourStarted: (stepCount: number) =>\n `I found ${stepCount} step${stepCount !== 1 ? \"s\" : \"\"} to help you. Starting the tour!`,\n} as const;\n","/**\n * Centralized logger for the Navieo SDK.\n *\n * Provides leveled logging (debug, info, warn, error) with a consistent\n * \"[Navieo]\" prefix. Log level can be controlled at runtime via\n * `Logger.setLevel()` or by setting `window.__NAVIEO_LOG_LEVEL__`.\n *\n * Levels (from most to least verbose):\n * debug → info → warn → error → silent\n *\n * Default level: \"info\" in development, \"warn\" in production.\n */\n\nexport type LogLevel = \"debug\" | \"info\" | \"warn\" | \"error\" | \"silent\";\n\nconst LEVEL_ORDER: Record<LogLevel, number> = {\n debug: 0,\n info: 1,\n warn: 2,\n error: 3,\n silent: 4,\n};\n\nconst PREFIX = \"[Navieo]\";\n\nfunction getDefaultLevel(): LogLevel {\n // Check for user override on window\n if (typeof window !== \"undefined\") {\n const override = (window as unknown as Record<string, unknown>).__NAVIEO_LOG_LEVEL__;\n if (typeof override === \"string\" && override in LEVEL_ORDER) {\n return override as LogLevel;\n }\n }\n\n // Default: debug in dev, warn in prod\n if (typeof process !== \"undefined\" && process.env?.NODE_ENV === \"production\") {\n return \"warn\";\n }\n return \"debug\";\n}\n\nclass NavieoLogger {\n private level: LogLevel = getDefaultLevel();\n\n /** Change the active log level at runtime. */\n setLevel(level: LogLevel) {\n this.level = level;\n }\n\n getLevel(): LogLevel {\n return this.level;\n }\n\n private shouldLog(level: LogLevel): boolean {\n return LEVEL_ORDER[level] >= LEVEL_ORDER[this.level];\n }\n\n /** Verbose diagnostic info — only shown at \"debug\" level. */\n debug(message: string, ...args: unknown[]) {\n if (this.shouldLog(\"debug\")) {\n console.log(`${PREFIX} ${message}`, ...args);\n }\n }\n\n /** Standard operational info — shown at \"info\" level and above. */\n info(message: string, ...args: unknown[]) {\n if (this.shouldLog(\"info\")) {\n console.log(`${PREFIX} ${message}`, ...args);\n }\n }\n\n /** Warnings — shown at \"warn\" level and above. */\n warn(message: string, ...args: unknown[]) {\n if (this.shouldLog(\"warn\")) {\n console.warn(`${PREFIX} ${message}`, ...args);\n }\n }\n\n /** Errors — always shown unless \"silent\". */\n error(message: string, ...args: unknown[]) {\n if (this.shouldLog(\"error\")) {\n console.error(`${PREFIX} ${message}`, ...args);\n }\n }\n\n /**\n * Log a structured diagnostic table for tour steps.\n * Only shown at \"debug\" level.\n */\n debugSteps(label: string, steps: Array<Record<string, unknown>>) {\n if (this.shouldLog(\"debug\")) {\n console.log(`${PREFIX} ${label}`);\n console.table(steps);\n }\n }\n}\n\n/** Singleton logger instance used throughout the SDK. */\nexport const logger = new NavieoLogger();\n"],"mappings":"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","names":["useCallback","useEffect","useMemo","useRef","useState","useEffect","useRef","useRef","useEffect","jsx","jsxs","useState","useEffect","useRef","useCallback","steps","useMemo"]}
@@ -0,0 +1,26 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import React from 'react';
3
+
4
+ interface NavieoNextProviderProps {
5
+ children: React.ReactNode;
6
+ apiEndpoint?: string;
7
+ appId?: string;
8
+ suggestions?: Array<{
9
+ label: string;
10
+ tag?: string;
11
+ }>;
12
+ renderChat?: boolean;
13
+ }
14
+ /**
15
+ * Next.js convenience wrapper for NavieoProvider.
16
+ * Automatically provides `currentRoute` via `usePathname()` and
17
+ * `onNavigate` via `useRouter().push()`.
18
+ *
19
+ * Import from `@navieo/react/next`:
20
+ * ```tsx
21
+ * import { NavieoNextProvider } from "@navieo/react/next";
22
+ * ```
23
+ */
24
+ declare function NavieoNextProvider({ children, ...props }: NavieoNextProviderProps): react_jsx_runtime.JSX.Element;
25
+
26
+ export { NavieoNextProvider, type NavieoNextProviderProps };
package/dist/next.d.ts ADDED
@@ -0,0 +1,26 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import React from 'react';
3
+
4
+ interface NavieoNextProviderProps {
5
+ children: React.ReactNode;
6
+ apiEndpoint?: string;
7
+ appId?: string;
8
+ suggestions?: Array<{
9
+ label: string;
10
+ tag?: string;
11
+ }>;
12
+ renderChat?: boolean;
13
+ }
14
+ /**
15
+ * Next.js convenience wrapper for NavieoProvider.
16
+ * Automatically provides `currentRoute` via `usePathname()` and
17
+ * `onNavigate` via `useRouter().push()`.
18
+ *
19
+ * Import from `@navieo/react/next`:
20
+ * ```tsx
21
+ * import { NavieoNextProvider } from "@navieo/react/next";
22
+ * ```
23
+ */
24
+ declare function NavieoNextProvider({ children, ...props }: NavieoNextProviderProps): react_jsx_runtime.JSX.Element;
25
+
26
+ export { NavieoNextProvider, type NavieoNextProviderProps };
package/dist/next.js ADDED
@@ -0,0 +1,51 @@
1
+ "use client";
2
+ "use strict";
3
+ "use client";
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
21
+
22
+ // src/next.tsx
23
+ var next_exports = {};
24
+ __export(next_exports, {
25
+ NavieoNextProvider: () => NavieoNextProvider
26
+ });
27
+ module.exports = __toCommonJS(next_exports);
28
+ var import_navigation = require("next/navigation");
29
+ var import_index = require("./index");
30
+ var import_jsx_runtime = require("react/jsx-runtime");
31
+ function NavieoNextProvider({
32
+ children,
33
+ ...props
34
+ }) {
35
+ const pathname = (0, import_navigation.usePathname)();
36
+ const router = (0, import_navigation.useRouter)();
37
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
38
+ import_index.NavieoProvider,
39
+ {
40
+ currentRoute: pathname,
41
+ onNavigate: (route) => router.push(route),
42
+ ...props,
43
+ children
44
+ }
45
+ );
46
+ }
47
+ // Annotate the CommonJS export names for ESM import in node:
48
+ 0 && (module.exports = {
49
+ NavieoNextProvider
50
+ });
51
+ //# sourceMappingURL=next.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/next.tsx"],"sourcesContent":["\"use client\";\n\nimport React from \"react\";\nimport { usePathname, useRouter } from \"next/navigation\";\nimport { NavieoProvider } from \"./index\";\n\nexport interface NavieoNextProviderProps {\n children: React.ReactNode;\n apiEndpoint?: string;\n appId?: string;\n suggestions?: Array<{ label: string; tag?: string }>;\n renderChat?: boolean;\n}\n\n/**\n * Next.js convenience wrapper for NavieoProvider.\n * Automatically provides `currentRoute` via `usePathname()` and\n * `onNavigate` via `useRouter().push()`.\n *\n * Import from `@navieo/react/next`:\n * ```tsx\n * import { NavieoNextProvider } from \"@navieo/react/next\";\n * ```\n */\nexport function NavieoNextProvider({\n children,\n ...props\n}: NavieoNextProviderProps) {\n const pathname = usePathname();\n const router = useRouter();\n\n return (\n <NavieoProvider\n currentRoute={pathname}\n onNavigate={(route) => router.push(route)}\n {...props}\n >\n {children}\n </NavieoProvider>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAGA,wBAAuC;AACvC,mBAA+B;AA4B3B;AARG,SAAS,mBAAmB;AAAA,EACjC;AAAA,EACA,GAAG;AACL,GAA4B;AAC1B,QAAM,eAAW,+BAAY;AAC7B,QAAM,aAAS,6BAAU;AAEzB,SACE;AAAA,IAAC;AAAA;AAAA,MACC,cAAc;AAAA,MACd,YAAY,CAAC,UAAU,OAAO,KAAK,KAAK;AAAA,MACvC,GAAG;AAAA,MAEH;AAAA;AAAA,EACH;AAEJ;","names":[]}
package/dist/next.mjs ADDED
@@ -0,0 +1,27 @@
1
+ "use client";
2
+ "use client";
3
+
4
+ // src/next.tsx
5
+ import { usePathname, useRouter } from "next/navigation";
6
+ import { NavieoProvider } from "./index";
7
+ import { jsx } from "react/jsx-runtime";
8
+ function NavieoNextProvider({
9
+ children,
10
+ ...props
11
+ }) {
12
+ const pathname = usePathname();
13
+ const router = useRouter();
14
+ return /* @__PURE__ */ jsx(
15
+ NavieoProvider,
16
+ {
17
+ currentRoute: pathname,
18
+ onNavigate: (route) => router.push(route),
19
+ ...props,
20
+ children
21
+ }
22
+ );
23
+ }
24
+ export {
25
+ NavieoNextProvider
26
+ };
27
+ //# sourceMappingURL=next.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/next.tsx"],"sourcesContent":["\"use client\";\n\nimport React from \"react\";\nimport { usePathname, useRouter } from \"next/navigation\";\nimport { NavieoProvider } from \"./index\";\n\nexport interface NavieoNextProviderProps {\n children: React.ReactNode;\n apiEndpoint?: string;\n appId?: string;\n suggestions?: Array<{ label: string; tag?: string }>;\n renderChat?: boolean;\n}\n\n/**\n * Next.js convenience wrapper for NavieoProvider.\n * Automatically provides `currentRoute` via `usePathname()` and\n * `onNavigate` via `useRouter().push()`.\n *\n * Import from `@navieo/react/next`:\n * ```tsx\n * import { NavieoNextProvider } from \"@navieo/react/next\";\n * ```\n */\nexport function NavieoNextProvider({\n children,\n ...props\n}: NavieoNextProviderProps) {\n const pathname = usePathname();\n const router = useRouter();\n\n return (\n <NavieoProvider\n currentRoute={pathname}\n onNavigate={(route) => router.push(route)}\n {...props}\n >\n {children}\n </NavieoProvider>\n );\n}\n"],"mappings":";;;;AAGA,SAAS,aAAa,iBAAiB;AACvC,SAAS,sBAAsB;AA4B3B;AARG,SAAS,mBAAmB;AAAA,EACjC;AAAA,EACA,GAAG;AACL,GAA4B;AAC1B,QAAM,WAAW,YAAY;AAC7B,QAAM,SAAS,UAAU;AAEzB,SACE;AAAA,IAAC;AAAA;AAAA,MACC,cAAc;AAAA,MACd,YAAY,CAAC,UAAU,OAAO,KAAK,KAAK;AAAA,MACvC,GAAG;AAAA,MAEH;AAAA;AAAA,EACH;AAEJ;","names":[]}
package/package.json ADDED
@@ -0,0 +1,83 @@
1
+ {
2
+ "name": "@navieo/react",
3
+ "version": "1.0.0",
4
+ "description": "AI-powered contextual site guide SDK for React",
5
+ "main": "./dist/index.js",
6
+ "module": "./dist/index.mjs",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.mjs",
12
+ "require": "./dist/index.js"
13
+ },
14
+ "./next": {
15
+ "types": "./dist/next.d.ts",
16
+ "import": "./dist/next.mjs",
17
+ "require": "./dist/next.js"
18
+ }
19
+ },
20
+ "scripts": {
21
+ "build": "tsup",
22
+ "dev": "tsup --watch",
23
+ "lint": "tsc --noEmit",
24
+ "test": "vitest run",
25
+ "test:watch": "vitest",
26
+ "prepublishOnly": "tsup"
27
+ },
28
+ "peerDependencies": {
29
+ "next": ">=14.0.0",
30
+ "react": "^18.0.0 || ^19.0.0",
31
+ "react-dom": "^18.0.0 || ^19.0.0"
32
+ },
33
+ "peerDependenciesMeta": {
34
+ "next": {
35
+ "optional": true
36
+ }
37
+ },
38
+ "dependencies": {
39
+ "driver.js": "^1.4.0"
40
+ },
41
+ "devDependencies": {
42
+ "@navieo/types": "workspace:*",
43
+ "@testing-library/jest-dom": "^6.9.1",
44
+ "@testing-library/react": "^16.3.2",
45
+ "@testing-library/user-event": "^14.6.1",
46
+ "@types/node": "^25.2.3",
47
+ "@types/react": "^18",
48
+ "@types/react-dom": "^18",
49
+ "jsdom": "^28.1.0",
50
+ "react": "^18",
51
+ "react-dom": "^18",
52
+ "tsup": "^8",
53
+ "typescript": "^5",
54
+ "vitest": "^4.0.18"
55
+ },
56
+ "files": [
57
+ "dist"
58
+ ],
59
+ "license": "MIT",
60
+ "engines": {
61
+ "node": ">=18"
62
+ },
63
+ "publishConfig": {
64
+ "access": "public"
65
+ },
66
+ "repository": {
67
+ "type": "git",
68
+ "url": "https://github.com/Navieo-org/navieo-sdk.git",
69
+ "directory": "packages/react"
70
+ },
71
+ "homepage": "https://github.com/Navieo-org/navieo-sdk/tree/main/packages/react#readme",
72
+ "bugs": {
73
+ "url": "https://github.com/Navieo-org/navieo-sdk/issues"
74
+ },
75
+ "keywords": [
76
+ "navieo",
77
+ "guided-tour",
78
+ "react",
79
+ "sdk",
80
+ "onboarding",
81
+ "walkthrough"
82
+ ]
83
+ }