{"version":3,"sources":["../src/qa/types.ts","../src/qa/LegionQA.tsx"],"names":["LegionQA"],"mappings":"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","file":"qa.mjs","sourcesContent":["/**\n * Theming props for the Q&A Widget.\n * These map to CSS custom properties used internally.\n */\nexport interface QAThemingProps {\n  /** Primary accent color, e.g. \"#228be6\" */\n  qaPrimaryColor?: string;\n  /** Container background color */\n  qaBackgroundColor?: string;\n  /** Primary text color */\n  qaTextColor?: string;\n  /** Secondary text color */\n  qaSecondaryTextColor?: string;\n  /** Border color */\n  qaBorderColor?: string;\n  /** Staff badge color */\n  qaStaffBadgeColor?: string;\n  /** Accepted answer color */\n  qaAcceptedColor?: string;\n  /** Title font size, e.g. \"clamp(16px, 2vmin, 20px)\" */\n  qaTitleSize?: string;\n  /** Body font size */\n  qaBodySize?: string;\n  /** Meta text font size */\n  qaMetaSize?: string;\n  /** Font family */\n  qaFontFamily?: string;\n  /** Card padding, e.g. \"16px\" */\n  qaCardPadding?: string;\n  /** Gap between cards, e.g. \"12px\" */\n  qaCardGap?: string;\n  /** Border radius, e.g. \"8px\" */\n  qaBorderRadius?: string;\n  /** Card box shadow */\n  qaCardShadow?: string;\n  /** Button border radius, e.g. \"4px\" */\n  qaButtonRadius?: string;\n  /** Vote button size, e.g. \"28px\" */\n  qaVoteButtonSize?: string;\n}\n\n/**\n * Core configuration props for the Q&A Widget.\n */\nexport interface QAWidgetProps extends QAThemingProps {\n  /** Base URL of the Legion application (required) */\n  baseUrl: string;\n  /** JWT auth token for authenticated features */\n  authToken?: string;\n  /** Product ID to scope questions to a specific product */\n  productId?: string;\n  /** Display name for the user. Default: \"Anonymous\" */\n  username?: string;\n  /** Number of items per page. Default: 5 */\n  pageSize?: number;\n  /** Theme preset. Default: \"light\" */\n  theme?: \"light\" | \"dark\";\n  /** Show search bar. Default: true */\n  showSearch?: boolean;\n  /** Show the \"Ask a Question\" button. Default: true */\n  showAskButton?: boolean;\n  /** Widget width CSS value. Default: \"600px\" */\n  width?: string;\n  /** Widget height CSS value. Default: \"800px\" */\n  height?: string;\n  /** Additional CSS class name for the container */\n  className?: string;\n  /** Additional inline styles for the container */\n  style?: React.CSSProperties;\n  /** Callback when the widget iframe has loaded */\n  onLoad?: (detail: { widget: string; theme: string }) => void;\n  /** Callback when the widget iframe fails to load */\n  onError?: (message: string) => void;\n}\n\n/**\n * Mapping from camelCase theming prop names to the kebab-case query\n * parameter names used by the Q&A widget iframe URL.\n */\nexport const QA_THEMING_PROP_TO_PARAM: Record<keyof QAThemingProps, string> = {\n  qaPrimaryColor: \"qa-primary-color\",\n  qaBackgroundColor: \"qa-background-color\",\n  qaTextColor: \"qa-text-color\",\n  qaSecondaryTextColor: \"qa-secondary-text-color\",\n  qaBorderColor: \"qa-border-color\",\n  qaStaffBadgeColor: \"qa-staff-badge-color\",\n  qaAcceptedColor: \"qa-accepted-color\",\n  qaTitleSize: \"qa-title-size\",\n  qaBodySize: \"qa-body-size\",\n  qaMetaSize: \"qa-meta-size\",\n  qaFontFamily: \"qa-font-family\",\n  qaCardPadding: \"qa-card-padding\",\n  qaCardGap: \"qa-card-gap\",\n  qaBorderRadius: \"qa-border-radius\",\n  qaCardShadow: \"qa-card-shadow\",\n  qaButtonRadius: \"qa-button-radius\",\n  qaVoteButtonSize: \"qa-vote-button-size\",\n};\n\n","import React, {\n  useRef,\n  useCallback,\n  useMemo,\n  forwardRef,\n  useImperativeHandle,\n} from \"react\";\nimport {\n  type QAWidgetProps,\n  type QAThemingProps,\n  QA_THEMING_PROP_TO_PARAM,\n} from \"./types\";\n\n/**\n * Ref handle exposed by LegionQA for imperative control.\n */\nexport interface LegionQAHandle {\n  /** Reload the widget iframe */\n  refresh: () => void;\n}\n\n/**\n * Build the iframe src URL from widget props.\n */\nexport function buildQAWidgetUrl(props: QAWidgetProps): string {\n  const {\n    baseUrl,\n    productId,\n    username = \"Anonymous\",\n    pageSize = 5,\n    theme = \"light\",\n    showSearch = true,\n    showAskButton = true,\n  } = props;\n\n  const url = new URL(\"/widget/qa\", baseUrl);\n\n  if (productId) {\n    url.searchParams.set(\"productId\", productId);\n  }\n  if (username) {\n    url.searchParams.set(\"username\", username);\n  }\n  if (pageSize) {\n    url.searchParams.set(\"pageSize\", String(pageSize));\n  }\n  if (theme) {\n    url.searchParams.set(\"theme\", theme);\n  }\n  url.searchParams.set(\"showSearch\", String(showSearch));\n  url.searchParams.set(\"showAskButton\", String(showAskButton));\n\n  // Append theming params\n  const themingKeys = Object.keys(QA_THEMING_PROP_TO_PARAM) as Array<\n    keyof QAThemingProps\n  >;\n  for (const key of themingKeys) {\n    const value = props[key];\n    if (value !== undefined && value !== null && String(value).length > 0) {\n      url.searchParams.set(QA_THEMING_PROP_TO_PARAM[key], String(value));\n    }\n  }\n\n  return url.toString();\n}\n\n/**\n * LegionQA – a React component that embeds the Legion Q&A widget via an iframe.\n *\n * @example\n * ```tsx\n * import { LegionQA } from '@legionhandtech/lht-react-widgets';\n *\n * function App() {\n *   return (\n *     <LegionQA\n *       baseUrl=\"https://your-legion-domain.com\"\n *       authToken=\"your-jwt-token\"\n *       theme=\"light\"\n *     />\n *   );\n * }\n * ```\n */\nexport const LegionQA = forwardRef<LegionQAHandle, QAWidgetProps>(\n  function LegionQA(props, ref) {\n    const {\n      theme = \"light\",\n      authToken,\n      productId,\n      username,\n      pageSize,\n      showSearch,\n      showAskButton,\n      width = \"600px\",\n      height = \"800px\",\n      className,\n      style,\n      onLoad,\n      onError,\n      baseUrl,\n      ...rest\n    } = props;\n\n    const iframeRef = useRef<HTMLIFrameElement>(null);\n\n    useImperativeHandle(\n      ref,\n      () => ({\n        refresh: () => {\n          const iframe = iframeRef.current;\n          if (iframe?.contentWindow) {\n            iframe.contentWindow.location.reload();\n          }\n        },\n      }),\n      []\n    );\n\n    const src = useMemo(\n      () => buildQAWidgetUrl(props),\n      [\n        baseUrl,\n        productId,\n        username,\n        pageSize,\n        theme,\n        showSearch,\n        showAskButton,\n        ...Object.keys(QA_THEMING_PROP_TO_PARAM).map(\n          (k) => rest[k as keyof typeof rest]\n        ),\n      ]\n    );\n\n    const handleLoad = useCallback(() => {\n      // Send auth token via postMessage\n      if (authToken && iframeRef.current?.contentWindow) {\n        iframeRef.current.contentWindow.postMessage(\n          { type: \"AUTH_TOKEN\", token: authToken },\n          baseUrl\n        );\n      }\n      onLoad?.({ widget: \"qa\", theme });\n    }, [authToken, baseUrl, theme, onLoad]);\n\n    const handleError = useCallback(() => {\n      onError?.(\"Failed to load Q&A widget\");\n    }, [onError]);\n\n    const containerStyle: React.CSSProperties = {\n      display: \"block\",\n      width,\n      height,\n      ...style,\n    };\n\n    const iframeStyle: React.CSSProperties = {\n      border: \"none\",\n      borderRadius: \"8px\",\n      boxShadow: \"0 2px 10px rgba(0, 0, 0, 0.1)\",\n      width: \"100%\",\n      height: \"100%\",\n    };\n\n    return (\n      <div className={className} style={containerStyle}>\n        <iframe\n          ref={iframeRef}\n          src={src}\n          title=\"Community Q&A Widget\"\n          width=\"100%\"\n          height=\"100%\"\n          loading=\"lazy\"\n          style={iframeStyle}\n          onLoad={handleLoad}\n          onError={handleError}\n        />\n      </div>\n    );\n  }\n);\n\n"]}