"use strict";
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
  for (var name in all)
    __defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
  if (from && typeof from === "object" || typeof from === "function") {
    for (let key of __getOwnPropNames(from))
      if (!__hasOwnProp.call(to, key) && key !== except)
        __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  }
  return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
  // If the importer is in node compatibility mode or this is not an ESM
  // file that has been converted to a CommonJS file using a Babel-
  // compatible transform (i.e. "__esModule" has not been set), then set
  // "default" to the CommonJS "module.exports" for node compatibility.
  isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
  mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);

// src/exports/canvas.ts
var canvas_exports = {};
__export(canvas_exports, {
  default: () => AppCanvas
});
module.exports = __toCommonJS(canvas_exports);

// src/canvas/index.tsx
var React9 = __toESM(require("react"));
var import_invariant5 = __toESM(require("invariant"));
var import_lodash_es3 = require("lodash-es");
var import_runtime2 = require("@mui/toolpad-core/runtime");

// src/runtime/ToolpadApp.tsx
var React8 = __toESM(require("react"));
var import_material5 = require("@mui/material");
var import_toolpad_core = require("@mui/toolpad-core");
var import_react = require("@mui/toolpad-utils/react");
var import_collections5 = require("@mui/toolpad-utils/collections");
var import_lodash_es2 = require("lodash-es");
var import_react_query5 = require("@tanstack/react-query");
var import_react_router_dom3 = require("react-router-dom");
var import_react_error_boundary = require("react-error-boundary");
var import_runtime = require("@mui/toolpad-core/runtime");
var import_Error = __toESM(require("@mui/icons-material/Error"));
var import_jsBrowserRuntime = require("@mui/toolpad-core/jsBrowserRuntime");
var builtIns = __toESM(require("@mui/toolpad-components"));
var import_errors = require("@mui/toolpad-utils/errors");
var import_useBoolean = __toESM(require("@mui/toolpad-utils/hooks/useBoolean"));
var import_usePageTitle = __toESM(require("@mui/toolpad-utils/hooks/usePageTitle"));
var import_invariant4 = __toESM(require("invariant"));
var import_useEventCallback = __toESM(require("@mui/utils/useEventCallback"));

// src/appDom/index.ts
var import_non_secure = require("nanoid/non-secure");
var import_fractional_indexing = require("fractional-indexing");
var import_invariant = __toESM(require("invariant"));
var import_strings = require("@mui/toolpad-utils/strings");
var import_collections = require("@mui/toolpad-utils/collections");

// src/server/schema.ts
var import_zod = require("zod");
function toolpadObjectSchema(kind, spec) {
  return import_zod.z.object({
    apiVersion: import_zod.z.literal("v1").describe(
      `Defines the version of this object. Used in determining compatibility between Toolpad "${kind}" objects.`
    ),
    kind: import_zod.z.literal(kind).describe(`Describes the nature of this Toolpad "${kind}" object.`),
    spec: spec.optional().describe(`Defines the shape of this "${kind}" object`)
  });
}
var literalSchema = import_zod.z.union([import_zod.z.string(), import_zod.z.number(), import_zod.z.boolean(), import_zod.z.null()]);
function nameValuePairSchema(valueType) {
  return import_zod.z.object({
    name: import_zod.z.string().describe("The name"),
    value: valueType.describe(valueType.description ?? "The value")
  }).describe("A name/value pair.");
}
var jsExpressionBindingSchema = import_zod.z.object({
  $$jsExpression: import_zod.z.string().describe("The expression to be evaluated.")
}).describe("A binding that evaluates an expression and returns the result.");
var envBindingSchema = import_zod.z.object({
  $$env: import_zod.z.string().describe("The name of an environment variable.")
}).describe("An environment variable.");
function bindableSchema(valueType) {
  return import_zod.z.union([valueType, jsExpressionBindingSchema, envBindingSchema]);
}
var jsExpressionActionSchema = import_zod.z.object({
  $$jsExpressionAction: import_zod.z.string().describe("The code to be executed.")
}).describe("A javascript expression to be executed when this action is triggered.");
var navigationActionSchema = import_zod.z.object({
  $$navigationAction: import_zod.z.object({
    page: import_zod.z.string().describe("The page that is being navigated to"),
    parameters: import_zod.z.record(bindableSchema(import_zod.z.any())).describe("Parameters to pass when navigating to this page")
  })
}).describe(
  "A navigation from one page to another, optionally passing parameters to the next page."
);
var fetchModeSchema = import_zod.z.union([
  import_zod.z.literal("query").describe("Fetch automatically when the page opens"),
  import_zod.z.literal("mutation").describe("Fetch on manual action only")
]);
var nameStringValuePairSchema = nameValuePairSchema(import_zod.z.string()).describe(
  "a name/value pair with a string value."
);
var rawBodySchema = import_zod.z.object({
  kind: import_zod.z.literal("raw"),
  content: bindableSchema(import_zod.z.string()),
  contentType: import_zod.z.string()
});
var bindableNameStringValueSchema = nameValuePairSchema(bindableSchema(import_zod.z.string())).describe(
  "A name/value pair where the value is dynamically bindable to strings."
);
var urlEncodedBodySchema = import_zod.z.object({
  kind: import_zod.z.literal("urlEncoded"),
  content: import_zod.z.array(bindableNameStringValueSchema)
});
var fetchBodySchema = import_zod.z.discriminatedUnion("kind", [rawBodySchema, urlEncodedBodySchema]);
var rawResponseTypeSchema = import_zod.z.object({
  kind: import_zod.z.literal("raw")
}).describe("Don't interpret this body at all.");
var jsonResponseTypeSchema = import_zod.z.object({
  kind: import_zod.z.literal("json")
}).describe("Interpret the fetch response as JSON");
var csvResponseTypeSchema = import_zod.z.object({
  kind: import_zod.z.literal("csv"),
  headers: import_zod.z.boolean().describe("First row contains headers")
}).describe("Interpret the fetch response as CSV");
var xmlResponseTypeSchema = import_zod.z.object({
  kind: import_zod.z.literal("xml")
}).describe("Interpret the fetch response as XML");
var responseTypeSchema = import_zod.z.discriminatedUnion("kind", [
  rawResponseTypeSchema,
  jsonResponseTypeSchema,
  csvResponseTypeSchema,
  xmlResponseTypeSchema
]).describe("Describes how a the fetch response is to be interpreted.");
var fetchQueryConfigSchema = import_zod.z.object({
  kind: import_zod.z.literal("rest").describe("Designates this object as a fetch query."),
  url: bindableSchema(import_zod.z.string()).optional().describe("The URL of the request"),
  method: import_zod.z.string().optional().describe("The request method."),
  headers: import_zod.z.array(bindableNameStringValueSchema).optional().describe("Extra request headers."),
  searchParams: import_zod.z.array(bindableNameStringValueSchema).optional().describe("Extra url query parameters."),
  body: fetchBodySchema.optional().describe("The request body."),
  transformEnabled: import_zod.z.boolean().optional().describe("Run a custom transformer on the response."),
  transform: import_zod.z.string().optional().describe("The custom transformer to run when enabled."),
  response: responseTypeSchema.optional().describe("How to parse the response.")
});
var localQueryConfigSchema = import_zod.z.object({
  kind: import_zod.z.literal("local").describe("Designates this object as a local function query."),
  function: import_zod.z.string().optional().describe("The function to be executed on the backend by this query.")
});
var queryConfigSchema = import_zod.z.discriminatedUnion("kind", [
  fetchQueryConfigSchema,
  localQueryConfigSchema
]);
var querySchema = import_zod.z.object({
  name: import_zod.z.string().describe("A name for the query"),
  enabled: bindableSchema(import_zod.z.boolean()).optional().describe(
    "Activates or deactivates the query. When deactivated the data won't be loaded when the page opens."
  ),
  parameters: import_zod.z.array(nameValuePairSchema(bindableSchema(import_zod.z.any()))).optional().describe("Parameters to pass to this query."),
  mode: fetchModeSchema.optional().describe("How to fetch this query."),
  query: queryConfigSchema.optional().describe("Query definition"),
  transform: import_zod.z.string().optional().describe("Transformation to run on the response"),
  transformEnabled: import_zod.z.boolean().optional().describe("Enable the transformation"),
  refetchInterval: import_zod.z.number().optional().describe("Interval to rerun this query at"),
  cacheTime: import_zod.z.number().optional().describe("Time to cache before refetching")
});
var elementSchema;
var templateSchema = import_zod.z.object({
  $$template: import_zod.z.lazy(() => import_zod.z.array(elementSchema)).describe("The subtree, that describes the UI to be rendered by the template.")
}).describe("Describes a fragment of Toolpad elements, to be used as a template.");
var baseElementSchema = import_zod.z.object({
  component: import_zod.z.string().describe("The component that this element was based on."),
  name: import_zod.z.string().describe("a name for this component, which is used to reference it inside bindings."),
  layout: import_zod.z.object({
    horizontalAlign: import_zod.z.string().optional().describe("Lays out the element along the horizontal axis."),
    verticalAlign: import_zod.z.string().optional().describe("Lays out the element along the vertical axis."),
    columnSize: import_zod.z.number().optional().describe("The width this element takes up, expressed in terms of columns on the page.")
  }).optional().describe("Layout properties for this element.")
});
var bindablePropSchema = import_zod.z.lazy(
  () => import_zod.z.union([
    ...literalSchema.options,
    import_zod.z.array(bindablePropSchema),
    import_zod.z.record(
      import_zod.z.string().refine((key) => !key.startsWith("$$")),
      bindablePropSchema
    ),
    jsExpressionBindingSchema,
    envBindingSchema,
    jsExpressionActionSchema,
    navigationActionSchema,
    templateSchema
  ])
);
elementSchema = baseElementSchema.extend({
  children: import_zod.z.lazy(() => import_zod.z.array(elementSchema).optional()).describe("The children of this element."),
  props: import_zod.z.lazy(() => import_zod.z.record(bindablePropSchema).optional()).describe("The properties to configure this instance of the component.")
}).describe("The instance of a component. Used to build user interfaces in pages.");
var applicationSchema = toolpadObjectSchema(
  "application",
  import_zod.z.object({
    authorization: import_zod.z.object({
      roles: import_zod.z.array(
        import_zod.z.union([
          import_zod.z.string(),
          import_zod.z.object({
            name: import_zod.z.string().describe("The name of the role."),
            description: import_zod.z.string().optional().describe("A description of the role.")
          })
        ])
      ).optional().describe("Available roles for this application. These can be assigned to users.")
    }).optional().describe("Authorization configuration for this application.")
  })
);
var pageSchema = toolpadObjectSchema(
  "page",
  import_zod.z.object({
    displayName: import_zod.z.string().optional().describe("Page name to display in the UI."),
    id: import_zod.z.string().optional().describe("Serves as a canonical id of the page. Deprecated: use an alias instead."),
    alias: import_zod.z.array(import_zod.z.string()).optional().describe("Page name aliases."),
    title: import_zod.z.string().optional().describe("Title for this page."),
    parameters: import_zod.z.array(nameStringValuePairSchema).optional().describe("Parameters for the page. These can be set inside of the url query string."),
    queries: import_zod.z.array(querySchema).optional().describe("Queries that are used by the page. These will load data when the page opens."),
    content: import_zod.z.array(elementSchema).optional().describe("The content of the page. This defines the UI."),
    authorization: import_zod.z.object({
      allowAll: import_zod.z.boolean().optional().describe("Allow all users to access this page."),
      allowedRoles: import_zod.z.array(import_zod.z.string()).optional().describe("Roles that are allowed to access this page.")
    }).optional().describe("Authorization configuration for this page."),
    unstable_codeFile: import_zod.z.coerce.boolean().optional().describe("The content of the page as JSX. Experimental, do not use!."),
    display: import_zod.z.union([
      import_zod.z.literal("standalone").describe("Hide the Toolpad chrome and just display the content of the page"),
      import_zod.z.literal("shell").describe("Show Toolpad header and navigation.")
    ]).optional().describe(
      "Display mode of the page. This can also be set at runtime with the toolpad-display query parameter"
    )
  })
);
var simplePaletteColorOptionsSchema = import_zod.z.object({
  main: import_zod.z.string(),
  light: import_zod.z.string().optional(),
  dark: import_zod.z.string().optional(),
  contrastText: import_zod.z.string().optional()
});
var themeOptionsSchema = import_zod.z.object({
  // TODO: expand to full MUI theme object
  palette: import_zod.z.object({
    mode: import_zod.z.union([import_zod.z.literal("light"), import_zod.z.literal("dark")]).optional(),
    primary: simplePaletteColorOptionsSchema.optional(),
    secondary: simplePaletteColorOptionsSchema.optional()
  }).passthrough().optional()
}).passthrough();
var themeSchema = toolpadObjectSchema(
  "theme",
  import_zod.z.object({
    options: themeOptionsSchema.optional().describe("The ThemeOptions object that gets fed into MUI's createTheme function.")
  })
);

