import {
  PAGE_ROW_COMPONENT_ID,
  getElementNodeComponentId,
  isPageLayoutComponent,
  isPageRow
} from "./chunk-7HXI5QAG.mjs";

// src/runtime/CanvasHooksContext.tsx
import * as React from "react";
var CanvasHooksContext = React.createContext({});

// src/runtime/globalState.ts
import { createGlobalState } from "@toolpad/utils/react";
var componentsStore = createGlobalState({});

// src/runtime/ToolpadApp.tsx
import * as React11 from "react";
import {
  Stack as Stack2,
  CssBaseline,
  Alert as Alert3,
  Box as Box4,
  styled,
  AlertTitle,
  LinearProgress,
  Container,
  Tooltip,
  Typography as Typography3
} from "@mui/material";
import {
  createComponent,
  TOOLPAD_COMPONENT,
  Slots,
  Placeholder,
  getArgTypeDefaultValue,
  ComponentsContextProvider,
  isToolpadComponent,
  createToolpadComponentThatThrows,
  useComponents,
  useComponent,
  CanvasEventsContext,
  NodeRuntimeWrapper,
  ResetNodeErrorsKeyProvider,
  UseDataProviderContext,
  useAppHost as useAppHost3
} from "@toolpad/studio-runtime";
import { useAssertedContext, useNonNullableContext as useNonNullableContext3 } from "@toolpad/utils/react";
import { mapProperties, mapValues as mapValues2 } from "@toolpad/utils/collections";
import { set as setObjectPath2 } from "lodash-es";
import { useMutation as useMutation2 } from "@tanstack/react-query";
import {
  Routes,
  Route,
  useLocation as useLocation2,
  Navigate,
  useNavigate as useNavigate3,
  useMatch as useMatch2,
  useParams,
  Outlet,
  BrowserRouter
} from "react-router-dom";
import { ErrorBoundary } from "react-error-boundary";
import ErrorIcon from "@mui/icons-material/Error";
import { getBrowserRuntime } from "@toolpad/studio-runtime/jsBrowserRuntime";
import * as builtIns from "@toolpad/studio-components";
import { errorFrom } from "@toolpad/utils/errors";
import useBoolean from "@toolpad/utils/hooks/useBoolean";
import usePageTitle from "@toolpad/utils/hooks/usePageTitle";
import invariant3 from "invariant";
import useEventCallback from "@mui/utils/useEventCallback";
import * as appDom3 from "@toolpad/studio-runtime/appDom";
import useSsr from "@toolpad/utils/hooks/useSsr";

// src/runtime/bindings.ts
import { hasOwnProperty } from "@toolpad/utils/collections";
function getBindingType(binding) {
  if (binding && typeof binding === "object") {
    if (hasOwnProperty(binding, "$$jsExpression")) {
      return "jsExpression";
    }
    if (hasOwnProperty(binding, "$$env")) {
      return "env";
    }
    if (hasOwnProperty(binding, "$$jsExpressionAction")) {
      return "jsExpressionAction";
    }
    if (hasOwnProperty(binding, "$$navigationAction")) {
      return "navigationAction";
    }
  }
  return "const";
}
function getBindingValue(binding) {
  if (binding && typeof binding === "object") {
    if (hasOwnProperty(binding, "$$jsExpression")) {
      return binding.$$jsExpression;
    }
    if (hasOwnProperty(binding, "$$env")) {
      return binding.$$env;
    }
    if (hasOwnProperty(binding, "$$jsExpressionAction")) {
      return binding.$$jsExpressionAction;
    }
    if (hasOwnProperty(binding, "$$navigationAction")) {
      return binding.$$navigationAction;
    }
  }
  return binding;
}

// src/runtime/AppThemeProvider.tsx
import * as React2 from "react";
import { createTheme, ThemeProvider } from "@mui/material";
import { deepmerge } from "@mui/utils";
import * as appDom from "@toolpad/studio-runtime/appDom";
function createMuiThemeFromToolpadTheme(toolpadTheme = {}) {
  return createTheme(
    deepmerge(
      {
        typography: {
          h1: {
            fontSize: `3.25rem`,
            fontWeight: 800
          },
          h2: {
            fontSize: `2.25rem`,
            fontWeight: 700
          },
          h3: {
            fontSize: `1.75rem`,
            fontWeight: 700
          },
          h4: {
            fontSize: `1.5rem`,
            fontWeight: 700
          },
          h5: {
            fontSize: `1.25rem`,
            fontWeight: 700
          },
          h6: {
            fontSize: `1.15rem`,
            fontWeight: 700
          }
        },
        fontFamilyMonospaced: 'Consolas, Menlo, Monaco, "Andale Mono", "Ubuntu Mono", monospace'
      },
      toolpadTheme
    )
  );
}
function createToolpadAppTheme(dom) {
  const root = appDom.getApp(dom);
  const { themes = [] } = appDom.getChildNodes(dom, root);
  const themeNode = themes.length > 0 ? themes[0] : null;
  const toolpadTheme = themeNode?.theme;
  return createMuiThemeFromToolpadTheme(toolpadTheme);
}
function AppThemeProvider({ dom, children }) {
  const theme = React2.useMemo(() => createToolpadAppTheme(dom), [dom]);
  return /* @__PURE__ */ React2.createElement(ThemeProvider, { theme }, children);
}

// src/runtime/evalJsBindings.ts
import { mapValues } from "@toolpad/utils/collections";
import { setWith, clone, set as setObjectPath } from "lodash-es";
function updatePath(obj, path, value) {
  return setWith(clone(obj), path, value, clone);
}
function flattenDependency(deps, dep, history = /* @__PURE__ */ new Set([dep])) {
  const depDeps = deps.get(dep) ?? /* @__PURE__ */ new Set();
  const result = new Set(depDeps);
  for (const depDep of depDeps) {
    if (!history.has(depDep)) {
      const flat = flattenDependency(deps, depDep, /* @__PURE__ */ new Set([...history, depDep]));
      for (const flatted of flat) {
        result.add(flatted);
      }
    }
  }
  return result;
}
function flattenDependencies(deps) {
  const result = /* @__PURE__ */ new Map();
  for (const dep of deps.keys()) {
    result.set(dep, flattenDependency(deps, dep));
  }
  return result;
}
function bubbleError(flatDependencies, results, bindingId) {
  const result = results[bindingId];
  if (result.error) {
    return result.error;
  }
  const deps = flatDependencies.get(bindingId) ?? /* @__PURE__ */ new Set();
  for (const dep of deps) {
    const depResult = results[dep];
    if (depResult.error) {
      return depResult.error;
    }
  }
  return void 0;
}
function bubbleLoading(flatDependencies, results, bindingId) {
  const result = results[bindingId];
  if (result.loading) {
    return true;
  }
  const deps = flatDependencies.get(bindingId) ?? /* @__PURE__ */ new Set();
  for (const dep of deps) {
    const depResult = results[dep];
    if (depResult.loading) {
      return depResult.loading;
    }
  }
  return false;
}
function buildGlobalScope(base, bindings) {
  const globalScope = { ...base };
  for (const binding of Object.values(bindings)) {
    const value = binding.result?.value;
    if (binding.scopePath && getBindingType(value) === "const") {
      setObjectPath(globalScope, binding.scopePath, value);
    }
  }
  return globalScope;
}
function evalJsBindings(jsRuntime, bindings, globalScope) {
  const bindingsMap = new Map(Object.entries(bindings));
  const bindingIdMap = /* @__PURE__ */ new Map();
  for (const [bindingId, binding] of bindingsMap) {
    if (binding.scopePath) {
      bindingIdMap.set(binding.scopePath, bindingId);
    }
  }
  const computationStatuses = /* @__PURE__ */ new Map();
  let currentParentBinding;
  const dependencies = /* @__PURE__ */ new Map();
  let proxiedScope;
  const evaluateBinding = (bindingId, scopePath) => {
    const binding = bindingId && bindingsMap.get(bindingId);
    if (!binding) {
      return null;
    }
    if (currentParentBinding) {
      let bindingDependencies = dependencies.get(currentParentBinding);
      if (!bindingDependencies) {
        bindingDependencies = /* @__PURE__ */ new Set();
        dependencies.set(currentParentBinding, bindingDependencies);
      }
      bindingDependencies.add(bindingId);
    }
    const expression = binding.expression;
    if (expression) {
      const computed = computationStatuses.get(expression);
      if (computed) {
        if (computed.result) {
          return computed.result;
        }
        throw new Error(`Cycle detected "${scopePath}"`);
      }
      computationStatuses.set(expression, { result: null });
      const prevContext = currentParentBinding;
      currentParentBinding = bindingId;
      const result = jsRuntime.evaluateExpression(expression, proxiedScope);
      currentParentBinding = prevContext;
      computationStatuses.set(expression, { result });
      return result;
    }
    if (binding.result) {
      if (binding.dependencies) {
        dependencies.set(bindingId, new Set(binding.dependencies));
      }
      return binding.result;
    }
    const initializer = binding.initializer;
    if (initializer) {
      const result = jsRuntime.evaluateExpression(initializer, proxiedScope);
      if (result) {
        return result;
      }
    }
    return null;
  };
  const proxify = (obj, label) => new Proxy(obj, {
    get(target, prop, receiver) {
      if (typeof prop === "symbol") {
        return Reflect.get(target, prop, receiver);
      }
      const scopePath = label ? `${label}.${prop}` : prop;
      const bindingId = bindingIdMap.get(scopePath);
      if (bindingId) {
        const evaluated = evaluateBinding(bindingId, scopePath);
        if (evaluated) {
          return evaluated.value;
        }
      }
      const result = target[prop];
      if (result && typeof result === "object") {
        return proxify(result, scopePath);
      }
      return Reflect.get(target, prop, receiver);
    }
  });
  const scope = buildGlobalScope(globalScope, bindings);
  proxiedScope = proxify(scope);
  const results = mapValues(bindings, (binding, bindingId) => {
    return evaluateBinding(bindingId) || { value: void 0 };
  });
  const flatDependencies = flattenDependencies(dependencies);
  return mapValues(bindings, (binding, bindingId) => {
    const { scopePath } = binding;
    let bindingResult = results[bindingId];
    let nestedBindingsLoading;
    let nestedBindingsError;
    const seen = /* @__PURE__ */ new Set();
    const mergeNestedBindings = (value, parentBindingId) => {
      if (value && typeof value === "object") {
        if (seen.has(value)) {
          return;
        }
        seen.add(value);
        for (const nestedPropName of Object.keys(value)) {
          const nestedBindingId = `${parentBindingId}${Array.isArray(value) ? `[${nestedPropName}]` : `.${nestedPropName}`}`;
          const nestedBindingResult = results[nestedBindingId];
          if (nestedBindingResult) {
            if (!nestedBindingsError) {
              nestedBindingsError = bubbleError(flatDependencies, results, nestedBindingId);
            }
            if (!nestedBindingsLoading) {
              nestedBindingsLoading = bubbleLoading(flatDependencies, results, nestedBindingId);
            }
            bindingResult = updatePath(
              bindingResult,
              `value.${nestedBindingId.replace(bindingId, "")}`,
              nestedBindingResult.value
            );
          } else {
            mergeNestedBindings(
              value[nestedPropName],
              nestedBindingId
            );
          }
        }
      }
    };
    mergeNestedBindings(bindingResult.value, bindingId);
    return {
      scopePath,
      dependencies: Array.from(flatDependencies.get(bindingId) ?? []),
      result: {
        ...bindingResult,
        error: nestedBindingsError || bubbleError(flatDependencies, results, bindingId),
        loading: nestedBindingsLoading || bubbleLoading(flatDependencies, results, bindingId)
      }
    };
  });
}

