"use client";
import {
  useRequiredEndpointsRuntime
} from "./chunk-MJNXIEV2.js";
import {
  createNatsClient
} from "./chunk-PHWQLKVE.js";
import {
  useDebounce
} from "./chunk-ZXZJSTNV.js";
import {
  init_next_navigation,
  useRouter,
  useSearchParams
} from "./chunk-PLJLE4A4.js";
import {
  FlamingoLogo,
  MiamiCyberGangLogoFaceOnly,
  OpenFrameLogo,
  OpenmspLogo
} from "./chunk-V4IIBNTA.js";
import {
  cn,
  init_cn
} from "./chunk-XTCBRQN2.js";
import {
  AuthentikLogoGreyIcon,
  Chevron02DownIcon,
  FleetMdmLogoGreyIcon,
  MeshcentralLogoGreyIcon,
  OsqueryLogoGreyIcon,
  TacticalRmmLogoIcon,
  XmarkIcon
} from "./chunk-4WZOFD46.js";

// src/hooks/ui/use-header-height.ts
import { useEffect, useState } from "react";
function useHeaderHeight(defaultHeight = 64) {
  const [height, setHeight] = useState(defaultHeight);
  useEffect(() => {
    const measure = () => {
      let total = 0;
      const header2 = document.querySelector("header");
      if (header2) total += header2.offsetHeight;
      const bar2 = document.querySelector("[data-announcement-bar]");
      if (bar2 instanceof HTMLElement) total += bar2.offsetHeight;
      setHeight(total > 0 ? total : defaultHeight);
    };
    measure();
    const resizeObserver = new ResizeObserver(measure);
    const header = document.querySelector("header");
    if (header) resizeObserver.observe(header);
    const bar = document.querySelector("[data-announcement-bar]");
    if (bar) resizeObserver.observe(bar);
    const mutationObserver = new MutationObserver((mutations) => {
      for (const mutation of mutations) {
        if (mutation.type === "childList" || mutation.type === "attributes") {
          measure();
          const newBar = document.querySelector("[data-announcement-bar]");
          if (newBar) resizeObserver.observe(newBar);
        }
      }
    });
    mutationObserver.observe(document.body, {
      childList: true,
      subtree: true,
      attributes: true,
      attributeFilter: ["data-announcement-bar"]
    });
    return () => {
      resizeObserver.disconnect();
      mutationObserver.disconnect();
    };
  }, [defaultHeight]);
  return height;
}

// src/hooks/ui/use-horizontal-scrollbar.ts
import { useRef, useState as useState2, useCallback } from "react";
function useHorizontalScrollbar() {
  const scrollElRef = useRef(null);
  const trackRef = useRef(null);
  const thumbRef = useRef(null);
  const roRef = useRef(null);
  const moRef = useRef(null);
  const [thumbRatio, setThumbRatio] = useState2(0);
  const [canScrollLeft, setCanScrollLeft] = useState2(false);
  const [canScrollRight, setCanScrollRight] = useState2(false);
  const prevCanScrollLeftRef = useRef(false);
  const prevCanScrollRightRef = useRef(false);
  const isDraggingRef = useRef(false);
  const dragStartRef = useRef({ mouseX: 0, scrollLeft: 0 });
  const rafIdRef = useRef(0);
  const syncThumbToDOM = useCallback(() => {
    const el = scrollElRef.current;
    const thumb = thumbRef.current;
    if (!el || !thumb) return;
    const maxScroll = el.scrollWidth - el.clientWidth;
    if (maxScroll <= 0) {
      thumb.style.left = "0%";
      return;
    }
    const ratio = el.clientWidth / el.scrollWidth;
    const fraction = Math.min(Math.max(el.scrollLeft, 0), maxScroll) / maxScroll;
    thumb.style.left = `${fraction * (1 - ratio) * 100}%`;
  }, []);
  const syncEdgeFades = useCallback(() => {
    const el = scrollElRef.current;
    if (!el) return;
    const maxScroll = el.scrollWidth - el.clientWidth;
    const ratio = el.clientWidth / el.scrollWidth;
    if (ratio >= 1 || maxScroll <= 0) {
      if (prevCanScrollLeftRef.current) {
        prevCanScrollLeftRef.current = false;
        setCanScrollLeft(false);
      }
      if (prevCanScrollRightRef.current) {
        prevCanScrollRightRef.current = false;
        setCanScrollRight(false);
      }
      return;
    }
    const fraction = Math.min(Math.max(el.scrollLeft, 0), maxScroll) / maxScroll;
    const left = fraction > 1e-3;
    const right = fraction < 0.999;
    if (left !== prevCanScrollLeftRef.current) {
      prevCanScrollLeftRef.current = left;
      setCanScrollLeft(left);
    }
    if (right !== prevCanScrollRightRef.current) {
      prevCanScrollRightRef.current = right;
      setCanScrollRight(right);
    }
  }, []);
  const measure = useCallback(() => {
    const el = scrollElRef.current;
    if (!el) return;
    const ratio = el.clientWidth / el.scrollWidth;
    setThumbRatio(ratio >= 1 ? 0 : ratio);
    syncThumbToDOM();
    syncEdgeFades();
  }, [syncThumbToDOM, syncEdgeFades]);
  const scrollRef = useCallback((node) => {
    if (roRef.current) {
      roRef.current.disconnect();
      roRef.current = null;
    }
    if (moRef.current) {
      moRef.current.disconnect();
      moRef.current = null;
    }
    if (rafIdRef.current) {
      cancelAnimationFrame(rafIdRef.current);
      rafIdRef.current = 0;
    }
    scrollElRef.current = node;
    if (node) {
      const ratio = node.clientWidth / node.scrollWidth;
      setThumbRatio(ratio >= 1 ? 0 : ratio);
      const ro = new ResizeObserver(measure);
      roRef.current = ro;
      const observeAll = () => {
        ro.disconnect();
        ro.observe(node);
        for (const child of Array.from(node.children)) ro.observe(child);
      };
      observeAll();
      moRef.current = new MutationObserver(() => {
        observeAll();
        measure();
      });
      moRef.current.observe(node, { childList: true });
      requestAnimationFrame(() => {
        syncThumbToDOM();
        syncEdgeFades();
      });
    } else {
      setThumbRatio(0);
      prevCanScrollLeftRef.current = false;
      prevCanScrollRightRef.current = false;
      setCanScrollLeft(false);
      setCanScrollRight(false);
    }
  }, [measure, syncThumbToDOM, syncEdgeFades]);
  const onScroll = useCallback(() => {
    if (isDraggingRef.current) return;
    if (rafIdRef.current) cancelAnimationFrame(rafIdRef.current);
    rafIdRef.current = requestAnimationFrame(() => {
      syncThumbToDOM();
      syncEdgeFades();
    });
  }, [syncThumbToDOM, syncEdgeFades]);
  const onTrackClick = useCallback((e) => {
    if (e.target.closest("[data-scrollbar-thumb]")) return;
    const track = trackRef.current;
    const el = scrollElRef.current;
    if (!track || !el) return;
    const ratio = el.clientWidth / el.scrollWidth;
    if (ratio >= 1) return;
    const rect = track.getBoundingClientRect();
    const thumbWidth = rect.width * ratio;
    const maxThumbOffset = rect.width - thumbWidth;
    if (maxThumbOffset <= 0) return;
    const targetFraction = Math.max(0, Math.min(
      1,
      (e.clientX - rect.left - thumbWidth / 2) / maxThumbOffset
    ));
    const targetScrollLeft = targetFraction * (el.scrollWidth - el.clientWidth);
    el.scrollTo({ left: targetScrollLeft, behavior: "smooth" });
  }, []);
  const onTrackWheel = useCallback((e) => {
    const el = scrollElRef.current;
    if (!el) return;
    e.preventDefault();
    el.scrollLeft += e.deltaX || e.deltaY;
  }, []);
  const onThumbPointerDown = useCallback((e) => {
    e.preventDefault();
    e.stopPropagation();
    const el = scrollElRef.current;
    if (!el) return;
    isDraggingRef.current = true;
    dragStartRef.current = { mouseX: e.clientX, scrollLeft: el.scrollLeft };
    const target = e.currentTarget;
    target.setPointerCapture(e.pointerId);
    target.style.cursor = "grabbing";
  }, []);
  const onThumbPointerMove = useCallback((e) => {
    if (!isDraggingRef.current) return;
    const el = scrollElRef.current;
    const track = trackRef.current;
    if (!el || !track) return;
    const currentThumbRatio = el.clientWidth / el.scrollWidth;
    if (currentThumbRatio >= 1) return;
    const trackWidth = track.clientWidth;
    const thumbWidth = trackWidth * currentThumbRatio;
    const maxThumbTravel = trackWidth - thumbWidth;
    if (maxThumbTravel <= 0) return;
    const mouseDelta = e.clientX - dragStartRef.current.mouseX;
    const scrollRange = el.scrollWidth - el.clientWidth;
    el.scrollLeft = Math.min(
      Math.max(dragStartRef.current.scrollLeft + mouseDelta / maxThumbTravel * scrollRange, 0),
      scrollRange
    );
    syncThumbToDOM();
    syncEdgeFades();
  }, [syncThumbToDOM, syncEdgeFades]);
  const onThumbPointerUp = useCallback((e) => {
    isDraggingRef.current = false;
    const target = e.currentTarget;
    target.releasePointerCapture(e.pointerId);
    target.style.cursor = "grab";
  }, []);
  return {
    scrollRef,
    trackRef,
    thumbRef,
    thumbRatio,
    canScrollLeft,
    canScrollRight,
    onScroll,
    onTrackClick,
    onTrackWheel,
    onThumbPointerDown,
    onThumbPointerMove,
    onThumbPointerUp
  };
}

// src/hooks/ui/use-image-edge-color.ts
import { useState as useState3, useEffect as useEffect2 } from "react";
function extractEdgeColor(img) {
  const canvas = document.createElement("canvas");
  const ctx = canvas.getContext("2d");
  if (!ctx) return "#000000";
  const maxSize = 100;
  const scale = Math.min(maxSize / img.naturalWidth, maxSize / img.naturalHeight);
  const w = Math.round(img.naturalWidth * scale);
  const h = Math.round(img.naturalHeight * scale);
  canvas.width = w;
  canvas.height = h;
  ctx.drawImage(img, 0, 0, w, h);
  const data = ctx.getImageData(0, 0, w, h).data;
  const edgeW = Math.max(2, Math.round(w * 0.15));
  const edgeH = Math.max(2, Math.round(h * 0.15));
  const bucketSize = 32;
  const buckets = /* @__PURE__ */ new Map();
  for (let y = 0; y < h; y++) {
    for (let x = 0; x < w; x++) {
      const isEdge = x < edgeW || x >= w - edgeW || y < edgeH || y >= h - edgeH;
      if (!isEdge) continue;
      const i = (y * w + x) * 4;
      const a = data[i + 3];
      if (a < 128) continue;
      const r2 = data[i];
      const g2 = data[i + 1];
      const b2 = data[i + 2];
      const br = Math.floor(r2 / bucketSize) * bucketSize;
      const bg = Math.floor(g2 / bucketSize) * bucketSize;
      const bb = Math.floor(b2 / bucketSize) * bucketSize;
      const key = `${br},${bg},${bb}`;
      const existing = buckets.get(key);
      if (existing) {
        existing.r += r2;
        existing.g += g2;
        existing.b += b2;
        existing.count++;
      } else {
        buckets.set(key, { r: r2, g: g2, b: b2, count: 1 });
      }
    }
  }
  if (buckets.size === 0) return "#000000";
  let bestBucket = null;
  for (const bucket of buckets.values()) {
    if (!bestBucket || bucket.count > bestBucket.count) {
      bestBucket = bucket;
    }
  }
  if (!bestBucket || bestBucket.count === 0) return "#000000";
  const r = Math.round(bestBucket.r / bestBucket.count);
  const g = Math.round(bestBucket.g / bestBucket.count);
  const b = Math.round(bestBucket.b / bestBucket.count);
  return `rgb(${r}, ${g}, ${b})`;
}
function useImageEdgeColor(imageUrl, fallback = "#000000") {
  const [color, setColor] = useState3(fallback);
  useEffect2(() => {
    if (!imageUrl) {
      setColor(fallback);
      return;
    }
    let cancelled = false;
    const img = new Image();
    img.crossOrigin = "anonymous";
    img.onload = () => {
      if (cancelled) return;
      try {
        setColor(extractEdgeColor(img));
      } catch {
        setColor(fallback);
      }
    };
    img.onerror = () => {
      if (cancelled) return;
      setColor(fallback);
    };
    img.src = imageUrl;
    return () => {
      cancelled = true;
    };
  }, [imageUrl, fallback]);
  return color;
}

