var __defProp = Object.defineProperty;
var __returnValue = (v) => v;
function __exportSetter(name, newValue) {
  this[name] = __returnValue.bind(null, newValue);
}
var __export = (target, all) => {
  for (var name in all)
    __defProp(target, name, {
      get: all[name],
      enumerable: true,
      configurable: true,
      set: __exportSetter.bind(all, name)
    });
};
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
  get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
}) : x)(function(x) {
  if (typeof require !== "undefined")
    return require.apply(this, arguments);
  throw Error('Dynamic require of "' + x + '" is not supported');
});

// src/state.ts
function deepClone(obj) {
  if (obj === null || typeof obj !== "object") {
    return obj;
  }
  if (typeof obj === "function") {
    return obj;
  }
  if (typeof obj.__getSnapshot === "function") {
    return obj.__getSnapshot();
  }
  if (obj instanceof WeakMap || obj instanceof WeakSet) {
    return obj;
  }
  const visited = new WeakMap;
  function cloneInternal(value) {
    if (value === null || typeof value !== "object") {
      return value;
    }
    if (typeof value === "function") {
      return value;
    }
    if (visited.has(value)) {
      return visited.get(value);
    }
    if (value instanceof WeakMap || value instanceof WeakSet) {
      return value;
    }
    if (value instanceof Date || value instanceof RegExp || value instanceof Map || value instanceof Set || ArrayBuffer.isView(value) || value instanceof ArrayBuffer) {
      try {
        return structuredClone(value);
      } catch {}
    }
    if (Array.isArray(value)) {
      const arrClone = [];
      visited.set(value, arrClone);
      for (let i = 0;i < value.length; i++) {
        arrClone[i] = cloneInternal(value[i]);
      }
      return arrClone;
    }
    const objClone = {};
    visited.set(value, objClone);
    for (const key in value) {
      if (Object.prototype.hasOwnProperty.call(value, key)) {
        objClone[key] = cloneInternal(value[key]);
      }
    }
    const symbolKeys = Object.getOwnPropertySymbols(value);
    for (const sym of symbolKeys) {
      objClone[sym] = cloneInternal(value[sym]);
    }
    return objClone;
  }
  return cloneInternal(obj);
}
function diffState(oldState, newState, basePath = "") {
  const paths = [];
  const newValues = {};
  function diff(oldVal, newVal, path) {
    if (oldVal === newVal)
      return;
    if (typeof oldVal !== "object" || typeof newVal !== "object" || oldVal === null || newVal === null) {
      if (oldVal !== newVal) {
        paths.push(path);
        newValues[path] = newVal;
      }
      return;
    }
    if (Array.isArray(oldVal) || Array.isArray(newVal)) {
      if (!Array.isArray(oldVal) || !Array.isArray(newVal) || oldVal.length !== newVal.length) {
        paths.push(path);
        newValues[path] = newVal;
        return;
      }
      for (let i = 0;i < newVal.length; i++) {
        const itemPath = path ? `${path}.${i}` : `${i}`;
        diff(oldVal[i], newVal[i], itemPath);
      }
      return;
    }
    const oldKeys = new Set(Object.keys(oldVal));
    const newKeys = new Set(Object.keys(newVal));
    for (const key of newKeys) {
      const propPath = path ? `${path}.${key}` : key;
      if (!oldKeys.has(key)) {
        paths.push(propPath);
        newValues[propPath] = newVal[key];
      } else {
        diff(oldVal[key], newVal[key], propPath);
      }
    }
    for (const key of oldKeys) {
      if (!newKeys.has(key)) {
        const propPath = path ? `${path}.${key}` : key;
        paths.push(propPath);
        newValues[propPath] = undefined;
      }
    }
  }
  diff(oldState, newState, basePath);
  return { paths, newValues };
}
function createObservableState(initialState, options) {
  const opts = options || { onChange: () => {} };
  if (initialState === null || initialState === undefined) {
    initialState = {};
  }
  if (initialState instanceof Number || initialState instanceof String || initialState instanceof Boolean) {
    throw new TypeError("Cannot create observable state from primitive wrapper objects (Number, String, Boolean). " + "Use plain primitives or regular objects instead.");
  }
  initialState = deepClone(initialState);
  let lastSnapshot = deepClone(initialState);
  const pathPrefix = opts.pathPrefix || "";
  let batchDepth = 0;
  let pendingChange = null;
  function notifyChange() {
    if (batchDepth > 0)
      return;
    const change = diffState(lastSnapshot, state, pathPrefix);
    if (change.paths.length > 0) {
      lastSnapshot = deepClone(state);
      if (pendingChange) {
        change.paths.push(...pendingChange.paths);
        Object.assign(change.newValues, pendingChange.newValues);
        pendingChange = null;
      }
      opts.onChange(change);
    }
  }
  let notificationPending = false;
  function scheduleBatch() {
    if (batchDepth === 0) {
      if (!notificationPending) {
        notificationPending = true;
        queueMicrotask(() => {
          notificationPending = false;
          if (batchDepth === 0) {
            notifyChange();
          } else {}
        });
      }
    } else {
      pendingChange = pendingChange || { paths: [], newValues: {} };
    }
  }
  const proxyCache = new WeakMap;
  function createProxy(target, basePath) {
    const cached = proxyCache.get(target);
    if (cached)
      return cached;
    const proxy = new Proxy(target, {
      get(obj, prop) {
        if (prop === IS_PROXY)
          return true;
        if (prop === RAW_TARGET)
          return obj;
        if (prop === "__beginBatch") {
          return () => {
            batchDepth++;
          };
        }
        if (prop === "__endBatch") {
          return () => {
            batchDepth--;
            if (batchDepth === 0) {
              notifyChange();
            }
          };
        }
        if (prop === "__getSnapshot") {
          return () => deepClone(obj);
        }
        const value = obj[prop];
        if (value && typeof value === "object") {
          if (value[IS_PROXY]) {
            return value;
          }
          if (value instanceof Date || value instanceof RegExp || value instanceof Map || value instanceof Set || value instanceof WeakMap || value instanceof WeakSet) {
            return value;
          }
          const cachedNested = proxyCache.get(value);
          if (cachedNested) {
            return cachedNested;
          }
          const nestedProxy = createProxy(value, basePath ? `${basePath}.${String(prop)}` : String(prop));
          return nestedProxy;
        }
        return value;
      },
      set(obj, prop, value) {
        const oldValue = obj[prop];
        if (value && typeof value === "object" && value[IS_PROXY]) {
          value = value[RAW_TARGET];
        }
        obj[prop] = value;
        if (oldValue !== value) {
          scheduleBatch();
        }
        return true;
      },
      deleteProperty(obj, prop) {
        const existed = Object.prototype.hasOwnProperty.call(obj, prop);
        const result = delete obj[prop];
        if (existed) {
          scheduleBatch();
        }
        return result;
      }
    });
    proxyCache.set(target, proxy);
    return proxy;
  }
  const state = createProxy(initialState, pathPrefix);
  return state;
}
function batchStateUpdates(state, fn) {
  const s = state;
  if (s.__beginBatch && s.__endBatch) {
    s.__beginBatch();
    try {
      fn();
    } finally {
      s.__endBatch();
    }
  } else {
    fn();
  }
}
function getStateSnapshot(state) {
  const s = state;
  if (s.__getSnapshot) {
    return s.__getSnapshot();
  }
  return deepClone(state);
}
function isStateProxy(value) {
  return value !== null && typeof value === "object" && value[IS_PROXY] === true;
}
function unwrapProxy(value) {
  if (value !== null && typeof value === "object" && value[IS_PROXY]) {
    return value[RAW_TARGET];
  }
  return value;
}
var IS_PROXY, RAW_TARGET;
var init_state = __esm(() => {
  IS_PROXY = Symbol.for("hypen.isProxy");
  RAW_TARGET = Symbol.for("hypen.rawTarget");
});