// src/appDom/index.ts
function compareFractionalIndex(index1, index2) {
  if (index1 === index2) {
    return 0;
  }
  return index1 > index2 ? 1 : -1;
}
function isType(node, type) {
  return node.type === type;
}
function assertIsType(node, type) {
  (0, import_invariant.default)(isType(node, type), `Expected node type "${type}" but got "${node.type}"`);
}
function getMaybeNode(dom, nodeId, type) {
  const node = dom.nodes[nodeId];
  if (!node) {
    return null;
  }
  if (type) {
    assertIsType(node, type);
  }
  return node;
}
function getNode(dom, nodeId, type) {
  const node = getMaybeNode(dom, nodeId, type);
  if (!node) {
    throw new Error(`Node "${nodeId}" not found`);
  }
  return node;
}
function assertIsApp(node) {
  assertIsType(node, "app");
}
function isPage(node) {
  return isType(node, "page");
}
function isElement(node) {
  return isType(node, "element");
}
function assertIsElement(node) {
  assertIsType(node, "element");
}
function isQuery(node) {
  return isType(node, "query");
}
function isMutation(node) {
  return isType(node, "mutation");
}
function getRoot(dom) {
  return getNode(dom, dom.root);
}
function getApp(dom) {
  const app = getRoot(dom);
  assertIsApp(app);
  return app;
}
var childrenMemo = /* @__PURE__ */ new WeakMap();
function getChildNodes(dom, parent) {
  let domChildrenMemo = childrenMemo.get(dom);
  if (!domChildrenMemo) {
    domChildrenMemo = /* @__PURE__ */ new Map();
    childrenMemo.set(dom, domChildrenMemo);
  }
  let result = domChildrenMemo.get(parent.id);
  if (!result) {
    result = {};
    domChildrenMemo.set(parent.id, result);
    const allNodeChildren = Object.values(dom.nodes).filter(
      (node) => node.parentId === parent.id
    );
    for (const child of allNodeChildren) {
      const prop = child.parentProp || "children";
      let existing = result[prop];
      if (!existing) {
        existing = [];
        result[prop] = existing;
      }
      existing.push(child);
    }
    for (const childArray of Object.values(result)) {
      childArray?.sort((node1, node2) => {
        (0, import_invariant.default)(
          node1.parentIndex && node2.parentIndex,
          `Nodes inside the dom should have a parentIndex if they have a parent`
        );
        return compareFractionalIndex(node1.parentIndex, node2.parentIndex);
      });
    }
  }
  return result;
}
var RENDERTREE_NODES = ["app", "page", "element", "query", "mutation", "theme"];
var frontendNodes = new Set(RENDERTREE_NODES);
function getPageDisplayName(node) {
  return node.attributes.displayName || (0, import_strings.guessTitle)(node.name);
}
function getPageTitle(node) {
  return node.attributes.title || getPageDisplayName(node);
}

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

// src/runtime/toolpadComponents/index.tsx
var PAGE_ROW_COMPONENT_ID = "PageRow";
var PAGE_COLUMN_COMPONENT_ID = "PageColumn";
function getElementNodeComponentId(elementNode) {
  return elementNode.attributes.component;
}
function isPageRow(elementNode) {
  return getElementNodeComponentId(elementNode) === PAGE_ROW_COMPONENT_ID;
}
function isPageColumn(elementNode) {
  return getElementNodeComponentId(elementNode) === PAGE_COLUMN_COMPONENT_ID;
}
function isPageLayoutComponent(elementNode) {
  return isPageRow(elementNode) || isPageColumn(elementNode);
}