// src/hooks/ui/use-local-storage.ts
import { useEffect as useEffect3, useRef as useRef2, useState as useState4 } from "react";
function useLocalStorage(key, initialValue) {
  const [storedValue, setStoredValue] = useState4(() => {
    try {
      if (typeof window !== "undefined") {
        const item = window.localStorage.getItem(key);
        return item ? JSON.parse(item) : initialValue;
      }
    } catch (error) {
      console.error(`Error reading localStorage key "${key}":`, error);
    }
    return initialValue;
  });
  const isInitialized = useRef2(true);
  const isFromStorageEvent = useRef2(false);
  useEffect3(() => {
    if (!isInitialized.current) return;
    const handleStorageChange = (e) => {
      if (e.key === key && e.newValue !== null) {
        try {
          const newValue = JSON.parse(e.newValue);
          isFromStorageEvent.current = true;
          setStoredValue(newValue);
          console.log(`\u{1F504} Updated localStorage key "${key}" from storage event`);
        } catch (error) {
          console.error(`Error parsing storage event for key "${key}":`, error);
        }
      }
    };
    const handleCustomStorageUpdate = (e) => {
      if (e.detail.key === key) {
        try {
          if (e.detail.newValue === null || e.detail.newValue === void 0) {
            isFromStorageEvent.current = true;
            setStoredValue(initialValue);
            console.log(`\u{1F504} Cleared localStorage key "${key}" from custom storage event`);
          } else {
            const newValue = JSON.parse(e.detail.newValue);
            isFromStorageEvent.current = true;
            setStoredValue(newValue);
            console.log(`\u{1F504} Updated localStorage key "${key}" from custom storage event`);
          }
        } catch (error) {
          console.error(`Error parsing custom storage event for key "${key}":`, error);
        }
      }
    };
    window.addEventListener("storage", handleStorageChange);
    window.addEventListener("localStorageUpdate", handleCustomStorageUpdate);
    return () => {
      window.removeEventListener("storage", handleStorageChange);
      window.removeEventListener("localStorageUpdate", handleCustomStorageUpdate);
    };
  }, [key]);
  useEffect3(() => {
    if (!isInitialized.current) return;
    if (isFromStorageEvent.current) {
      isFromStorageEvent.current = false;
      return;
    }
    try {
      if (typeof window !== "undefined") {
        window.localStorage.setItem(key, JSON.stringify(storedValue));
      }
    } catch (error) {
      console.error(`Error writing to localStorage key "${key}":`, error);
    }
  }, [key, storedValue]);
  const setValue = (value) => {
    try {
      const valueToStore = value instanceof Function ? value(storedValue) : value;
      setStoredValue(valueToStore);
    } catch (error) {
      console.error(`Error setting value for localStorage key "${key}":`, error);
    }
  };
  return [storedValue, setValue];
}

// src/hooks/ui/use-media-query.ts
import { useLayoutEffect, useState as useState5 } from "react";
function useMediaQuery(query) {
  const [matches, setMatches] = useState5(void 0);
  useLayoutEffect(() => {
    const matchMedia = window.matchMedia(query);
    const handleChange = () => {
      setMatches(matchMedia.matches);
    };
    handleChange();
    matchMedia.addEventListener("change", handleChange);
    return () => {
      matchMedia.removeEventListener("change", handleChange);
    };
  }, [query]);
  return matches;
}
var breakpoints = {
  md: "(min-width: 800px)",
  // Tablet: 50rem
  lg: "(min-width: 1280px)"
  // Desktop: 80rem
};
function useSmUp() {
  return useMdUp();
}
function useMdUp() {
  const matches = useMediaQuery(breakpoints.md);
  return matches === void 0 ? void 0 : matches;
}
function useLgUp() {
  const matches = useMediaQuery(breakpoints.lg);
  return matches === void 0 ? void 0 : matches;
}

// src/hooks/ui/use-memoized-callback.ts
import { useCallback as useCallback2, useRef as useRef3 } from "react";
function useMemoizedCallback(callback, dependencies) {
  const callbackRef = useRef3(callback);
  const dependenciesRef = useRef3(dependencies);
  callbackRef.current = callback;
  const depsChanged = dependencies.some((dep, i) => !Object.is(dep, dependenciesRef.current[i]));
  if (depsChanged) {
    dependenciesRef.current = dependencies;
  }
  return useCallback2(((...args) => callbackRef.current(...args)), [depsChanged]);
}

// src/hooks/ui/use-notification-permission.ts
import { useCallback as useCallback3, useEffect as useEffect4, useState as useState6 } from "react";
function useNotificationPermission() {
  const [supported, setSupported] = useState6(false);
  const [permission, setPermission] = useState6("default");
  useEffect4(() => {
    if (typeof window === "undefined" || !("Notification" in window)) return;
    setSupported(true);
    const sync = () => setPermission(Notification.permission);
    sync();
    let cancelled = false;
    let status;
    navigator.permissions?.query({ name: "notifications" }).then((s) => {
      if (cancelled) return;
      status = s;
      s.addEventListener("change", sync);
    }).catch(() => void 0);
    document.addEventListener("visibilitychange", sync);
    window.addEventListener("focus", sync);
    return () => {
      cancelled = true;
      status?.removeEventListener("change", sync);
      document.removeEventListener("visibilitychange", sync);
      window.removeEventListener("focus", sync);
    };
  }, []);
  const request = useCallback3(async () => {
    if (typeof window === "undefined" || !("Notification" in window)) {
      return "denied";
    }
    const result = await new Promise((resolve) => {
      const maybePromise = Notification.requestPermission(resolve);
      if (maybePromise && typeof maybePromise.then === "function") void maybePromise.then(resolve);
    });
    setPermission(Notification.permission);
    return result;
  }, []);
  return { supported, permission, request };
}

// src/hooks/ui/use-onboarding-state.ts
import { useState as useState7, useEffect as useEffect5, useCallback as useCallback4 } from "react";

// src/utils/onboarding-storage.ts
var DEFAULT_STATE = {
  completedSteps: [],
  skippedSteps: [],
  dismissed: false,
  lastUpdated: (/* @__PURE__ */ new Date()).toISOString()
};
function saveOnboardingState(key, state) {
  if (typeof window === "undefined") return;
  try {
    localStorage.setItem(key, JSON.stringify(state));
    console.log("\u{1F4BE} Saved onboarding state:", state);
    if (typeof window !== "undefined") {
      window.dispatchEvent(
        new CustomEvent("localStorageUpdate", {
          detail: { key, newValue: JSON.stringify(state) }
        })
      );
    }
  } catch (err) {
    console.warn("[onboarding-storage] Failed saving to localStorage:", err);
  }
}
function loadOnboardingState(key) {
  if (typeof window === "undefined") return DEFAULT_STATE;
  try {
    const raw = localStorage.getItem(key);
    if (!raw) return DEFAULT_STATE;
    const parsed = JSON.parse(raw);
    return parsed;
  } catch (err) {
    console.warn("[onboarding-storage] Failed parsing localStorage data:", err);
    return DEFAULT_STATE;
  }
}
function markMultipleComplete(key, stepIds) {
  const state = loadOnboardingState(key);
  const newState = {
    ...state,
    completedSteps: [.../* @__PURE__ */ new Set([...state.completedSteps, ...stepIds])],
    skippedSteps: state.skippedSteps.filter((id) => !stepIds.includes(id)),
    lastUpdated: (/* @__PURE__ */ new Date()).toISOString()
  };
  saveOnboardingState(key, newState);
  return newState;
}
function markStepComplete(key, stepId) {
  return markMultipleComplete(key, [stepId]);
}
function markStepSkipped(key, stepId) {
  const state = loadOnboardingState(key);
  const newState = {
    ...state,
    skippedSteps: [.../* @__PURE__ */ new Set([...state.skippedSteps, stepId])],
    completedSteps: state.completedSteps.filter((id) => id !== stepId),
    lastUpdated: (/* @__PURE__ */ new Date()).toISOString()
  };
  saveOnboardingState(key, newState);
  return newState;
}
function dismissOnboarding(key) {
  const state = loadOnboardingState(key);
  const newState = {
    ...state,
    dismissed: true,
    lastUpdated: (/* @__PURE__ */ new Date()).toISOString()
  };
  saveOnboardingState(key, newState);
  return newState;
}

// src/hooks/ui/use-onboarding-state.ts
function useOnboardingState(storageKey = "openframe-onboarding-state") {
  const [state, setState] = useState7(() => loadOnboardingState(storageKey));
  const [, forceUpdate] = useState7(0);
  useEffect5(() => {
    const handleStorageUpdate = (e) => {
      if (e.detail.key === storageKey) {
        const newState = loadOnboardingState(storageKey);
        setState(newState);
        forceUpdate((prev) => prev + 1);
        console.log("\u{1F504} State updated from storage event:", newState);
      }
    };
    window.addEventListener("localStorageUpdate", handleStorageUpdate);
    return () => {
      window.removeEventListener("localStorageUpdate", handleStorageUpdate);
    };
  }, [storageKey]);
  const markComplete = useCallback4((stepId) => {
    console.log(`\u{1F3AF} markComplete called for: "${stepId}"`);
    const newState = markStepComplete(storageKey, stepId);
    setState(newState);
    forceUpdate((prev) => prev + 1);
  }, [storageKey]);
  const markSkipped = useCallback4((stepId) => {
    console.log(`\u23ED\uFE0F markSkipped called for: "${stepId}"`);
    const newState = markStepSkipped(storageKey, stepId);
    setState(newState);
    forceUpdate((prev) => prev + 1);
  }, [storageKey]);
  const dismissOnboarding2 = useCallback4(() => {
    console.log(`\u{1F6AB} dismissOnboarding called`);
    const newState = dismissOnboarding(storageKey);
    setState(newState);
    forceUpdate((prev) => prev + 1);
  }, [storageKey]);
  const markMultipleComplete2 = useCallback4((stepIds) => {
    console.log(`\u{1F3AF} markMultipleComplete called for:`, stepIds);
    const newState = markMultipleComplete(storageKey, stepIds);
    setState(newState);
    forceUpdate((prev) => prev + 1);
    console.log(`\u{1F4DD} State after batch:`, newState);
  }, [storageKey]);
  const isStepComplete = useCallback4((stepId) => {
    return state.completedSteps.includes(stepId);
  }, [state.completedSteps]);
  const isStepSkipped = useCallback4((stepId) => {
    return state.skippedSteps.includes(stepId);
  }, [state.skippedSteps]);
  const allStepsComplete = useCallback4((steps) => {
    return steps.every((step) => isStepComplete(step.id) || isStepSkipped(step.id));
  }, [isStepComplete, isStepSkipped]);
  return {
    state,
    markComplete,
    markSkipped,
    dismissOnboarding: dismissOnboarding2,
    isStepComplete,
    isStepSkipped,
    allStepsComplete,
    markMultipleComplete: markMultipleComplete2
  };
}

// src/hooks/ui/use-search.ts
import { useState as useState8, useEffect as useEffect6, useCallback as useCallback5 } from "react";
function useSearch(config) {
  const { searchFn, mapResult, debounceMs = 300, minQueryLength = 2 } = config;
  const [query, setQuery] = useState8("");
  const [results, setResults] = useState8([]);
  const [isLoading, setIsLoading] = useState8(false);
  const [error, setError] = useState8(null);
  const debouncedQuery = useDebounce(query, debounceMs);
  const clearResults = useCallback5(() => {
    setResults([]);
    setError(null);
  }, []);
  useEffect6(() => {
    if (!debouncedQuery || debouncedQuery.length < minQueryLength) {
      setResults([]);
      setIsLoading(false);
      setError(null);
      return;
    }
    let cancelled = false;
    const run = async () => {
      setIsLoading(true);
      setError(null);
      try {
        const rawResults = await searchFn(debouncedQuery);
        if (!cancelled) {
          setResults(rawResults.map(mapResult));
        }
      } catch (err) {
        if (!cancelled) {
          setError(err instanceof Error ? err.message : "Search failed");
          setResults([]);
        }
      } finally {
        if (!cancelled) {
          setIsLoading(false);
        }
      }
    };
    run();
    return () => {
      cancelled = true;
    };
  }, [debouncedQuery, minQueryLength]);
  return { query, setQuery, results, isLoading, error, clearResults };
}

// src/hooks/ui/use-table-pagination.ts
import { useMemo } from "react";
function useTablePagination(config) {
  return useMemo(() => {
    if (!config) return void 0;
    if (config.type === "client") {
      if (config.totalPages <= 1) return void 0;
      return {
        hasNextPage: config.currentPage < config.totalPages,
        hasPreviousPage: config.currentPage > 1,
        isFirstPage: config.currentPage === 1,
        startCursor: (config.currentPage - 1).toString(),
        endCursor: config.currentPage.toString(),
        currentCount: config.itemCount,
        itemName: config.itemName || "items",
        onNext: () => config.onNext(),
        onPrevious: () => config.onPrevious(),
        showInfo: config.showInfo ?? true
      };
    } else {
      return {
        hasNextPage: config.hasNextPage,
        hasPreviousPage: config.hasLoadedBeyondFirst,
        isFirstPage: !config.hasLoadedBeyondFirst,
        startCursor: config.startCursor,
        endCursor: config.endCursor,
        currentCount: config.itemCount,
        itemName: config.itemName || "items",
        onNext: config.onNext,
        onPrevious: config.onReset,
        // Previous button goes back to first page
        showInfo: config.showInfo ?? true
      };
    }
  }, [config]);
}

