'use strict';

var react = require('react');
var jsxRuntime = require('react/jsx-runtime');

var DEFAULT_SLOTS = {
  main: null,
  sidebar: null,
  modal: null,
  drawer: null,
  overlay: null,
  center: null,
  toast: null,
  "hud-top": null,
  "hud-bottom": null,
  "hud-left": null,
  "hud-right": null,
  floating: null
};
var idCounter = 0;
function generateId() {
  return `slot-content-${++idCounter}-${Date.now()}`;
}
function useUISlotManager() {
  const [slots, setSlots] = react.useState(DEFAULT_SLOTS);
  const subscribersRef = react.useRef(/* @__PURE__ */ new Set());
  const timersRef = react.useRef(/* @__PURE__ */ new Map());
  const traitIndexRef = react.useRef(/* @__PURE__ */ new Map());
  const traitSubscribersRef = react.useRef(/* @__PURE__ */ new Map());
  react.useEffect(() => {
    return () => {
      timersRef.current.forEach((timer) => clearTimeout(timer));
      timersRef.current.clear();
    };
  }, []);
  const notifySubscribers = react.useCallback((slot, content) => {
    subscribersRef.current.forEach((callback) => {
      try {
        callback(slot, content);
      } catch (error) {
        console.error("[UISlots] Subscriber error:", error);
      }
    });
  }, []);
  const notifyTraitSubscribers = react.useCallback(
    (traitName, content) => {
      const subs = traitSubscribersRef.current.get(traitName);
      if (!subs) return;
      subs.forEach((callback) => {
        try {
          callback(content);
        } catch (error) {
          console.error(`[UISlots] Trait subscriber error (${traitName}):`, error);
        }
      });
    },
    []
  );
  const indexTraitRender = react.useCallback(
    (traitName, content) => {
      traitIndexRef.current.set(traitName, content);
    },
    []
  );
  const unindexTrait = react.useCallback((traitName) => {
    traitIndexRef.current.delete(traitName);
  }, []);
  const render = react.useCallback((config) => {
    const id = generateId();
    const content = {
      id,
      pattern: config.pattern,
      props: config.props ?? {},
      priority: config.priority ?? 0,
      animation: config.animation ?? "fade",
      onDismiss: config.onDismiss,
      sourceTrait: config.sourceTrait
    };
    if (config.autoDismissMs && config.autoDismissMs > 0) {
      content.autoDismissAt = Date.now() + config.autoDismissMs;
      const timer = setTimeout(() => {
        setSlots((prev) => {
          if (prev[config.target]?.id === id) {
            content.onDismiss?.();
            notifySubscribers(config.target, null);
            return { ...prev, [config.target]: null };
          }
          return prev;
        });
        timersRef.current.delete(id);
      }, config.autoDismissMs);
      timersRef.current.set(id, timer);
    }
    setSlots((prev) => {
      const existing = prev[config.target];
      if (existing && existing.priority > content.priority) {
        console.warn(
          `[UISlots] Slot "${config.target}" already has higher priority content (${existing.priority} > ${content.priority})`
        );
        return prev;
      }
      if (content.sourceTrait) {
        indexTraitRender(content.sourceTrait, content);
        notifyTraitSubscribers(content.sourceTrait, content);
      }
      notifySubscribers(config.target, content);
      return { ...prev, [config.target]: content };
    });
    return id;
  }, [notifySubscribers, notifyTraitSubscribers, indexTraitRender]);
  const clear = react.useCallback((slot) => {
    setSlots((prev) => {
      const content = prev[slot];
      if (content) {
        const timer = timersRef.current.get(content.id);
        if (timer) {
          clearTimeout(timer);
          timersRef.current.delete(content.id);
        }
        content.onDismiss?.();
        if (content.sourceTrait) {
          unindexTrait(content.sourceTrait);
          notifyTraitSubscribers(content.sourceTrait, null);
        }
        notifySubscribers(slot, null);
      }
      return { ...prev, [slot]: null };
    });
  }, [notifySubscribers, notifyTraitSubscribers, unindexTrait]);
  const clearById = react.useCallback((id) => {
    setSlots((prev) => {
      const entry = Object.entries(prev).find(([, content]) => content?.id === id);
      if (entry) {
        const [slot, content] = entry;
        const timer = timersRef.current.get(id);
        if (timer) {
          clearTimeout(timer);
          timersRef.current.delete(id);
        }
        content.onDismiss?.();
        if (content.sourceTrait) {
          unindexTrait(content.sourceTrait);
          notifyTraitSubscribers(content.sourceTrait, null);
        }
        notifySubscribers(slot, null);
        return { ...prev, [slot]: null };
      }
      return prev;
    });
  }, [notifySubscribers, notifyTraitSubscribers, unindexTrait]);
  const clearAll = react.useCallback(() => {
    timersRef.current.forEach((timer) => clearTimeout(timer));
    timersRef.current.clear();
    setSlots((prev) => {
      Object.entries(prev).forEach(([slot, content]) => {
        if (content) {
          content.onDismiss?.();
          if (content.sourceTrait) {
            notifyTraitSubscribers(content.sourceTrait, null);
          }
          notifySubscribers(slot, null);
        }
      });
      return DEFAULT_SLOTS;
    });
    traitIndexRef.current.clear();
  }, [notifySubscribers, notifyTraitSubscribers]);
  const subscribe = react.useCallback((callback) => {
    subscribersRef.current.add(callback);
    return () => {
      subscribersRef.current.delete(callback);
    };
  }, []);
  const hasContent = react.useCallback((slot) => {
    return slots[slot] !== null;
  }, [slots]);
  const getContent = react.useCallback((slot) => {
    return slots[slot];
  }, [slots]);
  const getTraitContent = react.useCallback(
    (traitName) => {
      return traitIndexRef.current.get(traitName) ?? null;
    },
    []
  );
  const subscribeTrait = react.useCallback(
    (traitName, callback) => {
      let set = traitSubscribersRef.current.get(traitName);
      if (!set) {
        set = /* @__PURE__ */ new Set();
        traitSubscribersRef.current.set(traitName, set);
      }
      set.add(callback);
      return () => {
        const s = traitSubscribersRef.current.get(traitName);
        if (!s) return;
        s.delete(callback);
        if (s.size === 0) {
          traitSubscribersRef.current.delete(traitName);
        }
      };
    },
    []
  );
  return {
    slots,
    render,
    clear,
    clearById,
    clearAll,
    subscribe,
    hasContent,
    getContent,
    getTraitContent,
    subscribeTrait
  };
}
var UISlotContext = react.createContext(null);
function UISlotProvider({ children }) {
  const slotManager = useUISlotManager();
  const contextValue = react.useMemo(() => slotManager, [slotManager]);
  return /* @__PURE__ */ jsxRuntime.jsx(UISlotContext.Provider, { value: contextValue, children });
}
function useUISlots() {
  const context = react.useContext(UISlotContext);
  if (!context) {
    throw new Error(
      "useUISlots must be used within a UISlotProvider. Make sure your component tree is wrapped with <UISlotProvider>."
    );
  }
  return context;
}
function useSlotContent(slot) {
  const { getContent } = useUISlots();
  return getContent(slot);
}
function useSlotHasContent(slot) {
  const { hasContent } = useUISlots();
  return hasContent(slot);
}
var BUILT_IN_THEMES = [
  {
    name: "wireframe",
    displayName: "Wireframe",
    hasLightMode: true,
    hasDarkMode: true
  },
  {
    name: "minimalist",
    displayName: "Minimalist",
    hasLightMode: true,
    hasDarkMode: true
  },
  {
    name: "almadar",
    displayName: "Almadar",
    hasLightMode: true,
    hasDarkMode: true
  },
  {
    name: "trait-wars",
    displayName: "Trait Wars",
    hasLightMode: false,
    hasDarkMode: true
  },
  // Extended themes
  {
    name: "ocean",
    displayName: "Ocean",
    hasLightMode: true,
    hasDarkMode: true
  },
  {
    name: "forest",
    displayName: "Forest",
    hasLightMode: true,
    hasDarkMode: true
  },
  {
    name: "sunset",
    displayName: "Sunset",
    hasLightMode: true,
    hasDarkMode: true
  },
  {
    name: "lavender",
    displayName: "Lavender",
    hasLightMode: true,
    hasDarkMode: true
  },
  {
    name: "rose",
    displayName: "Rose",
    hasLightMode: true,
    hasDarkMode: true
  },
  {
    name: "slate",
    displayName: "Slate",
    hasLightMode: true,
    hasDarkMode: true
  },
  {
    name: "ember",
    displayName: "Ember",
    hasLightMode: true,
    hasDarkMode: true
  },
  {
    name: "midnight",
    displayName: "Midnight",
    hasLightMode: true,
    hasDarkMode: true
  },
  {
    name: "sand",
    displayName: "Sand",
    hasLightMode: true,
    hasDarkMode: true
  },
  {
    name: "neon",
    displayName: "Neon",
    hasLightMode: true,
    hasDarkMode: true
  },
  {
    name: "arctic",
    displayName: "Arctic",
    hasLightMode: true,
    hasDarkMode: true
  },
  {
    name: "copper",
    displayName: "Copper",
    hasLightMode: true,
    hasDarkMode: true
  }
];
var ThemeContext = react.createContext(void 0);
var THEME_STORAGE_KEY = "theme";
var MODE_STORAGE_KEY = "theme-mode";
function getSystemMode() {
  if (typeof window === "undefined") return "light";
  return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
}
function resolveMode(mode) {
  if (mode === "system") {
    return getSystemMode();
  }
  return mode;
}
var ThemeProvider = ({
  children,
  themes = [],
  defaultTheme = "wireframe",
  defaultMode = "system",
  targetRef
}) => {
  const availableThemes = react.useMemo(() => {
    const themeMap = /* @__PURE__ */ new Map();
    BUILT_IN_THEMES.forEach((t) => themeMap.set(t.name, t));
    themes.forEach((t) => themeMap.set(t.name, t));
    return Array.from(themeMap.values());
  }, [themes]);
  const isScoped = !!targetRef;
  const [theme, setThemeState] = react.useState(() => {
    if (isScoped || typeof window === "undefined") return defaultTheme;
    const stored = localStorage.getItem(THEME_STORAGE_KEY);
    const validThemes = [
      ...BUILT_IN_THEMES.map((t) => t.name),
      ...themes.map((t) => t.name)
    ];
    if (stored && validThemes.includes(stored)) {
      return stored;
    }
    return defaultTheme;
  });
  const [mode, setModeState] = react.useState(() => {
    if (isScoped || typeof window === "undefined") return defaultMode;
    const stored = localStorage.getItem(MODE_STORAGE_KEY);
    if (stored === "light" || stored === "dark" || stored === "system") {
      return stored;
    }
    return defaultMode;
  });
  const [resolvedMode, setResolvedMode] = react.useState(
    () => resolveMode(mode)
  );
  const appliedTheme = react.useMemo(
    () => `${theme}-${resolvedMode}`,
    [theme, resolvedMode]
  );
  react.useEffect(() => {
    const updateResolved = () => {
      setResolvedMode(resolveMode(mode));
    };
    updateResolved();
    if (mode === "system") {
      const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
      const handleChange = () => updateResolved();
      mediaQuery.addEventListener("change", handleChange);
      return () => mediaQuery.removeEventListener("change", handleChange);
    }
    return void 0;
  }, [mode]);
  react.useEffect(() => {
    if (isScoped) {
      if (targetRef?.current) {
        targetRef.current.setAttribute("data-theme", appliedTheme);
        targetRef.current.classList.remove("light", "dark");
        targetRef.current.classList.add(resolvedMode);
      }
      return;
    }
    const root = document.documentElement;
    root.setAttribute("data-theme", appliedTheme);
    root.classList.remove("light", "dark");
    root.classList.add(resolvedMode);
  }, [appliedTheme, resolvedMode, targetRef, isScoped]);
  const setTheme = react.useCallback(
    (newTheme) => {
      const validTheme = availableThemes.find((t) => t.name === newTheme);
      if (validTheme) {
        setThemeState(newTheme);
        if (!isScoped && typeof window !== "undefined") {
          localStorage.setItem(THEME_STORAGE_KEY, newTheme);
        }
      } else {
        console.warn(
          `Theme "${newTheme}" not found. Available: ${availableThemes.map((t) => t.name).join(", ")}`
        );
      }
    },
    [availableThemes]
  );
  const setMode = react.useCallback((newMode) => {
    setModeState(newMode);
    if (!isScoped && typeof window !== "undefined") {
      localStorage.setItem(MODE_STORAGE_KEY, newMode);
    }
  }, []);
  const toggleMode = react.useCallback(() => {
    const newMode = resolvedMode === "dark" ? "light" : "dark";
    setMode(newMode);
  }, [resolvedMode, setMode]);
  const contextValue = react.useMemo(
    () => ({
      theme,
      mode,
      resolvedMode,
      setTheme,
      setMode,
      toggleMode,
      availableThemes,
      appliedTheme
    }),
    [
      theme,
      mode,
      resolvedMode,
      setTheme,
      setMode,
      toggleMode,
      availableThemes,
      appliedTheme
    ]
  );
  return /* @__PURE__ */ jsxRuntime.jsx(ThemeContext.Provider, { value: contextValue, children });
};
function useTheme() {
  const context = react.useContext(ThemeContext);
  if (context === void 0) {
    return {
      theme: "wireframe",
      mode: "light",
      resolvedMode: "light",
      setTheme: () => {
      },
      setMode: () => {
      },
      toggleMode: () => {
      },
      availableThemes: BUILT_IN_THEMES,
      appliedTheme: "wireframe-light"
    };
  }
  return context;
}
var ThemeContext_default = ThemeContext;