// src/runtime/toolpadComponents/layoutBox.ts
var LAYOUT_DIRECTION_HORIZONTAL = "horizontal";
var LAYOUT_DIRECTION_VERTICAL = "vertical";
var LAYOUT_DIRECTION_BOTH = "both";
var layoutBoxArgTypes = {
  horizontalAlign: {
    helperText: "Horizontal alignment of the component",
    type: "string",
    enum: ["start", "center", "end", "space-between", "space-around", "space-evenly"],
    default: "start",
    label: "Horizontal alignment",
    control: { type: "HorizontalAlign", hideLabel: true, bindable: false }
  },
  verticalAlign: {
    helperText: "Vertical alignment of the component.",
    type: "string",
    enum: ["start", "center", "end", "space-between", "space-around", "space-evenly"],
    default: "start",
    label: "Vertical alignment",
    control: { type: "VerticalAlign", hideLabel: true, bindable: false }
  }
};

// src/runtime/useDataQuery.ts
import * as React4 from "react";
import { useQuery as useQuery2 } from "@tanstack/react-query";
import { useNonNullableContext } from "@toolpad/utils/react";

// src/runtime/api.ts
import * as React3 from "react";
import { queryClient } from "@toolpad/studio-runtime";

// src/rpcClient.ts
import * as superjson from "superjson";
import invariant from "invariant";
import {
  useMutation,
  useQuery,
  useSuspenseQuery
} from "@tanstack/react-query";
function createRpcClient(endpoint) {
  return new Proxy({}, {
    get(target, prop) {
      return async (...params) => {
        const body = {
          name: prop,
          params
        };
        const res = await fetch(endpoint, {
          method: "POST",
          headers: {
            "content-type": "application/json"
          },
          body: JSON.stringify(body)
        });
        if (res.ok) {
          const response = await res.json();
          if (response.error) {
            const toolpadError = new Error(response.error.message, {
              cause: response.error
            });
            if (response.error.code) {
              toolpadError.code = response.error.code;
            }
            throw toolpadError;
          }
          return superjson.parse(response.result);
        }
        throw new Error(`HTTP ${res.status}`);
      };
    }
  });
}
function createRpcApi(queryClient2, endpoint) {
  const methods = createRpcClient(endpoint);
  return {
    methods,
    useQuery: (key, params, options) => {
      return useQuery({
        ...options,
        enabled: !!params && options?.enabled !== false,
        queryKey: [key, params],
        queryFn: () => {
          invariant(params, `"enabled" prop of useQuery should prevent this call'`);
          return methods[key](...params);
        }
      });
    },
    useSuspenseQuery: (key, params, options) => {
      return useSuspenseQuery({
        ...options,
        queryKey: [key, params],
        queryFn: () => {
          invariant(params, "Query has no parameters");
          return methods[key](...params);
        }
      });
    },
    useMutation: (key, options) => useMutation({ mutationFn: (params) => methods[key](...params), ...options }),
    refetchQueries(key, params) {
      return queryClient2.refetchQueries({ queryKey: [key, params] });
    },
    invalidateQueries(key, params) {
      return queryClient2.invalidateQueries({ queryKey: [key, params] });
    }
  };
}

// src/runtime/api.ts
function createApi(url) {
  return createRpcApi(queryClient, new URL(url, window.location.href));
}
var RuntimeApiContext = React3.createContext(null);

// src/runtime/useDataQuery.ts
var EMPTY_ARRAY = [];
var EMPTY_OBJECT = {};
function useDataQuery(page, node, params, {
  enabled = true,
  ...options
}) {
  const { savedNodes } = React4.useContext(CanvasHooksContext);
  const queryName = node.name;
  const pageName = page.name;
  const isNodeAvailableOnServer = savedNodes ? !!savedNodes[node.id] : true;
  const runtimeApi = useNonNullableContext(RuntimeApiContext);
  const {
    isLoading,
    isFetching,
    error: fetchError,
    data: responseData = EMPTY_OBJECT,
    refetch
  } = useQuery2({
    queryKey: [pageName, queryName, params],
    queryFn: () => runtimeApi.methods.execQuery(pageName, queryName, params),
    ...options,
    enabled: isNodeAvailableOnServer && enabled
  });
  const { data, error: apiError } = responseData;
  const error = apiError || fetchError;
  const rows = Array.isArray(data) ? data : EMPTY_ARRAY;
  const result = React4.useMemo(
    () => ({
      isLoading: isLoading && !!enabled,
      isFetching,
      error,
      data,
      rows,
      refetch,
      fetch: async () => {
        throw new Error(`"fetch" is unsupported for automatic queries`);
      },
      call: async () => {
        throw new Error(`"call" is unsupported for automatic queries`);
      }
    }),
    [isLoading, enabled, isFetching, error, data, rows, refetch]
  );
  return result;
}

// src/runtime/PreviewHeader.tsx
import * as React5 from "react";
import { Button, Typography, Box, useTheme, Alert } from "@mui/material";
import EditIcon from "@mui/icons-material/Edit";
import { Link, useMatch } from "react-router-dom";
import { useAppHost } from "@toolpad/studio-runtime";
function OpenInEditorButton({
  children = "Open in editor",
  ...props
}) {
  return /* @__PURE__ */ React5.createElement(Button, { color: "inherit", size: "small", startIcon: /* @__PURE__ */ React5.createElement(EditIcon, null), ...props }, children);
}
function PreviewHeader() {
  const pageMatch = useMatch("/pages/:slug");
  const activePage = pageMatch?.params.slug;
  const theme = useTheme();
  const appContext = useAppHost();
  let action = null;
  action = /* @__PURE__ */ React5.createElement(
    OpenInEditorButton,
    {
      component: Link,
      to: activePage ? `/editor/app/pages/${activePage}` : "/editor/app"
    }
  );
  return appContext ? /* @__PURE__ */ React5.createElement(
    Box,
    {
      sx: {
        position: "relative",
        width: "100%",
        zIndex: theme.zIndex.drawer + 2
      }
    },
    /* @__PURE__ */ React5.createElement(
      Alert,
      {
        severity: "warning",
        sx: {
          borderRadius: 0
        },
        action
      },
      /* @__PURE__ */ React5.createElement(Typography, { variant: "body2" }, "This is a preview version of the application, not suitable for production.")
    )
  ) : null;
}

// src/runtime/AppLayout.tsx
import * as React7 from "react";
import { Box as Box2, useTheme as useTheme2 } from "@mui/material";
import { useNavigate as useNavigate2, useSearchParams } from "react-router-dom";
import { DashboardLayout } from "@toolpad/core/DashboardLayout";
import { AppProvider } from "@toolpad/core/react-router-dom";