// src/hooks/ui/use-throttle.ts
import { useState as useState9, useEffect as useEffect7, useRef as useRef4 } from "react";
function useThrottle(value, limit = 200) {
  const [throttledValue, setThrottledValue] = useState9(value);
  const lastUpdated = useRef4(Date.now());
  useEffect7(() => {
    const now = Date.now();
    const elapsed = now - lastUpdated.current;
    if (elapsed >= limit) {
      setThrottledValue(value);
      lastUpdated.current = now;
    } else {
      const timerId = setTimeout(() => {
        setThrottledValue(value);
        lastUpdated.current = Date.now();
      }, limit - elapsed);
      return () => {
        clearTimeout(timerId);
      };
    }
  }, [value, limit]);
  return throttledValue;
}

// src/hooks/ui/use-window-size.ts
import { useLayoutEffect as useLayoutEffect2, useState as useState10 } from "react";
function useWindowSize() {
  const [windowSize, setWindowSize] = useState10({
    width: 0,
    height: 0
  });
  const [isClient, setIsClient] = useState10(false);
  useLayoutEffect2(() => {
    setIsClient(true);
    if (!isClient) return;
    const handleResize = () => {
      setWindowSize({
        width: window.innerWidth,
        height: window.innerHeight
      });
    };
    handleResize();
    window.addEventListener("resize", handleResize);
    return () => window.removeEventListener("resize", handleResize);
  }, [isClient]);
  return windowSize;
}

// src/hooks/platform/use-platform-config.ts
import { useState as useState11, useEffect as useEffect8 } from "react";

// src/utils/platform-config.tsx
import { Globe } from "lucide-react";
import { jsx } from "react/jsx-runtime";
var platformIcons = {
  openframe: /* @__PURE__ */ jsx(OpenFrameLogo, { className: "h-5 w-5", lowerPathColor: "#FFC008", upperPathColor: "#ffffff" }),
  openmsp: /* @__PURE__ */ jsx(OpenmspLogo, { className: "h-5 w-5" }),
  flamingo: /* @__PURE__ */ jsx(FlamingoLogo, { className: "h-5 w-5", fill: "#EC4899" }),
  "flamingo-teaser": /* @__PURE__ */ jsx(FlamingoLogo, { className: "h-5 w-5", fill: "#EC4899" }),
  "marketing-hub": /* @__PURE__ */ jsx(FlamingoLogo, { className: "h-5 w-5", fill: "#F357BB" }),
  "product-hub": /* @__PURE__ */ jsx(FlamingoLogo, { className: "h-5 w-5", fill: "#5EA62E" }),
  "revenue-hub": /* @__PURE__ */ jsx(FlamingoLogo, { className: "h-5 w-5", fill: "#FFC008" }),
  "people-hub": /* @__PURE__ */ jsx(FlamingoLogo, { className: "h-5 w-5", fill: "#5EFAF0" }),
  "company-hub": /* @__PURE__ */ jsx(FlamingoLogo, { className: "h-5 w-5", fill: "#f36666" }),
  tmcg: /* @__PURE__ */ jsx(MiamiCyberGangLogoFaceOnly, { className: "h-5 w-5" }),
  universal: /* @__PURE__ */ jsx(Globe, { className: "h-5 w-5 text-[#10B981]" })
};
var platformColors = {
  openmsp: "bg-[#3B82F6]",
  openframe: "bg-[#8B5CF6]",
  flamingo: "bg-[#EC4899]",
  "flamingo-teaser": "bg-[#F59E0B]",
  "marketing-hub": "bg-[#F357BB]",
  "product-hub": "bg-[#5EA62E]",
  "revenue-hub": "bg-[#FFC008]",
  "people-hub": "bg-[#5EFAF0]",
  "company-hub": "bg-[#f36666]",
  tmcg: "bg-[#FF6B6B]",
  universal: "bg-[#10B981]"
};
var platformDisplayNames = {
  openmsp: "OpenMSP",
  openframe: "OpenFrame",
  flamingo: "Flamingo",
  "flamingo-teaser": "Flamingo Teaser",
  "marketing-hub": "Flamingo Marketing Hub",
  "product-hub": "Flamingo Product Hub",
  "revenue-hub": "Flamingo Revenue Hub",
  "people-hub": "Flamingo People Hub",
  "company-hub": "Flamingo Company Hub",
  tmcg: "TMCG",
  universal: "Universal"
};
var platformDescriptions = {
  openmsp: "Comprehensive directory and comparison platform for managed service providers (MSPs) and technology vendors. Reduce vendor costs and discover open-source alternatives.",
  openframe: "AI-driven open-source security operations center (SOC) and endpoint detection platform for MSPs.",
  flamingo: "AI-driven open-source OS for MSPs. Swap bloated vendor tools for open ones. Automate the boring crap. Take your margin back.",
  "flamingo-teaser": "Preview of Flamingo - the AI-driven open-source OS for MSPs.",
  tmcg: "The Miami Cyber Gang - A cybersecurity community focused on education and collaboration.",
  universal: "Cross-platform universal content."
};
var platformSlogans = {
  openmsp: "Find Your Perfect MSP Partner",
  openframe: "Open-Source Security Operations",
  flamingo: "Open-Source OS for MSPs",
  "flamingo-teaser": "Coming Soon: Open-Source OS for MSPs",
  tmcg: "Miami Cyber Community",
  universal: "Universal Platform"
};
var platformHexColors = {
  openmsp: "#FFC008",
  openframe: "#FFC008",
  flamingo: "#FF6B9D",
  universal: "#FFC008",
  "flamingo-teaser": "#F59E0B",
  "marketing-hub": "#F357BB",
  "product-hub": "#5EA62E",
  "revenue-hub": "#FFC008",
  "people-hub": "#5EFAF0",
  "company-hub": "#f36666",
  tmcg: "#FF6B6B"
};
var platformIconNames = {
  openmsp: "openmsp-logo",
  openframe: "openframe-logo",
  flamingo: "flamingo-logo",
  universal: "globe",
  "flamingo-teaser": "flamingo-logo",
  "marketing-hub": "flamingo-logo",
  "product-hub": "flamingo-logo",
  "revenue-hub": "flamingo-logo",
  "people-hub": "flamingo-logo",
  "company-hub": "flamingo-logo",
  tmcg: "tmcg-logo"
};
function getDefaultColorForPlatform(platformName) {
  return platformHexColors[platformName] || platformHexColors.universal;
}
function getDefaultIconForPlatform(platformName) {
  return platformIconNames[platformName] || platformIconNames.universal;
}
function transformPlatformConfigsToOptions(platformConfigs) {
  return platformConfigs.map((platform) => ({
    id: platform.id,
    // Database UUID for matching
    name: platform.name,
    // Platform name enum
    displayName: platform.display_name,
    // Human-readable name
    description: platform.description,
    icon: platformIcons[platform.name] || platformIcons.universal,
    color: platformColors[platform.name] || platformColors.universal
  }));
}
function getPlatformIcon(platformName) {
  return platformIcons[platformName] || platformIcons.universal;
}
function getPlatformColor(platformName) {
  return platformColors[platformName] || platformColors.universal;
}
function getPlatformDisplayName(platformName) {
  return platformDisplayNames[platformName] || platformName;
}
function getPlatformDescription(platformName) {
  return platformDescriptions[platformName] || platformName;
}
function getPlatformSlogan(platformName) {
  return platformSlogans[platformName] || platformName;
}
function getSmallPlatformIcon(platformName) {
  const className = "h-4 w-4 flex-shrink-0";
  switch (platformName) {
    case "openframe":
      return /* @__PURE__ */ jsx(OpenFrameLogo, { className, lowerPathColor: "#FFC008", upperPathColor: "#ffffff" });
    case "openmsp":
      return /* @__PURE__ */ jsx(OpenmspLogo, { className, frontBubbleColor: "#f1f1f1", innerFrontBubbleColor: "#000000", backBubbleColor: "#FFC008" });
    case "flamingo":
    case "flamingo-teaser":
      return /* @__PURE__ */ jsx(FlamingoLogo, { className: `${className}`, fill: "#EC4899" });
    case "marketing-hub":
      return /* @__PURE__ */ jsx(FlamingoLogo, { className, fill: "var(--ods-flamingo-pink-base)" });
    case "product-hub":
      return /* @__PURE__ */ jsx(FlamingoLogo, { className, fill: "var(--ods-attention-green-success)" });
    case "revenue-hub":
      return /* @__PURE__ */ jsx(FlamingoLogo, { className, fill: "var(--ods-attention-yellow-warning)" });
    case "people-hub":
      return /* @__PURE__ */ jsx(FlamingoLogo, { className, fill: "var(--ods-flamingo-cyan-base)" });
    case "company-hub":
      return /* @__PURE__ */ jsx(FlamingoLogo, { className, fill: "var(--ods-attention-red-error)" });
    case "tmcg":
      return /* @__PURE__ */ jsx(MiamiCyberGangLogoFaceOnly, { className });
    case "universal":
    default:
      return /* @__PURE__ */ jsx(Globe, { className });
  }
}
function getPlatformIconComponent(platformName, className = "h-6 w-6") {
  switch (platformName) {
    case "openframe":
      return /* @__PURE__ */ jsx(OpenFrameLogo, { className });
    case "openmsp":
      return /* @__PURE__ */ jsx(OpenmspLogo, { className, color: "#f1f1f1" });
    case "flamingo":
    case "flamingo-teaser":
      return /* @__PURE__ */ jsx(FlamingoLogo, { className: `${className} text-white` });
    case "marketing-hub":
      return /* @__PURE__ */ jsx(FlamingoLogo, { className, fill: "var(--ods-flamingo-pink-base)" });
    case "product-hub":
      return /* @__PURE__ */ jsx(FlamingoLogo, { className, fill: "var(--ods-attention-green-success)" });
    case "revenue-hub":
      return /* @__PURE__ */ jsx(FlamingoLogo, { className, fill: "var(--ods-attention-yellow-warning)" });
    case "people-hub":
      return /* @__PURE__ */ jsx(FlamingoLogo, { className, fill: "var(--ods-flamingo-cyan-base)" });
    case "company-hub":
      return /* @__PURE__ */ jsx(FlamingoLogo, { className, fill: "var(--ods-attention-red-error)" });
    case "tmcg":
      return /* @__PURE__ */ jsx(MiamiCyberGangLogoFaceOnly, { size: 24, className });
    case "universal":
    default:
      return /* @__PURE__ */ jsx(Globe, { className });
  }
}

// src/hooks/platform/use-platform-config.ts
var platformCache = null;
var fetchPromise = null;
function usePlatformConfig() {
  const [platforms, setPlatforms] = useState11(platformCache || []);
  const [isLoading, setIsLoading] = useState11(!platformCache);
  const [error, setError] = useState11(null);
  useEffect8(() => {
    if (platformCache) {
      setPlatforms(platformCache);
      setIsLoading(false);
      return;
    }
    if (fetchPromise) {
      fetchPromise.then((data) => {
        setPlatforms(data);
        setIsLoading(false);
      }).catch((err) => {
        setError(err);
        setIsLoading(false);
      });
      return;
    }
    console.log("\u{1F527} Fetching platform configurations from API (should only happen once)");
    fetchPromise = fetch("/api/config/platforms").then((response) => {
      if (!response.ok) {
        throw new Error(`Failed to fetch platform config: ${response.statusText}`);
      }
      return response.json();
    }).then((data) => {
      const platforms2 = data.platforms || data;
      console.log("\u2705 Platform configurations loaded:", platforms2.length, "platforms");
      platformCache = platforms2;
      fetchPromise = null;
      return platforms2;
    });
    fetchPromise.then((data) => {
      setPlatforms(data);
      setIsLoading(false);
    }).catch((err) => {
      console.error("\u274C Failed to fetch platform config:", err);
      setError(err);
      setIsLoading(false);
      fetchPromise = null;
    });
  }, []);
  const platformOptions = [
    { value: "all", label: "All Platforms" },
    ...platforms.map((platform) => ({
      value: platform.value,
      label: platform.label
    }))
  ];
  const selectableOptions = transformPlatformConfigsToOptions(platforms);
  return {
    platforms,
    platformOptions,
    selectableOptions,
    isLoading,
    error
  };
}
function usePlatformByValue(value) {
  const { platforms } = usePlatformConfig();
  return platforms.find((platform) => platform.value === value);
}
function useValidatePlatform(value) {
  const { platforms } = usePlatformConfig();
  return platforms.some((platform) => platform.value === value);
}