// src/logger.ts
function isProduction() {
  if (typeof process !== "undefined" && process.env) {
    return false;
  }
  return false;
}
function setLogLevel(level) {
  config.level = level;
}
function getLogLevel() {
  return config.level;
}
function configureLogger(options) {
  config = { ...config, ...options };
}
function enableLogging() {
  config.level = "debug";
}
function disableLogging() {
  config.level = "none";
}
function setDebugMode(enabled) {
  config.level = enabled ? "debug" : "error";
}
function isDebugMode() {
  return config.level === "debug";
}
function shouldLog(level) {
  return LOG_LEVEL_ORDER[level] >= LOG_LEVEL_ORDER[config.level];
}
function formatTag(tag, level) {
  const timestamp = config.timestamps ? `${new Date().toISOString()} ` : "";
  if (config.colors && level !== "none") {
    const color = LOG_LEVEL_COLORS[level];
    return `${timestamp}${color}[${tag}]${RESET_COLOR}`;
  }
  return `${timestamp}[${tag}]`;
}

class Logger {
  tag;
  constructor(tag) {
    this.tag = tag;
  }
  debug(...args) {
    if (!shouldLog("debug"))
      return;
    if (config.handler) {
      config.handler.debug(this.tag, ...args);
    } else {
      console.log(formatTag(this.tag, "debug"), ...args);
    }
  }
  info(...args) {
    if (!shouldLog("info"))
      return;
    if (config.handler) {
      config.handler.info(this.tag, ...args);
    } else {
      console.info(formatTag(this.tag, "info"), ...args);
    }
  }
  warn(...args) {
    if (!shouldLog("warn"))
      return;
    if (config.handler) {
      config.handler.warn(this.tag, ...args);
    } else {
      console.warn(formatTag(this.tag, "warn"), ...args);
    }
  }
  error(...args) {
    if (!shouldLog("error"))
      return;
    if (config.handler) {
      config.handler.error(this.tag, ...args);
    } else {
      console.error(formatTag(this.tag, "error"), ...args);
    }
  }
  time(label, fn) {
    if (!shouldLog("debug")) {
      return fn();
    }
    const start = performance.now();
    try {
      return fn();
    } finally {
      const duration = performance.now() - start;
      this.debug(`${label}: ${duration.toFixed(2)}ms`);
    }
  }
  async timeAsync(label, fn) {
    if (!shouldLog("debug")) {
      return fn();
    }
    const start = performance.now();
    try {
      return await fn();
    } finally {
      const duration = performance.now() - start;
      this.debug(`${label}: ${duration.toFixed(2)}ms`);
    }
  }
  child(subTag) {
    return new Logger(`${this.tag}:${subTag}`);
  }
  debugIf(condition, ...args) {
    if (condition)
      this.debug(...args);
  }
  warnIf(condition, ...args) {
    if (condition)
      this.warn(...args);
  }
  errorIf(condition, ...args) {
    if (condition)
      this.error(...args);
  }
  loggedOnce = new Set;
  warnOnce(key, ...args) {
    if (this.loggedOnce.has(key))
      return;
    this.loggedOnce.add(key);
    this.warn(...args);
  }
  debugOnce(key, ...args) {
    if (this.loggedOnce.has(key))
      return;
    this.loggedOnce.add(key);
    this.debug(...args);
  }
}
function createLogger(tag) {
  return new Logger(tag);
}
var LOG_LEVEL_ORDER, LOG_LEVEL_COLORS, RESET_COLOR = "\x1B[0m", config, logger, log, frameworkLoggers;
var init_logger = __esm(() => {
  LOG_LEVEL_ORDER = {
    debug: 0,
    info: 1,
    warn: 2,
    error: 3,
    none: 4
  };
  LOG_LEVEL_COLORS = {
    debug: "\x1B[36m",
    info: "\x1B[32m",
    warn: "\x1B[33m",
    error: "\x1B[31m"
  };
  config = {
    level: isProduction() ? "error" : "info",
    colors: true,
    timestamps: false
  };
  logger = createLogger("Hypen");
  log = {
    debug: (tag, ...args) => {
      if (!shouldLog("debug"))
        return;
      console.log(formatTag(tag, "debug"), ...args);
    },
    info: (tag, ...args) => {
      if (!shouldLog("info"))
        return;
      console.info(formatTag(tag, "info"), ...args);
    },
    warn: (tag, ...args) => {
      if (!shouldLog("warn"))
        return;
      console.warn(formatTag(tag, "warn"), ...args);
    },
    error: (tag, ...args) => {
      if (!shouldLog("error"))
        return;
      console.error(formatTag(tag, "error"), ...args);
    }
  };
  frameworkLoggers = {
    hypen: createLogger("Hypen"),
    engine: createLogger("Engine"),
    router: createLogger("Router"),
    state: createLogger("State"),
    events: createLogger("Events"),
    remote: createLogger("Remote"),
    renderer: createLogger("Renderer"),
    module: createLogger("Module"),
    lifecycle: createLogger("Lifecycle"),
    loader: createLogger("Loader"),
    context: createLogger("Context"),
    discovery: createLogger("Discovery"),
    plugin: createLogger("Plugin"),
    canvas: createLogger("Canvas"),
    debug: createLogger("Debug")
  };
});