// src/runtime/AppThemeProvider.tsx
var React = __toESM(require("react"));
var import_material = require("@mui/material");
var import_utils = require("@mui/utils");
function createMuiThemeFromToolpadTheme(toolpadTheme = {}) {
  return (0, import_material.createTheme)(
    (0, import_utils.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 = getApp(dom);
  const { themes = [] } = getChildNodes(dom, root);
  const themeNode = themes.length > 0 ? themes[0] : null;
  const toolpadTheme = themeNode?.theme;
  return createMuiThemeFromToolpadTheme(toolpadTheme);
}
function AppThemeProvider({ dom, children }) {
  const theme = React.useMemo(() => createToolpadAppTheme(dom), [dom]);
  return /* @__PURE__ */ React.createElement(import_material.ThemeProvider, { theme }, children);
}

// src/runtime/evalJsBindings.ts
var import_collections3 = require("@mui/toolpad-utils/collections");
var import_lodash_es = require("lodash-es");
function updatePath(obj, path, value) {
  return (0, import_lodash_es.setWith)((0, import_lodash_es.clone)(obj), path, value, import_lodash_es.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") {
      (0, import_lodash_es.set)(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 = evaluateBinding(initializer, scopePath);
      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 = (0, import_collections3.mapValues)(bindings, (binding, bindingId) => {
    return evaluateBinding(bindingId) || { value: void 0 };
  });
  const flatDependencies = flattenDependencies(dependencies);
  return (0, import_collections3.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/constants.ts
var HTML_ID_EDITOR_OVERLAY = "editor-overlay";
var IS_PREVIEW = process.env.NODE_ENV !== "production";
var IS_CUSTOM_SERVER = process.env.TOOLPAD_CUSTOM_SERVER === "true";
var PREVIEW_HEADER_HEIGHT = 52;

// src/runtime/toolpadComponents/layoutBox.ts
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 }
  },
  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 }
  }
};

// src/runtime/useDataQuery.ts
var React3 = __toESM(require("react"));
var import_react_query3 = require("@tanstack/react-query");

// src/runtime/CanvasHooksContext.tsx
var React2 = __toESM(require("react"));
var CanvasHooksContext = React2.createContext({});

// src/runtime/api.ts
var import_react_query2 = require("@tanstack/react-query");

// src/rpcClient.ts
var superjson = __toESM(require("superjson"));
var import_invariant2 = __toESM(require("invariant"));
var import_react_query = require("@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 (0, import_react_query.useQuery)({
        ...options,
        enabled: !!params && options?.enabled !== false,
        queryKey: [key, params],
        queryFn: () => {
          (0, import_invariant2.default)(params, `"enabled" prop of useQuery should prevent this call'`);
          return methods[key](...params);
        }
      });
    },
    useSuspenseQuery: (key, params, options) => {
      return (0, import_react_query.useSuspenseQuery)({
        ...options,
        queryKey: [key, params],
        queryFn: () => {
          (0, import_invariant2.default)(params, "Query has no parameters");
          return methods[key](...params);
        }
      });
    },
    useMutation: (key, options) => (0, import_react_query.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
var queryClient = new import_react_query2.QueryClient({
  defaultOptions: {
    queries: {
      retry: false,
      networkMode: "always"
    },
    mutations: {
      networkMode: "always"
    }
  }
});
var api_default = createRpcApi(
  queryClient,
  new URL(`${process.env.BASE_URL}/api/runtime-rpc`, window.location.href)
);

// src/runtime/useDataQuery.ts
var EMPTY_ARRAY = [];
var EMPTY_OBJECT = {};
function useDataQuery(page, node, params, {
  enabled = true,
  ...options
}) {
  const { savedNodes } = React3.useContext(CanvasHooksContext);
  const queryName = node.name;
  const pageName = page.name;
  const isNodeAvailableOnServer = savedNodes ? !!savedNodes[node.id] : true;
  const {
    isLoading,
    isFetching,
    error: fetchError,
    data: responseData = EMPTY_OBJECT,
    refetch
  } = (0, import_react_query3.useQuery)({
    queryKey: [pageName, queryName, params],
    queryFn: () => api_default.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 = React3.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
var React4 = __toESM(require("react"));
var import_material2 = require("@mui/material");
var import_Edit = __toESM(require("@mui/icons-material/Edit"));
var import_react_router_dom = require("react-router-dom");
var import_ContentCopy = __toESM(require("@mui/icons-material/ContentCopy"));
function CopyToClipboardButton({ content, onClick, ...props }) {
  const [confirmSnackbarOpen, setConfirmSnackbarOpen] = React4.useState(false);
  const handleClick = React4.useCallback(
    (event) => {
      window.navigator.clipboard.writeText(content);
      setConfirmSnackbarOpen(true);
      onClick?.(event);
    },
    [content, onClick]
  );
  const handleCopySnackbarClose = React4.useCallback(() => setConfirmSnackbarOpen(false), []);
  return /* @__PURE__ */ React4.createElement(React4.Fragment, null, /* @__PURE__ */ React4.createElement(import_material2.Tooltip, { title: "Copy to clipboard" }, /* @__PURE__ */ React4.createElement(import_material2.IconButton, { ...props, onClick: handleClick }, /* @__PURE__ */ React4.createElement(import_ContentCopy.default, { fontSize: "inherit" }))), /* @__PURE__ */ React4.createElement(
    import_material2.Snackbar,
    {
      open: confirmSnackbarOpen,
      autoHideDuration: 3e3,
      onClose: handleCopySnackbarClose,
      message: "Copied to clipboard"
    }
  ));
}
var classes = {
  copyToClipboardButton: "Toolpad_CodeView_CopyToClipboardButton",
  hasCopyToClipboardButton: "Toolpad_CodeView_hasCopyToClipboardButton"
};
var CodeViewRoot = (0, import_material2.styled)("pre")(({ theme }) => ({
  position: "relative",
  border: `1px solid ${theme.palette.divider}`,
  padding: theme.spacing(2),
  paddingRight: theme.spacing(5),
  borderRadius: theme.shape.borderRadius,
  fontFamily: theme.fontFamilyMonospaced,
  overflow: "hidden",
  textOverflow: "ellipsis",
  whiteSpace: "nowrap",
  [`& .${classes.copyToClipboardButton}`]: {
    position: "absolute",
    top: 0,
    right: 0,
    marginTop: theme.spacing(1),
    marginRight: theme.spacing(1)
  }
}));
function CodeView({ children }) {
  return /* @__PURE__ */ React4.createElement(CodeViewRoot, null, /* @__PURE__ */ React4.createElement(import_material2.Typography, { noWrap: true, component: "code", fontFamily: "inherit" }, children), children ? /* @__PURE__ */ React4.createElement(
    CopyToClipboardButton,
    {
      size: "small",
      content: children,
      className: classes.copyToClipboardButton
    }
  ) : null);
}
function OpenInEditorButton({ children = "Open in editor", ...props }) {
  return /* @__PURE__ */ React4.createElement(import_material2.Button, { color: "inherit", size: "small", startIcon: /* @__PURE__ */ React4.createElement(import_Edit.default, null), ...props }, children);
}
function CustomServerInstructions({ basename }) {
  const id = React4.useId();
  const [anchorEl, setAnchorEl] = React4.useState(null);
  const handleClick = (event) => {
    setAnchorEl(event.currentTarget);
  };
  const handleClose = () => {
    setAnchorEl(null);
  };
  const open = Boolean(anchorEl);
  const appUrl = React4.useMemo(() => {
    return new URL(basename, window.location.origin).href;
  }, [basename]);
  return /* @__PURE__ */ React4.createElement(React4.Fragment, null, /* @__PURE__ */ React4.createElement(OpenInEditorButton, { "aria-describedby": id, onClick: handleClick }), /* @__PURE__ */ React4.createElement(
    import_material2.Popover,
    {
      id,
      open,
      anchorEl,
      onClose: handleClose,
      anchorOrigin: {
        vertical: "bottom",
        horizontal: "right"
      },
      transformOrigin: {
        vertical: "top",
        horizontal: "right"
      },
      sx: {
        [`& .${import_material2.popoverClasses.paper}`]: {
          maxWidth: 700
        }
      }
    },
    /* @__PURE__ */ React4.createElement(import_material2.Box, { sx: { p: 2 } }, /* @__PURE__ */ React4.createElement(import_material2.Typography, null, "This application is running under a custom server. Run the standalone Toolpad editor to make changes to this application."), /* @__PURE__ */ React4.createElement(CodeView, null, `npx @mui/toolpad editor ${appUrl}`))
  ));
}
function PreviewHeader({ basename }) {
  const pageMatch = (0, import_react_router_dom.useMatch)("/pages/:slug");
  const activePage = pageMatch?.params.slug;
  const theme = (0, import_material2.useTheme)();
  return /* @__PURE__ */ React4.createElement(
    import_material2.Box,
    {
      sx: {
        position: "fixed",
        width: "100%",
        height: PREVIEW_HEADER_HEIGHT,
        zIndex: theme.zIndex.drawer + 1
      }
    },
    /* @__PURE__ */ React4.createElement(
      import_material2.Alert,
      {
        severity: "warning",
        sx: {
          borderRadius: 0
        },
        action: IS_CUSTOM_SERVER ? /* @__PURE__ */ React4.createElement(CustomServerInstructions, { basename }) : /* @__PURE__ */ React4.createElement(
          OpenInEditorButton,
          {
            component: "a",
            href: activePage ? `/_toolpad/app/pages/${activePage}` : "/_toolpad/app"
          }
        )
      },
      /* @__PURE__ */ React4.createElement(import_material2.Typography, { variant: "body2" }, "This is a preview version of the application, not suitable for production.")
    )
  );
}

// src/runtime/AppLayout.tsx
var React5 = __toESM(require("react"));
var import_material3 = require("@mui/material");
var import_react_router_dom2 = require("react-router-dom");
var TOOLPAD_DISPLAY_MODE_URL_PARAM = "toolpad-display";
var RETAINED_URL_PARAMS = /* @__PURE__ */ new Set([TOOLPAD_DISPLAY_MODE_URL_PARAM]);
var DRAWER_WIDTH = 250;
function AppPagesNavigation({
  activePage,
  pages,
  clipped = false,
  search
}) {
  const navListSubheaderId = React5.useId();
  return /* @__PURE__ */ React5.createElement(
    import_material3.Drawer,
    {
      variant: "permanent",
      anchor: "left",
      open: true,
      sx: {
        width: DRAWER_WIDTH,
        flexShrink: 0,
        [`& .MuiDrawer-paper`]: {
          width: DRAWER_WIDTH,
          boxSizing: "border-box",
          border: "none"
        }
      }
    },
    clipped ? /* @__PURE__ */ React5.createElement(import_material3.Box, { sx: { height: PREVIEW_HEADER_HEIGHT } }) : null,
    /* @__PURE__ */ React5.createElement(import_material3.List, { component: "nav", sx: { px: 2 }, "aria-labelledby": navListSubheaderId }, pages.map((page) => /* @__PURE__ */ React5.createElement(
      import_material3.ListItem,
      {
        key: page.slug,
        disablePadding: true,
        sx: {
          borderRadius: "24px",
          overflow: "hidden"
        }
      },
      /* @__PURE__ */ React5.createElement(
        import_material3.ListItemButton,
        {
          component: import_react_router_dom2.Link,
          to: `pages/${page.slug}${search}`,
          selected: activePage === page.slug
        },
        /* @__PURE__ */ React5.createElement(import_material3.ListItemText, { primary: page.displayName, sx: { ml: 2 } })
      )
    )))
  );
}
function AppLayout({
  activePage,
  pages = [],
  hasShell: hasShellProp = true,
  children,
  clipped
}) {
  const [urlParams] = (0, import_react_router_dom2.useSearchParams)();
  const retainedSearch = React5.useMemo(() => {
    for (const name of urlParams.keys()) {
      if (!RETAINED_URL_PARAMS.has(name)) {
        urlParams.delete(name);
      }
    }
    return urlParams.size > 0 ? `?${urlParams.toString()}` : "";
  }, [urlParams]);
  const navEntry = pages.find((page) => page.slug === activePage);
  const displayMode = urlParams.get(TOOLPAD_DISPLAY_MODE_URL_PARAM);
  const hasShell = hasShellProp && navEntry?.hasShell !== false && displayMode !== "standalone";
  return /* @__PURE__ */ React5.createElement(import_material3.Box, { sx: { flex: 1, display: "flex" } }, hasShell ? /* @__PURE__ */ React5.createElement(
    AppPagesNavigation,
    {
      activePage,
      pages,
      clipped,
      search: retainedSearch
    }
  ) : null, /* @__PURE__ */ React5.createElement(import_material3.Box, { sx: { minWidth: 0, flex: 1, position: "relative" } }, children));
}

// src/runtime/useDataProvider.ts
var React6 = __toESM(require("react"));
var import_react_query4 = require("@tanstack/react-query");
var import_invariant3 = __toESM(require("invariant"));
var useDataProvider = (id) => {
  const {
    isLoading,
    error,
    data: introspection
  } = (0, import_react_query4.useQuery)({
    queryKey: ["introspectDataProvider", id],
    enabled: !!id,
    queryFn: async () => {
      (0, import_invariant3.default)(id, "id is required");
      const [filePath, name] = id.split(":");
      return api_default.methods.introspectDataProvider(filePath, name);
    }
  });
  const dataProvider = React6.useMemo(() => {
    if (!introspection) {
      return null;
    }
    return {
      paginationMode: introspection.paginationMode,
      getRecords: async (...args) => {
        (0, import_invariant3.default)(id, "id is required");
        const [filePath, name] = id.split(":");
        return api_default.methods.getDataProviderRecords(filePath, name, ...args);
      },
      deleteRecord: introspection.hasDeleteRecord ? async (recordId) => {
        (0, import_invariant3.default)(id, "id is required");
        const [filePath, name] = id.split(":");
        return api_default.methods.deleteDataProviderRecord(filePath, name, recordId);
      } : void 0,
      updateRecord: introspection.hasUpdateRecord ? async (recordId, values) => {
        (0, import_invariant3.default)(id, "id is required");
        const [filePath, name] = id.split(":");
        return api_default.methods.updateDataProviderRecord(filePath, name, recordId, values);
      } : void 0,
      createRecord: introspection.hasCreateRecord ? async (values) => {
        (0, import_invariant3.default)(id, "id is required");
        const [filePath, name] = id.split(":");
        return api_default.methods.createDataProviderRecord(filePath, name, values);
      } : void 0
    };
  }, [id, introspection]);
  return { isLoading, error, dataProvider };
};

// src/runtime/auth.tsx
var React7 = __toESM(require("react"));
var import_collections4 = require("@mui/toolpad-utils/collections");
var import_material4 = require("@mui/material");
var UserContext = React7.createContext(null);
function AuthenticationProvider({ children, user = null }) {
  return /* @__PURE__ */ React7.createElement(UserContext.Provider, { value: user }, children);
}
function RequireAuthorization({ children, allowedRole }) {
  const user = React7.useContext(UserContext);
  const allowedRolesSet = React7.useMemo(
    () => new Set((0, import_collections4.asArray)(allowedRole ?? [])),
    [allowedRole]
  );
  let reason = null;
  if (!user) {
    reason = "User is not authenticated.";
  } else if (!user.roles || user.roles.length <= 0) {
    reason = "User has no roles defined.";
  } else if (!user.roles.some((role) => allowedRolesSet.has(role))) {
    const rolesList = user?.roles?.map((role) => JSON.stringify(role)).join(", ");
    reason = `User with role(s) ${rolesList} is not allowed access to this resource.`;
  }
  return reason ? /* @__PURE__ */ React7.createElement(
    import_material4.Box,
    {
      sx: {
        flex: 1,
        display: "flex",
        alignItems: "center",
        justifyContent: "center"
      }
    },
    "Unauthorized. ",
    reason
  ) : children;
}

// src/runtime/ToolpadApp.tsx
var browserJsRuntime = (0, import_jsBrowserRuntime.getBrowserRuntime)();
var IS_RENDERED_IN_CANVAS = typeof window === "undefined" ? false : !!window.frameElement?.dataset?.toolpadCanvas;
var SHOW_PREVIEW_HEADER = IS_PREVIEW && !IS_RENDERED_IN_CANVAS;
var componentsStore = (0, import_react.createGlobalState)({});
var pageComponentsStore = (0, import_react.createGlobalState)({});
var Pre = (0, import_material5.styled)("pre")(({ theme }) => ({
  margin: 0,
  fontFamily: theme.fontFamilyMonospaced
}));
var internalComponents = Object.fromEntries(
  Object.entries(builtIns).map(([name, builtIn]) => {
    if (!(0, import_toolpad_core.isToolpadComponent)(builtIn)) {
      builtIn = (0, import_toolpad_core.createToolpadComponentThatThrows)(
        new Error(`Imported builtIn "${name}" is not a ToolpadComponent`)
      );
    }
    return [name, builtIn];
  })
);
var ReactQueryDevtoolsProduction = React8.lazy(
  () => (
    // eslint-disable-next-line import/extensions
    import("@tanstack/react-query-devtools/build/modern/production.js").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 = (0, import_react_router_dom3.useNavigate)();
  const canvasEvents = React8.useContext(import_runtime.CanvasEventsContext);
  const navigateToPage = React8.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 = (0, import_material5.styled)("div")({
  overflow: "auto",
  position: "relative",
  minHeight: "100vh",
  display: "flex",
  flexDirection: "column",
  paddingTop: SHOW_PREVIEW_HEADER ? PREVIEW_HEADER_HEIGHT : 0
});
var EditorOverlay = (0, import_material5.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: (0, import_collections5.mapValues)(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(() => {
      onUpdate(vm);
      scheduledUpdate = void 0;
    });
  };
  return React8.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 = React8.createContext(void 0);
var RuntimeScopeContext = React8.createContext(void 0);
var [useDomContext, DomContextProvider] = (0, import_react.createProvidedContext)("Dom");
var [useEvaluateScopeExpression, EvaluateScopeExpressionProvider] = (0, import_react.createProvidedContext)("EvaluateScopeExpression");
var SetBindingContext = React8.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 };
    }
    (0, import_lodash_es2.set)(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 = getChildNodes(dom, rootNode);
  const result = [];
  for (const [prop, children] of Object.entries(childNodes)) {
    if (isElement(rootNode)) {
      const componentId = getComponentId(rootNode);
      const Component = components[componentId];
      const componentConfig = Component?.[import_toolpad_core.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 isResizableHeightProp = propName === componentConfig.resizableHeightProp;
  const argType = componentConfig.argTypes?.[propName];
  return !isResizableHeightProp && 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 (isElement(elm)) {
      const componentId = getComponentId(elm);
      const Component = components[componentId];
      const componentConfig = Component?.[import_toolpad_core.TOOLPAD_COMPONENT] ?? {};
      const { argTypes = {} } = componentConfig;
      const propsMeta = {};
      for (const [propName, argType] of Object.entries(argTypes)) {
        (0, import_invariant4.default)(argType, `Missing argType for prop "${propName}"`);
        const initializerId = argType.defaultValueProp ? `${elm.id}.props.${argType.defaultValueProp}` : void 0;
        const propValue = elm.props?.[propName];
        const binding = propValue ?? (0, import_toolpad_core.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: initializerId
            });
          } 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 ? (0, import_toolpad_core.getArgTypeDefaultValue)(argType) : void 0);
          const bindingId = `${elm.id}.layout.${propName}`;
          parsedBindingsMap.set(bindingId, parseBinding(binding, {}));
        }
      }
    }
    if (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 (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) && isPage(rootNode)) {
    if (location && !Array.isArray(rootNode) && 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 (0, import_toolpad_core.useComponent)(componentId);
}
function RenderedNode({ nodeId }) {
  const dom = useDomContext();
  const node = getNode(dom, nodeId, "element");
  const Component = useElmToolpadComponent(node);
  const childNodeGroups = getChildNodes(dom, node);
  return /* @__PURE__ */ React8.createElement(RenderedNodeContent, { node, childNodeGroups, Component });
}
function RuntimeScoped({
  id,
  parseBindingsResult,
  localScope,
  onUpdate,
  children
}) {
  const parentScope = React8.useContext(RuntimeScopeContext);
  const dom = useDomContext();
  const { parsedBindings, controlled, scopeMeta } = parseBindingsResult;
  const [scopeBindings, setScopeBindings] = React8.useState(parsedBindings);
  const prevDom = React8.useRef(dom);
  React8.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 } = React8.useContext(SetBindingContext) ?? {};
  const setBinding = React8.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 = React8.useMemo(
    () => new Map(
      Object.entries(scopeBindings).map(
        ([bindingId, binding]) => [binding.scopePath, bindingId]
      )
    ),
    [scopeBindings]
  );
  const setBindingByScopePath = React8.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 = React8.useCallback(
    (bindingId, result) => {
      if (!controlled.has(bindingId)) {
        throw new Error(`Not a controlled binding "${bindingId}"`);
      }
      setBinding(bindingId, result);
    },
    [controlled, setBinding]
  );
  const childScope = React8.useMemo(
    () => createScope(id, scopeBindings, {
      localValues: localScope,
      parentScope,
      meta: scopeMeta
    }),
    [id, localScope, parentScope, scopeBindings, scopeMeta]
  );
  const vmRef = React8.useContext(ApplicationVmApiContext);
  React8.useEffect(() => {
    if (!vmRef) {
      return () => {
      };
    }
    return vmRef.current.registerScope(childScope);
  }, [vmRef, childScope]);
  const evaluateScopeExpression = React8.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]
  );
  React8.useEffect(() => {
    onUpdate?.({
      scopeMeta,
      scope: childScope
    });
  }, [scopeMeta, childScope, onUpdate]);
  const setBindingContext = React8.useMemo(
    () => ({
      setBinding,
      setControlledBinding,
      setBindingByScopePath
    }),
    [setBinding, setControlledBinding, setBindingByScopePath]
  );
  return /* @__PURE__ */ React8.createElement(RuntimeScopeContext.Provider, { value: childScope }, /* @__PURE__ */ React8.createElement(SetBindingContext.Provider, { value: setBindingContext }, /* @__PURE__ */ React8.createElement(EvaluateScopeExpressionProvider, { value: evaluateScopeExpression }, children)));
}
function TemplateScoped({ id, node, localScope, propName, children }) {
  const dom = useDomContext();
  const components = (0, import_toolpad_core.useComponents)();
  const location = (0, import_react_router_dom3.useLocation)();
  const parseBindingsResult = React8.useMemo(() => {
    const { [propName]: templateChildren = [] } = getChildNodes(dom, node);
    return parseBindings(dom, templateChildren, components, location);
  }, [components, dom, node, propName, location]);
  return /* @__PURE__ */ React8.createElement(RuntimeScoped, { id, parseBindingsResult, localScope }, children);
}
function NodeError({ error }) {
  return /* @__PURE__ */ React8.createElement(import_material5.Tooltip, { title: error.message }, /* @__PURE__ */ React8.createElement(
    "span",
    {
      style: {
        display: "inline-flex",
        flexDirection: "row",
        alignItems: "center",
        padding: 8,
        background: "red",
        color: "white"
      }
    },
    /* @__PURE__ */ React8.createElement(import_Error.default, { color: "inherit", style: { marginRight: 8 } }),
    " Error"
  ));
}
function RenderedNodeContent({ node, childNodeGroups, Component }) {
  const { setControlledBinding } = React8.useContext(SetBindingContext) ?? {};
  (0, import_invariant4.default)(setControlledBinding, "Node must be rendered in a RuntimeScoped context");
  const nodeId = node.id;
  const componentConfig = Component[import_toolpad_core.TOOLPAD_COMPONENT];
  const {
    argTypes = {},
    errorProp,
    loadingProp,
    loadingPropSource,
    errorPropSource
  } = componentConfig;
  const isLayoutNode = isPage(node) || isElement(node) && isPageLayoutComponent(node);
  const scope = (0, import_react.useAssertedContext)(RuntimeScopeContext);
  const liveBindings = scope.bindings;
  const boundProps = React8.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) {
        hookResult[propName] = (0, import_toolpad_core.getArgTypeDefaultValue)(argType);
      }
    }
    if (error) {
      if (errorProp) {
        hookResult[errorProp] = error;
      } else {
        console.error((0, import_errors.errorFrom)(error));
      }
    }
    if (loadingProp && loading) {
      hookResult[loadingProp] = true;
    }
    return hookResult;
  }, [argTypes, errorProp, errorPropSource, liveBindings, loadingProp, loadingPropSource, nodeId]);
  const boundLayoutProps = React8.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] = (0, import_toolpad_core.getArgTypeDefaultValue)(argType);
      }
    }
    return hookResult;
  }, [isLayoutNode, liveBindings, nodeId]);
  const onChangeHandlers = React8.useMemo(
    () => (0, import_collections5.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 = React8.useMemo(() => {
    return (0, import_collections5.mapProperties)(argTypes, ([key, argType]) => {
      if (!argType || argType.type !== "event" || !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 = React8.useMemo(() => {
    const result = {};
    for (const [prop, childNodes] of Object.entries(childNodeGroups)) {
      result[prop] = childNodes.map((child) => /* @__PURE__ */ React8.createElement(RenderedNode, { key: child.id, nodeId: child.id }));
    }
    return result;
  }, [childNodeGroups]);
  const layoutElementProps = React8.useMemo(() => {
    if (isElement(node) && isPageRow(node)) {
      return {
        layoutColumnSizes: childNodeGroups.children.map((child) => child.layout?.columnSize)
      };
    }
    return {};
  }, [childNodeGroups.children, node]);
  const props = React8.useMemo(() => {
    return {
      ...boundProps,
      ...onChangeHandlers,
      ...eventHandlers,
      ...layoutElementProps,
      ...reactChildren
    };
  }, [boundProps, eventHandlers, layoutElementProps, onChangeHandlers, reactChildren]);
  const previousProps = React8.useRef(props);
  const [hasSetInitialBindings, setHasSetInitialBindings] = React8.useState(false);
  React8.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 = React8.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__ */ React8.createElement(import_toolpad_core.Slots, { prop: propName, hasLayout: argType.control?.type === "layoutSlot" }, value);
        } else if (argType.control?.type === "slot") {
          wrappedValue = /* @__PURE__ */ React8.createElement(import_toolpad_core.Placeholder, { prop: propName }, value);
        }
        if (isTemplate) {
          assertIsElement(node);
          hookResult[propName] = (key, localScope) => {
            return /* @__PURE__ */ React8.createElement(
              TemplateScoped,
              {
                id: `${node.id}.props.${propName}.${key}`,
                localScope,
                node,
                propName
              },
              wrappedValue
            );
          };
        } else {
          hookResult[propName] = wrappedValue;
        }
      }
    }
    return hookResult;
  }, [argTypes, node, props]);
  const vmRef = React8.useContext(ApplicationVmApiContext);
  React8.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]);
  return /* @__PURE__ */ React8.createElement(
    import_runtime.NodeRuntimeWrapper,
    {
      nodeId,
      nodeName: node.name,
      componentConfig: Component[import_toolpad_core.TOOLPAD_COMPONENT],
      NodeError
    },
    isLayoutNode ? /* @__PURE__ */ React8.createElement(Component, { ...wrappedProps }) : /* @__PURE__ */ React8.createElement(
      import_material5.Box,
      {
        sx: {
          display: "flex",
          alignItems: boundLayoutProps.verticalAlign,
          justifyContent: boundLayoutProps.horizontalAlign
        }
      },
      /* @__PURE__ */ React8.createElement(Component, { ...wrappedProps })
    )
  );
}
function PageRoot({ children }) {
  return /* @__PURE__ */ React8.createElement(import_material5.Container, null, /* @__PURE__ */ React8.createElement(
    import_material5.Stack,
    {
      "data-testid": "page-root",
      direction: "column",
      sx: {
        my: 2,
        gap: 1
      }
    },
    children
  ));
}
var PageRootComponent = (0, import_toolpad_core.createComponent)(PageRoot, {
  argTypes: {
    children: {
      type: "element",
      control: { type: "slots" }
    }
  }
});
function QueryNode({ page, node }) {
  const { setControlledBinding } = React8.useContext(SetBindingContext) ?? {};
  (0, import_invariant4.default)(setControlledBinding, "QueryNode must be rendered in a RuntimeScoped context");
  const { bindings } = (0, import_react.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
  });
  React8.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 } = React8.useContext(SetBindingContext) ?? {};
  (0, import_invariant4.default)(setControlledBinding, "MutationNode must be rendered in a RuntimeScoped context");
  const { bindings } = (0, import_react.useAssertedContext)(RuntimeScopeContext);
  const { value: params } = resolveBindables(
    bindings,
    `${node.id}.params`,
    Object.fromEntries(node.params ?? [])
  );
  const {
    isPending,
    data: responseData = EMPTY_OBJECT2,
    error: fetchError,
    mutateAsync
  } = (0, import_react_query5.useMutation)({
    mutationKey: [node.name, params],
    mutationFn: async (overrides = {}) => {
      return api_default.methods.execQuery(page.name, node.name, { ...params, ...overrides });
    }
  });
  const { data, error: apiError } = responseData || EMPTY_OBJECT2;
  const error = apiError || fetchError;
  const mutationResult = React8.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]);
  React8.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__ */ React8.createElement(QueryNode, { node, page });
    case "mutation":
      return /* @__PURE__ */ React8.createElement(MutationNode, { node, page });
    default:
      throw new Error(`Unrecognized fetch mode "${mode}"`);
  }
}
function RenderedProCodePage({ page }) {
  const pageComponents = pageComponentsStore.useValue();
  const PageComponent = pageComponents[page.name] ?? PageNotFound;
  return /* @__PURE__ */ React8.createElement(PageComponent, null);
}
function RenderedLowCodePage({ page }) {
  const dom = useDomContext();
  const { children = [], queries = [] } = getChildNodes(dom, page);
  (0, import_usePageTitle.default)(getPageTitle(page));
  const location = (0, import_react_router_dom3.useLocation)();
  const components = (0, import_toolpad_core.useComponents)();
  const parseBindingsResult = React8.useMemo(
    () => parseBindings(dom, page, components, location),
    [components, dom, location, page]
  );
  const canvasEvents = React8.useContext(import_runtime.CanvasEventsContext);
  const onUpdate = (0, import_useEventCallback.default)(({ scope, scopeMeta }) => {
    if (canvasEvents) {
      canvasEvents.emit("pageStateUpdated", {
        pageState: scope.values,
        globalScopeMeta: scopeMeta
      });
      canvasEvents.emit("pageBindingsUpdated", { bindings: scope.bindings });
    }
  });
  const applicationVm = useApplicationVm((vm) => {
    if (canvasEvents) {
      canvasEvents.emit("vmUpdated", { vm });
    }
  });
  return /* @__PURE__ */ React8.createElement(ApplicationVmApiContext.Provider, { value: applicationVm }, /* @__PURE__ */ React8.createElement(RuntimeScoped, { id: "global", parseBindingsResult, onUpdate }, /* @__PURE__ */ React8.createElement(
    RenderedNodeContent,
    {
      node: page,
      childNodeGroups: { children },
      Component: PageRootComponent
    }
  ), queries.map((node) => /* @__PURE__ */ React8.createElement(FetchNode, { key: node.id, page, node }))));
}
function RenderedPage({ page }) {
  (0, import_usePageTitle.default)(getPageTitle(page));
  if (page.attributes.codeFile) {
    return /* @__PURE__ */ React8.createElement(RenderedProCodePage, { page });
  }
  return /* @__PURE__ */ React8.createElement(RenderedLowCodePage, { page });
}
function PageNotFound() {
  return /* @__PURE__ */ React8.createElement(
    import_material5.Container,
    {
      sx: {
        display: "flex",
        alignItems: "center",
        justifyContent: "center",
        flexDirection: "column"
      }
    },
    /* @__PURE__ */ React8.createElement(import_material5.Typography, { variant: "h1" }, "Not found"),
    /* @__PURE__ */ React8.createElement(import_material5.Typography, null, "The page doesn't exist in this application.")
  );
}
function useAppHasAuthentication() {
  return false;
}
function RenderedPages({ pages }) {
  const defaultPage = pages[0];
  const defaultPageNavigation = /* @__PURE__ */ React8.createElement(import_react_router_dom3.Navigate, { to: `/pages/${defaultPage.name}`, replace: true });
  const { search } = (0, import_react_router_dom3.useLocation)();
  const appAuthenticationEnabled = useAppHasAuthentication();
  return /* @__PURE__ */ React8.createElement(import_react_router_dom3.Routes, null, pages.map((page) => {
    let pageContent = /* @__PURE__ */ React8.createElement(
      RenderedPage,
      {
        page,
        key: page.name
      }
    );
    if (!IS_RENDERED_IN_CANVAS && appAuthenticationEnabled && page.attributes.authorization) {
      pageContent = /* @__PURE__ */ React8.createElement(RequireAuthorization, { allowedRole: page.attributes.authorization.allowedRoles }, pageContent);
    }
    return /* @__PURE__ */ React8.createElement(import_react_router_dom3.Route, { key: page.name, path: `/pages/${page.name}`, element: pageContent });
  }), pages.flatMap(
    (page) => page.attributes.alias?.map((alias) => /* @__PURE__ */ React8.createElement(
      import_react_router_dom3.Route,
      {
        key: `${page.name}-${alias}`,
        path: `/pages/${alias}`,
        element: /* @__PURE__ */ React8.createElement(import_react_router_dom3.Navigate, { to: `/pages/${page.name}${search}`, replace: true })
      }
    ))
  ), /* @__PURE__ */ React8.createElement(import_react_router_dom3.Route, { path: "/pages", element: defaultPageNavigation }), /* @__PURE__ */ React8.createElement(import_react_router_dom3.Route, { path: "/", element: defaultPageNavigation }), /* @__PURE__ */ React8.createElement(import_react_router_dom3.Route, { path: "*", element: /* @__PURE__ */ React8.createElement(PageNotFound, null) }));
}
var FullPageCentered = (0, import_material5.styled)("div")({
  width: "100%",
  height: "100%",
  display: "flex",
  alignItems: "center",
  justifyContent: "center"
});
function AppLoading() {
  return /* @__PURE__ */ React8.createElement(import_material5.LinearProgress, null);
}
function AppError({ error }) {
  return /* @__PURE__ */ React8.createElement(FullPageCentered, null, /* @__PURE__ */ React8.createElement(import_material5.Alert, { severity: "error" }, /* @__PURE__ */ React8.createElement(import_material5.AlertTitle, null, "Something went wrong"), /* @__PURE__ */ React8.createElement(Pre, null, error.message), /* @__PURE__ */ React8.createElement(Pre, null, error.stack)));
}
function ToolpadAppLayout({ dom }) {
  const root = getApp(dom);
  const { pages = [] } = getChildNodes(dom, root);
  const pageMatch = (0, import_react_router_dom3.useMatch)("/pages/:slug");
  const activePage = pageMatch?.params.slug;
  const navEntries = React8.useMemo(
    () => pages.map((page) => ({
      slug: page.name,
      displayName: getPageDisplayName(page),
      hasShell: page?.attributes.display !== "standalone"
    })),
    [pages]
  );
  return /* @__PURE__ */ React8.createElement(
    AppLayout,
    {
      activePage,
      pages: navEntries,
      hasShell: !IS_RENDERED_IN_CANVAS,
      clipped: SHOW_PREVIEW_HEADER
    },
    /* @__PURE__ */ React8.createElement(RenderedPages, { pages })
  );
}
function ToolpadApp({ rootRef, basename, state }) {
  const { dom } = state;
  const extraComponents = componentsStore.useValue();
  const components = React8.useMemo(
    () => ({ ...internalComponents, ...extraComponents }),
    [extraComponents]
  );
  const [resetNodeErrorsKey, setResetNodeErrorsKey] = React8.useState(0);
  React8.useEffect(() => setResetNodeErrorsKey((key) => key + 1), [dom]);
  const { value: showDevtools, toggle: toggleDevtools } = (0, import_useBoolean.default)(false);
  React8.useEffect(() => {
    window.toggleDevtools = () => toggleDevtools();
  }, [toggleDevtools]);
  const currentUser = null;
  return /* @__PURE__ */ React8.createElement(import_react_router_dom3.BrowserRouter, { basename }, /* @__PURE__ */ React8.createElement(import_runtime.UseDataProviderContext.Provider, { value: useDataProvider }, /* @__PURE__ */ React8.createElement(AppThemeProvider, { dom }, /* @__PURE__ */ React8.createElement(import_material5.CssBaseline, { enableColorScheme: true }), SHOW_PREVIEW_HEADER ? /* @__PURE__ */ React8.createElement(PreviewHeader, { basename }) : null, /* @__PURE__ */ React8.createElement(AppRoot, { ref: rootRef }, /* @__PURE__ */ React8.createElement(import_toolpad_core.ComponentsContextProvider, { value: components }, /* @__PURE__ */ React8.createElement(DomContextProvider, { value: dom }, /* @__PURE__ */ React8.createElement(import_react_error_boundary.ErrorBoundary, { FallbackComponent: AppError }, /* @__PURE__ */ React8.createElement(import_runtime.ResetNodeErrorsKeyProvider, { value: resetNodeErrorsKey }, /* @__PURE__ */ React8.createElement(React8.Suspense, { fallback: /* @__PURE__ */ React8.createElement(AppLoading, null) }, /* @__PURE__ */ React8.createElement(import_react_query5.QueryClientProvider, { client: queryClient }, /* @__PURE__ */ React8.createElement(AuthenticationProvider, { user: currentUser }, /* @__PURE__ */ React8.createElement(ToolpadAppLayout, { dom })), showDevtools ? /* @__PURE__ */ React8.createElement(ReactQueryDevtoolsProduction, { initialIsOpen: false }) : null)))))), /* @__PURE__ */ React8.createElement(EditorOverlay, { id: HTML_ID_EDITOR_OVERLAY })))));
}