// src/hooks/use-toast.ts
import { toast as sonnerToast2 } from "sonner";

// src/components/ui/toaster.tsx
import * as React from "react";
import { Toaster as SonnerToaster, toast as sonnerToast } from "sonner";

// src/types/tool.types.ts
var ToolTypeValues = {
  TACTICAL_RMM: "TACTICAL_RMM",
  FLEET_MDM: "FLEET_MDM",
  MESHCENTRAL: "MESHCENTRAL",
  AUTHENTIK: "AUTHENTIK",
  OPENFRAME: "OPENFRAME",
  OPENFRAME_CHAT: "OPENFRAME_CHAT",
  OPENFRAME_CLIENT: "OPENFRAME_CLIENT",
  OSQUERY: "OSQUERY",
  SYSTEM: "SYSTEM"
};
var toolLabels = {
  TACTICAL_RMM: "Tactical",
  FLEET_MDM: "Fleet",
  MESHCENTRAL: "MeshCentral",
  AUTHENTIK: "Authentik",
  OPENFRAME: "OpenFrame",
  OPENFRAME_CHAT: "OpenFrame Chat",
  OPENFRAME_CLIENT: "OpenFrame Client",
  OSQUERY: "Osquery",
  SYSTEM: "System"
};

// src/components/tool-icon.tsx
import { Fragment, jsx as jsx2 } from "react/jsx-runtime";
var renderOpenFrameLogo = (_size, className) => (
  // eslint-disable-next-line deprecation/deprecation
  /* @__PURE__ */ jsx2(
    OpenFrameLogo,
    {
      className: className ?? "h-4 w-auto",
      lowerPathColor: "var(--color-accent-primary)",
      upperPathColor: "var(--color-text-primary)"
    }
  )
);
var toolIconMap = {
  [ToolTypeValues.FLEET_MDM]: (size, className) => /* @__PURE__ */ jsx2(FleetMdmLogoGreyIcon, { size, className }),
  [ToolTypeValues.MESHCENTRAL]: (size, className) => /* @__PURE__ */ jsx2(MeshcentralLogoGreyIcon, { size, className }),
  [ToolTypeValues.TACTICAL_RMM]: (size, className) => /* @__PURE__ */ jsx2(TacticalRmmLogoIcon, { size, className }),
  [ToolTypeValues.OPENFRAME]: renderOpenFrameLogo,
  [ToolTypeValues.OPENFRAME_CHAT]: renderOpenFrameLogo,
  [ToolTypeValues.OPENFRAME_CLIENT]: renderOpenFrameLogo,
  [ToolTypeValues.AUTHENTIK]: (size, className) => /* @__PURE__ */ jsx2(AuthentikLogoGreyIcon, { size, className }),
  [ToolTypeValues.OSQUERY]: (size, className) => /* @__PURE__ */ jsx2(OsqueryLogoGreyIcon, { size, className }),
  [ToolTypeValues.SYSTEM]: () => null
};
var ToolIcon = ({ toolType, size = 16, className }) => /* @__PURE__ */ jsx2(Fragment, { children: toolIconMap[toolType]?.(size, className) ?? null });
ToolIcon.displayName = "ToolIcon";

// src/components/ui/toaster.tsx
init_cn();
import { Fragment as Fragment2, jsx as jsx3, jsxs } from "react/jsx-runtime";
var dotColorByVariant = {
  default: "bg-ods-text-secondary",
  success: "bg-ods-success",
  warning: "bg-ods-warning",
  error: "bg-ods-error",
  info: "bg-ods-text-secondary"
};
var progressColorByVariant = {
  default: "bg-ods-text-secondary",
  success: "bg-ods-success",
  warning: "bg-ods-warning",
  error: "bg-ods-error",
  info: "bg-ods-text-secondary"
};
function ToastHeader({
  id,
  variant,
  title,
  description,
  duration = 4e3,
  dismissible = true,
  className,
  showProgress = true
}) {
  return /* @__PURE__ */ jsxs(
    "div",
    {
      className: cn(
        "relative flex w-full items-start gap-2 overflow-hidden bg-ods-card p-3",
        className
      ),
      children: [
        /* @__PURE__ */ jsx3("div", { className: "flex size-6 shrink-0 items-center justify-center", children: /* @__PURE__ */ jsx3("span", { className: cn("size-[9px] rounded-full", dotColorByVariant[variant]) }) }),
        /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-1 flex-col justify-center font-['DM_Sans'] font-medium", children: [
          title ? /* @__PURE__ */ jsx3("p", { className: "truncate pr-5 text-[18px] leading-6 text-ods-text-primary", title: typeof title === "string" ? title : void 0, children: title }) : null,
          description ? /* @__PURE__ */ jsx3("p", { className: "text-[14px] leading-5 text-ods-text-secondary line-clamp-3", title: typeof description === "string" ? description : void 0, children: description }) : null
        ] }),
        dismissible ? /* @__PURE__ */ jsx3(
          "button",
          {
            type: "button",
            "aria-label": "Close",
            onClick: () => sonnerToast.dismiss(id),
            className: "absolute right-[7px] top-[7px] flex size-4 items-center justify-center text-ods-text-secondary transition-colors hover:text-ods-text-primary",
            children: /* @__PURE__ */ jsx3(XmarkIcon, { size: 16 })
          }
        ) : null,
        showProgress && duration !== Infinity && duration > 0 ? /* @__PURE__ */ jsx3(
          "div",
          {
            className: cn(
              "absolute inset-x-0 bottom-0 h-1 origin-left",
              progressColorByVariant[variant]
            ),
            style: {
              animation: `toast-progress ${duration}ms linear forwards`
            }
          }
        ) : null
      ]
    }
  );
}
function ToastCard({
  id,
  variant = "default",
  title,
  description,
  duration = 4e3,
  dismissible = true,
  className
}) {
  return /* @__PURE__ */ jsx3(
    "div",
    {
      role: "status",
      className: cn(
        "w-[368px] max-w-[calc(100vw-32px)] overflow-hidden rounded-md border border-ods-border bg-ods-card shadow-lg",
        className
      ),
      children: /* @__PURE__ */ jsx3(
        ToastHeader,
        {
          id,
          variant,
          title,
          description,
          duration,
          dismissible
        }
      )
    }
  );
}
function CommandApprovalToast({
  id,
  variant = "warning",
  title = "Tech Required",
  description = "Approval is required to execute the command.",
  command,
  toolType,
  approvalDescription,
  approveLabel = "Approve",
  rejectLabel = "Reject",
  onApprove,
  onReject,
  duration = Infinity,
  dismissible = true,
  defaultExpanded = false,
  className
}) {
  const [expanded, setExpanded] = React.useState(defaultExpanded);
  const handleApprove = () => {
    onApprove?.();
    sonnerToast.dismiss(id);
  };
  const handleReject = () => {
    onReject?.();
    sonnerToast.dismiss(id);
  };
  return /* @__PURE__ */ jsxs(
    "div",
    {
      role: "status",
      className: cn(
        "flex w-[368px] max-w-[calc(100vw-32px)] flex-col overflow-hidden rounded-md border border-ods-border bg-ods-bg shadow-lg",
        className
      ),
      children: [
        /* @__PURE__ */ jsx3(
          ToastHeader,
          {
            id,
            variant,
            title,
            description,
            duration,
            dismissible,
            showProgress: !expanded,
            className: "border-b border-ods-border"
          }
        ),
        /* @__PURE__ */ jsx3(
          "div",
          {
            className: "grid transition-[grid-template-rows] duration-300 ease-out",
            style: { gridTemplateRows: expanded ? "1fr" : "0fr" },
            "aria-hidden": !expanded,
            children: /* @__PURE__ */ jsxs("div", { className: "overflow-hidden", children: [
              /* @__PURE__ */ jsxs("div", { className: "flex h-11 w-full items-center gap-2 border-b border-ods-border bg-ods-card px-3 py-2", children: [
                /* @__PURE__ */ jsx3("p", { className: "min-w-0 flex-1 truncate font-['DM_Sans'] text-[14px] font-medium leading-5 text-ods-text-primary", title: command, children: command }),
                toolType ? /* @__PURE__ */ jsx3(ToolIcon, { toolType, size: 16 }) : null
              ] }),
              /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2 bg-ods-bg p-3", children: [
                approvalDescription ? /* @__PURE__ */ jsx3("p", { className: "font-['DM_Sans'] text-[14px] font-medium leading-5 text-ods-text-secondary", children: approvalDescription }) : null,
                /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-4", children: [
                  /* @__PURE__ */ jsx3(
                    "button",
                    {
                      type: "button",
                      onClick: handleApprove,
                      tabIndex: expanded ? 0 : -1,
                      className: "flex flex-1 items-center justify-center rounded-md bg-ods-accent px-2 py-2 font-['Azeret_Mono'] text-[14px] font-medium uppercase tracking-[-0.28px] text-ods-text-on-accent transition-colors hover:bg-ods-accent-hover active:bg-ods-accent-active",
                      children: approveLabel
                    }
                  ),
                  /* @__PURE__ */ jsx3(
                    "button",
                    {
                      type: "button",
                      onClick: handleReject,
                      tabIndex: expanded ? 0 : -1,
                      className: "flex flex-1 items-center justify-center rounded-md border border-ods-border bg-ods-card px-2 py-2 font-['Azeret_Mono'] text-[14px] font-medium uppercase tracking-[-0.28px] text-ods-text-primary transition-colors hover:bg-ods-bg-hover",
                      children: rejectLabel
                    }
                  )
                ] })
              ] })
            ] })
          }
        ),
        expanded ? null : /* @__PURE__ */ jsxs(
          "button",
          {
            type: "button",
            onClick: () => setExpanded(true),
            className: "flex w-full items-center gap-2 bg-ods-card px-3 py-2 text-left font-['DM_Sans'] text-[14px] font-medium leading-5 text-ods-text-primary transition-colors hover:bg-ods-bg-hover",
            "aria-expanded": false,
            children: [
              /* @__PURE__ */ jsx3("span", { className: "flex-1", children: "Show Command" }),
              /* @__PURE__ */ jsx3(Chevron02DownIcon, { size: 16 })
            ]
          }
        )
      ]
    }
  );
}
function Toaster({
  position = "bottom-right",
  offset = 24,
  gap = 8,
  toastOptions,
  ...rest
} = {}) {
  const { classNames: userClassNames, ...restToastOptions } = toastOptions ?? {};
  return /* @__PURE__ */ jsxs(Fragment2, { children: [
    /* @__PURE__ */ jsx3("style", { children: `
        @keyframes toast-progress {
          from { transform: scaleX(1); }
          to { transform: scaleX(0); }
        }
      ` }),
    /* @__PURE__ */ jsx3(
      SonnerToaster,
      {
        position,
        offset,
        gap,
        toastOptions: {
          unstyled: true,
          ...restToastOptions,
          classNames: {
            toast: "w-full",
            ...userClassNames
          }
        },
        ...rest
      }
    )
  ] });
}
function showToast(options) {
  const opts = typeof options === "string" ? { title: options } : options;
  const {
    title,
    description,
    variant = "default",
    duration = 4e3,
    dismissible = true,
    ...rest
  } = opts;
  return sonnerToast.custom(
    (id) => /* @__PURE__ */ jsx3(
      ToastCard,
      {
        id,
        variant,
        title,
        description,
        duration,
        dismissible
      }
    ),
    { duration, dismissible, ...rest }
  );
}
function showCommandApprovalToast(options) {
  const {
    variant,
    title,
    description,
    command,
    toolType,
    approvalDescription,
    approveLabel,
    rejectLabel,
    onApprove,
    onReject,
    defaultExpanded,
    duration = Infinity,
    dismissible = true,
    ...rest
  } = options;
  return sonnerToast.custom(
    (id) => /* @__PURE__ */ jsx3(
      CommandApprovalToast,
      {
        id,
        variant,
        title,
        description,
        command,
        toolType,
        approvalDescription,
        approveLabel,
        rejectLabel,
        onApprove,
        onReject,
        defaultExpanded,
        duration,
        dismissible
      }
    ),
    { duration, dismissible, ...rest }
  );
}

// src/hooks/use-toast.ts
var normalizeVariant = (variant) => {
  if (variant === "destructive") return "error";
  if (!variant) return "default";
  return variant;
};
var toast = (options) => {
  if (typeof options === "string") {
    return showToast({ title: options });
  }
  const { title, description, variant, duration, dismissible } = options;
  return showToast({
    title,
    description,
    variant: normalizeVariant(variant),
    duration,
    dismissible
  });
};
var useToast = () => ({
  toast,
  dismiss: sonnerToast2.dismiss,
  promise: sonnerToast2.promise
});