// src/runtime/useAuth.ts
import * as React6 from "react";
import * as appDom2 from "@toolpad/studio-runtime/appDom";
import { useLocation, useNavigate } from "react-router-dom";
import { useAppHost as useAppHost2 } from "@toolpad/studio-runtime";
var AUTH_API_PATH = "/api/auth";
var AUTH_SESSION_PATH = `${AUTH_API_PATH}/session`;
var AUTH_CSRF_PATH = `${AUTH_API_PATH}/csrf`;
var AUTH_SIGNIN_PATH = `${AUTH_API_PATH}/signin`;
var AUTH_SIGNOUT_PATH = `${AUTH_API_PATH}/signout`;
function isResponseJSON(response) {
  return response.headers.get("content-type")?.includes("application/json") || false;
}
var AuthContext = React6.createContext({
  session: null,
  signIn: () => {
  },
  signOut: () => {
  },
  isSigningIn: false,
  isSigningOut: false,
  authProviders: [],
  hasAuthentication: false
});
function navigateNative(url) {
  window.location.href = url;
}
function useAuth({ dom, basename, signInPagePath }) {
  const location = useLocation();
  const navigate = useNavigate();
  const authProviders = React6.useMemo(() => {
    const app = appDom2.getApp(dom);
    const authProviderConfigs = app.attributes.authentication?.providers ?? [];
    return authProviderConfigs.map((providerConfig) => providerConfig.provider);
  }, [dom]);
  const hasAuthentication = authProviders.length > 0;
  const [session, setSession] = React6.useState(null);
  const [isSigningIn, setIsSigningIn] = React6.useState(true);
  const [isSigningOut, setIsSigningOut] = React6.useState(true);
  const getCsrfToken = React6.useCallback(async () => {
    let csrfToken = "";
    try {
      const csrfResponse = await fetch(`${basename}${AUTH_CSRF_PATH}`, {
        headers: {
          "Content-Type": "application/json"
        }
      });
      if (isResponseJSON(csrfResponse)) {
        csrfToken = (await csrfResponse.json())?.csrfToken;
      }
    } catch (error) {
      console.error(error.message);
    }
    return csrfToken ?? "";
  }, [basename]);
  const signOut = React6.useCallback(async () => {
    setIsSigningOut(true);
    const csrfToken = await getCsrfToken();
    try {
      await fetch(`${basename}${AUTH_SIGNOUT_PATH}`, {
        method: "POST",
        headers: {
          "Content-Type": "application/x-www-form-urlencoded",
          "X-Auth-Return-Redirect": "1"
        },
        body: new URLSearchParams({ csrfToken })
      });
    } catch (error) {
      console.error(error.message);
    }
    setSession(null);
    setIsSigningOut(false);
    if (location.pathname !== signInPagePath) {
      navigate(signInPagePath);
    }
  }, [basename, getCsrfToken, location.pathname, navigate, signInPagePath]);
  const getSession = React6.useCallback(async () => {
    setIsSigningIn(true);
    await getCsrfToken();
    try {
      setIsSigningIn(true);
      const sessionResponse = await fetch(`${basename}${AUTH_SESSION_PATH}`, {
        headers: {
          "Content-Type": "application/json"
        }
      });
      if (isResponseJSON(sessionResponse)) {
        const currentSession = await sessionResponse.json();
        setSession(currentSession);
        if (!currentSession) {
          signOut();
        }
      } else {
        signOut();
      }
    } catch (error) {
      console.error(error.message);
      signOut();
    }
    setIsSigningIn(false);
  }, [basename, getCsrfToken, signOut]);
  const signIn = React6.useCallback(
    async (provider, payload, isLocalProvider = false) => {
      setIsSigningIn(true);
      const csrfToken = await getCsrfToken();
      try {
        const signInResponse = await fetch(
          isLocalProvider ? `${basename}${AUTH_API_PATH}/callback/${provider}` : `${basename}${AUTH_SIGNIN_PATH}/${provider}`,
          {
            method: "POST",
            headers: {
              "Content-Type": "application/x-www-form-urlencoded",
              "X-Auth-Return-Redirect": "1"
            },
            body: new URLSearchParams({ ...payload, csrfToken })
          }
        );
        const { url: signInUrl } = await signInResponse.json();
        navigateNative(signInUrl);
      } catch (error) {
        console.error(error.message);
        signOut();
        setIsSigningIn(false);
      }
    },
    [basename, getCsrfToken, signOut]
  );
  const appHost = useAppHost2();
  React6.useEffect(() => {
    if (hasAuthentication && !appHost.isCanvas) {
      getSession();
    }
  }, [getCsrfToken, getSession, hasAuthentication, appHost.isCanvas]);
  return {
    session,
    signIn,
    signOut,
    isSigningIn,
    isSigningOut,
    authProviders,
    hasAuthentication
  };
}

// src/runtime/AppLayout.tsx
var TOOLPAD_DISPLAY_MODE_URL_PARAM = "toolpad-display";
var RETAINED_URL_PARAMS = /* @__PURE__ */ new Set([TOOLPAD_DISPLAY_MODE_URL_PARAM]);
function AppLayout({
  activePageSlug,
  pages = [],
  hasLayout: hasLayoutProp = true,
  children
}) {
  const theme = useTheme2();
  const [searchParams] = useSearchParams();
  const navigate = useNavigate2();
  const retainedSearch = React7.useMemo(() => {
    for (const name of searchParams.keys()) {
      if (!RETAINED_URL_PARAMS.has(name)) {
        searchParams.delete(name);
      }
    }
    return searchParams.size > 0 ? `?${searchParams.toString()}` : "";
  }, [searchParams]);
  const navEntry = pages.find((page) => page.slug === activePageSlug);
  const displayMode = searchParams.get(TOOLPAD_DISPLAY_MODE_URL_PARAM);
  const hasShell = navEntry?.hasShell !== false && displayMode !== "standalone";
  const hasLayout = hasLayoutProp && hasShell;
  const { session, signOut, hasAuthentication } = React7.useContext(AuthContext);
  const navigation = React7.useMemo(
    () => pages.map(({ slug, displayName }) => ({
      segment: `pages/${slug}${retainedSearch}`,
      title: displayName
    })),
    [pages, retainedSearch]
  );
  const authentication = React7.useMemo(
    () => hasAuthentication ? {
      signIn: () => {
        navigate("/signin");
      },
      signOut
    } : void 0,
    [hasAuthentication, navigate, signOut]
  );
  const layoutContent = /* @__PURE__ */ React7.createElement(Box2, { sx: { minWidth: 0, flex: 1, position: "relative", flexDirection: "column" } }, children);
  return /* @__PURE__ */ React7.createElement(
    AppProvider,
    {
      theme,
      navigation,
      branding: {
        title: "Toolpad Studio"
      },
      authentication,
      session
    },
    hasLayout ? /* @__PURE__ */ React7.createElement(DashboardLayout, { sx: { height: "100%" } }, layoutContent) : layoutContent
  );
}

// src/runtime/useDataProvider.ts
import * as React8 from "react";
import { useQuery as useQuery3 } from "@tanstack/react-query";
import invariant2 from "invariant";
import { useNonNullableContext as useNonNullableContext2 } from "@toolpad/utils/react";
var useDataProvider = (id) => {
  const runtimeApi = useNonNullableContext2(RuntimeApiContext);
  const {
    isLoading,
    error,
    data: introspection
  } = useQuery3({
    queryKey: ["introspectDataProvider", id],
    enabled: !!id,
    queryFn: async () => {
      invariant2(id, "id is required");
      const [filePath, name] = id.split(":");
      return runtimeApi.methods.introspectDataProvider(filePath, name);
    }
  });
  const dataProvider = React8.useMemo(() => {
    if (!introspection) {
      return null;
    }
    return {
      paginationMode: introspection.paginationMode,
      getRecords: async (...args) => {
        invariant2(id, "id is required");
        const [filePath, name] = id.split(":");
        return runtimeApi.methods.getDataProviderRecords(filePath, name, ...args);
      },
      deleteRecord: introspection.hasDeleteRecord ? async (recordId) => {
        invariant2(id, "id is required");
        const [filePath, name] = id.split(":");
        return runtimeApi.methods.deleteDataProviderRecord(filePath, name, recordId);
      } : void 0,
      updateRecord: introspection.hasUpdateRecord ? async (recordId, values) => {
        invariant2(id, "id is required");
        const [filePath, name] = id.split(":");
        return runtimeApi.methods.updateDataProviderRecord(filePath, name, recordId, values);
      } : void 0,
      createRecord: introspection.hasCreateRecord ? async (values) => {
        invariant2(id, "id is required");
        const [filePath, name] = id.split(":");
        return runtimeApi.methods.createDataProviderRecord(filePath, name, values);
      } : void 0
    };
  }, [id, introspection, runtimeApi]);
  return { isLoading, error, dataProvider };
};

// src/runtime/auth.tsx
import * as React9 from "react";
import { asArray } from "@toolpad/utils/collections";
import { Box as Box3 } from "@mui/material";
function RequireAuthorization({
  children,
  allowAll,
  allowedRoles
}) {
  const { session } = React9.useContext(AuthContext);
  const user = session?.user ?? null;
  const allowedRolesSet = React9.useMemo(
    () => new Set(asArray(allowedRoles ?? [])),
    [allowedRoles]
  );
  let reason = null;
  if (!allowAll && !user?.roles.some((role) => allowedRolesSet.has(role))) {
    reason = `User does not have the roles to access this page.`;
  }
  return reason ? /* @__PURE__ */ React9.createElement(
    Box3,
    {
      sx: {
        flex: 1,
        display: "flex",
        alignItems: "center",
        justifyContent: "center",
        mt: 6
      }
    },
    "Unauthorized. ",
    reason
  ) : children;
}