// src/canvas/getPageViewState.ts
var import_toolpad_core2 = require("@mui/toolpad-core");

// src/utils/geometry.ts
function getRelativeBoundingRect(containerElm, childElm) {
  const containerRect = containerElm.getBoundingClientRect();
  const childRect = childElm.getBoundingClientRect();
  return {
    x: childRect.x - containerRect.x,
    y: childRect.y - containerRect.y,
    width: childRect.width,
    height: childRect.height
  };
}
function getRelativeOuterRect(containerElm, childElm) {
  const { x, y, width, height } = getRelativeBoundingRect(containerElm, childElm);
  const styles = window.getComputedStyle(childElm);
  const parseMarginStyle = (style) => style === "auto" ? 0 : parseFloat(style);
  let offsetLeft = parseMarginStyle(styles.marginLeft);
  let offsetRight = parseMarginStyle(styles.marginRight);
  let offsetTop = parseMarginStyle(styles.marginTop);
  let offsetBottom = parseMarginStyle(styles.marginBottom);
  if (styles.boxSizing === "content-box") {
    offsetLeft += parseFloat(styles.paddingLeft) + parseFloat(styles.borderLeftWidth);
    offsetRight += parseFloat(styles.paddingRight) + parseFloat(styles.borderRightWidth);
    offsetTop += parseFloat(styles.paddingTop) + parseFloat(styles.borderTopWidth);
    offsetBottom += parseFloat(styles.paddingBottom) + parseFloat(styles.borderBottomWidth);
  }
  return {
    x: x - offsetLeft,
    y: y - offsetTop,
    width: width + offsetLeft + offsetRight,
    height: height + offsetTop + offsetBottom
  };
}
function rectContainsPoint(rect, x, y) {
  return rect.x <= x && rect.x + rect.width >= x && rect.y <= y && rect.y + rect.height >= y;
}