// src/hooks/use-contact-submission.ts
import { useState as useState13, useCallback as useCallback6, useEffect as useEffect9 } from "react";
init_next_navigation();
function useContactSubmission(options = {}) {
  const { userId, successRedirectUrl, successToastMessage, onSuccess } = options;
  const { toast: toast2 } = useToast();
  const router = useRouter();
  const { contactUrl } = useRequiredEndpointsRuntime();
  const [isSubmitting, setIsSubmitting] = useState13(false);
  const [isSuccess, setIsSuccess] = useState13(false);
  const submit = useCallback6(async (formData) => {
    if (isSubmitting) return;
    setIsSubmitting(true);
    try {
      const response = await fetch(contactUrl, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          ...formData,
          user_id: userId
        })
      });
      const data = await response.json();
      if (!response.ok) {
        throw new Error(data.error || "Failed to submit contact form");
      }
      setIsSuccess(true);
      const message = successToastMessage ? `Thank you! Your message has been sent. ${successToastMessage}` : "Thank you! Your message has been sent successfully.";
      toast2({
        title: "Message sent!",
        description: message,
        variant: "success"
      });
    } catch (error) {
      const message = error instanceof Error ? error.message : "Something went wrong. Please try again.";
      toast2({
        title: "Failed to send message",
        description: message,
        variant: "destructive"
      });
      throw error;
    } finally {
      setIsSubmitting(false);
    }
  }, [isSubmitting, toast2, userId, successToastMessage, contactUrl]);
  useEffect9(() => {
    if (isSuccess && successRedirectUrl) {
      console.log("\u{1F680} Contact submission successful, redirecting to:", successRedirectUrl);
      const timer = setTimeout(() => {
        console.log("\u{1F3AF} Performing redirect now to:", successRedirectUrl);
        if (successRedirectUrl.startsWith("http")) {
          window.location.href = successRedirectUrl;
        } else {
          router.push(successRedirectUrl);
        }
      }, 1500);
      return () => clearTimeout(timer);
    }
  }, [isSuccess, successRedirectUrl, router]);
  useEffect9(() => {
    if (isSuccess && onSuccess) {
      onSuccess();
    }
  }, [isSuccess, onSuccess]);
  return { submit, isSubmitting, isSuccess, setIsSuccess };
}

// src/hooks/use-quick-action-hint.ts
import { useEffect as useEffect10, useState as useState14, useRef as useRef5, useCallback as useCallback7 } from "react";
function useQuickActionHint({
  actionCount,
  cycleDuration = 5e3,
  enabled = true
}) {
  const [activeHintIndex, setActiveHintIndex] = useState14(-1);
  const containerRef = useRef5(null);
  const timeoutRef = useRef5(null);
  const cycleCountRef = useRef5(0);
  const currentIndexRef = useRef5(0);
  const sequenceRef = useRef5([]);
  const shuffleIndices = useCallback7((length) => {
    const indices = Array.from({ length }, (_, i) => i);
    for (let i = indices.length - 1; i > 0; i--) {
      const j = Math.floor(Math.random() * (i + 1));
      [indices[i], indices[j]] = [indices[j], indices[i]];
    }
    return indices;
  }, []);
  const stopHint = useCallback7(() => {
    if (timeoutRef.current) {
      clearTimeout(timeoutRef.current);
      timeoutRef.current = null;
    }
    setActiveHintIndex(-1);
    cycleCountRef.current = 0;
    currentIndexRef.current = 0;
    sequenceRef.current = [];
  }, []);
  const advanceHint = useCallback7(() => {
    if (currentIndexRef.current === 0) {
      sequenceRef.current = shuffleIndices(actionCount);
    }
    const nextIndex = sequenceRef.current[currentIndexRef.current];
    setActiveHintIndex(nextIndex);
    currentIndexRef.current++;
    if (currentIndexRef.current >= actionCount) {
      currentIndexRef.current = 0;
      cycleCountRef.current++;
    }
    timeoutRef.current = setTimeout(advanceHint, cycleDuration);
  }, [actionCount, cycleDuration, shuffleIndices]);
  useEffect10(() => {
    if (!enabled || actionCount === 0) {
      return;
    }
    if (typeof window !== "undefined") {
      const prefersReducedMotion = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
      if (prefersReducedMotion) return;
    }
    const startTimeout = setTimeout(() => {
      cycleCountRef.current = 0;
      currentIndexRef.current = 0;
      advanceHint();
    }, 500);
    return () => {
      clearTimeout(startTimeout);
      stopHint();
    };
  }, [enabled, actionCount, advanceHint, stopHint]);
  return {
    activeHintIndex,
    stopHint,
    containerRef
  };
}

// src/hooks/use-copy-to-clipboard.ts
import { useCallback as useCallback8, useState as useState15 } from "react";
function useCopyToClipboard({
  successTitle = "Copied",
  successDescription = "Copied to clipboard",
  errorTitle = "Copy failed",
  errorDescription = "Could not copy to clipboard",
  resetDelay = 2e3
} = {}) {
  const { toast: toast2 } = useToast();
  const [copied, setCopied] = useState15(false);
  const copy = useCallback8(
    async (text) => {
      try {
        await navigator.clipboard.writeText(text);
        setCopied(true);
        toast2({ title: successTitle, description: successDescription, variant: "success" });
        setTimeout(() => setCopied(false), resetDelay);
      } catch {
        toast2({ title: errorTitle, description: errorDescription, variant: "destructive" });
      }
    },
    [successTitle, successDescription, errorTitle, errorDescription, resetDelay, toast2]
  );
  return { copy, copied };
}

// src/hooks/use-batch-images.ts
import { useEffect as useEffect11, useMemo as useMemo2, useState as useState16, useRef as useRef6 } from "react";
var globalBatchImageConfig = {};
function configureBatchImageFetch(config) {
  globalBatchImageConfig = { ...globalBatchImageConfig, ...config };
}
function getBatchImageConfig() {
  return {
    tenantHostUrl: globalBatchImageConfig.tenantHostUrl || "",
    enableDevMode: globalBatchImageConfig.enableDevMode ?? false,
    accessTokenKey: globalBatchImageConfig.accessTokenKey || "of_access_token"
  };
}
async function batchFetchAuthenticatedImages(imageUrls, config) {
  const results = {};
  if (imageUrls.length === 0) {
    return results;
  }
  const { tenantHostUrl, enableDevMode, accessTokenKey } = {
    ...getBatchImageConfig(),
    ...config
  };
  const fetchPromises = imageUrls.map(async (imageUrl) => {
    try {
      let fullImageUrl;
      if (imageUrl.startsWith("http://") || imageUrl.startsWith("https://")) {
        fullImageUrl = imageUrl;
      } else if (imageUrl.startsWith("/api/")) {
        fullImageUrl = `${tenantHostUrl}${imageUrl}`;
      } else if (imageUrl.startsWith("/")) {
        fullImageUrl = `${tenantHostUrl}/api${imageUrl}`;
      } else {
        fullImageUrl = `${tenantHostUrl}/api/${imageUrl}`;
      }
      const cacheBuster = `?t=${Date.now()}`;
      fullImageUrl = fullImageUrl + cacheBuster;
      const headers = {
        "Accept": "image/*",
        "Cache-Control": "no-cache, no-store, must-revalidate",
        "Pragma": "no-cache"
      };
      if (enableDevMode) {
        try {
          const accessToken = localStorage.getItem(accessTokenKey);
          if (accessToken) {
            headers["Authorization"] = `Bearer ${accessToken}`;
          }
        } catch (error) {
        }
      }
      const response = await fetch(fullImageUrl, {
        method: "GET",
        credentials: "include",
        // Include cookies for authentication
        headers
      });
      if (!response.ok) {
        throw new Error(`Failed to fetch image: ${response.status}`);
      }
      const blob = await response.blob();
      const objectUrl = URL.createObjectURL(blob);
      return { imageUrl, fetchedUrl: objectUrl };
    } catch (error) {
      console.warn(`Failed to fetch image ${imageUrl}:`, error);
      return { imageUrl, fetchedUrl: void 0 };
    }
  });
  const fetchResults = await Promise.all(fetchPromises);
  fetchResults.forEach(({ imageUrl, fetchedUrl }) => {
    results[imageUrl] = fetchedUrl;
  });
  return results;
}
function useBatchImages(imageUrls, config) {
  const [fetchedImages, setFetchedImages] = useState16({});
  const [loading, setLoading] = useState16(false);
  const uniqueUrls = useMemo2(
    () => Array.from(new Set(imageUrls.filter((url) => Boolean(url)))),
    [imageUrls]
  );
  const requestedUrls = useRef6(/* @__PURE__ */ new Set());
  useEffect11(() => {
    if (uniqueUrls.length === 0) {
      setFetchedImages({});
      return;
    }
    const urlsToFetch = uniqueUrls.filter((url) => !requestedUrls.current.has(url));
    if (urlsToFetch.length === 0) {
      return;
    }
    urlsToFetch.forEach((url) => requestedUrls.current.add(url));
    setLoading(true);
    batchFetchAuthenticatedImages(urlsToFetch, config).then((newResults) => {
      setFetchedImages((prev) => ({ ...prev, ...newResults }));
    }).catch((error) => {
      console.error("Failed to batch fetch images:", error);
    }).finally(() => {
      setLoading(false);
    });
    return () => {
      Object.values(fetchedImages).forEach((blobUrl) => {
        if (blobUrl && blobUrl.startsWith("blob:")) {
          URL.revokeObjectURL(blobUrl);
        }
      });
    };
  }, [uniqueUrls, config]);
  return fetchedImages;
}

// src/hooks/use-authenticated-image.ts
import { useEffect as useEffect12, useState as useState17, useRef as useRef7 } from "react";
var globalImageConfig = {};
var imageCache = /* @__PURE__ */ new Map();
var pendingRequests = /* @__PURE__ */ new Map();
var CACHE_CLEANUP_INTERVAL = 5 * 60 * 1e3;
var CACHE_MAX_AGE = 30 * 60 * 1e3;
function cleanupImageCache() {
  const now = Date.now();
  for (const [key, entry] of imageCache.entries()) {
    if (entry.refCount === 0 && now - entry.timestamp > CACHE_MAX_AGE) {
      URL.revokeObjectURL(entry.blobUrl);
      imageCache.delete(key);
    }
  }
}
if (typeof window !== "undefined") {
  setInterval(cleanupImageCache, CACHE_CLEANUP_INTERVAL);
}
function configureAuthenticatedImage(config) {
  globalImageConfig = { ...globalImageConfig, ...config };
}
function getImageConfig() {
  return {
    tenantHostUrl: globalImageConfig.tenantHostUrl || "",
    enableDevMode: globalImageConfig.enableDevMode ?? false,
    accessTokenKey: globalImageConfig.accessTokenKey || "of_access_token"
  };
}
function useAuthenticatedImage(imageUrl, refreshKey, config) {
  const [fetchedImageUrl, setFetchedImageUrl] = useState17();
  const [isLoading, setIsLoading] = useState17(false);
  const [error, setError] = useState17(null);
  const currentCacheKeyRef = useRef7(null);
  useEffect12(() => {
    if (!imageUrl) {
      setFetchedImageUrl(void 0);
      setIsLoading(false);
      setError(null);
      if (currentCacheKeyRef.current) {
        const entry = imageCache.get(currentCacheKeyRef.current);
        if (entry) {
          entry.refCount--;
        }
        currentCacheKeyRef.current = null;
      }
      return;
    }
    const { tenantHostUrl, enableDevMode, accessTokenKey } = {
      ...getImageConfig(),
      ...config
    };
    let fullImageUrl;
    if (imageUrl.startsWith("http://") || imageUrl.startsWith("https://")) {
      fullImageUrl = imageUrl;
    } else if (imageUrl.startsWith("/api/")) {
      fullImageUrl = `${tenantHostUrl}${imageUrl}`;
    } else if (imageUrl.startsWith("/")) {
      fullImageUrl = `${tenantHostUrl}/api${imageUrl}`;
    } else {
      fullImageUrl = `${tenantHostUrl}/api/${imageUrl}`;
    }
    const cacheKey = refreshKey ? `${fullImageUrl}?v=${refreshKey}` : fullImageUrl;
    if (currentCacheKeyRef.current && currentCacheKeyRef.current !== cacheKey) {
      const prevEntry = imageCache.get(currentCacheKeyRef.current);
      if (prevEntry) {
        prevEntry.refCount--;
      }
    }
    currentCacheKeyRef.current = cacheKey;
    const cachedEntry = imageCache.get(cacheKey);
    if (cachedEntry) {
      cachedEntry.refCount++;
      cachedEntry.timestamp = Date.now();
      setFetchedImageUrl(cachedEntry.blobUrl);
      setIsLoading(false);
      setError(null);
      return;
    }
    const pendingRequest = pendingRequests.get(cacheKey);
    if (pendingRequest) {
      setIsLoading(true);
      setError(null);
      pendingRequest.then((blobUrl) => {
        if (blobUrl) {
          const entry = imageCache.get(cacheKey);
          if (entry) {
            entry.refCount++;
            setFetchedImageUrl(blobUrl);
          }
        }
        setIsLoading(false);
      }).catch((err) => {
        setError(err instanceof Error ? err.message : "Failed to fetch image");
        setIsLoading(false);
      });
      return;
    }
    setIsLoading(true);
    setError(null);
    const requestUrl = refreshKey ? cacheKey : `${fullImageUrl}?t=${Date.now()}`;
    const headers = {
      "Accept": "image/*",
      "Cache-Control": "no-cache, no-store, must-revalidate",
      "Pragma": "no-cache"
    };
    if (enableDevMode) {
      try {
        const accessToken = localStorage.getItem(accessTokenKey);
        if (accessToken) {
          headers["Authorization"] = `Bearer ${accessToken}`;
        }
      } catch (error2) {
      }
    }
    const fetchPromise2 = fetch(requestUrl, {
      method: "GET",
      credentials: "include",
      // Include cookies for authentication
      headers
    }).then((response) => {
      if (!response.ok) {
        throw new Error(`Failed to fetch image: ${response.status}`);
      }
      return response.blob();
    }).then((blob) => {
      const objectUrl = URL.createObjectURL(blob);
      imageCache.set(cacheKey, {
        blobUrl: objectUrl,
        timestamp: Date.now(),
        refCount: 1
      });
      setFetchedImageUrl(objectUrl);
      setIsLoading(false);
      return objectUrl;
    }).catch((err) => {
      setError(err instanceof Error ? err.message : "Failed to fetch image");
      setFetchedImageUrl(void 0);
      setIsLoading(false);
      throw err;
    }).finally(() => {
      pendingRequests.delete(cacheKey);
    });
    pendingRequests.set(cacheKey, fetchPromise2);
  }, [imageUrl, refreshKey, config]);
  useEffect12(() => {
    return () => {
      if (currentCacheKeyRef.current) {
        const entry = imageCache.get(currentCacheKeyRef.current);
        if (entry) {
          entry.refCount--;
        }
      }
    };
  }, []);
  return { imageUrl: fetchedImageUrl, isLoading, error };
}