// src/disposable.ts
init_logger();
var log2 = frameworkLoggers.lifecycle;
function isDisposable(obj) {
  return obj !== null && typeof obj === "object" && "dispose" in obj && typeof obj.dispose === "function";
}

class DisposableStack {
  stack = [];
  disposed = false;
  add(disposable) {
    if (this.disposed) {
      disposable.dispose();
      return disposable;
    }
    this.stack.push(disposable);
    return disposable;
  }
  addCallback(callback) {
    this.add({ dispose: callback });
  }
  addValue(value, dispose) {
    this.add({ dispose: () => dispose(value) });
    return value;
  }
  dispose() {
    if (this.disposed)
      return;
    this.disposed = true;
    while (this.stack.length > 0) {
      const item = this.stack.pop();
      try {
        item.dispose();
      } catch (error) {
        log2.error("Error during dispose:", error);
      }
    }
  }
  get isDisposed() {
    return this.disposed;
  }
  get size() {
    return this.stack.length;
  }
}
function disposableListener(target, event, handler, options) {
  target.addEventListener(event, handler, options);
  return {
    dispose: () => target.removeEventListener(event, handler, options)
  };
}
function disposableTimeout(callback, ms) {
  const id = setTimeout(callback, ms);
  return {
    id,
    dispose: () => clearTimeout(id)
  };
}
function disposableInterval(callback, ms) {
  const id = setInterval(callback, ms);
  return {
    id,
    dispose: () => clearInterval(id)
  };
}
function disposableWebSocket(ws) {
  return {
    dispose: () => {
      if (ws.readyState === WebSocket.OPEN || ws.readyState === WebSocket.CONNECTING) {
        ws.close();
      }
    }
  };
}
function disposableAbortController() {
  const controller = new AbortController;
  return {
    controller,
    signal: controller.signal,
    dispose: () => controller.abort()
  };
}
function disposableSubscription(unsubscribe) {
  return { dispose: unsubscribe };
}
var ELEMENT_DISPOSABLES = Symbol("hypen.disposables");
function getElementDisposables(element) {
  const existing = element[ELEMENT_DISPOSABLES];
  if (existing instanceof DisposableStack) {
    return existing;
  }
  const stack = new DisposableStack;
  element[ELEMENT_DISPOSABLES] = stack;
  return stack;
}
function disposeElement(element) {
  const stack = element[ELEMENT_DISPOSABLES];
  if (stack instanceof DisposableStack) {
    stack.dispose();
    delete element[ELEMENT_DISPOSABLES];
  }
}
function hasElementDisposables(element) {
  return element[ELEMENT_DISPOSABLES] instanceof DisposableStack;
}