// src/canvas/getPageViewState.ts
function getNodeViewInfo(fiber, viewElm, elm, nodeId, fiberHostProps) {
  if (nodeId) {
    const rect = getRelativeOuterRect(viewElm, elm);
    const props = fiber.child?.memoizedProps ?? {};
    return {
      nodeId,
      error: fiberHostProps.nodeError,
      componentConfig: fiberHostProps.componentConfig,
      rect,
      slots: {},
      props
    };
  }
  return null;
}
function walkFibers(node, visitor) {
  visitor(node);
  if (node.child) {
    walkFibers(node.child, visitor);
  }
  if (node.sibling) {
    walkFibers(node.sibling, visitor);
  }
}
function getNodesViewInfo(rootElm) {
  const devtoolsHook = rootElm.ownerDocument.defaultView?.__REACT_DEVTOOLS_GLOBAL_HOOK__;
  if (!devtoolsHook) {
    console.warn(`Can't read page layout as react devtools are not installed`);
    return { nodes: {} };
  }
  const nodes = {};
  const rendererId = 1;
  const nodeElms = /* @__PURE__ */ new Map();
  Array.from(devtoolsHook.getFiberRoots(rendererId)).forEach((fiberRoot) => {
    if (fiberRoot.current) {
      walkFibers(fiberRoot.current, (fiber) => {
        if (!fiber.memoizedProps) {
          return;
        }
        const nodeIdPropValue = fiber.memoizedProps[import_toolpad_core2.RUNTIME_PROP_NODE_ID];
        if (nodeIdPropValue) {
          const fiberHostProps = fiber.memoizedProps;
          const nodeId = fiberHostProps[import_toolpad_core2.RUNTIME_PROP_NODE_ID];
          if (nodes[nodeId]) {
            return;
          }
          const elm = devtoolsHook.renderers.get(rendererId)?.findHostInstanceByFiber(fiber);
          if (elm) {
            nodeElms.set(nodeId, elm);
            const info = getNodeViewInfo(fiber, rootElm, elm, nodeId, fiberHostProps);
            if (info) {
              nodes[nodeId] = info;
            }
          }
        }
        const slotNamePropValue = fiber.memoizedProps[import_toolpad_core2.RUNTIME_PROP_SLOTS];
        if (slotNamePropValue) {
          const slotType = fiber.memoizedProps.slotType;
          const parentId = fiber.memoizedProps.parentId;
          const nodeSlots = nodes[parentId]?.slots;
          if (nodeSlots && nodeSlots[slotNamePropValue]) {
            return;
          }
          const firstChildElm = devtoolsHook.renderers.get(rendererId)?.findHostInstanceByFiber(fiber);
          const childContainerElm = firstChildElm?.parentElement;
          if (childContainerElm && nodeSlots) {
            const rect = slotType === "single" ? getRelativeBoundingRect(rootElm, firstChildElm) : getRelativeBoundingRect(rootElm, childContainerElm);
            const display = window.getComputedStyle(childContainerElm).display;
            let flowDirection = "row";
            if (slotType === "layout") {
              flowDirection = "column";
            } else if (display === "grid") {
              const gridAutoFlow = window.getComputedStyle(childContainerElm).gridAutoFlow;
              flowDirection = gridAutoFlow === "row" ? "column" : "row";
            } else if (display === "flex") {
              flowDirection = window.getComputedStyle(childContainerElm).flexDirection;
            }
            nodeSlots[slotNamePropValue] = {
              type: slotType,
              rect,
              flowDirection
            };
          }
        }
      });
    }
  });
  return { nodes };
}
function getPageViewState(rootElm) {
  return getNodesViewInfo(rootElm);
}