// src/hooks/state/use-query-params.ts
init_next_navigation();
import { useEffect as useEffect13, useState as useState18, useMemo as useMemo3, useCallback as useCallback9 } from "react";

// src/hooks/state/graphql-parser.ts
import {
  visit
} from "graphql";
function extractVariablesFromQuery(query) {
  const variables = {};
  visit(query, {
    VariableDefinition(node) {
      const name = node.variable.name.value;
      const typeInfo = parseGraphQLType(node.type);
      variables[name] = {
        name,
        type: mapGraphQLTypeToJS(typeInfo.typeName),
        required: typeInfo.isNonNull,
        isArray: typeInfo.isList,
        graphqlTypeName: typeInfo.typeName
      };
    }
  });
  return variables;
}
function parseGraphQLType(typeNode) {
  let typeName = "";
  let isNonNull = false;
  let isList = false;
  if (typeNode.kind === "NonNullType") {
    isNonNull = true;
    typeNode = typeNode.type;
  }
  if (typeNode.kind === "ListType") {
    isList = true;
    typeNode = typeNode.type;
    if (typeNode.kind === "NonNullType") {
      typeNode = typeNode.type;
    }
  }
  if (typeNode.kind === "NamedType") {
    typeName = typeNode.name.value;
  }
  return {
    typeName,
    isNonNull,
    isList
  };
}
function mapGraphQLTypeToJS(graphqlType) {
  const scalarTypeMap = {
    "String": "string",
    "Int": "number",
    "Float": "number",
    "Boolean": "boolean",
    "ID": "string"
  };
  if (scalarTypeMap[graphqlType]) {
    return scalarTypeMap[graphqlType];
  }
  return "object";
}
function isScalarType(graphqlTypeName) {
  const scalars = ["String", "Int", "Float", "Boolean", "ID"];
  return scalars.includes(graphqlTypeName);
}
function isInputObjectType(graphqlTypeName) {
  return !isScalarType(graphqlTypeName);
}

// src/hooks/state/flatten-schema.ts
async function flattenQueryVariables(queryVariables, introspector2) {
  const flattened = {};
  for (const [varName, varDef] of Object.entries(queryVariables)) {
    if (varDef.type !== "object") {
      flattened[varName] = {
        urlParamName: varName,
        graphqlPath: varName,
        type: varDef.isArray ? "array" : varDef.type,
        required: varDef.required,
        isArray: varDef.isArray
      };
      continue;
    }
    if (introspector2.isLoaded() && introspector2.hasType(varDef.graphqlTypeName)) {
      const fields = introspector2.getInputTypeFields(varDef.graphqlTypeName);
      for (const [fieldName, fieldDef] of Object.entries(fields)) {
        flattened[fieldName] = {
          urlParamName: fieldName,
          graphqlPath: `${varName}.${fieldName}`,
          type: fieldDef.isArray ? "array" : fieldDef.type,
          required: fieldDef.required,
          isArray: fieldDef.isArray
        };
      }
    } else {
      flattened[varName] = {
        urlParamName: varName,
        graphqlPath: varName,
        type: "object",
        required: varDef.required,
        isArray: false
      };
    }
  }
  return flattened;
}
function mergeDefaults(schema, defaults) {
  const merged = {};
  for (const [key, param] of Object.entries(schema)) {
    merged[key] = {
      ...param,
      defaultValue: defaults[key] !== void 0 ? defaults[key] : param.defaultValue
    };
  }
  return merged;
}
function validateSchema(schema) {
  const urlParamNames = /* @__PURE__ */ new Set();
  for (const [key, param] of Object.entries(schema)) {
    if (urlParamNames.has(param.urlParamName)) {
      throw new Error(
        `[FlattenSchema] Conflict: Multiple parameters map to URL param "${param.urlParamName}"`
      );
    }
    urlParamNames.add(param.urlParamName);
  }
}
function getArrayParams(schema) {
  return Object.entries(schema).filter(([_, param]) => param.type === "array" || param.isArray).map(([key]) => key);
}
function getRequiredParams(schema) {
  return Object.entries(schema).filter(([_, param]) => param.required).map(([key]) => key);
}
function shouldIncludeInUrl(value, param) {
  if (value === null || value === void 0) {
    return false;
  }
  if (Array.isArray(value) && value.length === 0) {
    return false;
  }
  if (value === "") {
    return false;
  }
  if (param.defaultValue !== void 0 && value === param.defaultValue) {
    return false;
  }
  return true;
}

// src/hooks/state/url-converter.ts
function urlParamsToVariables(searchParams, schema) {
  const variables = {};
  for (const [paramName, paramConfig] of Object.entries(schema)) {
    const rawValue = paramConfig.type === "array" || paramConfig.isArray ? searchParams.getAll(paramName) : searchParams.get(paramName);
    if (!rawValue || Array.isArray(rawValue) && rawValue.length === 0) {
      if (paramConfig.defaultValue !== void 0) {
        setNestedValue(variables, paramConfig.graphqlPath, paramConfig.defaultValue);
      }
      continue;
    }
    const value = coerceValue(rawValue, paramConfig.type);
    setNestedValue(variables, paramConfig.graphqlPath, value);
  }
  return variables;
}
function variablesToUrlParams(variables, schema) {
  const params = new URLSearchParams();
  for (const [paramName, paramConfig] of Object.entries(schema)) {
    const value = getNestedValue(variables, paramConfig.graphqlPath);
    if (!shouldIncludeInUrl(value, paramConfig)) {
      continue;
    }
    if (Array.isArray(value)) {
      value.forEach((v) => {
        if (v !== null && v !== void 0 && v !== "") {
          params.append(paramName, String(v));
        }
      });
    } else {
      params.set(paramName, String(value));
    }
  }
  return params;
}
function coerceValue(value, type) {
  if (Array.isArray(value)) {
    return value.map((v) => coerceValue(v, type === "array" ? "string" : type));
  }
  switch (type) {
    case "number":
      const num = parseFloat(value);
      return isNaN(num) ? null : num;
    case "boolean":
      return value === "true" || value === "1";
    case "array":
      return [value];
    case "string":
    default:
      return value;
  }
}
function setNestedValue(obj, path, value) {
  const parts = path.split(".");
  let current = obj;
  for (let i = 0; i < parts.length - 1; i++) {
    const part = parts[i];
    if (!(part in current) || typeof current[part] !== "object") {
      current[part] = {};
    }
    current = current[part];
  }
  const lastPart = parts[parts.length - 1];
  current[lastPart] = value;
}
function getNestedValue(obj, path) {
  return path.split(".").reduce((current, key) => {
    return current?.[key];
  }, obj);
}
function mergeVariables(currentVariables, updates, schema) {
  const merged = { ...currentVariables };
  for (const [paramName, value] of Object.entries(updates)) {
    const paramConfig = schema[paramName];
    if (!paramConfig) continue;
    setNestedValue(merged, paramConfig.graphqlPath, value);
  }
  return merged;
}
function clearParams(variables, paramNames, schema) {
  const cleared = { ...variables };
  for (const paramName of paramNames) {
    const paramConfig = schema[paramName];
    if (!paramConfig) continue;
    setNestedValue(cleared, paramConfig.graphqlPath, void 0);
  }
  return cleared;
}
function validateVariables(variables, schema) {
  const errors = [];
  for (const [paramName, paramConfig] of Object.entries(schema)) {
    const value = getNestedValue(variables, paramConfig.graphqlPath);
    if (paramConfig.required && (value === null || value === void 0)) {
      errors.push(`Required parameter "${paramName}" is missing`);
    }
    if (value !== null && value !== void 0) {
      const actualType = Array.isArray(value) ? "array" : typeof value;
      const expectedType = paramConfig.type === "array" ? "array" : paramConfig.type;
      if (actualType !== expectedType && actualType !== "object") {
        errors.push(
          `Parameter "${paramName}" has wrong type: expected ${expectedType}, got ${actualType}`
        );
      }
    }
  }
  return errors;
}