// src/runtime/SignInPage.tsx
import * as React10 from "react";
import {
  Alert as Alert2,
  Button as Button2,
  Divider,
  Snackbar,
  Stack,
  TextField,
  Typography as Typography2,
  useTheme as useTheme3
} from "@mui/material";
import GitHubIcon from "@mui/icons-material/GitHub";
import PasswordIcon from "@mui/icons-material/Password";
import ArrowBackIcon from "@mui/icons-material/ArrowBack";
import { LoadingButton } from "@mui/lab";
import { useSearchParams as useSearchParams2 } from "react-router-dom";
import { useForm, Controller } from "react-hook-form";
import productIconDark from "./product-icon-dark-XGNA2SGZ.svg";
import productIconLight from "./product-icon-light-AJK4O7HC.svg";
var AUTH_ERROR_URL_PARAM = "error";
var azureIconSvg = /* @__PURE__ */ React10.createElement("svg", { viewBox: "0 0 59.242 47.271", width: 18, height: 18, xmlns: "http://www.w3.org/2000/svg" }, /* @__PURE__ */ React10.createElement(
  "path",
  {
    d: "m32.368 0-17.468 15.145-14.9 26.75h13.437zm2.323 3.543-7.454 21.008 14.291 17.956-27.728 4.764h45.442z",
    fill: "currentColor"
  }
));
function SignInPage() {
  const theme = useTheme3();
  const [urlParams] = useSearchParams2();
  const { signIn, isSigningIn } = React10.useContext(AuthContext);
  const [errorSnackbarMessage, setErrorSnackbarMessage] = React10.useState("");
  const [latestSelectedProvider, setLatestSelectedProvider] = React10.useState(
    null
  );
  const [isCredentialsSignIn, setIsCredentialsSignIn] = React10.useState(false);
  const { authProviders } = React10.useContext(AuthContext);
  const handleSignIn = React10.useCallback(
    (provider, payload, isLocalProvider) => () => {
      setLatestSelectedProvider(provider);
      signIn(provider, payload, isLocalProvider);
    },
    [signIn]
  );
  const handleCredentialsSignIn = React10.useCallback(() => {
    setIsCredentialsSignIn(true);
  }, []);
  const handleCredentialsBack = React10.useCallback(() => {
    setIsCredentialsSignIn(false);
  }, []);
  React10.useEffect(() => {
    const authError = urlParams.get(AUTH_ERROR_URL_PARAM);
    if (authError === "AccessDenied" || authError === "CredentialsSignin") {
      setErrorSnackbarMessage("Access unauthorized.");
    } else if (authError === "CallbackRouteError") {
      setErrorSnackbarMessage(
        "There was an error with your authentication provider configuration."
      );
    } else if (authError === "MissingSecretError") {
      setErrorSnackbarMessage("Missing secret for authentication. Please provide a secret.");
    } else if (authError) {
      setErrorSnackbarMessage("An authentication error occurred.");
    }
  }, [urlParams]);
  const handleErrorSnackbarClose = React10.useCallback(() => {
    setErrorSnackbarMessage("");
  }, []);
  const { handleSubmit: handleCredentialsSubmit, control: credentialsFormControl } = useForm({
    defaultValues: {
      username: "",
      password: ""
    }
  });
  const onCredentialsSubmit = React10.useCallback(
    (data) => {
      handleSignIn("credentials", data, true)();
    },
    [handleSignIn]
  );
  const productIcon = theme.palette.mode === "dark" ? productIconDark : productIconLight;
  return /* @__PURE__ */ React10.createElement(React10.Fragment, null, /* @__PURE__ */ React10.createElement(
    Stack,
    {
      direction: "column",
      alignItems: "center",
      justifyContent: "center",
      flex: 1,
      gap: 2,
      sx: { backgroundColor: theme.palette.background.default }
    },
    /* @__PURE__ */ React10.createElement("img", { src: productIcon, alt: "Toolpad logo", width: 56, height: 56 }),
    /* @__PURE__ */ React10.createElement(Typography2, { variant: "h1" }, "Sign In"),
    /* @__PURE__ */ React10.createElement(Typography2, { variant: "subtitle1", mb: 1 }, "You must be authenticated to use this app."),
    /* @__PURE__ */ React10.createElement(Stack, { sx: { width: 300 }, gap: 2 }, isCredentialsSignIn ? /* @__PURE__ */ React10.createElement(React10.Fragment, null, /* @__PURE__ */ React10.createElement(Stack, { direction: "row", alignItems: "center" }, /* @__PURE__ */ React10.createElement(Button2, { onClick: handleCredentialsBack }, /* @__PURE__ */ React10.createElement(ArrowBackIcon, null), /* @__PURE__ */ React10.createElement(Typography2, { variant: "button", sx: { ml: 1 } }, "Back"))), /* @__PURE__ */ React10.createElement("form", { onSubmit: handleCredentialsSubmit(onCredentialsSubmit) }, /* @__PURE__ */ React10.createElement(Stack, { direction: "column", gap: 2 }, /* @__PURE__ */ React10.createElement(
      Controller,
      {
        name: "username",
        rules: { required: "Username is required" },
        control: credentialsFormControl,
        render: ({ field: { onChange, value }, fieldState: { error } }) => /* @__PURE__ */ React10.createElement(
          TextField,
          {
            helperText: error ? error.message : null,
            error: !!error,
            onChange,
            value,
            fullWidth: true,
            label: "Username",
            variant: "outlined"
          }
        )
      }
    ), /* @__PURE__ */ React10.createElement(
      Controller,
      {
        name: "password",
        rules: { required: "Password is required" },
        control: credentialsFormControl,
        render: ({ field: { onChange, value }, fieldState: { error } }) => /* @__PURE__ */ React10.createElement(
          TextField,
          {
            type: "password",
            helperText: error ? error.message : null,
            error: !!error,
            onChange,
            value,
            fullWidth: true,
            label: "Password",
            variant: "outlined"
          }
        )
      }
    ), /* @__PURE__ */ React10.createElement(
      LoadingButton,
      {
        variant: "contained",
        type: "submit",
        loading: isSigningIn && latestSelectedProvider === "credentials",
        disabled: isSigningIn,
        size: "large",
        fullWidth: true
      },
      "Sign in"
    )))) : /* @__PURE__ */ React10.createElement(React10.Fragment, null, authProviders.includes("github") ? /* @__PURE__ */ React10.createElement(
      LoadingButton,
      {
        variant: "contained",
        onClick: handleSignIn("github"),
        startIcon: /* @__PURE__ */ React10.createElement(GitHubIcon, null),
        loading: isSigningIn && latestSelectedProvider === "github",
        disabled: isSigningIn,
        loadingPosition: "start",
        size: "large",
        fullWidth: true,
        sx: {
          backgroundColor: "#24292F"
        }
      },
      "Sign in with GitHub"
    ) : null, authProviders.includes("google") ? /* @__PURE__ */ React10.createElement(
      LoadingButton,
      {
        variant: "contained",
        onClick: handleSignIn("google"),
        startIcon: /* @__PURE__ */ React10.createElement(
          "img",
          {
            alt: "Google logo",
            loading: "lazy",
            height: "18",
            width: "18",
            src: "https://authjs.dev/img/providers/google.svg",
            style: { marginLeft: "2px", marginRight: "2px" }
          }
        ),
        loading: isSigningIn && latestSelectedProvider === "google",
        disabled: isSigningIn,
        loadingPosition: "start",
        size: "large",
        fullWidth: true,
        sx: {
          backgroundColor: "#fff",
          color: "#000",
          "&:hover": {
            color: theme.palette.primary.contrastText
          }
        }
      },
      "Sign in with Google"
    ) : null, authProviders.includes("azure-ad") ? /* @__PURE__ */ React10.createElement(
      LoadingButton,
      {
        variant: "contained",
        onClick: handleSignIn("azure-ad"),
        startIcon: azureIconSvg,
        loading: isSigningIn && latestSelectedProvider === "azure-ad",
        disabled: isSigningIn,
        loadingPosition: "start",
        size: "large",
        fullWidth: true,
        sx: {
          backgroundColor: "#0072c6"
        }
      },
      "Sign in with Azure AD"
    ) : null, authProviders.includes("credentials") ? /* @__PURE__ */ React10.createElement(React10.Fragment, null, authProviders.length > 1 ? /* @__PURE__ */ React10.createElement(Divider, null, /* @__PURE__ */ React10.createElement(Typography2, { variant: "caption" }, "OR")) : null, /* @__PURE__ */ React10.createElement(
      LoadingButton,
      {
        variant: "contained",
        onClick: handleCredentialsSignIn,
        startIcon: /* @__PURE__ */ React10.createElement(PasswordIcon, null),
        loading: isSigningIn && latestSelectedProvider === "credentials",
        disabled: isSigningIn,
        loadingPosition: "start",
        size: "large",
        fullWidth: true
      },
      "Sign in with credentials"
    )) : null))
  ), /* @__PURE__ */ React10.createElement(
    Snackbar,
    {
      open: !!errorSnackbarMessage,
      autoHideDuration: 6e3,
      onClose: handleErrorSnackbarClose
    },
    errorSnackbarMessage ? /* @__PURE__ */ React10.createElement(Alert2, { onClose: handleErrorSnackbarClose, severity: "error" }, errorSnackbarMessage) : void 0
  ));
}