// src/canvas/ToolpadBridge.tsx
var import_events = require("@mui/toolpad-utils/events");

// src/constants.ts
var TOOLPAD_BRIDGE_GLOBAL = "__TOOLPAD_BRIDGE__";
var VERSION_CHECK_INTERVAL = 1e3 * 60 * 10;

// src/canvas/ToolpadBridge.tsx
var COMMAND_HANDLERS = Symbol("hidden property to hold the command handlers");
function createCommands(initial = {}) {
  return new Proxy(
    {
      [COMMAND_HANDLERS]: initial
    },
    {
      get(target, prop, receiver) {
        if (typeof prop !== "string") {
          return Reflect.get(target, prop, receiver);
        }
        return (...args) => {
          const handler = target[COMMAND_HANDLERS][prop];
          if (typeof handler !== "function") {
            throw new Error(`Command "${prop}" not recognized.`);
          }
          return handler(...args);
        };
      }
    }
  );
}
function setCommandHandler(commands, name, handler) {
  commands[COMMAND_HANDLERS][name] = handler;
}
var isRenderedInCanvas = typeof window !== "undefined" && window.frameElement?.dataset.toolpadCanvas;
var canvasIsReady = false;
var bridge = isRenderedInCanvas ? {
  editorEvents: new import_events.Emitter(),
  editorCommands: createCommands(),
  canvasEvents: new import_events.Emitter(),
  canvasCommands: createCommands({
    isReady: () => canvasIsReady,
    getPageViewState: () => {
      throw new Error("Not implemented");
    },
    getViewCoordinates: () => {
      throw new Error("Not implemented");
    },
    invalidateQueries: () => {
      throw new Error("Not implemented");
    },
    update: () => {
      throw new Error("Not implemented");
    }
  })
} : null;
bridge?.canvasEvents.on("ready", () => {
  canvasIsReady = true;
});
if (bridge) {
  if (typeof window[TOOLPAD_BRIDGE_GLOBAL] === "function") {
    window[TOOLPAD_BRIDGE_GLOBAL](bridge);
  }
  window[TOOLPAD_BRIDGE_GLOBAL] = bridge;
}