// src/hooks/state/introspection.ts
import {
  getIntrospectionQuery,
  buildClientSchema,
  isInputObjectType as isInputObjectType2
} from "graphql";
var GraphQLIntrospector = class {
  constructor() {
    this.schema = null;
    this.cacheKey = "graphql-schema-cache-v1";
    this.cacheDuration = 24 * 60 * 60 * 1e3;
    // 24 hours
    this.schemaVersion = "1.0.0";
  }
  /**
   * Fetch GraphQL schema via introspection query
   *
   * @param endpoint - GraphQL endpoint URL
   * @param headers - HTTP headers (e.g., authentication)
   * @param skipCache - Force fresh fetch, ignore cache
   *
   * @example
   * await introspector.fetchSchema(
   *   'http://localhost/api/graphql',
   *   { 'Authorization': 'Bearer token123' }
   * )
   */
  async fetchSchema(endpoint, headers = {}, skipCache = false) {
    if (!skipCache) {
      const cached = this.loadFromCache();
      if (cached && Date.now() - cached.timestamp < this.cacheDuration) {
        try {
          this.schema = buildClientSchema(cached.schema);
          return;
        } catch (error) {
          console.warn("[Introspector] Failed to build schema from cache:", error);
        }
      }
    }
    try {
      const response = await fetch(endpoint, {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
          ...headers
        },
        body: JSON.stringify({
          query: getIntrospectionQuery()
        })
      });
      if (!response.ok) {
        throw new Error(`HTTP ${response.status}: ${response.statusText}`);
      }
      const { data, errors } = await response.json();
      if (errors) {
        throw new Error(`GraphQL errors: ${JSON.stringify(errors)}`);
      }
      if (!data) {
        throw new Error("No data returned from introspection query");
      }
      this.schema = buildClientSchema(data);
      this.saveToCache(data);
    } catch (error) {
      console.error("[Introspector] Failed to fetch schema:", error);
      throw error;
    }
  }
  /**
   * Get fields from a GraphQL input object type
   *
   * @param typeName - Name of the input type (e.g., "LogFilterInput")
   * @returns Record of field definitions
   *
   * @example
   * const fields = introspector.getInputTypeFields('LogFilterInput')
   * // {
   * //   severity: { name: 'severity', type: 'array', ... },
   * //   toolType: { name: 'toolType', type: 'array', ... }
   * // }
   */
  getInputTypeFields(typeName) {
    if (!this.schema) {
      return {};
    }
    const type = this.schema.getType(typeName);
    if (!type || !isInputObjectType2(type)) {
      return {};
    }
    const fields = {};
    const typeFields = type.getFields();
    for (const [fieldName, field] of Object.entries(typeFields)) {
      const fieldType = this.unwrapType(field.type);
      fields[fieldName] = {
        name: fieldName,
        type: this.mapGraphQLTypeToJS(fieldType.typeName),
        required: fieldType.isNonNull,
        isArray: fieldType.isList,
        graphqlTypeName: fieldType.typeName
      };
    }
    return fields;
  }
  /**
   * Check if a type exists in the schema
   */
  hasType(typeName) {
    if (!this.schema) return false;
    return this.schema.getType(typeName) !== void 0;
  }
  /**
   * Get the schema (if loaded)
   */
  getSchema() {
    return this.schema;
  }
  /**
   * Check if schema is loaded
   */
  isLoaded() {
    return this.schema !== null;
  }
  /**
   * Clear cached schema
   */
  clearCache() {
    try {
      localStorage.removeItem(this.cacheKey);
      this.schema = null;
    } catch {
    }
  }
  /**
   * Unwrap GraphQL type to get base type info
   * Handles NonNull and List wrappers
   */
  unwrapType(type) {
    let typeName = "";
    let isNonNull = false;
    let isList = false;
    let current = type;
    if (current.toString().endsWith("!")) {
      isNonNull = true;
      current = "ofType" in current ? current.ofType : current;
    }
    if (current.toString().startsWith("[")) {
      isList = true;
      current = "ofType" in current ? current.ofType : current;
    }
    if (current.toString().endsWith("!")) {
      current = "ofType" in current ? current.ofType : current;
    }
    typeName = current.name || current.toString().replace(/[[\]!]/g, "");
    return { typeName, isNonNull, isList };
  }
  /**
   * Map GraphQL types to JavaScript types for URL handling
   */
  mapGraphQLTypeToJS(graphqlType) {
    const typeMap = {
      "String": "string",
      "Int": "number",
      "Float": "number",
      "Boolean": "boolean",
      "ID": "string"
    };
    return typeMap[graphqlType] || "object";
  }
  /**
   * Load schema from localStorage cache
   */
  loadFromCache() {
    try {
      const cached = localStorage.getItem(this.cacheKey);
      if (!cached) return null;
      const parsed = JSON.parse(cached);
      if (parsed.version !== this.schemaVersion) {
        return null;
      }
      return parsed;
    } catch (error) {
      console.warn("[Introspector] Failed to load cache:", error);
      return null;
    }
  }
  /**
   * Save schema to localStorage cache
   */
  saveToCache(schema) {
    try {
      const cache = {
        schema,
        timestamp: Date.now(),
        version: this.schemaVersion
      };
      localStorage.setItem(this.cacheKey, JSON.stringify(cache));
    } catch (error) {
      console.warn("[Introspector] Failed to save cache:", error);
    }
  }
};
var introspector = new GraphQLIntrospector();

// src/hooks/state/use-query-params.ts
function useQueryParams(query, options = {}) {
  const router = useRouter();
  const searchParams = useSearchParams();
  const [isLoading, setIsLoading] = useState18(true);
  const [isReady, setIsReady] = useState18(false);
  const [error, setError] = useState18(null);
  const [schema, setSchema] = useState18({});
  const defaultValues = options.defaultValues || {};
  const skipIntrospection = options.skipIntrospection || false;
  const debug = options.debug || false;
  useEffect13(() => {
    async function initialize() {
      try {
        if (debug) console.log("[useQueryParams] Initializing...");
        const queryVariables = extractVariablesFromQuery(query);
        if (debug) {
          console.log("[useQueryParams] Extracted variables:", queryVariables);
        }
        if (!skipIntrospection && !introspector.isLoaded()) {
          const endpoint = options.introspectionEndpoint || (typeof window !== "undefined" && process.env.NEXT_PUBLIC_API_URL ? `${process.env.NEXT_PUBLIC_API_URL}/graphql` : "");
          if (endpoint) {
            try {
              await introspector.fetchSchema(endpoint, options.introspectionHeaders);
              if (debug) console.log("[useQueryParams] Introspection complete");
            } catch (err) {
              console.warn("[useQueryParams] Introspection failed, continuing without it:", err);
            }
          }
        }
        let flattenedSchema = await flattenQueryVariables(queryVariables, introspector);
        if (options.paramMapping) {
          flattenedSchema = applyParamMapping(flattenedSchema, options.paramMapping);
        }
        flattenedSchema = mergeDefaults(flattenedSchema, defaultValues);
        validateSchema(flattenedSchema);
        if (debug) {
          console.log("[useQueryParams] Flattened schema:", flattenedSchema);
        }
        setSchema(flattenedSchema);
        setIsReady(true);
      } catch (err) {
        const error2 = err instanceof Error ? err : new Error(String(err));
        console.error("[useQueryParams] Initialization failed:", error2);
        setError(error2);
      } finally {
        setIsLoading(false);
      }
    }
    initialize();
  }, [query, options.introspectionEndpoint, skipIntrospection, debug]);
  const variables = useMemo3(() => {
    if (!isReady) {
      return defaultValues;
    }
    try {
      const varsFromUrl = urlParamsToVariables(searchParams, schema);
      const merged = { ...defaultValues, ...varsFromUrl };
      if (debug) {
        console.log("[useQueryParams] Variables from URL:", merged);
      }
      return merged;
    } catch (err) {
      console.error("[useQueryParams] Failed to convert URL to variables:", err);
      return defaultValues;
    }
  }, [searchParams, schema, isReady, defaultValues, debug]);
  const params = useMemo3(() => {
    const result = {};
    searchParams.forEach((value, key) => {
      if (result[key]) {
        if (!Array.isArray(result[key])) {
          result[key] = [result[key]];
        }
        result[key].push(value);
      } else {
        result[key] = value;
      }
    });
    return result;
  }, [searchParams]);
  const updateUrl = useCallback9((newParams) => {
    const url = newParams.toString() ? `?${newParams.toString()}` : window.location.pathname;
    if (debug) {
      console.log("[useQueryParams] Updating URL:", url);
    }
    router.replace(url, { scroll: false });
  }, [router, debug]);
  const setParam = useCallback9((key, value) => {
    if (!isReady) {
      console.warn("[useQueryParams] Schema not ready, cannot set param");
      return;
    }
    try {
      const currentVars = variables;
      const updated = mergeVariables(currentVars, { [key]: value }, schema);
      const newParams = variablesToUrlParams(updated, schema);
      updateUrl(newParams);
    } catch (err) {
      console.error("[useQueryParams] Failed to set param:", err);
    }
  }, [variables, schema, isReady, updateUrl]);
  const setParams = useCallback9((updates) => {
    if (!isReady) {
      console.warn("[useQueryParams] Schema not ready, cannot set params");
      return;
    }
    try {
      const currentVars = variables;
      const updated = mergeVariables(currentVars, updates, schema);
      const newParams = variablesToUrlParams(updated, schema);
      updateUrl(newParams);
    } catch (err) {
      console.error("[useQueryParams] Failed to set params:", err);
    }
  }, [variables, schema, isReady, updateUrl]);
  const clearParamsHandler = useCallback9((keys) => {
    if (!isReady) {
      console.warn("[useQueryParams] Schema not ready, cannot clear params");
      return;
    }
    try {
      const currentVars = variables;
      const updated = clearParams(currentVars, keys, schema);
      const newParams = variablesToUrlParams(updated, schema);
      updateUrl(newParams);
    } catch (err) {
      console.error("[useQueryParams] Failed to clear params:", err);
    }
  }, [variables, schema, isReady, updateUrl]);
  const resetParams = useCallback9(() => {
    if (debug) {
      console.log("[useQueryParams] Resetting params");
    }
    router.replace(window.location.pathname, { scroll: false });
  }, [router, debug]);
  return {
    variables,
    params,
    schema,
    setParam,
    setParams,
    clearParams: clearParamsHandler,
    resetParams,
    isReady,
    isLoading,
    error
  };
}
function applyParamMapping(schema, mapping) {
  const mapped = {};
  for (const [key, param] of Object.entries(schema)) {
    const newKey = mapping[key] || key;
    mapped[newKey] = {
      ...param,
      urlParamName: mapping[key] || param.urlParamName
    };
  }
  return mapped;
}

// src/hooks/state/use-api-params.ts
init_next_navigation();
import { useCallback as useCallback10, useMemo as useMemo4, useRef as useRef8 } from "react";
function useContentStable(value, key) {
  const ref = useRef8(void 0);
  if (ref.current && ref.current.key === key) return ref.current.value;
  ref.current = { value, key };
  return value;
}
function reuseIfShallowEqual(prev, next) {
  if (!Array.isArray(prev) || prev.length !== next.length) return next;
  for (let i = 0; i < next.length; i++) {
    if (prev[i] !== next[i]) return next;
  }
  return prev;
}
function useApiParams(schema, options = {}) {
  const router = useRouter();
  const searchParamsLive = useSearchParams();
  const debug = options.debug || false;
  const searchString = searchParamsLive.toString();
  const schemaKey = useMemo4(() => JSON.stringify(schema), [schema]);
  const stableSchema = useContentStable(schema, schemaKey);
  const flattenedSchema = useMemo4(() => {
    const flattened = {};
    for (const [key, config] of Object.entries(stableSchema)) {
      flattened[key] = {
        urlParamName: key,
        graphqlPath: key,
        type: config.type,
        defaultValue: config.default,
        required: config.required,
        isArray: config.type === "array"
      };
    }
    return flattened;
  }, [schemaKey]);
  const prevParamsRef = useRef8(void 0);
  const params = useMemo4(() => {
    const sp = new URLSearchParams(searchString);
    const result = {};
    const prev = prevParamsRef.current;
    for (const [key, config] of Object.entries(stableSchema)) {
      const rawValue = config.type === "array" ? sp.getAll(key) : sp.get(key);
      let value;
      if (rawValue && (Array.isArray(rawValue) ? rawValue.length > 0 : true)) {
        value = coerceValue(rawValue, config.type);
      } else {
        value = config.default;
      }
      if (Array.isArray(value) && prev) {
        value = reuseIfShallowEqual(prev[key], value);
      }
      result[key] = value;
    }
    if (debug) {
      console.log("[useApiParams] Parsed params:", result);
    }
    prevParamsRef.current = result;
    return result;
  }, [searchString, schemaKey, debug]);
  const addParamToSearchParams = useCallback10((searchParams, key, value) => {
    if (value === void 0 || value === "" || value === null) {
      return;
    }
    if (Array.isArray(value)) {
      value.forEach((v) => {
        if (v !== void 0 && v !== "" && v !== null) {
          searchParams.append(key, String(v));
        }
      });
    } else if (typeof value === "object") {
      searchParams.set(key, JSON.stringify(value));
    } else {
      searchParams.set(key, String(value));
    }
  }, []);
  const urlSearchParams = useMemo4(() => {
    const newParams = new URLSearchParams();
    for (const key of Object.keys(stableSchema)) {
      const value = params[key];
      const paramConfig = flattenedSchema[key];
      if (!shouldIncludeInUrl(value, paramConfig)) {
        continue;
      }
      addParamToSearchParams(newParams, key, value);
    }
    return newParams;
  }, [params, schemaKey, flattenedSchema, addParamToSearchParams]);
  const updateUrl = useCallback10((newParams, keysToRemove = []) => {
    const finalParams = new URLSearchParams(searchString);
    keysToRemove.forEach((key) => {
      if (key in stableSchema) {
        finalParams.delete(key);
      }
    });
    newParams.forEach((_, key) => {
      if (key in stableSchema) {
        finalParams.delete(key);
      }
    });
    newParams.forEach((value, key) => {
      if (key in stableSchema) {
        if (finalParams.has(key)) {
          finalParams.append(key, value);
        } else {
          finalParams.set(key, value);
        }
      }
    });
    const url = finalParams.toString() ? `?${finalParams.toString()}` : window.location.pathname;
    if (debug) {
      console.log("[useApiParams] Updating URL:", url);
    }
    router.replace(url, { scroll: false });
  }, [router, debug, searchString, schemaKey]);
  const isEmptyValue = (value) => {
    if (value === void 0 || value === null || value === "") {
      return true;
    }
    if (Array.isArray(value)) {
      return value.length === 0 || value.every((v) => v === void 0 || v === null || v === "");
    }
    return false;
  };
  const setParam = useCallback10((key, value) => {
    const config = stableSchema[key];
    if (!config) {
      console.warn(`[useApiParams] Unknown parameter: ${key}`);
      return;
    }
    const newParams = new URLSearchParams();
    if (isEmptyValue(value)) {
      updateUrl(newParams, [key]);
    } else {
      addParamToSearchParams(newParams, key, value);
      updateUrl(newParams);
    }
  }, [schemaKey, updateUrl, addParamToSearchParams]);
  const setParams = useCallback10((updates) => {
    const newParams = new URLSearchParams();
    const keysToRemove = [];
    for (const [key, value] of Object.entries(updates)) {
      const config = stableSchema[key];
      if (!config) {
        console.warn(`[useApiParams] Unknown parameter: ${key}`);
        continue;
      }
      if (isEmptyValue(value)) {
        keysToRemove.push(key);
      } else {
        addParamToSearchParams(newParams, key, value);
      }
    }
    updateUrl(newParams, keysToRemove);
  }, [schemaKey, updateUrl, addParamToSearchParams]);
  const clearParams2 = useCallback10((keys) => {
    const newParams = new URLSearchParams();
    updateUrl(newParams, keys);
  }, [updateUrl]);
  const resetParams = useCallback10(() => {
    if (debug) {
      console.log("[useApiParams] Resetting params");
    }
    router.replace(window.location.pathname, { scroll: false });
  }, [router, debug]);
  return {
    params,
    urlSearchParams,
    setParam,
    setParams,
    clearParams: clearParams2,
    resetParams
  };
}
function createSearchParams(params) {
  const searchParams = new URLSearchParams();
  for (const [key, value] of Object.entries(params)) {
    if (value === void 0 || value === "" || value === null) {
      continue;
    }
    if (Array.isArray(value)) {
      value.forEach((v) => {
        if (v !== void 0 && v !== "" && v !== null) {
          searchParams.append(key, String(v));
        }
      });
    } else if (typeof value === "object") {
      searchParams.set(key, JSON.stringify(value));
    } else {
      searchParams.set(key, String(value));
    }
  }
  return searchParams;
}