// src/runtime/ToolpadApp.tsx
var browserJsRuntime = getBrowserRuntime();
var Pre = styled("pre")(({ theme }) => ({
  margin: 0,
  fontFamily: theme.fontFamilyMonospaced
}));
var internalComponents = Object.fromEntries(
  Object.entries(builtIns).map(([name, builtIn]) => {
    if (!isToolpadComponent(builtIn)) {
      builtIn = createToolpadComponentThatThrows(
        new Error(`Imported builtIn "${name}" is not a ToolpadComponent`)
      );
    }
    return [name, builtIn];
  })
);
var ReactQueryDevtoolsProduction = React11.lazy(
  () => import("@tanstack/react-query-devtools/production").then((d) => ({
    default: d.ReactQueryDevtools
  }))
);
var EMPTY_ARRAY2 = [];
var EMPTY_OBJECT2 = {};
var INITIAL_FETCH = {
  call: async () => {
  },
  refetch: async () => {
  },
  fetch: async () => {
  },
  isLoading: false,
  isFetching: false,
  error: null,
  data: null,
  rows: []
};
function usePageNavigator() {
  const navigate = useNavigate3();
  const canvasEvents = React11.useContext(CanvasEventsContext);
  const navigateToPage = React11.useCallback(
    (pageName, pageParameters) => {
      const urlParams = pageParameters && new URLSearchParams(pageParameters);
      if (canvasEvents) {
        canvasEvents.emit("pageNavigationRequest", { pageName });
      } else {
        navigate({
          pathname: `/pages/${pageName}`,
          ...urlParams ? {
            search: urlParams.toString()
          } : {}
        });
      }
    },
    [canvasEvents, navigate]
  );
  return navigateToPage;
}
function isEqual(a, b) {
  return a.value === b.value && !!a.error === !!b.error && a.loading === b.loading;
}
var AppRoot = styled("div")({
  overflow: "auto",
  position: "relative",
  display: "flex",
  flex: 1,
  flexDirection: "column"
});
var EditorOverlay = styled("div")({
  position: "absolute",
  inset: "0 0 0 0",
  pointerEvents: "none",
  overflow: "hidden"
});
function createScope(id, bindings, { localValues, parentScope, meta = {} }) {
  const scopeValues = { ...parentScope?.values, ...localValues };
  const evaluatedBindings = evalJsBindings(browserJsRuntime, bindings, scopeValues);
  return {
    id,
    parentScope,
    bindings: mapValues2(evaluatedBindings, (binding) => binding.result || { value: void 0 }),
    values: buildGlobalScope(scopeValues, evaluatedBindings),
    meta
  };
}
function useApplicationVm(onUpdate) {
  const vm = { scopes: {}, bindingScopes: {} };
  let scheduledUpdate;
  const scheduleUpdate = () => {
    if (scheduledUpdate) {
      return;
    }
    scheduledUpdate = Promise.resolve().then(async () => {
      onUpdate(vm);
      await Promise.resolve();
      scheduledUpdate = void 0;
    });
  };
  return React11.useRef({
    registerScope(scope) {
      if (vm.scopes[scope.id]) {
        throw new Error(`Scope with id "${scope.id}" already registered`);
      }
      vm.scopes[scope.id] = scope;
      scheduleUpdate();
      return () => {
        delete vm.scopes[scope.id];
        scheduleUpdate();
      };
    },
    registerBindingScope(bindingId, scope) {
      if (vm.bindingScopes[bindingId]) {
        return () => {
        };
      }
      vm.bindingScopes[bindingId] = scope.id;
      scheduleUpdate();
      return () => {
        delete vm.bindingScopes[bindingId];
        scheduleUpdate();
      };
    }
  });
}
var ApplicationVmApiContext = React11.createContext(void 0);
var RuntimeScopeContext = React11.createContext(void 0);
var DomContext = React11.createContext(void 0);
var useDomContext = () => useNonNullableContext3(DomContext);
var EvaluateScopeExpressionContext = React11.createContext(
  void 0
);
var useEvaluateScopeExpression = () => useNonNullableContext3(EvaluateScopeExpressionContext);
var SetBindingContext = React11.createContext(void 0);
function getComponentId(elm) {
  const componentId = getElementNodeComponentId(elm);
  return componentId;
}
function flattenNestedBindables(params, prefix = "") {
  if (!params) {
    return [];
  }
  if (Array.isArray(params)) {
    return params.flatMap((param, i) => {
      return flattenNestedBindables(param[1], `${prefix}[${i}][1]`);
    });
  }
  if (typeof params !== "object" || getBindingType(params) !== "const") {
    return [[prefix, params]];
  }
  return Object.entries(params).flatMap(
    ([key, param]) => flattenNestedBindables(param, `${prefix}.${key}`)
  );
}
function resolveBindables(bindings, bindingId, params) {
  const result = {};
  const resultKey = "value";
  const flattened = flattenNestedBindables(params);
  for (const [path] of flattened) {
    const resolvedBinding = bindings[`${bindingId}${path}`];
    if (resolvedBinding?.error) {
      return { error: resolvedBinding?.error };
    }
    if (resolvedBinding?.loading) {
      return { loading: true };
    }
    setObjectPath2(result, `${resultKey}${path}`, resolvedBinding?.value);
  }
  return { value: result[resultKey] || {} };
}
function parseBinding(bindable, { scopePath } = {}) {
  const bindingType = getBindingType(bindable);
  if (bindingType === "const") {
    return {
      scopePath,
      result: { value: bindable }
    };
  }
  if (bindingType === "env") {
    return {
      scopePath,
      result: { value: bindable }
    };
  }
  if (bindingType === "jsExpression") {
    return {
      scopePath,
      expression: bindable.$$jsExpression
    };
  }
  return {
    scopePath,
    result: { value: void 0 }
  };
}
function getScopeElements(dom, rootNode, components) {
  if (Array.isArray(rootNode)) {
    return [...rootNode, ...rootNode.flatMap((child) => getScopeElements(dom, child, components))];
  }
  const childNodes = appDom3.getChildNodes(dom, rootNode);
  const result = [];
  for (const [prop, children] of Object.entries(childNodes)) {
    if (appDom3.isElement(rootNode)) {
      const componentId = getComponentId(rootNode);
      const Component = components[componentId];
      const componentConfig = Component?.[TOOLPAD_COMPONENT];
      const { argTypes = {} } = componentConfig ?? {};
      if (argTypes[prop]?.type !== "template") {
        result.push(
          ...children,
          ...children.flatMap((child) => getScopeElements(dom, child, components))
        );
      }
    } else {
      result.push(
        ...children,
        ...children.flatMap((child) => getScopeElements(dom, child, components))
      );
    }
  }
  return result;
}
function getQueryConfigBindings({ enabled, refetchInterval }) {
  return { enabled, refetchInterval };
}
function isBindableProp(componentConfig, propName) {
  const argType = componentConfig.argTypes?.[propName];
  return argType?.control?.bindable !== false && argType?.type !== "template" && argType?.type !== "event";
}
function parseBindings(dom, rootNode, components, location) {
  const scopeElements = getScopeElements(dom, rootNode, components);
  const parsedBindingsMap = /* @__PURE__ */ new Map();
  const controlled = /* @__PURE__ */ new Set();
  const scopeMeta = {};
  for (const elm of scopeElements) {
    if (appDom3.isElement(elm)) {
      const componentId = getComponentId(elm);
      const Component = components[componentId];
      const componentConfig = Component?.[TOOLPAD_COMPONENT] ?? {};
      const { argTypes = {} } = componentConfig;
      const propsMeta = {};
      for (const [propName, argType] of Object.entries(argTypes)) {
        invariant3(argType, `Missing argType for prop "${propName}"`);
        const initializerExpression = argType.defaultValueProp ? `${elm.name}.${argType.defaultValueProp}` : JSON.stringify(getArgTypeDefaultValue(argType));
        const propValue = elm.props?.[propName];
        const binding = propValue ?? getArgTypeDefaultValue(argType);
        const bindingId = `${elm.id}.props.${propName}`;
        let scopePath;
        if (componentId !== PAGE_ROW_COMPONENT_ID && isBindableProp(componentConfig, propName)) {
          scopePath = `${elm.name}.${propName}`;
        }
        propsMeta[propName] = {
          tsType: argType?.tsType
        };
        if (argType) {
          if (argType.onChangeProp) {
            controlled.add(bindingId);
            parsedBindingsMap.set(bindingId, {
              scopePath,
              initializer: initializerExpression
            });
          } else {
            parsedBindingsMap.set(bindingId, parseBinding(binding, { scopePath }));
          }
        }
        const parseNestedBindings = (value, parentBindingId) => {
          if (value && typeof value === "object") {
            for (const [nestedPropName, nestedProp] of Object.entries(value)) {
              const nestedBindingId = `${parentBindingId}${Array.isArray(value) ? `[${nestedPropName}]` : `.${nestedPropName}`}`;
              if (nestedProp && getBindingType(nestedProp) !== "const") {
                parsedBindingsMap.set(nestedBindingId, parseBinding(nestedProp));
              } else {
                parseNestedBindings(
                  value[nestedPropName],
                  nestedBindingId
                );
              }
            }
          }
        };
        const propBindingValue = propValue && getBindingValue(propValue);
        parseNestedBindings(propBindingValue, bindingId);
      }
      if (componentId !== PAGE_ROW_COMPONENT_ID) {
        scopeMeta[elm.name] = {
          kind: "element",
          componentId,
          props: propsMeta
        };
      }
      if (!isPageLayoutComponent(elm)) {
        for (const [propName, argType] of Object.entries(layoutBoxArgTypes)) {
          const binding = elm.layout?.[propName] ?? (argType ? getArgTypeDefaultValue(argType) : void 0);
          const bindingId = `${elm.id}.layout.${propName}`;
          parsedBindingsMap.set(bindingId, parseBinding(binding, {}));
        }
      }
    }
    if (appDom3.isQuery(elm)) {
      let kind = "query";
      if (elm.attributes.mode === "mutation") {
        kind = "action";
      }
      scopeMeta[elm.name] = {
        kind
      };
      if (elm.params) {
        const nestedBindablePaths2 = flattenNestedBindables(Object.fromEntries(elm.params ?? []));
        for (const [nestedPath, paramValue] of nestedBindablePaths2) {
          const bindingId = `${elm.id}.params${nestedPath}`;
          const scopePath = `${elm.name}.params${nestedPath}`;
          const bindable = paramValue;
          parsedBindingsMap.set(bindingId, parseBinding(bindable, { scopePath }));
        }
      }
      for (const [key, value] of Object.entries(INITIAL_FETCH)) {
        const bindingId = `${elm.id}.${key}`;
        const scopePath = `${elm.name}.${key}`;
        controlled.add(bindingId);
        parsedBindingsMap.set(bindingId, {
          scopePath,
          result: { value, loading: true }
        });
      }
      const configBindings = getQueryConfigBindings(elm.attributes);
      const nestedBindablePaths = flattenNestedBindables(configBindings);
      for (const [nestedPath, paramValue] of nestedBindablePaths) {
        const bindingId = `${elm.id}.config${nestedPath}`;
        const scopePath = `${elm.name}.config${nestedPath}`;
        const bindable = paramValue;
        parsedBindingsMap.set(bindingId, parseBinding(bindable, { scopePath }));
      }
    }
    if (appDom3.isMutation(elm)) {
      if (elm.params) {
        for (const [paramName, bindable] of Object.entries(elm.params)) {
          const bindingId = `${elm.id}.params.${paramName}`;
          const scopePath = `${elm.name}.params.${paramName}`;
          const bindingType = getBindingType(bindable);
          if (bindingType === "const") {
            parsedBindingsMap.set(bindingId, {
              scopePath,
              result: { value: bindable }
            });
          } else if (bindingType === "jsExpression") {
            parsedBindingsMap.set(bindingId, {
              scopePath,
              expression: bindable.$$jsExpression
            });
          }
        }
      }
      for (const [key, value] of Object.entries(INITIAL_FETCH)) {
        const bindingId = `${elm.id}.${key}`;
        const scopePath = `${elm.name}.${key}`;
        controlled.add(bindingId);
        parsedBindingsMap.set(bindingId, {
          scopePath,
          result: { value, loading: true }
        });
      }
    }
  }
  if (!Array.isArray(rootNode) && appDom3.isPage(rootNode)) {
    if (location && !Array.isArray(rootNode) && appDom3.isPage(rootNode)) {
      const urlParams = new URLSearchParams(location.search);
      const pageParameters = rootNode.attributes.parameters || [];
      for (const [paramName, paramDefault] of pageParameters) {
        const bindingId = `${rootNode.id}.parameters.${paramName}`;
        const scopePath = `page.parameters.${paramName}`;
        parsedBindingsMap.set(bindingId, {
          scopePath,
          result: { value: urlParams.get(paramName) || paramDefault }
        });
      }
    }
  }
  const parsedBindings = Object.fromEntries(parsedBindingsMap);
  return { parsedBindings, controlled, scopeMeta };
}
function useElmToolpadComponent(elm) {
  const componentId = getElementNodeComponentId(elm);
  return useComponent(componentId);
}
function RenderedNode({ nodeId }) {
  const dom = useDomContext();
  const node = appDom3.getNode(dom, nodeId, "element");
  const Component = useElmToolpadComponent(node);
  const childNodeGroups = appDom3.getChildNodes(dom, node);
  return /* @__PURE__ */ React11.createElement(RenderedNodeContent, { node, childNodeGroups, Component });
}
function RuntimeScoped({
  id,
  parseBindingsResult,
  localScope,
  onUpdate,
  children
}) {
  const parentScope = React11.useContext(RuntimeScopeContext);
  const dom = useDomContext();
  const { parsedBindings, controlled, scopeMeta } = parseBindingsResult;
  const [scopeBindings, setScopeBindings] = React11.useState(parsedBindings);
  const prevDom = React11.useRef(dom);
  React11.useEffect(() => {
    if (dom === prevDom.current) {
      return;
    }
    prevDom.current = dom;
    setScopeBindings((existingBindings) => {
      const updated = {};
      for (const [key, binding] of Object.entries(parsedBindings)) {
        updated[key] = controlled.has(key) ? existingBindings[key] || binding : binding;
      }
      return updated;
    });
  }, [parsedBindings, controlled, dom]);
  const { setBindingByScopePath: setParentBindingByScopePath } = React11.useContext(SetBindingContext) ?? {};
  const setBinding = React11.useCallback(
    (bindingId, result) => {
      setScopeBindings((existingBindings) => {
        const { expression, initializer, ...parsedBinding } = parsedBindings[bindingId];
        const existingBinding = existingBindings[bindingId];
        if (existingBinding?.result && isEqual(existingBinding.result, result)) {
          return existingBindings;
        }
        return {
          ...existingBindings,
          ...{
            [bindingId]: { ...parsedBinding, result }
          }
        };
      });
    },
    [parsedBindings]
  );
  const bindingsByScopePath = React11.useMemo(
    () => new Map(
      Object.entries(scopeBindings).map(
        ([bindingId, binding]) => [binding.scopePath, bindingId]
      )
    ),
    [scopeBindings]
  );
  const setBindingByScopePath = React11.useCallback(
    (scopePath, result) => {
      const bindingToUpdateId = bindingsByScopePath.get(scopePath);
      if (bindingToUpdateId) {
        setBinding(bindingToUpdateId, result);
      } else if (setParentBindingByScopePath) {
        setParentBindingByScopePath(scopePath, result);
      } else {
        throw new Error(`No binding found for scope path "${scopePath}"`);
      }
    },
    [bindingsByScopePath, setBinding, setParentBindingByScopePath]
  );
  const setControlledBinding = React11.useCallback(
    (bindingId, result) => {
      if (!controlled.has(bindingId)) {
        throw new Error(`Not a controlled binding "${bindingId}"`);
      }
      setBinding(bindingId, result);
    },
    [controlled, setBinding]
  );
  const childScope = React11.useMemo(
    () => createScope(id, scopeBindings, {
      localValues: localScope,
      parentScope,
      meta: scopeMeta
    }),
    [id, localScope, parentScope, scopeBindings, scopeMeta]
  );
  const vmRef = React11.useContext(ApplicationVmApiContext);
  React11.useEffect(() => {
    if (!vmRef) {
      return () => {
      };
    }
    return vmRef.current.registerScope(childScope);
  }, [vmRef, childScope]);
  const evaluateScopeExpression = React11.useCallback(
    async (expression) => {
      const updates = {};
      const proxify = (obj, scopePathSegments) => {
        return new Proxy(obj, {
          get(target, prop, receiver) {
            if (typeof prop === "symbol") {
              return Reflect.get(target, prop, receiver);
            }
            const result2 = target[prop];
            if (result2 && typeof result2 === "object") {
              return proxify(result2, [...scopePathSegments, prop]);
            }
            return Reflect.get(target, prop, receiver);
          },
          set(target, prop, newValue, receiver) {
            if (typeof prop === "symbol") {
              return Reflect.set(target, prop, newValue, receiver);
            }
            const scopePath = [...scopePathSegments, prop].join(".");
            updates[scopePath] = newValue;
            return Reflect.set(target, prop, newValue, receiver);
          }
        });
      };
      const scopeValues = childScope.values;
      const result = browserJsRuntime.evaluateExpression(expression, proxify(scopeValues, []));
      await result.value;
      for (const [scopePath, newValue] of Object.entries(updates)) {
        setBindingByScopePath(scopePath, { value: newValue });
      }
      return result;
    },
    [childScope.values, setBindingByScopePath]
  );
  React11.useEffect(() => {
    onUpdate?.({
      scopeMeta,
      scope: childScope
    });
  }, [scopeMeta, childScope, onUpdate]);
  const setBindingContext = React11.useMemo(
    () => ({
      setBinding,
      setControlledBinding,
      setBindingByScopePath
    }),
    [setBinding, setControlledBinding, setBindingByScopePath]
  );
  return /* @__PURE__ */ React11.createElement(RuntimeScopeContext.Provider, { value: childScope }, /* @__PURE__ */ React11.createElement(SetBindingContext.Provider, { value: setBindingContext }, /* @__PURE__ */ React11.createElement(EvaluateScopeExpressionContext.Provider, { value: evaluateScopeExpression }, children)));
}
function TemplateScoped({ id, node, localScope, propName, children }) {
  const dom = useDomContext();
  const components = useComponents();
  const location = useLocation2();
  const parseBindingsResult = React11.useMemo(() => {
    const { [propName]: templateChildren = [] } = appDom3.getChildNodes(dom, node);
    return parseBindings(dom, templateChildren, components, location);
  }, [components, dom, node, propName, location]);
  return /* @__PURE__ */ React11.createElement(RuntimeScoped, { id, parseBindingsResult, localScope }, children);
}
function NodeError({ error }) {
  return /* @__PURE__ */ React11.createElement(Tooltip, { title: error.message }, /* @__PURE__ */ React11.createElement(
    "span",
    {
      style: {
        display: "inline-flex",
        flexDirection: "row",
        alignItems: "center",
        padding: 8,
        background: "red",
        color: "white"
      }
    },
    /* @__PURE__ */ React11.createElement(ErrorIcon, { color: "inherit", style: { marginRight: 8 } }),
    " Error"
  ));
}
function RenderedNodeContent({
  node,
  childNodeGroups,
  Component,
  staticProps
}) {
  const { setControlledBinding } = React11.useContext(SetBindingContext) ?? {};
  invariant3(setControlledBinding, "Node must be rendered in a RuntimeScoped context");
  const nodeId = node.id;
  const componentConfig = Component[TOOLPAD_COMPONENT];
  const {
    argTypes = {},
    errorProp,
    loadingProp,
    loadingPropSource,
    errorPropSource
  } = componentConfig;
  const isLayoutNode = appDom3.isPage(node) || appDom3.isElement(node) && isPageLayoutComponent(node);
  const scope = useAssertedContext(RuntimeScopeContext);
  const liveBindings = scope.bindings;
  const boundProps = React11.useMemo(() => {
    const loadingPropSourceSet = loadingPropSource ? new Set(loadingPropSource) : null;
    const errorPropSourceSet = errorPropSource ? new Set(errorPropSource) : null;
    const hookResult = {};
    let error;
    let loading = false;
    for (const [propName, argType] of Object.entries(argTypes)) {
      const bindingId = `${nodeId}.props.${propName}`;
      const binding = liveBindings[bindingId];
      if (binding) {
        hookResult[propName] = binding.value;
        if (binding.loading && (!loadingPropSourceSet || loadingPropSourceSet.has(propName))) {
          loading = true;
        } else if (!error && binding.error && (!errorPropSourceSet || errorPropSourceSet.has(propName))) {
          error = binding.error;
        }
      }
      if (typeof hookResult[propName] === "undefined" && argType) {
        const defaultValue = getArgTypeDefaultValue(argType);
        if (typeof defaultValue !== "undefined") {
          hookResult[propName] = getArgTypeDefaultValue(argType);
        }
      }
    }
    if (error) {
      if (errorProp) {
        hookResult[errorProp] = error;
      } else {
        console.error(errorFrom(error));
      }
    }
    if (loadingProp && loading) {
      hookResult[loadingProp] = true;
    }
    return hookResult;
  }, [argTypes, errorProp, errorPropSource, liveBindings, loadingProp, loadingPropSource, nodeId]);
  const boundLayoutProps = React11.useMemo(() => {
    const hookResult = {};
    for (const [propName, argType] of isLayoutNode ? [] : Object.entries(layoutBoxArgTypes)) {
      const bindingId = `${nodeId}.layout.${propName}`;
      const binding = liveBindings[bindingId];
      if (binding) {
        hookResult[propName] = binding.value;
      }
      if (typeof hookResult[propName] === "undefined" && argType) {
        hookResult[propName] = getArgTypeDefaultValue(argType);
      }
    }
    return hookResult;
  }, [isLayoutNode, liveBindings, nodeId]);
  const onChangeHandlers = React11.useMemo(
    () => mapProperties(argTypes, ([key, argType]) => {
      if (!argType || !argType.onChangeProp) {
        return null;
      }
      const handler = (param) => {
        const bindingId = `${nodeId}.props.${key}`;
        const value = argType.onChangeHandler ? argType.onChangeHandler(param) : param;
        setControlledBinding(bindingId, { value });
      };
      return [argType.onChangeProp, handler];
    }),
    [argTypes, nodeId, setControlledBinding]
  );
  const navigateToPage = usePageNavigator();
  const evaluateScopeExpression = useEvaluateScopeExpression();
  const eventHandlers = React11.useMemo(() => {
    return mapProperties(argTypes, ([key, argType]) => {
      if (!argType || argType.type !== "event" || !appDom3.isElement(node)) {
        return null;
      }
      const action = node.props?.[key];
      if (action?.$$navigationAction) {
        const handler = async () => {
          const { page, parameters = {} } = action.$$navigationAction;
          if (page) {
            const parsedParameterEntries = await Promise.all(
              Object.keys(parameters).map(async (parameterName) => {
                const parameterValue = parameters[parameterName];
                if (parameterValue?.$$jsExpression) {
                  const result = await evaluateScopeExpression(parameterValue.$$jsExpression);
                  return [parameterName, result.value];
                }
                return [parameterName, parameterValue];
              })
            );
            const parsedParameters = Object.fromEntries(parsedParameterEntries);
            navigateToPage(page, parsedParameters);
          }
        };
        return [key, handler];
      }
      if (action?.$$jsExpressionAction) {
        const handler = () => {
          const code = action.$$jsExpressionAction;
          const exprToEvaluate = `(async () => {${code}})()`;
          evaluateScopeExpression(exprToEvaluate);
        };
        return [key, handler];
      }
      return null;
    });
  }, [argTypes, node, navigateToPage, evaluateScopeExpression]);
  const reactChildren = React11.useMemo(() => {
    const result = {};
    for (const [prop, childNodes] of Object.entries(childNodeGroups)) {
      result[prop] = childNodes.map((child) => /* @__PURE__ */ React11.createElement(RenderedNode, { key: child.id, nodeId: child.id }));
    }
    return result;
  }, [childNodeGroups]);
  const layoutElementProps = React11.useMemo(() => {
    if (appDom3.isElement(node) && isPageRow(node)) {
      return {
        layoutColumnSizes: childNodeGroups.children.map((child) => child.layout?.columnSize)
      };
    }
    return {};
  }, [childNodeGroups.children, node]);
  const props = React11.useMemo(() => {
    return {
      ...staticProps,
      ...boundProps,
      ...onChangeHandlers,
      ...eventHandlers,
      ...layoutElementProps,
      ...reactChildren
    };
  }, [staticProps, boundProps, eventHandlers, layoutElementProps, onChangeHandlers, reactChildren]);
  const previousProps = React11.useRef(props);
  const [hasSetInitialBindings, setHasSetInitialBindings] = React11.useState(false);
  React11.useEffect(() => {
    Object.entries(argTypes).forEach(([key, argType]) => {
      if (!argType?.defaultValueProp) {
        return;
      }
      if (hasSetInitialBindings && previousProps.current[argType.defaultValueProp] === props[argType.defaultValueProp]) {
        return;
      }
      const bindingIdToUpdate = `${nodeId}.props.${key}`;
      setControlledBinding(bindingIdToUpdate, { value: props[argType.defaultValueProp] });
    });
    previousProps.current = props;
    setHasSetInitialBindings(true);
  }, [props, argTypes, nodeId, setControlledBinding, hasSetInitialBindings]);
  const wrappedProps = React11.useMemo(() => {
    const hookResult = { ...props };
    for (const [propName, argType] of Object.entries(argTypes)) {
      const isElement2 = argType?.type === "element";
      const isTemplate = argType?.type === "template";
      if (isElement2 || isTemplate) {
        const value = hookResult[propName];
        let wrappedValue = value;
        if (argType.control?.type === "slots" || argType.control?.type === "layoutSlot") {
          wrappedValue = /* @__PURE__ */ React11.createElement(Slots, { prop: propName, hasLayout: argType.control?.type === "layoutSlot" }, value);
        } else if (argType.control?.type === "slot") {
          wrappedValue = /* @__PURE__ */ React11.createElement(Placeholder, { prop: propName }, value);
        }
        if (isTemplate) {
          appDom3.assertIsElement(node);
          hookResult[propName] = (key, localScope) => {
            return /* @__PURE__ */ React11.createElement(
              TemplateScoped,
              {
                id: `${node.id}.props.${propName}.${key}`,
                localScope,
                node,
                propName
              },
              wrappedValue
            );
          };
        } else {
          hookResult[propName] = wrappedValue;
        }
      }
    }
    return hookResult;
  }, [argTypes, node, props]);
  const vmRef = React11.useContext(ApplicationVmApiContext);
  React11.useEffect(() => {
    if (!vmRef) {
      return () => {
      };
    }
    const unsubscribers = [];
    for (const propName of Object.keys(argTypes)) {
      const unsubscribe = vmRef.current.registerBindingScope(`${nodeId}.props.${propName}`, scope);
      unsubscribers.push(unsubscribe);
    }
    return () => {
      unsubscribers.forEach((unsubscribe) => unsubscribe());
    };
  }, [nodeId, argTypes, vmRef, scope]);
  const nodeRef = React11.useRef();
  const canvasHooks = React11.useContext(CanvasHooksContext);
  React11.useEffect(() => {
    return canvasHooks.registerNode?.(node, wrappedProps, componentConfig, nodeRef.current);
  }, [node, wrappedProps, componentConfig, canvasHooks]);
  return /* @__PURE__ */ React11.createElement(NodeRuntimeWrapper, { nodeId, nodeName: node.name, NodeError }, isLayoutNode ? /* @__PURE__ */ React11.createElement(
    Component,
    {
      ...wrappedProps,
      ref: nodeRef,
      "data-toolpad-node-id": nodeId,
      "data-toolpad-slot-name": "children",
      "data-toolpad-slot-parent": nodeId,
      "data-toolpad-slot-type": "multiple"
    }
  ) : /* @__PURE__ */ React11.createElement(
    Box4,
    {
      sx: {
        display: "flex",
        alignItems: boundLayoutProps.verticalAlign,
        justifyContent: boundLayoutProps.horizontalAlign,
        height: node.layout?.height ?? componentConfig.defaultLayoutHeight,
        minHeight: "100%",
        "&:empty": {
          display: "none"
        }
      },
      ref: nodeRef,
      "data-toolpad-node-id": nodeId
    },
    /* @__PURE__ */ React11.createElement(Component, { ...wrappedProps })
  ));
}
var PageRoot = React11.forwardRef(function PageRoot2({ children, maxWidth, ...props }, ref) {
  const containerMaxWidth = maxWidth === "none" ? false : maxWidth ?? appDom3.DEFAULT_CONTAINER_WIDTH;
  return /* @__PURE__ */ React11.createElement(Container, { ref, maxWidth: containerMaxWidth }, /* @__PURE__ */ React11.createElement(Stack2, { "data-testid": "page-root", direction: "column", sx: { my: 2, gap: 1 }, ...props }, children));
});
var PageRootComponent = createComponent(PageRoot, {
  argTypes: {
    children: {
      type: "element",
      control: { type: "slots" }
    },
    maxWidth: {
      type: "string",
      enum: ["xs", "sm", "md", "lg", "xl", "none"],
      control: { type: "ToggleButtons" }
    }
  }
});
function QueryNode({ page, node }) {
  const { setControlledBinding } = React11.useContext(SetBindingContext) ?? {};
  invariant3(setControlledBinding, "QueryNode must be rendered in a RuntimeScoped context");
  const { bindings } = useAssertedContext(RuntimeScopeContext);
  const params = resolveBindables(
    bindings,
    `${node.id}.params`,
    Object.fromEntries(node.params ?? [])
  );
  const configBindings = getQueryConfigBindings(node.attributes);
  const options = resolveBindables(bindings, `${node.id}.config`, configBindings);
  const inputError = params.error || options.error;
  const inputIsLoading = params.loading || options.loading;
  const queryResult = useDataQuery(page, node, params.value, {
    ...options.value,
    enabled: !inputIsLoading && !inputError
  });
  React11.useEffect(() => {
    const { isLoading: queryIsLoading, error: queryError, data, rows, ...result } = queryResult;
    const error = queryError || inputError;
    const isLoading = queryIsLoading || inputIsLoading;
    for (const [key, value] of Object.entries(result)) {
      const bindingId = `${node.id}.${key}`;
      setControlledBinding(bindingId, { value });
    }
    setControlledBinding(`${node.id}.isLoading`, { value: isLoading });
    setControlledBinding(`${node.id}.error`, {
      value: error ? String(error.message || error) : void 0
    });
    const deferredStatus = { loading: isLoading, error };
    setControlledBinding(`${node.id}.data`, { ...deferredStatus, value: data });
    setControlledBinding(`${node.id}.rows`, { ...deferredStatus, value: rows });
  }, [node.name, node.id, queryResult, setControlledBinding, inputError, inputIsLoading]);
  return null;
}
function MutationNode({ node, page }) {
  const { setControlledBinding } = React11.useContext(SetBindingContext) ?? {};
  invariant3(setControlledBinding, "MutationNode must be rendered in a RuntimeScoped context");
  const { bindings } = useAssertedContext(RuntimeScopeContext);
  const { value: params } = resolveBindables(
    bindings,
    `${node.id}.params`,
    Object.fromEntries(node.params ?? [])
  );
  const runtimeApi = useNonNullableContext3(RuntimeApiContext);
  const {
    isPending,
    data: responseData = EMPTY_OBJECT2,
    error: fetchError,
    mutateAsync
  } = useMutation2({
    mutationKey: [node.name, params],
    mutationFn: async (overrides = {}) => {
      return runtimeApi.methods.execQuery(page.name, node.name, { ...params, ...overrides });
    }
  });
  const { data, error: apiError } = responseData || EMPTY_OBJECT2;
  const error = apiError || fetchError;
  const mutationResult = React11.useMemo(() => {
    const call = async (overrides = {}) => {
      await mutateAsync(overrides);
    };
    return {
      isLoading: isPending,
      isFetching: isPending,
      error,
      data,
      rows: Array.isArray(data) ? data : EMPTY_ARRAY2,
      call,
      fetch: call,
      refetch: () => {
        throw new Error(`refetch is not supported in manual queries`);
      }
    };
  }, [isPending, error, data, mutateAsync]);
  React11.useEffect(() => {
    for (const [key, value] of Object.entries(mutationResult)) {
      const bindingId = `${node.id}.${key}`;
      setControlledBinding(bindingId, { value });
    }
  }, [node.id, mutationResult, setControlledBinding]);
  return null;
}
function FetchNode({ node, page }) {
  const mode = node.attributes.mode || "query";
  switch (mode) {
    case "query":
      return /* @__PURE__ */ React11.createElement(QueryNode, { node, page });
    case "mutation":
      return /* @__PURE__ */ React11.createElement(MutationNode, { node, page });
    default:
      throw new Error(`Unrecognized fetch mode "${mode}"`);
  }
}
function RenderedLowCodePage({ page }) {
  usePageTitle(appDom3.getPageTitle(page));
  const dom = useDomContext();
  const { children = [], queries = [] } = appDom3.getChildNodes(dom, page);
  const location = useLocation2();
  const components = useComponents();
  const parseBindingsResult = React11.useMemo(
    () => parseBindings(dom, page, components, location),
    [components, dom, location, page]
  );
  const canvasEvents = React11.useContext(CanvasEventsContext);
  const onUpdate = useEventCallback(({ scope, scopeMeta }) => {
    if (canvasEvents) {
      canvasEvents.emit("pageStateUpdated", {
        pageState: scope.values,
        globalScopeMeta: scopeMeta
      });
      canvasEvents.emit("pageBindingsUpdated", { bindings: scope.bindings });
    }
  });
  const onApplicationVmUpdate = useEventCallback((vm) => {
    if (canvasEvents) {
      canvasEvents.emit("vmUpdated", { vm });
    }
  });
  const applicationVm = useApplicationVm(onApplicationVmUpdate);
  const pageProps = React11.useMemo(
    () => ({
      maxWidth: page.attributes.maxWidth
    }),
    [page.attributes.maxWidth]
  );
  return /* @__PURE__ */ React11.createElement(ApplicationVmApiContext.Provider, { value: applicationVm }, /* @__PURE__ */ React11.createElement(RuntimeScoped, { id: "global", parseBindingsResult, onUpdate }, /* @__PURE__ */ React11.createElement(
    RenderedNodeContent,
    {
      node: page,
      childNodeGroups: { children },
      Component: PageRootComponent,
      staticProps: pageProps
    }
  ), queries.map((node) => /* @__PURE__ */ React11.createElement(FetchNode, { key: node.id, page, node }))));
}
function RenderedPage({ page }) {
  const appHost = useAppHost3();
  let pageContent = /* @__PURE__ */ React11.createElement(RenderedLowCodePage, { page, key: page.name });
  if (!appHost.isCanvas) {
    pageContent = /* @__PURE__ */ React11.createElement(
      RequireAuthorization,
      {
        allowAll: page.attributes.authorization?.allowAll ?? true,
        allowedRoles: page.attributes.authorization?.allowedRoles ?? []
      },
      pageContent
    );
  }
  return pageContent;
}
function PageNotFound({ msg = "The page doesn't exist in this application." }) {
  return /* @__PURE__ */ React11.createElement(
    Container,
    {
      sx: {
        display: "flex",
        alignItems: "center",
        justifyContent: "center",
        flexDirection: "column"
      }
    },
    /* @__PURE__ */ React11.createElement(Typography3, { variant: "h1" }, "Not found"),
    /* @__PURE__ */ React11.createElement(Typography3, null, msg)
  );
}
function isPageAllowed(page, session) {
  const userRoles = session?.user?.roles ?? [];
  const { allowAll = true, allowedRoles = [] } = page.attributes.authorization ?? {};
  return allowAll || userRoles.some((role) => allowedRoles.includes(role));
}
var FullPageCentered = styled("div")({
  width: "100%",
  height: "100%",
  display: "flex",
  alignItems: "center",
  justifyContent: "center"
});
function AppLoading() {
  return /* @__PURE__ */ React11.createElement(LinearProgress, null);
}
function AppError({ error }) {
  return /* @__PURE__ */ React11.createElement(FullPageCentered, null, /* @__PURE__ */ React11.createElement(Alert3, { severity: "error" }, /* @__PURE__ */ React11.createElement(AlertTitle, null, "Something went wrong"), /* @__PURE__ */ React11.createElement(Pre, null, error.message), /* @__PURE__ */ React11.createElement(Pre, null, error.stack)));
}
function shouldShowPreviewHeader(appHost) {
  return !!appHost.isPreview && !appHost.isCanvas;
}
function ToolpadAppLayout({ children }) {
  const dom = useDomContext();
  const root = appDom3.getApp(dom);
  const { pages = [] } = appDom3.getChildNodes(dom, root);
  const { session, hasAuthentication } = React11.useContext(AuthContext);
  const pageMatch = useMatch2("/pages/:slug");
  const activePageSlug = pageMatch?.params.slug;
  const navEntries = React11.useMemo(
    () => pages.filter((page) => isPageAllowed(page, session)).map((page) => ({
      slug: page.name,
      displayName: appDom3.getPageDisplayName(page),
      hasShell: page?.attributes.display !== "standalone"
    })),
    [pages, session]
  );
  const appHost = useAppHost3();
  if (!appHost.isCanvas && !session?.user && hasAuthentication) {
    return /* @__PURE__ */ React11.createElement(AppLoading, null);
  }
  return /* @__PURE__ */ React11.createElement(AppLayout, { activePageSlug, pages: navEntries, hasLayout: !appHost.isCanvas }, children);
}
function PageRoute() {
  const { pageName } = useParams();
  invariant3(pageName, "Page name must be provided as a route parameter");
  const dom = useDomContext();
  const { search } = useLocation2();
  const page = appDom3.getPageByName(dom, pageName);
  if (!page) {
    const aliasedPageName = appDom3.getPageForAlias(dom, pageName);
    if (aliasedPageName) {
      return /* @__PURE__ */ React11.createElement(Navigate, { to: `/pages/${aliasedPageName}${search}`, replace: true });
    }
    return /* @__PURE__ */ React11.createElement(PageNotFound, null);
  }
  return /* @__PURE__ */ React11.createElement(RenderedPage, { page });
}
function PagesLayoutRoute() {
  return /* @__PURE__ */ React11.createElement(ToolpadAppLayout, null, /* @__PURE__ */ React11.createElement(Outlet, null));
}
function DefaultPageRoute() {
  const { search } = useLocation2();
  const dom = useDomContext();
  const { session } = React11.useContext(AuthContext);
  const root = appDom3.getApp(dom);
  const { pages = [] } = appDom3.getChildNodes(dom, root);
  const defaultPage = React11.useMemo(
    () => pages.find((page) => isPageAllowed(page, session)) ?? null,
    [pages, session]
  );
  return defaultPage ? /* @__PURE__ */ React11.createElement(Navigate, { to: `/pages/${defaultPage.name}${search}`, replace: true }) : /* @__PURE__ */ React11.createElement(PageNotFound, { msg: "No pages available." });
}
function ToolpadAppProvider({
  rootRef,
  basename,
  state,
  children,
  apiUrl = `${basename}/api/runtime-rpc`
}) {
  const { dom } = state;
  const extraComponents = componentsStore.useValue();
  const components = React11.useMemo(
    () => ({ ...internalComponents, ...extraComponents }),
    [extraComponents]
  );
  const [resetNodeErrorsKey, setResetNodeErrorsKey] = React11.useState(0);
  React11.useEffect(() => setResetNodeErrorsKey((key) => key + 1), [dom]);
  const { value: showDevtools, toggle: toggleDevtools } = useBoolean(false);
  React11.useEffect(() => {
    window.toggleDevtools = () => toggleDevtools();
  }, [toggleDevtools]);
  const authContext = useAuth({ dom, basename, signInPagePath: "/signin" });
  const appHost = useAppHost3();
  const showPreviewHeader = shouldShowPreviewHeader(appHost);
  const canvasHooks = React11.useContext(CanvasHooksContext);
  const runtimeApi = React11.useMemo(() => createApi(apiUrl), [apiUrl]);
  return /* @__PURE__ */ React11.createElement(RuntimeApiContext.Provider, { value: runtimeApi }, /* @__PURE__ */ React11.createElement(UseDataProviderContext.Provider, { value: useDataProvider }, /* @__PURE__ */ React11.createElement(ComponentsContextProvider, { value: components }, /* @__PURE__ */ React11.createElement(DomContext.Provider, { value: dom }, /* @__PURE__ */ React11.createElement(AuthContext.Provider, { value: authContext }, /* @__PURE__ */ React11.createElement(ResetNodeErrorsKeyProvider, { value: resetNodeErrorsKey }, /* @__PURE__ */ React11.createElement(AppThemeProvider, { dom }, /* @__PURE__ */ React11.createElement(CssBaseline, { enableColorScheme: true }), /* @__PURE__ */ React11.createElement(
    Box4,
    {
      sx: {
        display: "flex",
        flexDirection: "column",
        height: "100vh"
      }
    },
    showPreviewHeader ? /* @__PURE__ */ React11.createElement(PreviewHeader, null) : null,
    /* @__PURE__ */ React11.createElement(AppRoot, { ref: rootRef }, /* @__PURE__ */ React11.createElement(ErrorBoundary, { FallbackComponent: AppError }, /* @__PURE__ */ React11.createElement(React11.Suspense, { fallback: /* @__PURE__ */ React11.createElement(AppLoading, null) }, children)), /* @__PURE__ */ React11.createElement(EditorOverlay, { ref: canvasHooks.overlayRef }))
  )))), showDevtools ? /* @__PURE__ */ React11.createElement(ReactQueryDevtoolsProduction, { initialIsOpen: false }) : null))));
}
function ToolpadAppRoutes(props) {
  return /* @__PURE__ */ React11.createElement(Routes, null, /* @__PURE__ */ React11.createElement(
    Route,
    {
      path: "/",
      element: /* @__PURE__ */ React11.createElement(ToolpadAppProvider, { ...props }, /* @__PURE__ */ React11.createElement(Outlet, null))
    },
    /* @__PURE__ */ React11.createElement(Route, { path: "/signin", Component: SignInPage }),
    /* @__PURE__ */ React11.createElement(Route, { path: "/", Component: PagesLayoutRoute }, /* @__PURE__ */ React11.createElement(Route, { path: "/pages/:pageName", Component: PageRoute }), /* @__PURE__ */ React11.createElement(Route, { path: "/pages", Component: DefaultPageRoute }), /* @__PURE__ */ React11.createElement(Route, { path: "/", Component: DefaultPageRoute }), /* @__PURE__ */ React11.createElement(Route, { path: "*", Component: PageNotFound }))
  ));
}
function ToolpadApp(props) {
  const isSsr = useSsr();
  return isSsr ? null : /* @__PURE__ */ React11.createElement(BrowserRouter, { basename: props.basename }, /* @__PURE__ */ React11.createElement(Routes, null, /* @__PURE__ */ React11.createElement(
    Route,
    {
      path: "/",
      element: /* @__PURE__ */ React11.createElement(ToolpadAppProvider, { ...props }, /* @__PURE__ */ React11.createElement(Outlet, null))
    },
    /* @__PURE__ */ React11.createElement(Route, { path: "/signin", Component: SignInPage }),
    /* @__PURE__ */ React11.createElement(Route, { path: "/", Component: PagesLayoutRoute }, /* @__PURE__ */ React11.createElement(Route, { path: "/pages/:pageName", Component: PageRoute }), /* @__PURE__ */ React11.createElement(Route, { path: "/pages", Component: DefaultPageRoute }), /* @__PURE__ */ React11.createElement(Route, { path: "/", Component: DefaultPageRoute }), /* @__PURE__ */ React11.createElement(Route, { path: "*", Component: PageNotFound }))
  )));
}

export {
  createRpcApi,
  getBindingType,
  getBindingValue,
  createToolpadAppTheme,
  LAYOUT_DIRECTION_HORIZONTAL,
  LAYOUT_DIRECTION_VERTICAL,
  LAYOUT_DIRECTION_BOTH,
  layoutBoxArgTypes,
  CanvasHooksContext,
  createApi,
  componentsStore,
  RenderedPage,
  ToolpadAppProvider,
  ToolpadAppRoutes,
  ToolpadApp
};
//# sourceMappingURL=chunk-3OJ5QDPS.mjs.map