{"version":3,"file":"react.es.mjs","names":[],"sources":["../src/react/createReactRoot.ts","../src/react/ErrorBoundary.ts","../src/react/ShadowStyle.ts","../src/react/useClickOutside.ts","../src/react/useDebouncedValue.ts","../src/react/useForceFullScreenOverlay.ts","../src/react/useMediaQuery.ts","../src/react/useOptimisticSet.ts","../src/react/usePaginatedList.ts","../src/react/useReducedMotion.ts","../src/react/useResetScrollPosition.ts"],"sourcesContent":["import type { ReactElement } from 'react'\nimport * as ReactDOM from 'react-dom'\nimport type { ReactRoot } from '../types/react/ReactRoot'\n\ninterface LegacyReactDom {\n  render: (element: ReactElement, container: Element) => void\n  unmountComponentAtNode: (container: Element) => void\n}\n\ninterface ConcurrentReactDom {\n  createRoot: (container: Element) => {\n    render: (element: ReactElement) => void\n    unmount: () => void\n  }\n}\n\n/**\n * Mounts React into a container using whichever API the host's React provides.\n *\n * Staffbase widgets run against a host-supplied React that may be 18+ (concurrent\n * `createRoot`) or legacy 17 (`render`). This adapter picks the right one so a\n * widget mounts identically on both, returning a uniform render/unmount handle.\n * @param {Element} container - The element to mount into.\n * @returns {ReactRoot} The render/unmount handle.\n */\nexport const createReactRoot = (container: Element): ReactRoot => {\n  const reactDom = ReactDOM as unknown as\n    | ConcurrentReactDom\n    | (LegacyReactDom & Partial<ConcurrentReactDom>)\n\n  if (typeof reactDom.createRoot === 'function') {\n    const root = reactDom.createRoot(container)\n    return {\n      render(element: ReactElement) {\n        root.render(element)\n      },\n      unmount() {\n        root.unmount()\n      },\n    }\n  }\n\n  const legacy = reactDom as LegacyReactDom\n  return {\n    render(element: ReactElement) {\n      legacy.render(element, container)\n    },\n    unmount() {\n      legacy.unmountComponentAtNode(container)\n    },\n  }\n}\n","import type { ErrorInfo, ReactNode } from 'react'\nimport { Component } from 'react'\nimport type { ErrorBoundaryProps } from '../types/react/ErrorBoundaryProps'\n\ninterface ErrorBoundaryState {\n  hasError: boolean\n}\n\n/**\n * A render error boundary that isolates a failing subtree.\n *\n * Catches errors thrown during descendant render, shows the optional `fallback`\n * (nothing by default), and forwards the error to `onError` so the widget can\n * log it through its own logger. Written with the class API (no JSX) to match\n * the library's JSX-runtime-free build.\n */\nexport class ErrorBoundary extends Component<\n  ErrorBoundaryProps,\n  ErrorBoundaryState\n> {\n  public state: ErrorBoundaryState = { hasError: false }\n\n  /**\n   * Flips into the error state when a descendant throws.\n   * @returns {ErrorBoundaryState} The next state.\n   */\n  public static getDerivedStateFromError(): ErrorBoundaryState {\n    return { hasError: true }\n  }\n\n  /**\n   * Forwards the caught error and component stack to the optional handler.\n   * @param {Error} error - The thrown error.\n   * @param {ErrorInfo} info - React error info (component stack).\n   * @returns {void} Nothing.\n   */\n  public componentDidCatch(error: Error, info: ErrorInfo): void {\n    this.props.onError?.(error, info)\n  }\n\n  /**\n   * Renders the children, or the fallback once an error has been caught.\n   * @returns {ReactNode} The children or fallback.\n   */\n  public render(): ReactNode {\n    if (this.state.hasError) return this.props.fallback ?? null\n\n    return this.props.children\n  }\n}\n","import type { ReactElement } from 'react'\nimport { createElement, useEffect, useRef } from 'react'\nimport type { ShadowStyleProps } from '../types/react/ShadowStyleProps'\n\nconst DEFAULT_STYLE_ID = 'staffbase-shadow-style'\n\n/**\n * Injects CSS text into the ShadowRoot that surrounds it.\n *\n * Replaces the per-widget DrawerContentStyles components (identical in the\n * alerts and unacknowledged-bulletins widgets). Renders a hidden anchor, finds\n * the enclosing ShadowRoot via its root node (falling back to\n * `fallbackHostSelector` for content portaled elsewhere), and appends/updates a\n * single `<style>` keyed by `styleId` so re-renders never duplicate it.\n * @param {ShadowStyleProps} props - The CSS and targeting options.\n * @returns {ReactElement} A hidden anchor element.\n */\nexport const ShadowStyle = ({\n  css,\n  styleId = DEFAULT_STYLE_ID,\n  fallbackHostSelector,\n}: ShadowStyleProps): ReactElement => {\n  const anchorRef = useRef<HTMLSpanElement | null>(null)\n\n  useEffect(() => {\n    const rootNode = anchorRef.current?.getRootNode()\n    const shadowRoot =\n      rootNode instanceof ShadowRoot\n        ? rootNode\n        : fallbackHostSelector\n          ? (document.querySelector(fallbackHostSelector)?.shadowRoot ?? null)\n          : null\n\n    if (!shadowRoot) return\n\n    const selector = `style[data-shadow-style=\"${styleId}\"]`\n    const existing = shadowRoot.querySelector(selector)\n\n    if (existing instanceof HTMLStyleElement) {\n      if (existing.textContent !== css) existing.textContent = css\n      return\n    }\n\n    const styleEl = document.createElement('style')\n    styleEl.setAttribute('data-shadow-style', styleId)\n    styleEl.textContent = css\n    shadowRoot.appendChild(styleEl)\n  }, [css, styleId, fallbackHostSelector])\n\n  return createElement('span', {\n    ref: anchorRef,\n    style: { display: 'none' },\n  })\n}\n","import type { RefObject } from 'react'\nimport { useEffect } from 'react'\n\n/**\n * Calls `onOutside` when a pointer/touch press lands outside every referenced\n * element, while `active` is true.\n *\n * Accepts multiple refs (e.g. a trigger plus its popover) so clicks on any of\n * them count as inside. Listens in the capture phase on `pointerdown` and\n * `touchstart` to fire before click handlers. Shadow-DOM safe: it compares\n * against the refs' nodes, not document containment.\n * @param {ReadonlyArray<RefObject<HTMLElement | null>>} refs - Elements treated as inside.\n * @param {() => void} onOutside - Called on an outside press.\n * @param {boolean} [active] - Whether the listener is attached (default true).\n * @returns {void} Nothing.\n */\nexport const useClickOutside = (\n  refs: ReadonlyArray<RefObject<HTMLElement | null>>,\n  onOutside: () => void,\n  active = true,\n): void => {\n  useEffect(() => {\n    if (!active) return\n\n    /**\n     * Fires `onOutside` when the press target is outside every referenced element.\n     * @param {Event} event - The pointer/touch event.\n     * @returns {void} Nothing.\n     */\n    const handle = (event: Event): void => {\n      const target = event.target as Node | null\n      if (!target) return\n\n      const isInside = refs.some((ref) => ref.current?.contains(target))\n      if (!isInside) onOutside()\n    }\n\n    document.addEventListener('pointerdown', handle, true)\n    document.addEventListener('touchstart', handle, true)\n    return () => {\n      document.removeEventListener('pointerdown', handle, true)\n      document.removeEventListener('touchstart', handle, true)\n    }\n  }, [refs, onOutside, active])\n}\n","import { useEffect, useState } from 'react'\n\n/**\n * Returns a debounced copy of a value that only updates after it has stopped\n * changing for `delayMs`. Useful for search inputs and other rapid updates.\n * @template T The value type.\n * @param {T} value - The source value.\n * @param {number} delayMs - Quiet period before the debounced value updates.\n * @returns {T} The debounced value.\n */\nexport const useDebouncedValue = <T>(value: T, delayMs: number): T => {\n  const [debounced, setDebounced] = useState<T>(value)\n\n  useEffect(() => {\n    const timeoutId = window.setTimeout(() => setDebounced(value), delayMs)\n    return () => window.clearTimeout(timeoutId)\n  }, [value, delayMs])\n\n  return debounced\n}\n","import type { RefObject } from 'react'\nimport { useEffect } from 'react'\nimport type { ForceFullScreenOverlayOptions } from '../types/react/ForceFullScreenOverlayOptions'\n\n/**\n * Forces an element to stay a fixed, full-viewport overlay despite host CSS.\n *\n * Applies the fixed/inset/size rules with `!important` and re-applies them via a\n * MutationObserver whenever the host rewrites the element's `style`, so a widget\n * overlay cannot be shrunk or repositioned by the surrounding app. Only active\n * while `active` is true.\n * @param {RefObject<HTMLElement | null>} elementRef - The overlay element ref.\n * @param {boolean} active - Whether to enforce the overlay.\n * @param {ForceFullScreenOverlayOptions} [options] - pointer-events / z-index overrides.\n * @returns {void} Nothing.\n */\nexport const useForceFullScreenOverlay = (\n  elementRef: RefObject<HTMLElement | null>,\n  active: boolean,\n  options?: ForceFullScreenOverlayOptions,\n): void => {\n  const pointerEvents = options?.pointerEvents ?? 'auto'\n  const zIndex = options?.zIndex\n\n  useEffect(() => {\n    const element = elementRef.current\n    if (!active || !element) return\n\n    /**\n     * Applies the fixed, full-viewport style rules with `!important`.\n     * @returns {void} Nothing.\n     */\n    const apply = (): void => {\n      element.style.setProperty('position', 'fixed', 'important')\n      element.style.setProperty('top', '0', 'important')\n      element.style.setProperty('right', '0', 'important')\n      element.style.setProperty('bottom', '0', 'important')\n      element.style.setProperty('left', '0', 'important')\n      element.style.setProperty('width', '100vw', 'important')\n      element.style.setProperty('height', '100vh', 'important')\n      element.style.setProperty('overflow', 'hidden', 'important')\n      element.style.setProperty('pointer-events', pointerEvents, 'important')\n      if (typeof zIndex === 'number') {\n        element.style.setProperty('z-index', String(zIndex), 'important')\n      }\n    }\n\n    apply()\n    const observer = new MutationObserver(() =>\n      window.requestAnimationFrame(apply),\n    )\n    observer.observe(element, { attributes: true, attributeFilter: ['style'] })\n    return () => observer.disconnect()\n  }, [elementRef, active, pointerEvents, zIndex])\n}\n","import { useEffect, useState } from 'react'\n\n/**\n * Tracks whether a CSS media query currently matches, updating on change.\n *\n * SSR-safe: returns false when there is no `window`. Subscribes to the query's\n * change event and cleans up on unmount or when the query string changes.\n * @param {string} query - A media query string (e.g. `'(max-width: 768px)'`).\n * @returns {boolean} True while the query matches.\n */\nexport const useMediaQuery = (query: string): boolean => {\n  const [matches, setMatches] = useState<boolean>(() =>\n    typeof window === 'undefined' ? false : window.matchMedia(query).matches,\n  )\n\n  useEffect(() => {\n    if (typeof window === 'undefined') return\n\n    const mediaQuery = window.matchMedia(query)\n    setMatches(mediaQuery.matches)\n\n    const controller = new AbortController()\n    mediaQuery.addEventListener(\n      'change',\n      (event) => setMatches(event.matches),\n      { signal: controller.signal },\n    )\n    return () => controller.abort()\n  }, [query])\n\n  return matches\n}\n","import { useCallback, useState } from 'react'\nimport type { UseOptimisticSetReturn } from '../types/react/UseOptimisticSetReturn'\n\n/**\n * Manages a set of ids with optimistic add-and-rollback.\n *\n * Generalizes the alerts/unacknowledged-bulletins acknowledgement flow: an item\n * is hidden immediately by adding its id, the persistence call runs, and the id\n * is removed again if the call reports failure - so a failed write never leaves\n * a permanently hidden item.\n * @returns {UseOptimisticSetReturn} The set, membership test, and optimistic add.\n */\nexport const useOptimisticSet = (): UseOptimisticSetReturn => {\n  const [ids, setIds] = useState<Set<string>>(() => new Set())\n\n  const has = useCallback((id: string): boolean => ids.has(id), [ids])\n\n  const add = useCallback(\n    async (id: string, commit: () => Promise<boolean>): Promise<boolean> => {\n      setIds((prev) => new Set(prev).add(id))\n\n      const kept = await commit().catch(() => false)\n      if (!kept) {\n        setIds((prev) => {\n          const next = new Set(prev)\n          next.delete(id)\n          return next\n        })\n      }\n\n      return kept\n    },\n    [],\n  )\n\n  return { ids, has, add }\n}\n","import { useCallback, useEffect, useMemo, useState } from 'react'\nimport type { UsePaginatedListReturn } from '../types/react/UsePaginatedListReturn'\n\n/**\n * Client-side \"load more\" pagination over an in-memory list.\n *\n * Reveals `pageSize` items at a time and collapses back to the first page\n * whenever `resetKey` changes (e.g. the selected channel or language), matching\n * the alerts/unacknowledged-bulletins list behavior.\n * @template T The list item type.\n * @param {T[]} items - The full list.\n * @param {number} pageSize - Items revealed per page.\n * @param {unknown} [resetKey] - When it changes, pagination resets to page one.\n * @returns {UsePaginatedListReturn<T>} The visible slice and controls.\n */\nexport const usePaginatedList = <T>(\n  items: T[],\n  pageSize: number,\n  resetKey?: unknown,\n): UsePaginatedListReturn<T> => {\n  const [count, setCount] = useState<number>(pageSize)\n\n  useEffect(() => {\n    setCount(pageSize)\n  }, [resetKey, pageSize])\n\n  const visible = useMemo(() => items.slice(0, count), [items, count])\n  const loadMore = useCallback(\n    () => setCount((current) => current + pageSize),\n    [pageSize],\n  )\n  const reset = useCallback(() => setCount(pageSize), [pageSize])\n\n  return { visible, canLoadMore: count < items.length, loadMore, reset }\n}\n","import { useMediaQuery } from './useMediaQuery'\n\n/**\n * Whether the user has requested reduced motion\n * (`prefers-reduced-motion: reduce`). Use it to skip or shorten animations.\n * @returns {boolean} True when reduced motion is preferred.\n */\nexport const useReducedMotion = (): boolean =>\n  useMediaQuery('(prefers-reduced-motion: reduce)')\n","import type { DependencyList, RefObject } from 'react'\nimport { useLayoutEffect } from 'react'\n\n/**\n * Resets a scroll container to the top whenever `deps` change.\n *\n * Resets synchronously, then again on the next frame and after a short delay to\n * defeat iOS Safari's scroll restoration, which can re-apply the old position\n * after layout. Failures (detached node) are swallowed.\n * @param {RefObject<HTMLElement | null>} targetRef - The scroll container ref.\n * @param {DependencyList} deps - Dependencies that should trigger a reset.\n * @returns {void} Nothing.\n */\nexport const useResetScrollPosition = (\n  targetRef: RefObject<HTMLElement | null>,\n  deps: DependencyList,\n): void => {\n  useLayoutEffect(() => {\n    /**\n     * Scrolls the target container back to the top, ignoring detached-node errors.\n     * @returns {void} Nothing.\n     */\n    const reset = (): void => {\n      try {\n        if (targetRef.current) targetRef.current.scrollTop = 0\n      } catch {\n        // Ignore: the node may be detached mid-transition.\n      }\n    }\n\n    reset()\n    let timeoutId: number | null = null\n    const frameId = window.requestAnimationFrame(() => {\n      reset()\n      timeoutId = window.setTimeout(reset, 100)\n    })\n\n    return () => {\n      window.cancelAnimationFrame(frameId)\n      if (timeoutId !== null) window.clearTimeout(timeoutId)\n    }\n  }, [targetRef, ...deps])\n}\n"],"mappings":"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"}