// src/hooks/state/use-cursor-pagination-state.ts
import { useCallback as useCallback11, useEffect as useEffect14, useRef as useRef9, useState as useState19 } from "react";
var urlSchema = {
  search: { type: "string", default: "" },
  cursor: { type: "string", default: "" }
};
function useCursorPaginationState(options) {
  const {
    onInitialLoad,
    onSearchChange
  } = options;
  const { params, setParam, setParams } = useApiParams(urlSchema);
  const [searchInput, setSearchInput] = useState19(params.search || "");
  const [hasLoadedBeyondFirst, setHasLoadedBeyondFirst] = useState19(false);
  const [initialLoadCount, setInitialLoadCount] = useState19(0);
  const lastSearchRef = useRef9(null);
  const isSyncingFromUrl = useRef9(false);
  const isInitialLoadInProgress = useRef9(true);
  useEffect14(() => {
    if (isInitialLoadInProgress.current) return;
    const urlSearch = params.search || "";
    if (urlSearch !== searchInput) {
      isSyncingFromUrl.current = true;
      setSearchInput(urlSearch);
      setTimeout(() => {
        isSyncingFromUrl.current = false;
      }, 0);
    }
  }, [params.search, initialLoadCount]);
  useEffect14(() => {
    if (isInitialLoadInProgress.current) return;
    if (isSyncingFromUrl.current) return;
    if (searchInput !== params.search) {
      setParams({
        search: searchInput,
        cursor: ""
        // Reset cursor when search changes
      });
    }
  }, [searchInput, params.search, setParams, initialLoadCount]);
  useEffect14(() => {
    if (initialLoadCount === 0) {
      const cursor = params.cursor || null;
      const search = params.search || "";
      lastSearchRef.current = search;
      if (cursor) {
        setHasLoadedBeyondFirst(true);
      }
      Promise.resolve(onInitialLoad(search, cursor)).finally(() => {
        isInitialLoadInProgress.current = false;
        setInitialLoadCount(1);
      });
    }
  }, []);
  useEffect14(() => {
    if (isInitialLoadInProgress.current) return;
    if (initialLoadCount === 0) return;
    const currentSearch = params.search || "";
    if (lastSearchRef.current !== null && currentSearch !== lastSearchRef.current) {
      lastSearchRef.current = currentSearch;
      setHasLoadedBeyondFirst(false);
      onSearchChange(currentSearch);
    }
  }, [params.search, onSearchChange, initialLoadCount]);
  const handleNextPage = useCallback11(
    async (endCursor, fetchFn) => {
      setParam("cursor", endCursor);
      await fetchFn();
      setHasLoadedBeyondFirst(true);
    },
    [setParam]
  );
  const handleResetToFirstPage = useCallback11(
    async (fetchFn) => {
      setParam("cursor", "");
      await fetchFn();
      setHasLoadedBeyondFirst(false);
    },
    [setParam]
  );
  return {
    searchInput,
    setSearchInput,
    hasLoadedBeyondFirst,
    setHasLoadedBeyondFirst,
    handleNextPage,
    handleResetToFirstPage,
    params,
    setParam,
    setParams
  };
}

// src/hooks/nats/use-nats-client.ts
import { useEffect as useEffect15, useMemo as useMemo5, useState as useState20 } from "react";
function useNatsClient(clientOptions, options = {}) {
  const { autoConnect = true } = options;
  const client = useMemo5(() => {
    if (!clientOptions) return null;
    return createNatsClient(clientOptions);
  }, [clientOptions]);
  const [status, setStatus] = useState20("disconnected");
  const [lastError, setLastError] = useState20(null);
  useEffect15(() => {
    if (!client) {
      setStatus("disconnected");
      setLastError(null);
      return;
    }
    const off = client.onStatus((event) => {
      setStatus(event.status);
      if (event.status === "error") setLastError(event.data);
    });
    if (autoConnect) {
      client.connect().catch((e) => {
        setLastError(e);
        setStatus("error");
      });
    }
    return () => {
      off();
      client.close().catch(() => {
      });
    };
  }, [client, autoConnect]);
  return {
    client,
    status,
    isConnected: status === "connected",
    lastError
  };
}

// src/hooks/use-access-code-integration.ts
import React2 from "react";

// src/utils/access-code-client.ts
async function validateAccessCode(email, code, endpoints) {
  try {
    const response = await fetch(endpoints.validateUrl, {
      method: "POST",
      headers: {
        "Content-Type": "application/json"
      },
      body: JSON.stringify({ email, code })
    });
    if (!response.ok) {
      const error = await response.json().catch(() => ({}));
      throw new Error(error.error || "Validation request failed");
    }
    return await response.json();
  } catch (error) {
    return {
      valid: false,
      message: error instanceof Error ? error.message : "Validation failed"
    };
  }
}
async function consumeAccessCode(email, code, endpoints) {
  try {
    const response = await fetch(endpoints.consumeUrl, {
      method: "POST",
      headers: {
        "Content-Type": "application/json"
      },
      body: JSON.stringify({ email, code })
    });
    if (!response.ok) {
      const error = await response.json().catch(() => ({}));
      throw new Error(error.error || "Consumption request failed");
    }
    return await response.json();
  } catch (error) {
    return {
      success: false,
      consumed: false,
      message: error instanceof Error ? error.message : "Consumption failed"
    };
  }
}
async function validateAndConsumeAccessCode(email, code, endpoints) {
  const validation = await validateAccessCode(email, code, endpoints);
  if (!validation.valid) {
    return validation;
  }
  const consumption = await consumeAccessCode(email, code, endpoints);
  return {
    ...validation,
    consumed: consumption.consumed,
    message: consumption.consumed ? `Access granted for ${validation.cohort_name}` : consumption.message || validation.message
  };
}

// src/hooks/use-access-code-integration.ts
function useAccessCodeIntegration() {
  const runtime = useRequiredEndpointsRuntime();
  const endpoints = runtime.accessCode;
  const [isValidating, setIsValidating] = React2.useState(false);
  const [isConsuming, setIsConsuming] = React2.useState(false);
  const validate = async (email, code) => {
    setIsValidating(true);
    try {
      return await validateAccessCode(email, code, endpoints);
    } finally {
      setIsValidating(false);
    }
  };
  const consume = async (email, code) => {
    setIsConsuming(true);
    try {
      return await consumeAccessCode(email, code, endpoints);
    } finally {
      setIsConsuming(false);
    }
  };
  const validateAndConsume = async (email, code) => {
    setIsValidating(true);
    setIsConsuming(true);
    try {
      return await validateAndConsumeAccessCode(email, code, endpoints);
    } finally {
      setIsValidating(false);
      setIsConsuming(false);
    }
  };
  return {
    validate,
    consume,
    validateAndConsume,
    isValidating,
    isConsuming,
    isProcessing: isValidating || isConsuming
  };
}

// src/hooks/use-humanity-signals.ts
import { useCallback as useCallback12, useRef as useRef10 } from "react";

// src/utils/humanity-signals.ts
var HONEYPOT_FIELD = "contact_url_confirm";
var ELAPSED_MS_FIELD = "form_elapsed_ms";
var DEFAULT_MIN_FILL_MS = 700;
function extractHumanitySignals(body) {
  const b = body ?? {};
  const rawHp = b[HONEYPOT_FIELD];
  const honeypot = rawHp == null ? "" : String(rawHp);
  const rawMs = b[ELAPSED_MS_FIELD];
  const elapsedMs = typeof rawMs === "number" && Number.isFinite(rawMs) ? rawMs : null;
  return { honeypot, elapsedMs };
}
function evaluateHumanitySignals(body, opts) {
  const { honeypot, elapsedMs } = extractHumanitySignals(body);
  if (honeypot.trim() !== "") return { ok: false, reason: "honeypot" };
  if (elapsedMs !== null && elapsedMs < opts.minFillMs) return { ok: false, reason: "too_fast" };
  return { ok: true };
}
var splitCsvEnv = (s) => s?.split(",").map((t) => t.trim()).filter(Boolean) ?? [];

// src/hooks/use-humanity-signals.ts
function useHumanitySignals() {
  const ref = useRef10(null);
  const mountedAt = useRef10(typeof performance !== "undefined" ? performance.now() : 0);
  const getSignals = useCallback12(
    () => ({
      [HONEYPOT_FIELD]: ref.current?.value ?? "",
      [ELAPSED_MS_FIELD]: typeof performance !== "undefined" ? Math.round(performance.now() - mountedAt.current) : 0
    }),
    []
  );
  const resetSignals = useCallback12(() => {
    if (ref.current) ref.current.value = "";
    if (typeof performance !== "undefined") mountedAt.current = performance.now();
  }, []);
  return { honeypotInputProps: { ref, name: HONEYPOT_FIELD }, getSignals, resetSignals };
}

export {
  useHeaderHeight,
  useHorizontalScrollbar,
  useImageEdgeColor,
  useLocalStorage,
  useMediaQuery,
  breakpoints,
  useSmUp,
  useMdUp,
  useLgUp,
  useMemoizedCallback,
  useNotificationPermission,
  useOnboardingState,
  useSearch,
  useTablePagination,
  useThrottle,
  useWindowSize,
  platformIcons,
  platformColors,
  platformDisplayNames,
  platformDescriptions,
  platformSlogans,
  platformHexColors,
  platformIconNames,
  getDefaultColorForPlatform,
  getDefaultIconForPlatform,
  transformPlatformConfigsToOptions,
  getPlatformIcon,
  getPlatformColor,
  getPlatformDisplayName,
  getPlatformDescription,
  getPlatformSlogan,
  getSmallPlatformIcon,
  getPlatformIconComponent,
  usePlatformConfig,
  usePlatformByValue,
  useValidatePlatform,
  ToolTypeValues,
  toolLabels,
  ToolIcon,
  dotColorByVariant,
  progressColorByVariant,
  ToastCard,
  CommandApprovalToast,
  Toaster,
  showToast,
  showCommandApprovalToast,
  toast,
  useToast,
  useContactSubmission,
  useQuickActionHint,
  useCopyToClipboard,
  configureBatchImageFetch,
  batchFetchAuthenticatedImages,
  useBatchImages,
  configureAuthenticatedImage,
  useAuthenticatedImage,
  extractVariablesFromQuery,
  isScalarType,
  isInputObjectType,
  flattenQueryVariables,
  mergeDefaults,
  validateSchema,
  getArrayParams,
  getRequiredParams,
  shouldIncludeInUrl,
  urlParamsToVariables,
  variablesToUrlParams,
  coerceValue,
  setNestedValue,
  getNestedValue,
  mergeVariables,
  clearParams,
  validateVariables,
  GraphQLIntrospector,
  introspector,
  useQueryParams,
  useApiParams,
  createSearchParams,
  useCursorPaginationState,
  useNatsClient,
  validateAccessCode,
  consumeAccessCode,
  validateAndConsumeAccessCode,
  useAccessCodeIntegration,
  HONEYPOT_FIELD,
  ELAPSED_MS_FIELD,
  DEFAULT_MIN_FILL_MS,
  extractHumanitySignals,
  evaluateHumanitySignals,
  splitCsvEnv,
  useHumanitySignals
};
//# sourceMappingURL=chunk-ZMFT5XOB.js.map