// context/DesignThemeContext.tsx
var DesignThemeProvider = ThemeProvider;
function useDesignTheme() {
  const { theme, setTheme, availableThemes } = useTheme();
  return {
    designTheme: theme,
    setDesignTheme: setTheme,
    availableThemes: availableThemes.map((t) => t.name)
  };
}
var ANONYMOUS_USER = {
  id: "anonymous",
  role: "anonymous",
  permissions: []
};
var UserContext = react.createContext(null);
function UserProvider({
  user = null,
  children
}) {
  const hasRole = react.useCallback(
    (role) => {
      if (!user) return role === "anonymous";
      return user.role === role;
    },
    [user]
  );
  const hasPermission = react.useCallback(
    (permission) => {
      if (!user) return false;
      return user.permissions?.includes(permission) ?? false;
    },
    [user]
  );
  const hasAnyRole = react.useCallback(
    (roles) => {
      if (!user) return roles.includes("anonymous");
      return user.role ? roles.includes(user.role) : false;
    },
    [user]
  );
  const hasAllPermissions = react.useCallback(
    (permissions) => {
      if (!user || !user.permissions) return false;
      return permissions.every((p) => user.permissions?.includes(p));
    },
    [user]
  );
  const getUserField = react.useCallback(
    (path) => {
      const userData = user ?? ANONYMOUS_USER;
      const parts = path.split(".");
      let value = userData;
      for (const segment of parts) {
        if (value === null || value === void 0) {
          return void 0;
        }
        if (typeof value === "object") {
          value = value[segment];
        } else {
          return void 0;
        }
      }
      return value;
    },
    [user]
  );
  const contextValue = react.useMemo(
    () => ({
      user,
      isLoggedIn: user !== null,
      hasRole,
      hasPermission,
      hasAnyRole,
      hasAllPermissions,
      getUserField
    }),
    [user, hasRole, hasPermission, hasAnyRole, hasAllPermissions, getUserField]
  );
  return /* @__PURE__ */ jsxRuntime.jsx(UserContext.Provider, { value: contextValue, children });
}
function useUser() {
  const context = react.useContext(UserContext);
  if (!context) {
    return {
      user: null,
      isLoggedIn: false,
      hasRole: (role) => role === "anonymous",
      hasPermission: () => false,
      hasAnyRole: (roles) => roles.includes("anonymous"),
      hasAllPermissions: () => false,
      getUserField: () => void 0
    };
  }
  return context;
}
function useHasRole(role) {
  const { hasRole } = useUser();
  return hasRole(role);
}
function useHasPermission(permission) {
  const { hasPermission } = useUser();
  return hasPermission(permission);
}
function useUserForEvaluation() {
  const { user, isLoggedIn } = useUser();
  return isLoggedIn && user ? user : void 0;
}

exports.ANONYMOUS_USER = ANONYMOUS_USER;
exports.BUILT_IN_THEMES = BUILT_IN_THEMES;
exports.DesignThemeProvider = DesignThemeProvider;
exports.ThemeContext = ThemeContext_default;
exports.ThemeProvider = ThemeProvider;
exports.UISlotContext = UISlotContext;
exports.UISlotProvider = UISlotProvider;
exports.UserContext = UserContext;
exports.UserProvider = UserProvider;
exports.useDesignTheme = useDesignTheme;
exports.useHasPermission = useHasPermission;
exports.useHasRole = useHasRole;
exports.useSlotContent = useSlotContent;
exports.useSlotHasContent = useSlotHasContent;
exports.useTheme = useTheme;
exports.useUISlots = useUISlots;
exports.useUser = useUser;
exports.useUserForEvaluation = useUserForEvaluation;