// src/canvas/index.tsx
var handleScreenUpdate = (0, import_lodash_es3.throttle)(
  () => {
    bridge?.canvasEvents.emit("screenUpdate", {});
  },
  50,
  { trailing: true }
);
function AppCanvas({ basename, state: initialState }) {
  const [state, setState] = React9.useState(initialState);
  const [readyBridge, setReadyBridge] = React9.useState();
  const appRootRef = React9.useRef();
  const appRootCleanupRef = React9.useRef();
  const onAppRoot = React9.useCallback((appRoot) => {
    appRootCleanupRef.current?.();
    appRootCleanupRef.current = void 0;
    if (!appRoot) {
      return;
    }
    appRootRef.current = appRoot;
    const mutationObserver = new MutationObserver(handleScreenUpdate);
    mutationObserver.observe(appRoot, {
      attributes: true,
      childList: true,
      subtree: true,
      characterData: true
    });
    const resizeObserver = new ResizeObserver(handleScreenUpdate);
    resizeObserver.observe(appRoot);
    appRoot.querySelectorAll("*").forEach((elm) => resizeObserver.observe(elm));
    appRootCleanupRef.current = () => {
      handleScreenUpdate.cancel();
      mutationObserver.disconnect();
      resizeObserver.disconnect();
    };
  }, []);
  React9.useEffect(
    () => () => {
      appRootCleanupRef.current?.();
      appRootCleanupRef.current = void 0;
    },
    []
  );
  React9.useEffect(() => {
    if (appRootRef.current) {
      handleScreenUpdate();
    }
  });
  React9.useEffect(() => {
    if (!bridge) {
      return;
    }
    setCommandHandler(bridge.canvasCommands, "getPageViewState", () => {
      (0, import_invariant5.default)(appRootRef.current, "App ref not attached");
      return getPageViewState(appRootRef.current);
    });
    setCommandHandler(bridge.canvasCommands, "getViewCoordinates", (clientX, clientY) => {
      if (!appRootRef.current) {
        return null;
      }
      const rect = appRootRef.current.getBoundingClientRect();
      if (rectContainsPoint(rect, clientX, clientY)) {
        return { x: clientX - rect.x, y: clientY - rect.y };
      }
      return null;
    });
    setCommandHandler(bridge.canvasCommands, "update", (newState) => {
      React9.startTransition(() => setState(structuredClone(newState)));
    });
    setCommandHandler(bridge.canvasCommands, "invalidateQueries", () => {
      queryClient.invalidateQueries();
    });
    bridge.canvasEvents.emit("ready", {});
    setReadyBridge(bridge);
  }, []);
  const savedNodes = state?.savedNodes;
  const editorHooks = React9.useMemo(() => {
    return {
      savedNodes
    };
  }, [savedNodes]);
  if (IS_RENDERED_IN_CANVAS) {
    return readyBridge ? /* @__PURE__ */ React9.createElement(CanvasHooksContext.Provider, { value: editorHooks }, /* @__PURE__ */ React9.createElement(import_runtime2.CanvasEventsContext.Provider, { value: readyBridge.canvasEvents }, /* @__PURE__ */ React9.createElement(ToolpadApp, { rootRef: onAppRoot, basename, state }))) : null;
  }
  return /* @__PURE__ */ React9.createElement(ToolpadApp, { basename, state });
}
//# sourceMappingURL=canvas.js.map