react-headless-tour 0.1.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.
- package/LICENSE +21 -0
- package/README.md +245 -0
- package/dist/index.cjs +701 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +173 -0
- package/dist/index.d.ts +173 -0
- package/dist/index.js +689 -0
- package/dist/index.js.map +1 -0
- package/package.json +67 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/TourContext.tsx","../src/motion.ts","../src/useTargetRect.ts","../src/TourOverlay.tsx","../src/TourPopover.tsx","../src/DefaultCard.tsx"],"sourcesContent":["import {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n type CSSProperties,\n type ReactNode,\n} from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { useEntered, useReducedMotion } from \"./motion\";\nimport type { TourControls, TourProviderProps, TourStep, TourStopReason } from \"./types\";\nimport { resolveTarget, useTargetRect } from \"./useTargetRect\";\nimport { TourOverlay } from \"./TourOverlay\";\nimport { TourPopover } from \"./TourPopover\";\n\nconst TourContext = createContext<TourControls | null>(null);\n\n/** How long the closing fade runs before the tour UI unmounts, in ms. */\nconst EXIT_DURATION_MS = 220;\n\n/** Read tour state and control the tour from anywhere under <TourProvider>. */\nexport function useTour(): TourControls {\n const ctx = useContext(TourContext);\n if (!ctx) throw new Error(\"useTour must be used within a <TourProvider>\");\n return ctx;\n}\n\ntype Phase = \"idle\" | \"active\" | \"closing\";\n\n/** Fixed full-viewport layer that fades the tour UI in and out. */\nfunction TourLayer({\n closing,\n zIndex,\n className,\n theme,\n children,\n}: {\n closing: boolean;\n zIndex: number;\n className?: string;\n theme?: CSSProperties;\n children: ReactNode;\n}) {\n const entered = useEntered();\n const reducedMotion = useReducedMotion();\n return (\n <div\n data-tour-root=\"\"\n className={className}\n style={{\n position: \"fixed\",\n inset: 0,\n zIndex: `var(--tour-z-index, ${zIndex})` as unknown as number,\n pointerEvents: \"none\",\n opacity: entered && !closing ? 1 : 0,\n transition: reducedMotion ? undefined : `opacity ${EXIT_DURATION_MS}ms ease`,\n ...theme,\n }}\n >\n {children}\n </div>\n );\n}\n\nexport function TourProvider(props: TourProviderProps) {\n const {\n children,\n steps,\n autoStart = false,\n stepIndex: controlledIndex,\n onStepChange,\n onStart,\n onStop,\n keyboard = true,\n lockScroll = false,\n scrollIntoViewOptions = { behavior: \"smooth\", block: \"center\", inline: \"nearest\" },\n portalContainer,\n } = props;\n\n const [mounted, setMounted] = useState(false);\n const [phase, setPhase] = useState<Phase>(\"idle\");\n const [internalIndex, setInternalIndex] = useState(0);\n const isControlled = controlledIndex !== undefined;\n\n const isActive = phase === \"active\";\n const stepIndex = isActive ? (isControlled ? controlledIndex! : internalIndex) : -1;\n const step: TourStep | null =\n stepIndex >= 0 && stepIndex < steps.length ? steps[stepIndex] : null;\n\n // Snapshot of the last step so the closing fade can keep rendering it.\n const closingSnapshot = useRef<{ step: TourStep; stepIndex: number } | null>(null);\n const exitTimer = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n // Keep latest values in refs so control callbacks stay referentially stable.\n const stateRef = useRef({ steps, stepIndex, step, phase, onStepChange, onStart, onStop });\n stateRef.current = { steps, stepIndex, step, phase, onStepChange, onStart, onStop };\n\n useEffect(() => setMounted(true), []);\n useEffect(\n () => () => {\n if (exitTimer.current) clearTimeout(exitTimer.current);\n },\n []\n );\n\n const setIndex = useCallback(\n (index: number) => {\n const s = stateRef.current;\n const clamped = Math.max(0, Math.min(index, s.steps.length - 1));\n if (clamped === s.stepIndex) return;\n s.step?.onExit?.(s.step, s.stepIndex);\n if (!isControlled) setInternalIndex(clamped);\n s.onStepChange?.(clamped, s.steps[clamped]);\n },\n [isControlled]\n );\n\n const start = useCallback(\n (atIndex = 0) => {\n const s = stateRef.current;\n if (s.phase === \"active\" || s.steps.length === 0) return;\n if (exitTimer.current) clearTimeout(exitTimer.current);\n const clamped = Math.max(0, Math.min(atIndex, s.steps.length - 1));\n if (!isControlled) setInternalIndex(clamped);\n else s.onStepChange?.(clamped, s.steps[clamped]);\n setPhase(\"active\");\n s.onStart?.();\n },\n [isControlled]\n );\n\n const stop = useCallback((reason: TourStopReason = \"programmatic\") => {\n const s = stateRef.current;\n if (s.phase !== \"active\") return;\n s.step?.onExit?.(s.step, s.stepIndex);\n if (s.step) closingSnapshot.current = { step: s.step, stepIndex: s.stepIndex };\n setPhase(\"closing\");\n if (exitTimer.current) clearTimeout(exitTimer.current);\n exitTimer.current = setTimeout(() => {\n closingSnapshot.current = null;\n setPhase(\"idle\");\n }, EXIT_DURATION_MS);\n s.onStop?.(reason, s.stepIndex);\n }, []);\n\n const next = useCallback(() => {\n const s = stateRef.current;\n if (s.phase !== \"active\") return;\n if (s.stepIndex >= s.steps.length - 1) stop(\"finished\");\n else setIndex(s.stepIndex + 1);\n }, [setIndex, stop]);\n\n const prev = useCallback(() => {\n const s = stateRef.current;\n if (s.phase !== \"active\" || s.stepIndex <= 0) return;\n setIndex(s.stepIndex - 1);\n }, [setIndex]);\n\n const goTo = useCallback((index: number) => setIndex(index), [setIndex]);\n\n // Auto-start once mounted.\n const autoStartedRef = useRef(false);\n useEffect(() => {\n if (autoStart && mounted && !autoStartedRef.current) {\n autoStartedRef.current = true;\n start(0);\n }\n }, [autoStart, mounted, start]);\n\n // Step lifecycle: onEnter + scroll into view.\n useEffect(() => {\n if (!isActive || !step) return;\n step.onEnter?.(step, stepIndex);\n if (!step.disableScroll) {\n const el = resolveTarget(step);\n const reducedMotion =\n typeof window !== \"undefined\" &&\n window.matchMedia(\"(prefers-reduced-motion: reduce)\").matches;\n el?.scrollIntoView(\n reducedMotion ? { ...scrollIntoViewOptions, behavior: \"auto\" } : scrollIntoViewOptions\n );\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [isActive, stepIndex]);\n\n // Keyboard navigation.\n useEffect(() => {\n if (!isActive || !keyboard) return;\n const onKey = (e: KeyboardEvent) => {\n if (e.key === \"Escape\") stop(\"escape\");\n else if (e.key === \"ArrowRight\" || e.key === \"Enter\") next();\n else if (e.key === \"ArrowLeft\") prev();\n };\n window.addEventListener(\"keydown\", onKey);\n return () => window.removeEventListener(\"keydown\", onKey);\n }, [isActive, keyboard, next, prev, stop]);\n\n // Optional body scroll lock.\n useEffect(() => {\n if (!isActive || !lockScroll) return;\n const previous = document.body.style.overflow;\n document.body.style.overflow = \"hidden\";\n return () => {\n document.body.style.overflow = previous;\n };\n }, [isActive, lockScroll]);\n\n // While closing, keep rendering the last step so the fade-out has content.\n const renderStep = step ?? closingSnapshot.current?.step ?? null;\n const renderIndex = step ? stepIndex : closingSnapshot.current?.stepIndex ?? -1;\n const targetRect = useTargetRect(renderStep, phase !== \"idle\");\n\n const controls = useMemo<TourControls>(\n () => ({\n isActive,\n stepIndex,\n totalSteps: steps.length,\n step,\n isFirst: stepIndex <= 0,\n isLast: stepIndex === steps.length - 1,\n start,\n stop,\n next,\n prev,\n goTo,\n }),\n [isActive, stepIndex, steps.length, step, start, stop, next, prev, goTo]\n );\n\n const container =\n portalContainer ?? (typeof document !== \"undefined\" ? document.body : null);\n\n const zIndex = props.zIndex ?? 10000;\n const closing = phase === \"closing\";\n\n return (\n <TourContext.Provider value={controls}>\n {children}\n {mounted &&\n container &&\n phase !== \"idle\" &&\n renderStep &&\n createPortal(\n <TourLayer\n closing={closing}\n zIndex={zIndex}\n className={props.classNames?.root}\n theme={props.theme}\n >\n {(props.showOverlay ?? true) && (\n <TourOverlay\n rect={targetRect}\n step={renderStep}\n interactive={!closing}\n padding={renderStep.spotlightPadding ?? props.spotlightPadding ?? 8}\n radius={renderStep.spotlightRadius ?? props.spotlightRadius ?? 8}\n color={props.overlayColor}\n blur={props.overlayBlur ?? 0}\n className={props.classNames?.overlay}\n onMaskClick={props.closeOnMaskClick ? () => stop(\"mask\") : undefined}\n />\n )}\n <TourPopover\n key={renderIndex}\n rect={targetRect}\n controls={controls}\n step={renderStep}\n interactive={!closing}\n offset={props.offset ?? 12}\n padding={renderStep.spotlightPadding ?? props.spotlightPadding ?? 8}\n components={props.components}\n classNames={props.classNames}\n labels={props.labels}\n />\n </TourLayer>,\n container\n )}\n </TourContext.Provider>\n );\n}\n","import { useEffect, useState } from \"react\";\n\n/** Spring-like easing for movement (slight decelerating overshoot). */\nexport const EASE_SPRING = \"cubic-bezier(0.22, 1, 0.36, 1)\";\n\n/**\n * False on first paint, true one frame later — lets CSS transitions animate\n * an element from its \"initial\" styles to its \"entered\" styles on mount.\n */\nexport function useEntered(): boolean {\n const [entered, setEntered] = useState(false);\n useEffect(() => {\n let inner = 0;\n const outer = requestAnimationFrame(() => {\n inner = requestAnimationFrame(() => setEntered(true));\n });\n return () => {\n cancelAnimationFrame(outer);\n cancelAnimationFrame(inner);\n };\n }, []);\n return entered;\n}\n\n/**\n * True while any scrolling is happening (window or nested containers),\n * falling back to false after `idleMs` without a scroll event. Used to make\n * the spotlight track its target 1:1 during scrolls instead of transitioning\n * toward a moving destination.\n */\nexport function useIsScrolling(idleMs = 150): boolean {\n const [scrolling, setScrolling] = useState(false);\n useEffect(() => {\n let timer: ReturnType<typeof setTimeout> | null = null;\n const onScroll = () => {\n setScrolling(true);\n if (timer) clearTimeout(timer);\n timer = setTimeout(() => setScrolling(false), idleMs);\n };\n window.addEventListener(\"scroll\", onScroll, { capture: true, passive: true });\n return () => {\n window.removeEventListener(\"scroll\", onScroll, { capture: true });\n if (timer) clearTimeout(timer);\n };\n }, [idleMs]);\n return scrolling;\n}\n\n/** Tracks the user's prefers-reduced-motion setting (SSR-safe, live-updating). */\nexport function useReducedMotion(): boolean {\n const [reduced, setReduced] = useState(false);\n useEffect(() => {\n const mq = window.matchMedia(\"(prefers-reduced-motion: reduce)\");\n setReduced(mq.matches);\n const onChange = (e: MediaQueryListEvent) => setReduced(e.matches);\n mq.addEventListener(\"change\", onChange);\n return () => mq.removeEventListener(\"change\", onChange);\n }, []);\n return reduced;\n}\n","import { useEffect, useState } from \"react\";\nimport type { TargetRect, TourStep } from \"./types\";\n\nexport function resolveTarget(step: TourStep | null): Element | null {\n if (!step?.target) return null;\n if (typeof step.target === \"function\") return step.target();\n if (typeof document === \"undefined\") return null;\n return document.querySelector(step.target);\n}\n\nfunction readRect(el: Element): TargetRect {\n const r = el.getBoundingClientRect();\n return { x: r.left, y: r.top, width: r.width, height: r.height };\n}\n\nfunction rectsEqual(a: TargetRect | null, b: TargetRect | null) {\n if (a === b) return true;\n if (!a || !b) return false;\n return a.x === b.x && a.y === b.y && a.width === b.width && a.height === b.height;\n}\n\n/**\n * Tracks the viewport-relative rect of the active step's target, staying in\n * sync through scrolling, window resizes, element resizes and layout shifts.\n */\nexport function useTargetRect(step: TourStep | null, active: boolean): TargetRect | null {\n const [rect, setRect] = useState<TargetRect | null>(null);\n\n useEffect(() => {\n if (!active || !step) {\n setRect(null);\n return;\n }\n\n let el = resolveTarget(step);\n let frame = 0;\n let current: TargetRect | null = null;\n\n const update = () => {\n // Re-resolve in case the element mounted late (e.g. after a route change).\n if (!el || !el.isConnected) el = resolveTarget(step);\n const next = el ? readRect(el) : null;\n if (!rectsEqual(current, next)) {\n current = next;\n setRect(next);\n }\n };\n\n // A light rAF loop is the only approach that survives every way an element\n // can move (animations, sticky headers, virtualized lists, font loading).\n const tick = () => {\n update();\n frame = requestAnimationFrame(tick);\n };\n frame = requestAnimationFrame(tick);\n update();\n\n return () => cancelAnimationFrame(frame);\n }, [step, active]);\n\n return rect;\n}\n","import { useId } from \"react\";\nimport { EASE_SPRING, useIsScrolling, useReducedMotion } from \"./motion\";\nimport type { TargetRect, TourStep } from \"./types\";\n\ninterface TourOverlayProps {\n rect: TargetRect | null;\n step: TourStep;\n /** False while the tour is fading out — blockers must stop eating clicks. */\n interactive: boolean;\n padding: number;\n radius: number;\n color?: string;\n blur: number;\n className?: string;\n onMaskClick?: () => void;\n}\n\n/**\n * Dimming overlay with an animated spotlight \"hole\" cut out via an SVG mask.\n * The hole glides smoothly between targets as steps change (CSS transitions\n * on the SVG geometry properties — no animation library needed).\n */\nexport function TourOverlay({\n rect,\n step,\n interactive,\n padding,\n radius,\n color,\n blur,\n className,\n onMaskClick,\n}: TourOverlayProps) {\n const maskId = useId();\n const reducedMotion = useReducedMotion();\n const scrolling = useIsScrolling();\n\n const hole = rect\n ? {\n x: rect.x - padding,\n y: rect.y - padding,\n width: rect.width + padding * 2,\n height: rect.height + padding * 2,\n }\n : null;\n\n const fill = color ?? \"var(--tour-overlay-color, rgba(0, 0, 0, 0.55))\";\n const interactable = Boolean(step.interactable && hole);\n\n // While the page scrolls (auto scroll-into-view or the user's own), the\n // hole must stick to the target exactly — transitioning toward a moving\n // destination reads as lag. The glide only plays for stationary changes.\n const holeTransition =\n reducedMotion || scrolling\n ? undefined\n : [\"x\", \"y\", \"width\", \"height\", \"rx\"].map((p) => `${p} 350ms ${EASE_SPRING}`).join(\", \");\n\n const blockerStyle: React.CSSProperties = {\n position: \"absolute\",\n pointerEvents: interactive ? \"auto\" : \"none\",\n cursor: onMaskClick ? \"pointer\" : \"default\",\n };\n\n return (\n <div\n data-tour-overlay=\"\"\n className={className}\n style={{ position: \"absolute\", inset: 0, pointerEvents: \"none\" }}\n >\n <svg\n width=\"100%\"\n height=\"100%\"\n style={{\n position: \"absolute\",\n inset: 0,\n backdropFilter: blur ? `blur(${blur}px)` : undefined,\n WebkitBackdropFilter: blur ? `blur(${blur}px)` : undefined,\n }}\n aria-hidden=\"true\"\n >\n <defs>\n <mask id={maskId}>\n <rect x=\"0\" y=\"0\" width=\"100%\" height=\"100%\" fill=\"#fff\" />\n {hole && (\n <rect\n x={hole.x}\n y={hole.y}\n width={hole.width}\n height={hole.height}\n rx={radius}\n fill=\"#000\"\n style={{ transition: holeTransition }}\n />\n )}\n </mask>\n </defs>\n <rect x=\"0\" y=\"0\" width=\"100%\" height=\"100%\" fill={fill} mask={`url(#${maskId})`} />\n </svg>\n\n {/* Click interception. When the step is interactable we block only the\n dimmed region (four rects around the hole), leaving the target live. */}\n {interactable && hole ? (\n <>\n <div style={{ ...blockerStyle, left: 0, top: 0, right: 0, height: Math.max(0, hole.y) }} onClick={onMaskClick} />\n <div style={{ ...blockerStyle, left: 0, top: hole.y + hole.height, right: 0, bottom: 0 }} onClick={onMaskClick} />\n <div style={{ ...blockerStyle, left: 0, top: hole.y, width: Math.max(0, hole.x), height: hole.height }} onClick={onMaskClick} />\n <div style={{ ...blockerStyle, left: hole.x + hole.width, top: hole.y, right: 0, height: hole.height }} onClick={onMaskClick} />\n </>\n ) : (\n <div style={{ ...blockerStyle, inset: 0 }} onClick={onMaskClick} />\n )}\n </div>\n );\n}\n","import { useEffect, useMemo, useRef, useState } from \"react\";\nimport {\n arrow,\n autoUpdate,\n flip,\n offset,\n shift,\n size,\n useFloating,\n} from \"@floating-ui/react-dom\";\nimport { EASE_SPRING, useEntered, useReducedMotion } from \"./motion\";\nimport type {\n TargetRect,\n TourCardProps,\n TourClassNames,\n TourComponents,\n TourControls,\n TourProviderProps,\n TourStep,\n} from \"./types\";\nimport { DefaultCard } from \"./DefaultCard\";\n\ninterface TourPopoverProps {\n rect: TargetRect | null;\n step: TourStep;\n controls: TourControls;\n /** False while the tour is fading out. */\n interactive: boolean;\n offset: number;\n padding: number;\n components?: TourComponents;\n classNames?: TourClassNames;\n labels?: TourProviderProps[\"labels\"];\n}\n\nexport function TourPopover({\n rect,\n step,\n controls,\n interactive,\n offset: offsetDistance,\n padding,\n components,\n classNames,\n labels,\n}: TourPopoverProps) {\n const arrowRef = useRef<HTMLDivElement | null>(null);\n const popoverRef = useRef<HTMLDivElement | null>(null);\n const hasTarget = Boolean(rect);\n // Enter animation: this component remounts per step (keyed by index), so\n // `entered` flips false → true on every step change.\n const entered = useEntered();\n const reducedMotion = useReducedMotion();\n\n // Move focus into the popover on each step so screen readers announce it\n // and keyboard users can reach its controls immediately.\n useEffect(() => {\n if (interactive) popoverRef.current?.focus({ preventScroll: true });\n }, [interactive]);\n // Space actually available for the popover, kept in sync by the size()\n // middleware so large targets / small viewports can't push the card\n // off-screen.\n const [maxSize, setMaxSize] = useState<{ width: number; height: number } | null>(null);\n const maxSizeRef = useRef(maxSize);\n maxSizeRef.current = maxSize;\n\n const { refs, floatingStyles, middlewareData, placement, update, isPositioned } = useFloating({\n placement: step.placement ?? \"bottom\",\n strategy: \"fixed\",\n whileElementsMounted: autoUpdate,\n middleware: [\n offset(offsetDistance + padding),\n // If neither side of the preferred axis fits (e.g. a full-width target\n // with placement \"right\"), try the other axis too.\n flip({ padding: 12, fallbackAxisSideDirection: \"start\" }),\n // crossAxis lets shift pull the popover back into view even when that\n // means overlapping a large target.\n shift({ padding: 12, crossAxis: true }),\n size({\n padding: 12,\n apply({ availableWidth, availableHeight }) {\n const next = {\n width: Math.max(120, Math.floor(availableWidth)),\n height: Math.max(80, Math.floor(availableHeight)),\n };\n const current = maxSizeRef.current;\n if (!current || Math.abs(current.width - next.width) > 1 || Math.abs(current.height - next.height) > 1) {\n setMaxSize(next);\n }\n },\n }),\n arrow({ element: arrowRef, padding: 12 }),\n ],\n });\n\n // Anchor floating-ui to the tracked rect via a virtual element.\n useEffect(() => {\n if (!rect) return;\n refs.setReference({\n getBoundingClientRect: () => ({\n x: rect.x,\n y: rect.y,\n width: rect.width,\n height: rect.height,\n top: rect.y,\n left: rect.x,\n right: rect.x + rect.width,\n bottom: rect.y + rect.height,\n }),\n });\n update();\n }, [rect, refs, update]);\n\n const side = placement.split(\"-\")[0] as \"top\" | \"bottom\" | \"left\" | \"right\";\n\n const arrowNode = useMemo(() => {\n if (!hasTarget) return null;\n const { x, y } = middlewareData.arrow ?? {};\n const staticSide = { top: \"bottom\", bottom: \"top\", left: \"right\", right: \"left\" }[side];\n const ArrowComponent = components?.Arrow;\n return (\n <div\n ref={arrowRef}\n data-tour-arrow=\"\"\n className={classNames?.arrow}\n style={{\n position: \"absolute\",\n left: x != null ? x : undefined,\n top: y != null ? y : undefined,\n [staticSide]: \"calc(var(--tour-arrow-size, 12px) / -2)\",\n pointerEvents: \"none\",\n }}\n >\n {ArrowComponent ? (\n <ArrowComponent side={side} />\n ) : (\n <div\n style={{\n width: \"var(--tour-arrow-size, 12px)\",\n height: \"var(--tour-arrow-size, 12px)\",\n transform: \"rotate(45deg)\",\n background: \"var(--tour-bg, #ffffff)\",\n borderRadius: 2,\n }}\n />\n )}\n </div>\n );\n }, [hasTarget, middlewareData.arrow, side, components?.Arrow, classNames?.arrow]);\n\n const CustomCard = components?.Card;\n const cardProps: TourCardProps = { ...controls, step, arrow: arrowNode };\n\n const positionStyles: React.CSSProperties = hasTarget\n ? floatingStyles\n : {\n position: \"fixed\",\n top: \"50%\",\n left: \"50%\",\n transform: \"translate(-50%, -50%)\",\n };\n\n return (\n <div\n ref={(node) => {\n refs.setFloating(node);\n popoverRef.current = node;\n }}\n tabIndex={-1}\n data-tour-popover=\"\"\n className={classNames?.popover}\n style={{\n ...positionStyles,\n // Never paint before Floating UI has computed a real position — a\n // freshly mounted popover would otherwise flash at a stale spot.\n visibility: hasTarget && !isPositioned ? \"hidden\" : undefined,\n pointerEvents: interactive ? \"auto\" : \"none\",\n maxWidth: hasTarget && maxSize ? Math.min(maxSize.width, window.innerWidth - 24) : \"calc(100vw - 24px)\",\n maxHeight: hasTarget && maxSize ? maxSize.height : \"calc(100vh - 24px)\",\n overflowY: \"auto\",\n }}\n role=\"dialog\"\n aria-modal=\"false\"\n aria-label={`Tour step ${controls.stepIndex + 1} of ${controls.totalSteps}${\n typeof step.title === \"string\" ? `: ${step.title}` : \"\"\n }`}\n >\n <div\n style={{\n opacity: entered ? 1 : 0,\n transform: entered\n ? \"none\"\n : `scale(0.96) translateY(${side === \"top\" ? 6 : -6}px)`,\n transition: reducedMotion\n ? undefined\n : `opacity 200ms ease, transform 250ms ${EASE_SPRING}`,\n }}\n >\n {CustomCard ? (\n <CustomCard {...cardProps} />\n ) : (\n <DefaultCard {...cardProps} labels={labels} classNames={classNames} />\n )}\n </div>\n </div>\n );\n}\n","import type { CSSProperties } from \"react\";\nimport type { TourCardProps, TourClassNames, TourProviderProps } from \"./types\";\n\n/**\n * The zero-config default card. Every visual decision is a CSS variable with a\n * neutral fallback, so it can be re-themed without touching a line of code:\n *\n * --tour-bg, --tour-fg, --tour-muted, --tour-accent, --tour-accent-fg,\n * --tour-radius, --tour-shadow, --tour-border, --tour-font,\n * --tour-max-width, --tour-padding, --tour-arrow-size\n *\n * For full control, replace it entirely via <TourProvider components={{ Card }}>.\n */\nexport function DefaultCard(\n props: TourCardProps & {\n labels?: TourProviderProps[\"labels\"];\n classNames?: TourClassNames;\n }\n) {\n const { step, stepIndex, totalSteps, isFirst, isLast, next, prev, stop, arrow, labels, classNames } = props;\n\n const buttonBase: CSSProperties = {\n font: \"inherit\",\n fontSize: \"0.875em\",\n fontWeight: 500,\n border: \"var(--tour-border, 1px solid rgba(0,0,0,0.12))\",\n borderRadius: \"calc(var(--tour-radius, 12px) * 0.6)\",\n padding: \"0.45em 0.9em\",\n cursor: \"pointer\",\n background: \"transparent\",\n color: \"inherit\",\n };\n\n return (\n <div\n data-tour-card=\"\"\n className={classNames?.card}\n style={{\n position: \"relative\",\n background: \"var(--tour-bg, #ffffff)\",\n color: \"var(--tour-fg, #1a1a1a)\",\n fontFamily: \"var(--tour-font, inherit)\",\n borderRadius: \"var(--tour-radius, 12px)\",\n boxShadow: \"var(--tour-shadow, 0 10px 38px -10px rgba(0,0,0,0.35), 0 10px 20px -15px rgba(0,0,0,0.2))\",\n padding: \"var(--tour-padding, 16px)\",\n width: \"max-content\",\n maxWidth: \"min(var(--tour-max-width, 320px), 100%)\",\n boxSizing: \"border-box\",\n }}\n >\n {arrow}\n {step.title != null && (\n <div\n data-tour-title=\"\"\n className={classNames?.title}\n style={{ fontWeight: 600, fontSize: \"1em\", marginBottom: 6 }}\n >\n {step.title}\n </div>\n )}\n {step.content != null && (\n <div\n data-tour-content=\"\"\n className={classNames?.content}\n style={{ fontSize: \"0.9em\", lineHeight: 1.5, color: \"var(--tour-muted, #555)\" }}\n >\n {step.content}\n </div>\n )}\n <div\n data-tour-footer=\"\"\n className={classNames?.footer}\n style={{ display: \"flex\", alignItems: \"center\", gap: 8, marginTop: 14 }}\n >\n <span\n data-tour-progress=\"\"\n className={classNames?.progress}\n style={{ fontSize: \"0.8em\", color: \"var(--tour-muted, #888)\", marginRight: \"auto\" }}\n >\n {labels?.progress ? labels.progress(stepIndex, totalSteps) : `${stepIndex + 1} / ${totalSteps}`}\n </span>\n <button\n type=\"button\"\n data-tour-skip=\"\"\n className={classNames?.skipButton}\n onClick={() => stop(\"skipped\")}\n style={{ ...buttonBase, border: \"none\", color: \"var(--tour-muted, #888)\" }}\n >\n {labels?.skip ?? \"Skip\"}\n </button>\n {!isFirst && (\n <button\n type=\"button\"\n data-tour-prev=\"\"\n className={classNames?.navButton}\n onClick={prev}\n style={buttonBase}\n >\n {labels?.prev ?? \"Back\"}\n </button>\n )}\n <button\n type=\"button\"\n data-tour-next=\"\"\n className={classNames?.primaryButton}\n onClick={next}\n style={{\n ...buttonBase,\n border: \"none\",\n background: \"var(--tour-accent, #1a1a1a)\",\n color: \"var(--tour-accent-fg, #ffffff)\",\n }}\n >\n {isLast ? labels?.finish ?? \"Finish\" : labels?.next ?? \"Next\"}\n </button>\n </div>\n </div>\n );\n}\n"],"mappings":";;;AAAA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA,aAAAA;AAAA,EACA,WAAAC;AAAA,EACA,UAAAC;AAAA,EACA,YAAAC;AAAA,OAGK;AACP,SAAS,oBAAoB;;;ACX7B,SAAS,WAAW,gBAAgB;AAG7B,IAAM,cAAc;AAMpB,SAAS,aAAsB;AACpC,QAAM,CAAC,SAAS,UAAU,IAAI,SAAS,KAAK;AAC5C,YAAU,MAAM;AACd,QAAI,QAAQ;AACZ,UAAM,QAAQ,sBAAsB,MAAM;AACxC,cAAQ,sBAAsB,MAAM,WAAW,IAAI,CAAC;AAAA,IACtD,CAAC;AACD,WAAO,MAAM;AACX,2BAAqB,KAAK;AAC1B,2BAAqB,KAAK;AAAA,IAC5B;AAAA,EACF,GAAG,CAAC,CAAC;AACL,SAAO;AACT;AAQO,SAAS,eAAe,SAAS,KAAc;AACpD,QAAM,CAAC,WAAW,YAAY,IAAI,SAAS,KAAK;AAChD,YAAU,MAAM;AACd,QAAI,QAA8C;AAClD,UAAM,WAAW,MAAM;AACrB,mBAAa,IAAI;AACjB,UAAI,MAAO,cAAa,KAAK;AAC7B,cAAQ,WAAW,MAAM,aAAa,KAAK,GAAG,MAAM;AAAA,IACtD;AACA,WAAO,iBAAiB,UAAU,UAAU,EAAE,SAAS,MAAM,SAAS,KAAK,CAAC;AAC5E,WAAO,MAAM;AACX,aAAO,oBAAoB,UAAU,UAAU,EAAE,SAAS,KAAK,CAAC;AAChE,UAAI,MAAO,cAAa,KAAK;AAAA,IAC/B;AAAA,EACF,GAAG,CAAC,MAAM,CAAC;AACX,SAAO;AACT;AAGO,SAAS,mBAA4B;AAC1C,QAAM,CAAC,SAAS,UAAU,IAAI,SAAS,KAAK;AAC5C,YAAU,MAAM;AACd,UAAM,KAAK,OAAO,WAAW,kCAAkC;AAC/D,eAAW,GAAG,OAAO;AACrB,UAAM,WAAW,CAAC,MAA2B,WAAW,EAAE,OAAO;AACjE,OAAG,iBAAiB,UAAU,QAAQ;AACtC,WAAO,MAAM,GAAG,oBAAoB,UAAU,QAAQ;AAAA,EACxD,GAAG,CAAC,CAAC;AACL,SAAO;AACT;;;AC3DA,SAAS,aAAAC,YAAW,YAAAC,iBAAgB;AAG7B,SAAS,cAAc,MAAuC;AACnE,MAAI,CAAC,MAAM,OAAQ,QAAO;AAC1B,MAAI,OAAO,KAAK,WAAW,WAAY,QAAO,KAAK,OAAO;AAC1D,MAAI,OAAO,aAAa,YAAa,QAAO;AAC5C,SAAO,SAAS,cAAc,KAAK,MAAM;AAC3C;AAEA,SAAS,SAAS,IAAyB;AACzC,QAAM,IAAI,GAAG,sBAAsB;AACnC,SAAO,EAAE,GAAG,EAAE,MAAM,GAAG,EAAE,KAAK,OAAO,EAAE,OAAO,QAAQ,EAAE,OAAO;AACjE;AAEA,SAAS,WAAW,GAAsB,GAAsB;AAC9D,MAAI,MAAM,EAAG,QAAO;AACpB,MAAI,CAAC,KAAK,CAAC,EAAG,QAAO;AACrB,SAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,WAAW,EAAE;AAC7E;AAMO,SAAS,cAAc,MAAuB,QAAoC;AACvF,QAAM,CAAC,MAAM,OAAO,IAAIA,UAA4B,IAAI;AAExD,EAAAD,WAAU,MAAM;AACd,QAAI,CAAC,UAAU,CAAC,MAAM;AACpB,cAAQ,IAAI;AACZ;AAAA,IACF;AAEA,QAAI,KAAK,cAAc,IAAI;AAC3B,QAAI,QAAQ;AACZ,QAAI,UAA6B;AAEjC,UAAM,SAAS,MAAM;AAEnB,UAAI,CAAC,MAAM,CAAC,GAAG,YAAa,MAAK,cAAc,IAAI;AACnD,YAAM,OAAO,KAAK,SAAS,EAAE,IAAI;AACjC,UAAI,CAAC,WAAW,SAAS,IAAI,GAAG;AAC9B,kBAAU;AACV,gBAAQ,IAAI;AAAA,MACd;AAAA,IACF;AAIA,UAAM,OAAO,MAAM;AACjB,aAAO;AACP,cAAQ,sBAAsB,IAAI;AAAA,IACpC;AACA,YAAQ,sBAAsB,IAAI;AAClC,WAAO;AAEP,WAAO,MAAM,qBAAqB,KAAK;AAAA,EACzC,GAAG,CAAC,MAAM,MAAM,CAAC;AAEjB,SAAO;AACT;;;AC7DA,SAAS,aAAa;AAiFZ,SAqBF,UApBI,KADF;AA3DH,SAAS,YAAY;AAAA,EAC1B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAqB;AACnB,QAAM,SAAS,MAAM;AACrB,QAAM,gBAAgB,iBAAiB;AACvC,QAAM,YAAY,eAAe;AAEjC,QAAM,OAAO,OACT;AAAA,IACE,GAAG,KAAK,IAAI;AAAA,IACZ,GAAG,KAAK,IAAI;AAAA,IACZ,OAAO,KAAK,QAAQ,UAAU;AAAA,IAC9B,QAAQ,KAAK,SAAS,UAAU;AAAA,EAClC,IACA;AAEJ,QAAM,OAAO,SAAS;AACtB,QAAM,eAAe,QAAQ,KAAK,gBAAgB,IAAI;AAKtD,QAAM,iBACJ,iBAAiB,YACb,SACA,CAAC,KAAK,KAAK,SAAS,UAAU,IAAI,EAAE,IAAI,CAAC,MAAM,GAAG,CAAC,UAAU,WAAW,EAAE,EAAE,KAAK,IAAI;AAE3F,QAAM,eAAoC;AAAA,IACxC,UAAU;AAAA,IACV,eAAe,cAAc,SAAS;AAAA,IACtC,QAAQ,cAAc,YAAY;AAAA,EACpC;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC,qBAAkB;AAAA,MAClB;AAAA,MACA,OAAO,EAAE,UAAU,YAAY,OAAO,GAAG,eAAe,OAAO;AAAA,MAE/D;AAAA;AAAA,UAAC;AAAA;AAAA,YACC,OAAM;AAAA,YACN,QAAO;AAAA,YACP,OAAO;AAAA,cACL,UAAU;AAAA,cACV,OAAO;AAAA,cACP,gBAAgB,OAAO,QAAQ,IAAI,QAAQ;AAAA,cAC3C,sBAAsB,OAAO,QAAQ,IAAI,QAAQ;AAAA,YACnD;AAAA,YACA,eAAY;AAAA,YAEZ;AAAA,kCAAC,UACC,+BAAC,UAAK,IAAI,QACR;AAAA,oCAAC,UAAK,GAAE,KAAI,GAAE,KAAI,OAAM,QAAO,QAAO,QAAO,MAAK,QAAO;AAAA,gBACxD,QACC;AAAA,kBAAC;AAAA;AAAA,oBACC,GAAG,KAAK;AAAA,oBACR,GAAG,KAAK;AAAA,oBACR,OAAO,KAAK;AAAA,oBACZ,QAAQ,KAAK;AAAA,oBACb,IAAI;AAAA,oBACJ,MAAK;AAAA,oBACL,OAAO,EAAE,YAAY,eAAe;AAAA;AAAA,gBACtC;AAAA,iBAEJ,GACF;AAAA,cACA,oBAAC,UAAK,GAAE,KAAI,GAAE,KAAI,OAAM,QAAO,QAAO,QAAO,MAAY,MAAM,QAAQ,MAAM,KAAK;AAAA;AAAA;AAAA,QACpF;AAAA,QAIC,gBAAgB,OACf,iCACE;AAAA,8BAAC,SAAI,OAAO,EAAE,GAAG,cAAc,MAAM,GAAG,KAAK,GAAG,OAAO,GAAG,QAAQ,KAAK,IAAI,GAAG,KAAK,CAAC,EAAE,GAAG,SAAS,aAAa;AAAA,UAC/G,oBAAC,SAAI,OAAO,EAAE,GAAG,cAAc,MAAM,GAAG,KAAK,KAAK,IAAI,KAAK,QAAQ,OAAO,GAAG,QAAQ,EAAE,GAAG,SAAS,aAAa;AAAA,UAChH,oBAAC,SAAI,OAAO,EAAE,GAAG,cAAc,MAAM,GAAG,KAAK,KAAK,GAAG,OAAO,KAAK,IAAI,GAAG,KAAK,CAAC,GAAG,QAAQ,KAAK,OAAO,GAAG,SAAS,aAAa;AAAA,UAC9H,oBAAC,SAAI,OAAO,EAAE,GAAG,cAAc,MAAM,KAAK,IAAI,KAAK,OAAO,KAAK,KAAK,GAAG,OAAO,GAAG,QAAQ,KAAK,OAAO,GAAG,SAAS,aAAa;AAAA,WAChI,IAEA,oBAAC,SAAI,OAAO,EAAE,GAAG,cAAc,OAAO,EAAE,GAAG,SAAS,aAAa;AAAA;AAAA;AAAA,EAErE;AAEJ;;;ACjHA,SAAS,aAAAE,YAAW,SAAS,QAAQ,YAAAC,iBAAgB;AACrD;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;;;AC2CC,gBAAAC,MAiBF,QAAAC,aAjBE;AAvCD,SAAS,YACd,OAIA;AACA,QAAM,EAAE,MAAM,WAAW,YAAY,SAAS,QAAQ,MAAM,MAAM,MAAM,OAAAC,QAAO,QAAQ,WAAW,IAAI;AAEtG,QAAM,aAA4B;AAAA,IAChC,MAAM;AAAA,IACN,UAAU;AAAA,IACV,YAAY;AAAA,IACZ,QAAQ;AAAA,IACR,cAAc;AAAA,IACd,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,YAAY;AAAA,IACZ,OAAO;AAAA,EACT;AAEA,SACE,gBAAAD;AAAA,IAAC;AAAA;AAAA,MACC,kBAAe;AAAA,MACf,WAAW,YAAY;AAAA,MACvB,OAAO;AAAA,QACL,UAAU;AAAA,QACV,YAAY;AAAA,QACZ,OAAO;AAAA,QACP,YAAY;AAAA,QACZ,cAAc;AAAA,QACd,WAAW;AAAA,QACX,SAAS;AAAA,QACT,OAAO;AAAA,QACP,UAAU;AAAA,QACV,WAAW;AAAA,MACb;AAAA,MAEC;AAAA,QAAAC;AAAA,QACA,KAAK,SAAS,QACb,gBAAAF;AAAA,UAAC;AAAA;AAAA,YACC,mBAAgB;AAAA,YAChB,WAAW,YAAY;AAAA,YACvB,OAAO,EAAE,YAAY,KAAK,UAAU,OAAO,cAAc,EAAE;AAAA,YAE1D,eAAK;AAAA;AAAA,QACR;AAAA,QAED,KAAK,WAAW,QACf,gBAAAA;AAAA,UAAC;AAAA;AAAA,YACC,qBAAkB;AAAA,YAClB,WAAW,YAAY;AAAA,YACvB,OAAO,EAAE,UAAU,SAAS,YAAY,KAAK,OAAO,0BAA0B;AAAA,YAE7E,eAAK;AAAA;AAAA,QACR;AAAA,QAEF,gBAAAC;AAAA,UAAC;AAAA;AAAA,YACC,oBAAiB;AAAA,YACjB,WAAW,YAAY;AAAA,YACvB,OAAO,EAAE,SAAS,QAAQ,YAAY,UAAU,KAAK,GAAG,WAAW,GAAG;AAAA,YAEtE;AAAA,8BAAAD;AAAA,gBAAC;AAAA;AAAA,kBACC,sBAAmB;AAAA,kBACnB,WAAW,YAAY;AAAA,kBACvB,OAAO,EAAE,UAAU,SAAS,OAAO,2BAA2B,aAAa,OAAO;AAAA,kBAEjF,kBAAQ,WAAW,OAAO,SAAS,WAAW,UAAU,IAAI,GAAG,YAAY,CAAC,MAAM,UAAU;AAAA;AAAA,cAC/F;AAAA,cACA,gBAAAA;AAAA,gBAAC;AAAA;AAAA,kBACC,MAAK;AAAA,kBACL,kBAAe;AAAA,kBACf,WAAW,YAAY;AAAA,kBACvB,SAAS,MAAM,KAAK,SAAS;AAAA,kBAC7B,OAAO,EAAE,GAAG,YAAY,QAAQ,QAAQ,OAAO,0BAA0B;AAAA,kBAExE,kBAAQ,QAAQ;AAAA;AAAA,cACnB;AAAA,cACC,CAAC,WACA,gBAAAA;AAAA,gBAAC;AAAA;AAAA,kBACC,MAAK;AAAA,kBACL,kBAAe;AAAA,kBACf,WAAW,YAAY;AAAA,kBACvB,SAAS;AAAA,kBACT,OAAO;AAAA,kBAEN,kBAAQ,QAAQ;AAAA;AAAA,cACnB;AAAA,cAEF,gBAAAA;AAAA,gBAAC;AAAA;AAAA,kBACC,MAAK;AAAA,kBACL,kBAAe;AAAA,kBACf,WAAW,YAAY;AAAA,kBACvB,SAAS;AAAA,kBACT,OAAO;AAAA,oBACL,GAAG;AAAA,oBACH,QAAQ;AAAA,oBACR,YAAY;AAAA,oBACZ,OAAO;AAAA,kBACT;AAAA,kBAEC,mBAAS,QAAQ,UAAU,WAAW,QAAQ,QAAQ;AAAA;AAAA,cACzD;AAAA;AAAA;AAAA,QACF;AAAA;AAAA;AAAA,EACF;AAEJ;;;ADgBU,gBAAAG,YAAA;AAnGH,SAAS,YAAY;AAAA,EAC1B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,QAAQ;AAAA,EACR;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAqB;AACnB,QAAM,WAAW,OAA8B,IAAI;AACnD,QAAM,aAAa,OAA8B,IAAI;AACrD,QAAM,YAAY,QAAQ,IAAI;AAG9B,QAAM,UAAU,WAAW;AAC3B,QAAM,gBAAgB,iBAAiB;AAIvC,EAAAC,WAAU,MAAM;AACd,QAAI,YAAa,YAAW,SAAS,MAAM,EAAE,eAAe,KAAK,CAAC;AAAA,EACpE,GAAG,CAAC,WAAW,CAAC;AAIhB,QAAM,CAAC,SAAS,UAAU,IAAIC,UAAmD,IAAI;AACrF,QAAM,aAAa,OAAO,OAAO;AACjC,aAAW,UAAU;AAErB,QAAM,EAAE,MAAM,gBAAgB,gBAAgB,WAAW,QAAQ,aAAa,IAAI,YAAY;AAAA,IAC5F,WAAW,KAAK,aAAa;AAAA,IAC7B,UAAU;AAAA,IACV,sBAAsB;AAAA,IACtB,YAAY;AAAA,MACV,OAAO,iBAAiB,OAAO;AAAA;AAAA;AAAA,MAG/B,KAAK,EAAE,SAAS,IAAI,2BAA2B,QAAQ,CAAC;AAAA;AAAA;AAAA,MAGxD,MAAM,EAAE,SAAS,IAAI,WAAW,KAAK,CAAC;AAAA,MACtC,KAAK;AAAA,QACH,SAAS;AAAA,QACT,MAAM,EAAE,gBAAgB,gBAAgB,GAAG;AACzC,gBAAM,OAAO;AAAA,YACX,OAAO,KAAK,IAAI,KAAK,KAAK,MAAM,cAAc,CAAC;AAAA,YAC/C,QAAQ,KAAK,IAAI,IAAI,KAAK,MAAM,eAAe,CAAC;AAAA,UAClD;AACA,gBAAM,UAAU,WAAW;AAC3B,cAAI,CAAC,WAAW,KAAK,IAAI,QAAQ,QAAQ,KAAK,KAAK,IAAI,KAAK,KAAK,IAAI,QAAQ,SAAS,KAAK,MAAM,IAAI,GAAG;AACtG,uBAAW,IAAI;AAAA,UACjB;AAAA,QACF;AAAA,MACF,CAAC;AAAA,MACD,MAAM,EAAE,SAAS,UAAU,SAAS,GAAG,CAAC;AAAA,IAC1C;AAAA,EACF,CAAC;AAGD,EAAAD,WAAU,MAAM;AACd,QAAI,CAAC,KAAM;AACX,SAAK,aAAa;AAAA,MAChB,uBAAuB,OAAO;AAAA,QAC5B,GAAG,KAAK;AAAA,QACR,GAAG,KAAK;AAAA,QACR,OAAO,KAAK;AAAA,QACZ,QAAQ,KAAK;AAAA,QACb,KAAK,KAAK;AAAA,QACV,MAAM,KAAK;AAAA,QACX,OAAO,KAAK,IAAI,KAAK;AAAA,QACrB,QAAQ,KAAK,IAAI,KAAK;AAAA,MACxB;AAAA,IACF,CAAC;AACD,WAAO;AAAA,EACT,GAAG,CAAC,MAAM,MAAM,MAAM,CAAC;AAEvB,QAAM,OAAO,UAAU,MAAM,GAAG,EAAE,CAAC;AAEnC,QAAM,YAAY,QAAQ,MAAM;AAC9B,QAAI,CAAC,UAAW,QAAO;AACvB,UAAM,EAAE,GAAG,EAAE,IAAI,eAAe,SAAS,CAAC;AAC1C,UAAM,aAAa,EAAE,KAAK,UAAU,QAAQ,OAAO,MAAM,SAAS,OAAO,OAAO,EAAE,IAAI;AACtF,UAAM,iBAAiB,YAAY;AACnC,WACE,gBAAAD;AAAA,MAAC;AAAA;AAAA,QACC,KAAK;AAAA,QACL,mBAAgB;AAAA,QAChB,WAAW,YAAY;AAAA,QACvB,OAAO;AAAA,UACL,UAAU;AAAA,UACV,MAAM,KAAK,OAAO,IAAI;AAAA,UACtB,KAAK,KAAK,OAAO,IAAI;AAAA,UACrB,CAAC,UAAU,GAAG;AAAA,UACd,eAAe;AAAA,QACjB;AAAA,QAEC,2BACC,gBAAAA,KAAC,kBAAe,MAAY,IAE5B,gBAAAA;AAAA,UAAC;AAAA;AAAA,YACC,OAAO;AAAA,cACL,OAAO;AAAA,cACP,QAAQ;AAAA,cACR,WAAW;AAAA,cACX,YAAY;AAAA,cACZ,cAAc;AAAA,YAChB;AAAA;AAAA,QACF;AAAA;AAAA,IAEJ;AAAA,EAEJ,GAAG,CAAC,WAAW,eAAe,OAAO,MAAM,YAAY,OAAO,YAAY,KAAK,CAAC;AAEhF,QAAM,aAAa,YAAY;AAC/B,QAAM,YAA2B,EAAE,GAAG,UAAU,MAAM,OAAO,UAAU;AAEvE,QAAM,iBAAsC,YACxC,iBACA;AAAA,IACE,UAAU;AAAA,IACV,KAAK;AAAA,IACL,MAAM;AAAA,IACN,WAAW;AAAA,EACb;AAEJ,SACE,gBAAAA;AAAA,IAAC;AAAA;AAAA,MACC,KAAK,CAAC,SAAS;AACb,aAAK,YAAY,IAAI;AACrB,mBAAW,UAAU;AAAA,MACvB;AAAA,MACA,UAAU;AAAA,MACV,qBAAkB;AAAA,MAClB,WAAW,YAAY;AAAA,MACvB,OAAO;AAAA,QACL,GAAG;AAAA;AAAA;AAAA,QAGH,YAAY,aAAa,CAAC,eAAe,WAAW;AAAA,QACpD,eAAe,cAAc,SAAS;AAAA,QACtC,UAAU,aAAa,UAAU,KAAK,IAAI,QAAQ,OAAO,OAAO,aAAa,EAAE,IAAI;AAAA,QACnF,WAAW,aAAa,UAAU,QAAQ,SAAS;AAAA,QACnD,WAAW;AAAA,MACb;AAAA,MACA,MAAK;AAAA,MACL,cAAW;AAAA,MACX,cAAY,aAAa,SAAS,YAAY,CAAC,OAAO,SAAS,UAAU,GACvE,OAAO,KAAK,UAAU,WAAW,KAAK,KAAK,KAAK,KAAK,EACvD;AAAA,MAEA,0BAAAA;AAAA,QAAC;AAAA;AAAA,UACC,OAAO;AAAA,YACL,SAAS,UAAU,IAAI;AAAA,YACvB,WAAW,UACP,SACA,0BAA0B,SAAS,QAAQ,IAAI,EAAE;AAAA,YACrD,YAAY,gBACR,SACA,uCAAuC,WAAW;AAAA,UACxD;AAAA,UAEC,uBACC,gBAAAA,KAAC,cAAY,GAAG,WAAW,IAE3B,gBAAAA,KAAC,eAAa,GAAG,WAAW,QAAgB,YAAwB;AAAA;AAAA,MAExE;AAAA;AAAA,EACF;AAEJ;;;AJ7JI,gBAAAG,MAqMM,QAAAC,aArMN;AA/BJ,IAAM,cAAc,cAAmC,IAAI;AAG3D,IAAM,mBAAmB;AAGlB,SAAS,UAAwB;AACtC,QAAM,MAAM,WAAW,WAAW;AAClC,MAAI,CAAC,IAAK,OAAM,IAAI,MAAM,8CAA8C;AACxE,SAAO;AACT;AAKA,SAAS,UAAU;AAAA,EACjB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAMG;AACD,QAAM,UAAU,WAAW;AAC3B,QAAM,gBAAgB,iBAAiB;AACvC,SACE,gBAAAD;AAAA,IAAC;AAAA;AAAA,MACC,kBAAe;AAAA,MACf;AAAA,MACA,OAAO;AAAA,QACL,UAAU;AAAA,QACV,OAAO;AAAA,QACP,QAAQ,uBAAuB,MAAM;AAAA,QACrC,eAAe;AAAA,QACf,SAAS,WAAW,CAAC,UAAU,IAAI;AAAA,QACnC,YAAY,gBAAgB,SAAY,WAAW,gBAAgB;AAAA,QACnE,GAAG;AAAA,MACL;AAAA,MAEC;AAAA;AAAA,EACH;AAEJ;AAEO,SAAS,aAAa,OAA0B;AACrD,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA,YAAY;AAAA,IACZ,WAAW;AAAA,IACX;AAAA,IACA;AAAA,IACA;AAAA,IACA,WAAW;AAAA,IACX,aAAa;AAAA,IACb,wBAAwB,EAAE,UAAU,UAAU,OAAO,UAAU,QAAQ,UAAU;AAAA,IACjF;AAAA,EACF,IAAI;AAEJ,QAAM,CAAC,SAAS,UAAU,IAAIE,UAAS,KAAK;AAC5C,QAAM,CAAC,OAAO,QAAQ,IAAIA,UAAgB,MAAM;AAChD,QAAM,CAAC,eAAe,gBAAgB,IAAIA,UAAS,CAAC;AACpD,QAAM,eAAe,oBAAoB;AAEzC,QAAM,WAAW,UAAU;AAC3B,QAAM,YAAY,WAAY,eAAe,kBAAmB,gBAAiB;AACjF,QAAM,OACJ,aAAa,KAAK,YAAY,MAAM,SAAS,MAAM,SAAS,IAAI;AAGlE,QAAM,kBAAkBC,QAAqD,IAAI;AACjF,QAAM,YAAYA,QAA6C,IAAI;AAGnE,QAAM,WAAWA,QAAO,EAAE,OAAO,WAAW,MAAM,OAAO,cAAc,SAAS,OAAO,CAAC;AACxF,WAAS,UAAU,EAAE,OAAO,WAAW,MAAM,OAAO,cAAc,SAAS,OAAO;AAElF,EAAAC,WAAU,MAAM,WAAW,IAAI,GAAG,CAAC,CAAC;AACpC,EAAAA;AAAA,IACE,MAAM,MAAM;AACV,UAAI,UAAU,QAAS,cAAa,UAAU,OAAO;AAAA,IACvD;AAAA,IACA,CAAC;AAAA,EACH;AAEA,QAAM,WAAW;AAAA,IACf,CAAC,UAAkB;AACjB,YAAM,IAAI,SAAS;AACnB,YAAM,UAAU,KAAK,IAAI,GAAG,KAAK,IAAI,OAAO,EAAE,MAAM,SAAS,CAAC,CAAC;AAC/D,UAAI,YAAY,EAAE,UAAW;AAC7B,QAAE,MAAM,SAAS,EAAE,MAAM,EAAE,SAAS;AACpC,UAAI,CAAC,aAAc,kBAAiB,OAAO;AAC3C,QAAE,eAAe,SAAS,EAAE,MAAM,OAAO,CAAC;AAAA,IAC5C;AAAA,IACA,CAAC,YAAY;AAAA,EACf;AAEA,QAAM,QAAQ;AAAA,IACZ,CAAC,UAAU,MAAM;AACf,YAAM,IAAI,SAAS;AACnB,UAAI,EAAE,UAAU,YAAY,EAAE,MAAM,WAAW,EAAG;AAClD,UAAI,UAAU,QAAS,cAAa,UAAU,OAAO;AACrD,YAAM,UAAU,KAAK,IAAI,GAAG,KAAK,IAAI,SAAS,EAAE,MAAM,SAAS,CAAC,CAAC;AACjE,UAAI,CAAC,aAAc,kBAAiB,OAAO;AAAA,UACtC,GAAE,eAAe,SAAS,EAAE,MAAM,OAAO,CAAC;AAC/C,eAAS,QAAQ;AACjB,QAAE,UAAU;AAAA,IACd;AAAA,IACA,CAAC,YAAY;AAAA,EACf;AAEA,QAAM,OAAO,YAAY,CAAC,SAAyB,mBAAmB;AACpE,UAAM,IAAI,SAAS;AACnB,QAAI,EAAE,UAAU,SAAU;AAC1B,MAAE,MAAM,SAAS,EAAE,MAAM,EAAE,SAAS;AACpC,QAAI,EAAE,KAAM,iBAAgB,UAAU,EAAE,MAAM,EAAE,MAAM,WAAW,EAAE,UAAU;AAC7E,aAAS,SAAS;AAClB,QAAI,UAAU,QAAS,cAAa,UAAU,OAAO;AACrD,cAAU,UAAU,WAAW,MAAM;AACnC,sBAAgB,UAAU;AAC1B,eAAS,MAAM;AAAA,IACjB,GAAG,gBAAgB;AACnB,MAAE,SAAS,QAAQ,EAAE,SAAS;AAAA,EAChC,GAAG,CAAC,CAAC;AAEL,QAAM,OAAO,YAAY,MAAM;AAC7B,UAAM,IAAI,SAAS;AACnB,QAAI,EAAE,UAAU,SAAU;AAC1B,QAAI,EAAE,aAAa,EAAE,MAAM,SAAS,EAAG,MAAK,UAAU;AAAA,QACjD,UAAS,EAAE,YAAY,CAAC;AAAA,EAC/B,GAAG,CAAC,UAAU,IAAI,CAAC;AAEnB,QAAM,OAAO,YAAY,MAAM;AAC7B,UAAM,IAAI,SAAS;AACnB,QAAI,EAAE,UAAU,YAAY,EAAE,aAAa,EAAG;AAC9C,aAAS,EAAE,YAAY,CAAC;AAAA,EAC1B,GAAG,CAAC,QAAQ,CAAC;AAEb,QAAM,OAAO,YAAY,CAAC,UAAkB,SAAS,KAAK,GAAG,CAAC,QAAQ,CAAC;AAGvE,QAAM,iBAAiBD,QAAO,KAAK;AACnC,EAAAC,WAAU,MAAM;AACd,QAAI,aAAa,WAAW,CAAC,eAAe,SAAS;AACnD,qBAAe,UAAU;AACzB,YAAM,CAAC;AAAA,IACT;AAAA,EACF,GAAG,CAAC,WAAW,SAAS,KAAK,CAAC;AAG9B,EAAAA,WAAU,MAAM;AACd,QAAI,CAAC,YAAY,CAAC,KAAM;AACxB,SAAK,UAAU,MAAM,SAAS;AAC9B,QAAI,CAAC,KAAK,eAAe;AACvB,YAAM,KAAK,cAAc,IAAI;AAC7B,YAAM,gBACJ,OAAO,WAAW,eAClB,OAAO,WAAW,kCAAkC,EAAE;AACxD,UAAI;AAAA,QACF,gBAAgB,EAAE,GAAG,uBAAuB,UAAU,OAAO,IAAI;AAAA,MACnE;AAAA,IACF;AAAA,EAEF,GAAG,CAAC,UAAU,SAAS,CAAC;AAGxB,EAAAA,WAAU,MAAM;AACd,QAAI,CAAC,YAAY,CAAC,SAAU;AAC5B,UAAM,QAAQ,CAAC,MAAqB;AAClC,UAAI,EAAE,QAAQ,SAAU,MAAK,QAAQ;AAAA,eAC5B,EAAE,QAAQ,gBAAgB,EAAE,QAAQ,QAAS,MAAK;AAAA,eAClD,EAAE,QAAQ,YAAa,MAAK;AAAA,IACvC;AACA,WAAO,iBAAiB,WAAW,KAAK;AACxC,WAAO,MAAM,OAAO,oBAAoB,WAAW,KAAK;AAAA,EAC1D,GAAG,CAAC,UAAU,UAAU,MAAM,MAAM,IAAI,CAAC;AAGzC,EAAAA,WAAU,MAAM;AACd,QAAI,CAAC,YAAY,CAAC,WAAY;AAC9B,UAAM,WAAW,SAAS,KAAK,MAAM;AACrC,aAAS,KAAK,MAAM,WAAW;AAC/B,WAAO,MAAM;AACX,eAAS,KAAK,MAAM,WAAW;AAAA,IACjC;AAAA,EACF,GAAG,CAAC,UAAU,UAAU,CAAC;AAGzB,QAAM,aAAa,QAAQ,gBAAgB,SAAS,QAAQ;AAC5D,QAAM,cAAc,OAAO,YAAY,gBAAgB,SAAS,aAAa;AAC7E,QAAM,aAAa,cAAc,YAAY,UAAU,MAAM;AAE7D,QAAM,WAAWC;AAAA,IACf,OAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA,YAAY,MAAM;AAAA,MAClB;AAAA,MACA,SAAS,aAAa;AAAA,MACtB,QAAQ,cAAc,MAAM,SAAS;AAAA,MACrC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,CAAC,UAAU,WAAW,MAAM,QAAQ,MAAM,OAAO,MAAM,MAAM,MAAM,IAAI;AAAA,EACzE;AAEA,QAAM,YACJ,oBAAoB,OAAO,aAAa,cAAc,SAAS,OAAO;AAExE,QAAM,SAAS,MAAM,UAAU;AAC/B,QAAM,UAAU,UAAU;AAE1B,SACE,gBAAAJ,MAAC,YAAY,UAAZ,EAAqB,OAAO,UAC1B;AAAA;AAAA,IACA,WACC,aACA,UAAU,UACV,cACA;AAAA,MACE,gBAAAA;AAAA,QAAC;AAAA;AAAA,UACC;AAAA,UACA;AAAA,UACA,WAAW,MAAM,YAAY;AAAA,UAC7B,OAAO,MAAM;AAAA,UAEX;AAAA,mBAAM,eAAe,SACrB,gBAAAD;AAAA,cAAC;AAAA;AAAA,gBACC,MAAM;AAAA,gBACN,MAAM;AAAA,gBACN,aAAa,CAAC;AAAA,gBACd,SAAS,WAAW,oBAAoB,MAAM,oBAAoB;AAAA,gBAClE,QAAQ,WAAW,mBAAmB,MAAM,mBAAmB;AAAA,gBAC/D,OAAO,MAAM;AAAA,gBACb,MAAM,MAAM,eAAe;AAAA,gBAC3B,WAAW,MAAM,YAAY;AAAA,gBAC7B,aAAa,MAAM,mBAAmB,MAAM,KAAK,MAAM,IAAI;AAAA;AAAA,YAC7D;AAAA,YAEF,gBAAAA;AAAA,cAAC;AAAA;AAAA,gBAEC,MAAM;AAAA,gBACN;AAAA,gBACA,MAAM;AAAA,gBACN,aAAa,CAAC;AAAA,gBACd,QAAQ,MAAM,UAAU;AAAA,gBACxB,SAAS,WAAW,oBAAoB,MAAM,oBAAoB;AAAA,gBAClE,YAAY,MAAM;AAAA,gBAClB,YAAY,MAAM;AAAA,gBAClB,QAAQ,MAAM;AAAA;AAAA,cATT;AAAA,YAUP;AAAA;AAAA;AAAA,MACF;AAAA,MACA;AAAA,IACF;AAAA,KACJ;AAEJ;","names":["useEffect","useMemo","useRef","useState","useEffect","useState","useEffect","useState","jsx","jsxs","arrow","jsx","useEffect","useState","jsx","jsxs","useState","useRef","useEffect","useMemo"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "react-headless-tour",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Fully customizable, headless product tour / onboarding library for React & Next.js. All the logic, none of the opinions — bring your own theme.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"react",
|
|
7
|
+
"nextjs",
|
|
8
|
+
"tour",
|
|
9
|
+
"product-tour",
|
|
10
|
+
"onboarding",
|
|
11
|
+
"walkthrough",
|
|
12
|
+
"headless",
|
|
13
|
+
"spotlight",
|
|
14
|
+
"guide",
|
|
15
|
+
"tooltip"
|
|
16
|
+
],
|
|
17
|
+
"license": "MIT",
|
|
18
|
+
"type": "module",
|
|
19
|
+
"main": "./dist/index.cjs",
|
|
20
|
+
"module": "./dist/index.js",
|
|
21
|
+
"types": "./dist/index.d.ts",
|
|
22
|
+
"exports": {
|
|
23
|
+
".": {
|
|
24
|
+
"types": "./dist/index.d.ts",
|
|
25
|
+
"import": "./dist/index.js",
|
|
26
|
+
"require": "./dist/index.cjs"
|
|
27
|
+
},
|
|
28
|
+
"./package.json": "./package.json"
|
|
29
|
+
},
|
|
30
|
+
"files": [
|
|
31
|
+
"dist",
|
|
32
|
+
"README.md",
|
|
33
|
+
"LICENSE"
|
|
34
|
+
],
|
|
35
|
+
"sideEffects": false,
|
|
36
|
+
"scripts": {
|
|
37
|
+
"build": "tsup",
|
|
38
|
+
"dev": "tsup --watch",
|
|
39
|
+
"typecheck": "tsc --noEmit",
|
|
40
|
+
"prepublishOnly": "npm run build",
|
|
41
|
+
"demo": "npm run dev --prefix demo"
|
|
42
|
+
},
|
|
43
|
+
"peerDependencies": {
|
|
44
|
+
"react": ">=18",
|
|
45
|
+
"react-dom": ">=18"
|
|
46
|
+
},
|
|
47
|
+
"dependencies": {
|
|
48
|
+
"@floating-ui/react-dom": "^2.1.2"
|
|
49
|
+
},
|
|
50
|
+
"devDependencies": {
|
|
51
|
+
"@types/react": "^18.3.12",
|
|
52
|
+
"@types/react-dom": "^18.3.1",
|
|
53
|
+
"react": "^18.3.1",
|
|
54
|
+
"react-dom": "^18.3.1",
|
|
55
|
+
"tsup": "^8.3.5",
|
|
56
|
+
"typescript": "^5.6.3"
|
|
57
|
+
},
|
|
58
|
+
"repository": {
|
|
59
|
+
"type": "git",
|
|
60
|
+
"url": "git+https://github.com/Imran-Software-Engineer/react-headless-tour.git"
|
|
61
|
+
},
|
|
62
|
+
"homepage": "https://github.com/Imran-Software-Engineer/react-headless-tour#readme",
|
|
63
|
+
"bugs": {
|
|
64
|
+
"url": "https://github.com/Imran-Software-Engineer/react-headless-tour/issues"
|
|
65
|
+
},
|
|
66
|
+
"author": "Imran (https://github.com/Imran-Software-Engineer)"
|
|
67
|
+
}
|