class DisposableMixin {
  disposables = new DisposableStack;
  track(disposable) {
    return this.disposables.add(disposable);
  }
  onDispose(callback) {
    this.disposables.addCallback(callback);
  }
  dispose() {
    this.disposables.dispose();
  }
}
function compositeDisposable(...disposables) {
  return {
    dispose: () => {
      for (const d of disposables) {
        try {
          d.dispose();
        } catch (error) {
          log2.error("Error during dispose:", error);
        }
      }
    }
  };
}
async function using(resource, fn) {
  const r = typeof resource === "function" ? resource() : resource;
  try {
    return await fn(r);
  } finally {
    r.dispose();
  }
}
function usingSync(resource, fn) {
  const r = typeof resource === "function" ? resource() : resource;
  try {
    return fn(r);
  } finally {
    r.dispose();
  }
}

// src/router.ts
init_state();
init_logger();
var log3 = frameworkLoggers.router;

class HypenRouter {
  state;
  subscribers = new Set;
  isInitialized = false;
  isUpdating = false;
  browserListeners = [];
  constructor() {
    this.state = createObservableState({
      currentPath: "/",
      params: {},
      query: {},
      previousPath: null
    }, {
      onChange: () => {
        this.notifySubscribers();
      }
    });
    if (typeof window !== "undefined") {
      this.initializeBrowserSync();
    }
  }
  initializeBrowserSync() {
    const initialPath = this.getPathFromBrowser();
    this.state.currentPath = initialPath;
    this.state.params = {};
    this.state.query = this.parseQuery();
    this.browserListeners.push(disposableListener(window, "popstate", () => {
      const newPath = this.getPathFromBrowser();
      this.updatePath(newPath, false);
    }));
    this.browserListeners.push(disposableListener(window, "hashchange", () => {
      if (this.isUpdating)
        return;
      const newPath = this.getPathFromBrowser();
      this.updatePath(newPath, false);
    }));
    this.isInitialized = true;
    log3.debug("Router initialized at:", initialPath);
  }
  getPathFromBrowser() {
    if (typeof window === "undefined")
      return "/";
    const hash = window.location.hash.slice(1);
    if (hash)
      return hash;
    return window.location.pathname;
  }
  parseQuery() {
    if (typeof window === "undefined")
      return {};
    const query = {};
    const searchParams = new URLSearchParams(window.location.search);
    searchParams.forEach((value, key) => {
      query[key] = value;
    });
    return query;
  }
  push(path) {
    log3.debug("push:", path);
    this.updatePath(path, true);
  }
  replace(path) {
    log3.debug("replace:", path);
    this.updatePath(path, true, true);
  }
  back() {
    log3.debug("back");
    if (typeof window !== "undefined") {
      window.history.back();
    }
  }
  forward() {
    log3.debug("forward");
    if (typeof window !== "undefined") {
      window.history.forward();
    }
  }
  updatePath(path, updateBrowser, replace = false) {
    if (this.isUpdating)
      return;
    this.isUpdating = true;
    try {
      const oldPath = this.state.currentPath;
      this.state.previousPath = oldPath;
      this.state.currentPath = path;
      this.state.query = this.parseQuery();
      this.notifySubscribers();
      if (updateBrowser && typeof window !== "undefined") {
        const url = "#" + path;
        if (replace) {
          window.history.replaceState(null, "", url);
        } else {
          window.history.pushState(null, "", url);
        }
        const hashChangeEvent = new HashChangeEvent("hashchange", {
          oldURL: window.location.href.replace(window.location.hash, "#" + oldPath),
          newURL: window.location.href
        });
        window.dispatchEvent(hashChangeEvent);
      }
    } finally {
      this.isUpdating = false;
    }
  }
  getCurrentPath() {
    return this.state.currentPath;
  }
  getParams() {
    return { ...this.state.params };
  }
  getQuery() {
    return { ...this.state.query };
  }
  getState() {
    return getStateSnapshot(this.state);
  }
  matchPath(pattern, path) {
    if (!pattern || typeof pattern !== "string") {
      return null;
    }
    if (!path || typeof path !== "string") {
      return null;
    }
    if (pattern === path) {
      return {
        params: {},
        query: this.state.query,
        path
      };
    }
    if (pattern.endsWith("/*")) {
      const prefix = pattern.slice(0, -2);
      if (path === prefix || path.startsWith(prefix + "/")) {
        return {
          params: {},
          query: this.state.query,
          path
        };
      }
      return null;
    }
    const paramNames = [];
    const regexPattern = pattern.replace(/:([a-zA-Z_][a-zA-Z0-9_]*)/g, (_, name) => {
      paramNames.push(name);
      return "([^/]+)";
    }).replace(/\*/g, ".*");
    const regex = new RegExp(`^${regexPattern}$`);
    const match = path.match(regex);
    if (!match)
      return null;
    const params = {};
    paramNames.forEach((name, i) => {
      const value = match[i + 1];
      if (value !== undefined) {
        params[name] = decodeURIComponent(value);
      }
    });
    return {
      params,
      query: this.state.query,
      path
    };
  }
  onNavigate(callback) {
    this.subscribers.add(callback);
    try {
      callback(this.getState());
    } catch (error) {
      log3.error("Error in route subscriber:", error);
    }
    return () => {
      this.subscribers.delete(callback);
    };
  }
  notifySubscribers() {
    const routeState = this.getState();
    this.subscribers.forEach((callback) => {
      try {
        callback(routeState);
      } catch (error) {
        log3.error("Error in route subscriber:", error);
      }
    });
  }
  isActive(pattern) {
    return this.matchPath(pattern, this.state.currentPath) !== null;
  }
  buildUrl(path, query) {
    if (!query || Object.keys(query).length === 0) {
      return path;
    }
    const queryString = new URLSearchParams(query).toString();
    return `${path}?${queryString}`;
  }
  dispose() {
    for (const listener of this.browserListeners) {
      listener.dispose();
    }
    this.browserListeners = [];
    this.subscribers.clear();
    this.isInitialized = false;
    log3.debug("Router disposed");
  }
  [Symbol.dispose]() {
    this.dispose();
  }
}
export {
  HypenRouter
};

//# debugId=629142C841C9E81A64756E2164756E21
