// ../runtime/react-import.js
import React from "react";

// src/main.tsx
import { ChakraProvider } from "@chakra-ui/react";
import { initMetaUI as initMetaUI2 } from "@meta-ui/runtime";
import { StrictMode } from "react";
import ReactDOM from "react-dom";

// src/components/Editor.tsx
import { useEffect as useEffect5, useMemo as useMemo4, useState as useState7 } from "react";
import { DIALOG_CONTAINER_ID } from "@meta-ui/runtime";
import produce4 from "immer";
import { Box as Box10, Tabs as Tabs2, TabList as TabList2, Tab as Tab2, TabPanels as TabPanels2, TabPanel as TabPanel2 } from "@chakra-ui/react";

// src/components/StructureTree/StructureTree.tsx
import React3 from "react";
import { Box as Box4, Text as Text3, VStack as VStack2 } from "@chakra-ui/react";

// ../../node_modules/mitt/dist/mitt.mjs
function mitt_default(n) {
  return { all: n = n || new Map(), on: function(t, e) {
    var i = n.get(t);
    i ? i.push(e) : n.set(t, [e]);
  }, off: function(t, e) {
    var i = n.get(t);
    i && (e ? i.splice(i.indexOf(e) >>> 0, 1) : n.set(t, []));
  }, emit: function(t, e) {
    var i = n.get(t);
    i && i.slice().map(function(n2) {
      n2(e);
    }), (i = n.get("*")) && i.slice().map(function(n2) {
      n2(t, e);
    });
  } };
}

// src/eventBus.ts
var SelectComponentEvent = "selectComponent";
var HoverComponentEvent = "hoverComponent";
var emitter = mitt_default();
var eventBus = {
  on: emitter.on,
  off: emitter.off,
  send: emitter.emit
};

// src/operations/Operations.ts
var CreateComponentOperation = class {
  constructor(componentType, parentId, slot, componentId) {
    this.componentType = componentType;
    this.parentId = parentId;
    this.slot = slot;
    this.componentId = componentId;
    this.kind = "createComponent";
  }
};
var RemoveComponentOperation = class {
  constructor(componentId) {
    this.componentId = componentId;
    this.kind = "removeComponent";
  }
};
var ModifyComponentPropertyOperation = class {
  constructor(componentId, propertyKey, propertyValue) {
    this.componentId = componentId;
    this.propertyKey = propertyKey;
    this.propertyValue = propertyValue;
    this.kind = "modifyComponentProperty";
  }
};
var AddTraitOperation = class {
  constructor(componentId, traitType, properties) {
    this.componentId = componentId;
    this.traitType = traitType;
    this.properties = properties;
    this.kind = "addTraitOperation";
  }
};
var RemoveTraitOperation = class {
  constructor(componentId, traitIndex) {
    this.componentId = componentId;
    this.traitIndex = traitIndex;
    this.kind = "removeTraitOperation";
  }
};
var ModifyComponentIdOperation = class {
  constructor(componentId, value) {
    this.componentId = componentId;
    this.value = value;
    this.kind = "modifyComponentId";
  }
};
var ModifyTraitPropertyOperation = class {
  constructor(componentId, traitType, propertyKey, propertyValue) {
    this.componentId = componentId;
    this.traitType = traitType;
    this.propertyKey = propertyKey;
    this.propertyValue = propertyValue;
    this.kind = "modifyTraitProperty";
  }
};
var ModifyTraitPropertiesOperation = class {
  constructor(componentId, traitType, properties) {
    this.componentId = componentId;
    this.traitType = traitType;
    this.properties = properties;
    this.kind = "modifyTraitProperties";
  }
};
var SortComponentOperation = class {
  constructor(componentId, direction) {
    this.componentId = componentId;
    this.direction = direction;
    this.kind = "sortComponent";
  }
};

// src/components/StructureTree/ComponentItemView.tsx
import {
  ArrowDownIcon,
  ArrowUpIcon,
  ChevronDownIcon,
  ChevronRightIcon,
  DeleteIcon
} from "@chakra-ui/icons";
import { Box, HStack, IconButton, Text } from "@chakra-ui/react";
import { useState } from "react";
var ComponentItemView = (props) => {
  const {
    title,
    isSelected,
    noChevron,
    isExpanded,
    onClick,
    onToggleExpanded,
    onClickRemove,
    isDroppable,
    isSortable = false,
    onMoveUp,
    onMoveDown
  } = props;
  const [isDragOver, setIsDragOver] = useState(false);
  const expandIcon = /* @__PURE__ */ React.createElement(IconButton, {
    position: "absolute",
    left: "-5",
    "aria-label": "showChildren",
    size: "xs",
    variant: "unstyled",
    onClick: onToggleExpanded,
    _focus: {
      outline: "0"
    },
    icon: isExpanded ? /* @__PURE__ */ React.createElement(ChevronDownIcon, null) : /* @__PURE__ */ React.createElement(ChevronRightIcon, null)
  });
  const onDragOver = () => {
    if (isDroppable) {
      setIsDragOver(true);
    }
  };
  return /* @__PURE__ */ React.createElement(Box, {
    width: "full",
    onDragOver,
    onDragLeave: () => setIsDragOver(false),
    onDrop: () => setIsDragOver(false),
    background: isDragOver ? "gray.100" : void 0
  }, noChevron ? null : expandIcon, /* @__PURE__ */ React.createElement(HStack, {
    width: "full",
    justify: "space-between"
  }, /* @__PURE__ */ React.createElement(Text, {
    color: isSelected ? "red.500" : "black",
    onClick,
    cursor: "pointer",
    overflow: "hidden",
    whiteSpace: "nowrap",
    textOverflow: "ellipsis"
  }, title), /* @__PURE__ */ React.createElement(HStack, {
    spacing: "1"
  }, onClickRemove ? /* @__PURE__ */ React.createElement(IconButton, {
    variant: "ghost",
    size: "smx",
    "aria-label": "remove",
    icon: /* @__PURE__ */ React.createElement(DeleteIcon, null),
    onClick: onClickRemove
  }) : null, isSortable ? /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(IconButton, {
    variant: "ghost",
    size: "smx",
    "aria-label": "remove",
    icon: /* @__PURE__ */ React.createElement(ArrowUpIcon, null),
    onClick: onMoveUp
  }), /* @__PURE__ */ React.createElement(IconButton, {
    variant: "ghost",
    size: "smx",
    "aria-label": "remove",
    icon: /* @__PURE__ */ React.createElement(ArrowDownIcon, null),
    onClick: onMoveDown
  })) : null)));
};

// src/components/StructureTree/ComponentTree.tsx
import { Box as Box3, Text as Text2, VStack } from "@chakra-ui/react";
import React2, { useMemo, useState as useState2 } from "react";

// src/components/StructureTree/DropComponentWrapper.tsx
import { Box as Box2 } from "@chakra-ui/react";
var DropComponentWrapper = (props) => {
  const onDragOver = (e) => {
    e.preventDefault();
    e.stopPropagation();
  };
  const onDrop = (e) => {
    var _a;
    e.stopPropagation();
    e.preventDefault();
    const creatingComponent = ((_a = e.dataTransfer) == null ? void 0 : _a.getData("component")) || "";
    props.onDrop(creatingComponent);
  };
  return /* @__PURE__ */ React.createElement(Box2, {
    width: "full",
    onDrop,
    onDragOver
  }, props.children);
};

// src/components/StructureTree/ComponentTree.tsx
var ComponentTree = (props) => {
  const { component, childrenMap, selectedComponentId, onSelectComponent, registry } = props;
  const slots = registry.getComponentByType(component.type).spec.slots;
  const [isExpanded, setIsExpanded] = useState2(true);
  const slotsEle = useMemo(() => {
    if (slots.length === 0) {
      return null;
    }
    const slotsMap = childrenMap.get(component.id);
    return slots.map((slot) => {
      let slotContent;
      const slotChildren = slotsMap == null ? void 0 : slotsMap.get(slot);
      if (slotChildren && slotChildren.length > 0) {
        slotContent = slotChildren.map((c) => {
          return /* @__PURE__ */ React2.createElement(ComponentTree, {
            key: c.id,
            component: c,
            childrenMap,
            selectedComponentId,
            onSelectComponent,
            registry
          });
        });
      } else {
        slotContent = /* @__PURE__ */ React2.createElement(Text2, {
          fontSize: "sm",
          color: "gray.500"
        }, "Empty");
      }
      const onDrop2 = (creatingComponent) => {
        eventBus.send("operation", new CreateComponentOperation(creatingComponent, component.id, slot));
      };
      const slotName = /* @__PURE__ */ React2.createElement(DropComponentWrapper, {
        onDrop: onDrop2
      }, /* @__PURE__ */ React2.createElement(Text2, {
        color: "gray.500",
        fontWeight: "medium"
      }, "Slot: ", slot));
      return /* @__PURE__ */ React2.createElement(Box3, {
        key: slot,
        paddingLeft: "3",
        width: "full"
      }, slots.length > 1 ? slotName : null, /* @__PURE__ */ React2.createElement(VStack, {
        spacing: "2",
        width: "full",
        alignItems: "start"
      }, slotContent));
    });
  }, [component, childrenMap]);
  const onClickRemove = () => {
    eventBus.send("operation", new RemoveComponentOperation(component.id));
  };
  const onDrop = (creatingComponent) => {
    if (slots.length === 0)
      return;
    eventBus.send("operation", new CreateComponentOperation(creatingComponent, component.id, "content"));
  };
  const onMoveUp = () => {
    eventBus.send("operation", new SortComponentOperation(component.id, "up"));
  };
  const onMoveDown = () => {
    eventBus.send("operation", new SortComponentOperation(component.id, "down"));
  };
  return /* @__PURE__ */ React2.createElement(VStack, {
    key: component.id,
    position: "relative",
    spacing: "2",
    width: "full",
    alignItems: "start"
  }, /* @__PURE__ */ React2.createElement(DropComponentWrapper, {
    onDrop
  }, /* @__PURE__ */ React2.createElement(ComponentItemView, {
    title: component.id,
    isSelected: component.id === selectedComponentId,
    onClick: () => {
      onSelectComponent(component.id);
    },
    onClickRemove,
    noChevron: slots.length === 0,
    isExpanded,
    onToggleExpanded: () => setIsExpanded((prev) => !prev),
    isDroppable: slots.length > 0,
    isSortable: true,
    onMoveUp,
    onMoveDown
  })), isExpanded ? slotsEle : null);
};

// src/components/StructureTree/StructureTree.tsx
var StructureTree = (props) => {
  const { app, selectedComponentId, onSelectComponent, registry } = props;
  const topLevelComponents = [];
  const childrenMap = new Map();
  const components = app.spec.components.filter((c) => c.type !== "core/v1/dummy");
  const dataSources = app.spec.components.filter((c) => c.type === "core/v1/dummy");
  components.forEach((c) => {
    var _a, _b;
    const slotTrait = c.traits.find((t) => t.type === "core/v1/slot");
    if (slotTrait) {
      const { id: parentId, slot } = slotTrait.properties.container;
      if (!childrenMap.has(parentId)) {
        childrenMap.set(parentId, new Map());
      }
      if (!((_a = childrenMap.get(parentId)) == null ? void 0 : _a.has(slot))) {
        (_b = childrenMap.get(parentId)) == null ? void 0 : _b.set(slot, []);
      }
      childrenMap.get(parentId).get(slot).push(c);
    } else {
      topLevelComponents.push(c);
    }
  });
  const topEles = topLevelComponents.map((c) => /* @__PURE__ */ React3.createElement(ComponentTree, {
    key: c.id,
    component: c,
    childrenMap,
    selectedComponentId,
    onSelectComponent,
    registry
  }));
  const dataSourcesEles = dataSources.map((dummy) => {
    const onClickRemove = () => {
      eventBus.send("operation", new RemoveComponentOperation(dummy.id));
    };
    return /* @__PURE__ */ React3.createElement(ComponentItemView, {
      key: dummy.id,
      title: dummy.id,
      isSelected: dummy.id === selectedComponentId,
      onClick: () => {
        onSelectComponent(dummy.id);
      },
      onClickRemove,
      noChevron: true
    });
  });
  return /* @__PURE__ */ React3.createElement(VStack2, {
    spacing: "2",
    padding: "5",
    alignItems: "start"
  }, /* @__PURE__ */ React3.createElement(Text3, {
    fontSize: "lg",
    fontWeight: "bold"
  }, "Components"), /* @__PURE__ */ React3.createElement(RootItem, null), topEles, /* @__PURE__ */ React3.createElement(Text3, {
    fontSize: "lg",
    fontWeight: "bold"
  }, "DataSources"), dataSourcesEles);
};
function RootItem() {
  const onDrop = (creatingComponent) => {
    eventBus.send("operation", new CreateComponentOperation(creatingComponent));
  };
  return /* @__PURE__ */ React3.createElement(Box4, {
    width: "full"
  }, /* @__PURE__ */ React3.createElement(DropComponentWrapper, {
    onDrop
  }, /* @__PURE__ */ React3.createElement(ComponentItemView, {
    title: "Root",
    isSelected: false,
    onClick: () => void 0,
    isDroppable: true,
    noChevron: true
  })));
}

// src/components/ComponentForm/ComponentForm.tsx
import React5 from "react";
import { flatten } from "lodash-es";
import { FormControl as FormControl3, FormLabel as FormLabel3, Input as Input4, Textarea, VStack as VStack9 } from "@chakra-ui/react";
import { parseType, parseTypeBox as parseTypeBox3 } from "@meta-ui/runtime";

// src/components/ComponentForm/EventTraitForm/EventTraitForm.tsx
import { useMemo as useMemo2 } from "react";
import { AddIcon } from "@chakra-ui/icons";
import { HStack as HStack3, IconButton as IconButton4, VStack as VStack5 } from "@chakra-ui/react";
import produce2 from "immer";

// src/components/ComponentForm/EventTraitForm/EventHandlerForm.tsx
import { useEffect as useEffect2, useState as useState5 } from "react";
import {
  Box as Box5,
  FormControl,
  FormLabel,
  IconButton as IconButton3,
  Input as Input2,
  Select,
  Switch,
  VStack as VStack4
} from "@chakra-ui/react";
import { CloseIcon as CloseIcon2 } from "@chakra-ui/icons";
import { useFormik } from "formik";

// src/operations/useAppModel.ts
import { useEffect, useState as useState3 } from "react";

// src/constants.ts
var ignoreTraitsList = ["core/v1/slot", "core/v1/event", "core/v1/fetch"];
var DefaultAppSchema = {
  kind: "Application",
  version: "example/v1",
  metadata: {
    name: "dialog_component",
    description: "dialog component example"
  },
  spec: {
    components: [
      {
        id: "grid_layout1",
        type: "core/v1/grid_layout",
        properties: {
          layout: [
            {
              w: 10,
              h: 15,
              x: 0,
              y: 0,
              i: "tabs1",
              moved: false,
              static: false,
              isDraggable: true
            }
          ]
        },
        traits: []
      },
      {
        id: "fetchUsers",
        type: "core/v1/dummy",
        properties: {},
        traits: [
          {
            type: "core/v1/fetch",
            properties: {
              url: "https://6177d4919c328300175f5b99.mockapi.io/users",
              method: "get",
              lazy: false,
              headers: {},
              body: {},
              onComplete: []
            }
          }
        ]
      },
      {
        id: "usersTable",
        type: "chakra_ui/v1/table",
        properties: {
          data: "{{fetchUsers.fetch.data}}",
          columns: [
            { key: "username", title: "\u7528\u6237\u540D", type: "link" },
            { key: "job", title: "\u804C\u4F4D", type: "text" },
            { key: "area", title: "\u5730\u533A", type: "text" },
            {
              key: "createdTime",
              title: "\u521B\u5EFA\u65F6\u95F4",
              displayValue: "{{dayjs($listItem.createdTime).format('LL')}}"
            }
          ],
          majorKey: "id",
          rowsPerPage: "3",
          isMultiSelect: "false"
        },
        traits: [
          {
            type: "core/v1/slot",
            properties: {
              container: { id: "tabContentVStack", slot: "content" }
            }
          }
        ]
      },
      {
        id: "userInfoContainer",
        type: "chakra_ui/v1/vstack",
        properties: { spacing: "2", align: "stretch" },
        traits: [
          {
            type: "core/v1/slot",
            properties: {
              container: { id: "tabContentVStack", slot: "content" }
            }
          },
          {
            type: "core/v1/style",
            properties: {
              styleSlot: "content",
              style: "{{!usersTable.selectedItem ? 'display: none' : ''}}"
            }
          }
        ]
      },
      {
        id: "userInfoTitle",
        type: "core/v1/text",
        properties: { value: { raw: "**\u57FA\u672C\u4FE1\u606F**", format: "md" } },
        traits: [
          {
            type: "core/v1/slot",
            properties: {
              container: { id: "userInfoContainer", slot: "content" }
            }
          }
        ]
      },
      {
        id: "hstack1",
        type: "chakra_ui/v1/hstack",
        properties: { spacing: "24px", hideBorder: "" },
        traits: [
          {
            type: "core/v1/slot",
            properties: {
              container: { id: "userInfoContainer", slot: "content" }
            }
          },
          {
            type: "core/v1/style",
            properties: {
              styleSlot: "content",
              style: "padding: 0; border: none"
            }
          }
        ]
      },
      {
        id: "usernameLabel",
        type: "core/v1/text",
        properties: { value: { raw: "**\u7528\u6237\u540D**", format: "md" } },
        traits: [
          {
            type: "core/v1/slot",
            properties: {
              container: { id: "hstack1", slot: "content" }
            }
          }
        ]
      },
      {
        id: "usernameValue",
        type: "core/v1/text",
        properties: {
          value: {
            raw: "{{usersTable.selectedItem ? usersTable.selectedItem.username : ''}}",
            format: "plain"
          }
        },
        traits: [
          {
            type: "core/v1/slot",
            properties: {
              container: { id: "hstack1", slot: "content" }
            }
          }
        ]
      },
      {
        id: "divider1",
        type: "chakra_ui/v1/divider",
        properties: {},
        traits: [
          {
            type: "core/v1/slot",
            properties: {
              container: { id: "userInfoContainer", slot: "content" }
            }
          }
        ]
      },
      {
        id: "jobLabel",
        type: "core/v1/text",
        properties: { value: { raw: "**\u804C\u4F4D**", format: "md" } },
        traits: [
          {
            type: "core/v1/slot",
            properties: {
              container: { id: "hstack2", slot: "content" }
            }
          }
        ]
      },
      {
        id: "hstack2",
        type: "chakra_ui/v1/hstack",
        properties: { spacing: "24px", hideBorder: "" },
        traits: [
          {
            type: "core/v1/slot",
            properties: {
              container: { id: "userInfoContainer", slot: "content" }
            }
          },
          {
            type: "core/v1/style",
            properties: {
              styleSlot: "content",
              style: "padding: 0; border: none"
            }
          }
        ]
      },
      {
        id: "areaLabel",
        type: "core/v1/text",
        properties: { value: { raw: "**\u5730\u533A**", format: "md" } },
        traits: [
          {
            type: "core/v1/slot",
            properties: {
              container: { id: "hstack3", slot: "content" }
            }
          }
        ]
      },
      {
        id: "areaValue",
        type: "core/v1/text",
        properties: {
          value: {
            raw: "{{usersTable.selectedItem ? usersTable.selectedItem.area : ''}}",
            format: "plain"
          }
        },
        traits: [
          {
            type: "core/v1/slot",
            properties: {
              container: { id: "hstack3", slot: "content" }
            }
          }
        ]
      },
      {
        id: "divider2",
        type: "chakra_ui/v1/divider",
        properties: {},
        traits: [
          {
            type: "core/v1/slot",
            properties: {
              container: { id: "userInfoContainer", slot: "content" }
            }
          }
        ]
      },
      {
        id: "createdTimeLabel",
        type: "core/v1/text",
        properties: { value: { raw: "**\u521B\u5EFA\u65F6\u95F4**", format: "md" } },
        traits: [
          {
            type: "core/v1/slot",
            properties: {
              container: { id: "hstack4", slot: "content" }
            }
          }
        ]
      },
      {
        id: "createdTimeValue",
        type: "core/v1/text",
        properties: {
          value: {
            raw: "{{usersTable.selectedItem ? dayjs(usersTable.selectedItem.createdTime).format('LL') : ''}}",
            format: "plain"
          }
        },
        traits: [
          {
            type: "core/v1/slot",
            properties: {
              container: { id: "hstack4", slot: "content" }
            }
          },
          {
            type: "core/v1/style",
            properties: { string: { kind: {}, type: {} } }
          }
        ]
      },
      {
        id: "hstack3",
        type: "chakra_ui/v1/hstack",
        properties: { spacing: "24px", hideBorder: "" },
        traits: [
          {
            type: "core/v1/slot",
            properties: {
              container: { id: "userInfoContainer", slot: "content" }
            }
          },
          {
            type: "core/v1/style",
            properties: {
              styleSlot: "content",
              style: "padding: 0; border: none"
            }
          }
        ]
      },
      {
        id: "divider3",
        type: "chakra_ui/v1/divider",
        properties: {},
        traits: [
          {
            type: "core/v1/slot",
            properties: {
              container: { id: "userInfoContainer", slot: "content" }
            }
          }
        ]
      },
      {
        id: "hstack4",
        type: "chakra_ui/v1/hstack",
        properties: { spacing: "24px", hideBorder: "" },
        traits: [
          {
            type: "core/v1/slot",
            properties: {
              container: { id: "userInfoContainer", slot: "content" }
            }
          },
          {
            type: "core/v1/style",
            properties: {
              styleSlot: "content",
              style: "padding: 0; border: none"
            }
          }
        ]
      },
      {
        id: "tabs1",
        type: "chakra_ui/v1/tabs",
        properties: {
          tabNames: ["\u7528\u6237\u4FE1\u606F", "\u89D2\u8272"],
          initialSelectedTabIndex: 0
        },
        traits: [
          {
            type: "core/v1/slot",
            properties: {
              container: { id: "grid_layout1", slot: "content" }
            }
          }
        ]
      },
      {
        id: "tabContentVStack",
        type: "chakra_ui/v1/vstack",
        properties: { spacing: "24px" },
        traits: [
          {
            type: "core/v1/slot",
            properties: { container: { id: "tabs1", slot: "content" } }
          }
        ]
      },
      {
        id: "testtext",
        type: "core/v1/text",
        properties: { value: { raw: "**\u6D4B\u8BD5\u89D2\u8272**", format: "md" } },
        traits: [
          {
            type: "core/v1/slot",
            properties: { container: { id: "tabs1", slot: "content" } }
          }
        ]
      },
      {
        id: "jobValue",
        type: "chakra_ui/v1/vstack",
        properties: { spacing: "1", align: "stretch" },
        traits: [
          {
            type: "core/v1/slot",
            properties: {
              container: { id: "hstack2", slot: "content" }
            }
          },
          {
            type: "core/v1/style",
            properties: {
              styleSlot: "content",
              style: "padding: 0; border: none"
            }
          }
        ]
      },
      {
        id: "link1",
        type: "chakra_ui/v1/link",
        properties: {
          text: {
            raw: "{{usersTable.selectedItem ? usersTable.selectedItem.job : ''}}",
            format: "plain"
          },
          href: "https://www.google.com"
        },
        traits: [
          {
            type: "core/v1/slot",
            properties: {
              container: { id: "jobValue", slot: "content" }
            }
          }
        ]
      },
      {
        id: "link2",
        type: "chakra_ui/v1/link",
        properties: {
          text: {
            raw: "{{usersTable.selectedItem ? usersTable.selectedItem.job : ''}}",
            format: "plain"
          },
          href: "https://www.google.com"
        },
        traits: [
          {
            type: "core/v1/slot",
            properties: {
              container: { id: "jobValue", slot: "content" }
            }
          }
        ]
      }
    ]
  }
};

// src/operations/useAppModel.ts
function getDefaultAppFromLS() {
  try {
    const appFromLS = localStorage.getItem("schema");
    if (appFromLS) {
      return JSON.parse(appFromLS);
    }
    return DefaultAppSchema;
  } catch (error) {
    console.warn(error);
    return DefaultAppSchema;
  }
}
function useAppModel() {
  const [app, setApp] = useState3(getDefaultAppFromLS());
  useEffect(() => {
    const onAppChange = (app2) => {
      setApp(() => app2);
    };
    eventBus.on("appChange", onAppChange);
    return () => {
      eventBus.off("appChange", onAppChange);
    };
  }, []);
  return {
    app
  };
}

// src/components/ComponentForm/style.ts
import { css } from "@emotion/react";
var formWrapperCSS = css`
  width: 100%;
  padding: var(--chakra-space-4);
  background: white;
  border: 1px solid var(--chakra-colors-gray-200);
  border-radius: 4px;
  align-items: start;
`;

// src/components/KeyValueEditor.tsx
import { CloseIcon } from "@chakra-ui/icons";
import { Button, HStack as HStack2, IconButton as IconButton2, Input, VStack as VStack3 } from "@chakra-ui/react";
import produce from "immer";
import { fromPairs, toPairs } from "lodash-es";
import React4, { useState as useState4 } from "react";
var KeyValueEditor = (props) => {
  const [rows, setRows] = useState4(() => {
    return toPairs(props.initValue);
  });
  const emitDataChange = (newRows) => {
    const json = fromPairs(newRows);
    props.onChange(json);
  };
  const onAddRow = () => {
    setRows((prev) => [...prev, ["", ""]]);
  };
  const onRemoveRow = (i) => {
    const newRows = produce(rows, (draft) => {
      draft.splice(i, 1);
    });
    setRows(newRows);
    emitDataChange(newRows);
  };
  const rowItems = rows.map(([key, value], i) => {
    const onInputChange = (e) => {
      const target = e.target;
      const index = target.name === "key" ? 0 : 1;
      const newRows = produce(rows, (draft) => {
        draft[i][index] = target.value;
      });
      setRows(newRows);
    };
    const onBlur = () => emitDataChange(rows);
    return /* @__PURE__ */ React4.createElement(HStack2, {
      key: i,
      spacing: "1"
    }, /* @__PURE__ */ React4.createElement(Input, {
      name: "key",
      value: key,
      placeholder: "key",
      size: "sm",
      onChange: onInputChange,
      onBlur
    }), /* @__PURE__ */ React4.createElement(Input, {
      name: "value",
      value,
      placeholder: "value",
      size: "sm",
      onChange: onInputChange,
      onBlur
    }), /* @__PURE__ */ React4.createElement(IconButton2, {
      "aria-label": "remove row",
      icon: /* @__PURE__ */ React4.createElement(CloseIcon, null),
      size: "xs",
      onClick: () => onRemoveRow(i),
      variant: "ghost"
    }));
  });
  return /* @__PURE__ */ React4.createElement(VStack3, {
    spacing: "1",
    alignItems: "start"
  }, rowItems, /* @__PURE__ */ React4.createElement(Button, {
    onClick: onAddRow,
    size: "xs"
  }, "+ Add"));
};

// src/components/ComponentForm/EventTraitForm/EventHandlerForm.tsx
var EventHandlerForm = (props) => {
  var _a, _b;
  const { handler, eventTypes, onChange, onRemove, hideEventType, registry } = props;
  const { app } = useAppModel();
  const [methods, setMethods] = useState5([]);
  function updateMethods(componentId) {
    var _a2;
    const type = (_a2 = app.spec.components.find((c) => c.id === componentId)) == null ? void 0 : _a2.type;
    if (type) {
      const componentSpec = registry.getComponentByType(type).spec;
      setMethods(componentSpec.methods.map((m) => m.name));
    }
  }
  useEffect2(() => {
    if (handler.componentId) {
      updateMethods(handler.componentId);
    }
  }, [handler]);
  const onTargetComponentChange = (e) => {
    updateMethods(e.target.value);
  };
  const formik = useFormik({
    initialValues: handler,
    onSubmit: (values) => {
      onChange(values);
    }
  });
  const typeField = /* @__PURE__ */ React.createElement(FormControl, null, /* @__PURE__ */ React.createElement(FormLabel, null, "Event Type"), /* @__PURE__ */ React.createElement(Select, {
    placeholder: "Select Event Type",
    onChange: formik.handleChange,
    onBlur: () => formik.submitForm(),
    value: formik.values.type
  }, eventTypes.map((e) => /* @__PURE__ */ React.createElement("option", {
    key: e,
    value: e
  }, e))));
  const targetField = /* @__PURE__ */ React.createElement(FormControl, null, /* @__PURE__ */ React.createElement(FormLabel, null, "Target Component"), /* @__PURE__ */ React.createElement(Select, {
    name: "componentId",
    placeholder: "Select Target Component",
    onChange: (e) => {
      onTargetComponentChange(e);
      formik.handleChange(e);
    },
    onBlur: () => formik.submitForm(),
    value: formik.values.componentId
  }, app.spec.components.map((c) => /* @__PURE__ */ React.createElement("option", {
    key: c.id,
    value: c.id
  }, c.id))));
  const methodField = /* @__PURE__ */ React.createElement(FormControl, null, /* @__PURE__ */ React.createElement(FormLabel, null, "Method"), /* @__PURE__ */ React.createElement(Select, {
    name: "method.name",
    placeholder: "Select Method",
    onChange: formik.handleChange,
    onBlur: () => formik.submitForm(),
    value: formik.values.method.name
  }, methods.map((m) => /* @__PURE__ */ React.createElement("option", {
    key: m,
    value: m
  }, m))));
  const parametersField = /* @__PURE__ */ React.createElement(FormControl, null, /* @__PURE__ */ React.createElement(FormLabel, null, "Parameters"), /* @__PURE__ */ React.createElement(KeyValueEditor, {
    initValue: formik.values.method.parameters,
    onChange: (json) => {
      formik.setFieldValue("method.parameters", json);
      formik.submitForm();
    }
  }));
  const waitTypeField = /* @__PURE__ */ React.createElement(FormControl, null, /* @__PURE__ */ React.createElement(FormLabel, null, "Wait Type"), /* @__PURE__ */ React.createElement(Select, {
    name: "wait.type",
    onChange: formik.handleChange,
    onBlur: () => formik.submitForm(),
    value: (_a = formik.values.wait) == null ? void 0 : _a.type
  }, /* @__PURE__ */ React.createElement("option", {
    value: "delay"
  }, "delay"), /* @__PURE__ */ React.createElement("option", {
    value: "debounce"
  }, "debounce"), /* @__PURE__ */ React.createElement("option", {
    value: "throttle"
  }, "throttle")));
  const waitTimeField = /* @__PURE__ */ React.createElement(FormControl, null, /* @__PURE__ */ React.createElement(FormLabel, null, "Wait Time"), /* @__PURE__ */ React.createElement(Input2, {
    name: "wait.time",
    onChange: formik.handleChange,
    onBlur: () => formik.submitForm(),
    value: (_b = formik.values.wait) == null ? void 0 : _b.time
  }));
  const disabledField = /* @__PURE__ */ React.createElement(FormControl, null, /* @__PURE__ */ React.createElement(FormLabel, null, "Disabled"), /* @__PURE__ */ React.createElement(Switch, {
    name: "disabled",
    isChecked: formik.values.disabled,
    onChange: formik.handleChange,
    onBlur: () => formik.submitForm()
  }));
  return /* @__PURE__ */ React.createElement(Box5, {
    position: "relative"
  }, /* @__PURE__ */ React.createElement(VStack4, {
    css: formWrapperCSS
  }, hideEventType ? null : typeField, targetField, methodField, parametersField, waitTypeField, waitTimeField, disabledField), /* @__PURE__ */ React.createElement(IconButton3, {
    position: "absolute",
    right: "4",
    top: "4",
    "aria-label": "remove event handler",
    variant: "ghost",
    colorScheme: "red",
    size: "xs",
    icon: /* @__PURE__ */ React.createElement(CloseIcon2, null),
    onClick: onRemove
  }));
};

// src/components/ComponentForm/EventTraitForm/EventTraitForm.tsx
var EventTraitForm = (props) => {
  const { component, registry } = props;
  const handlers = useMemo2(() => {
    var _a;
    return (_a = component.traits.find((t) => t.type === "core/v1/event")) == null ? void 0 : _a.properties.handlers;
  }, [component]);
  const eventTypes = useMemo2(() => {
    return registry.getComponentByType(component.type).spec.events;
  }, [component]);
  if (!eventTypes.length)
    return null;
  const onClickAddHandler = () => {
    const newHandler = {
      type: eventTypes[0],
      componentId: "",
      method: {
        name: "",
        parameters: {}
      },
      disabled: false,
      wait: {
        type: "delay",
        time: 0
      }
    };
    if (!handlers) {
      eventBus.send("operation", new AddTraitOperation(component.id, "core/v1/event", { handlers: [newHandler] }));
    } else {
      eventBus.send("operation", new ModifyTraitPropertyOperation(component.id, "core/v1/event", "handlers", [
        ...handlers,
        newHandler
      ]));
    }
  };
  const handlerForms = () => (handlers || []).map((h, i) => {
    const onChange = (handler) => {
      const newHanlders = produce2(handlers, (draft) => {
        draft[i] = handler;
      });
      eventBus.send("operation", new ModifyTraitPropertyOperation(component.id, "core/v1/event", "handlers", newHanlders));
    };
    const onRemove = () => {
      const newHanlders = produce2(handlers, (draft) => {
        draft.splice(i, 1);
      });
      eventBus.send("operation", new ModifyTraitPropertyOperation(component.id, "core/v1/event", "handlers", newHanlders));
    };
    return /* @__PURE__ */ React.createElement(EventHandlerForm, {
      key: i,
      handler: h,
      eventTypes,
      onChange,
      onRemove,
      registry
    });
  });
  return /* @__PURE__ */ React.createElement(VStack5, {
    width: "full"
  }, /* @__PURE__ */ React.createElement(HStack3, {
    width: "full",
    justify: "space-between"
  }, /* @__PURE__ */ React.createElement("strong", null, "Events"), /* @__PURE__ */ React.createElement(IconButton4, {
    "aria-label": "add event",
    size: "sm",
    variant: "ghost",
    colorScheme: "blue",
    icon: /* @__PURE__ */ React.createElement(AddIcon, null),
    onClick: onClickAddHandler
  })), /* @__PURE__ */ React.createElement(VStack5, {
    width: "full"
  }, handlerForms()));
};

// src/components/ComponentForm/GeneralTraitFormList/GeneralTraitFormList.tsx
import { parseTypeBox as parseTypeBox2 } from "@meta-ui/runtime";
import { HStack as HStack5, VStack as VStack7 } from "@chakra-ui/react";

// src/components/ComponentForm/GeneralTraitFormList/AddTraitButton.tsx
import { AddIcon as AddIcon2, ChevronDownIcon as ChevronDownIcon2 } from "@chakra-ui/icons";
import { IconButton as IconButton5, Menu, MenuButton, MenuItem, MenuList } from "@chakra-ui/react";
import { useMemo as useMemo3 } from "react";
var AddTraitButton = (props) => {
  const { onAddTrait, registry } = props;
  const traitTypes = useMemo3(() => {
    return registry.getAllTraitTypes();
  }, []);
  const menuItems = traitTypes.map((type) => {
    return /* @__PURE__ */ React.createElement(MenuItem, {
      key: type,
      onClick: () => onAddTrait(type)
    }, type);
  });
  return /* @__PURE__ */ React.createElement(Menu, null, /* @__PURE__ */ React.createElement(MenuButton, {
    as: IconButton5,
    "aria-label": "add event",
    size: "sm",
    variant: "ghost",
    colorScheme: "blue",
    icon: /* @__PURE__ */ React.createElement(AddIcon2, null),
    rightIcon: /* @__PURE__ */ React.createElement(ChevronDownIcon2, null)
  }), /* @__PURE__ */ React.createElement(MenuList, null, menuItems));
};

// src/components/ComponentForm/GeneralTraitFormList/GeneralTraitForm.tsx
import { HStack as HStack4, IconButton as IconButton6, VStack as VStack6 } from "@chakra-ui/react";
import { parseTypeBox } from "@meta-ui/runtime";
import { CloseIcon as CloseIcon3 } from "@chakra-ui/icons";
var GeneralTraitForm = (props) => {
  const { trait, component, onRemove, registry } = props;
  const tImpl = registry.getTraitByType(trait.type);
  const properties = Object.assign(parseTypeBox(tImpl.spec.properties), trait.properties);
  const fields = Object.keys(properties || []).map((key) => {
    const value = trait.properties[key];
    return renderField({
      key,
      value,
      fullKey: key,
      type: trait.type,
      selectedId: component.id
    });
  });
  return /* @__PURE__ */ React.createElement(VStack6, {
    key: trait.type,
    css: formWrapperCSS
  }, /* @__PURE__ */ React.createElement(HStack4, {
    width: "full",
    justifyContent: "space-between"
  }, /* @__PURE__ */ React.createElement("strong", null, trait.type), /* @__PURE__ */ React.createElement(IconButton6, {
    "aria-label": "remove trait",
    variant: "ghost",
    colorScheme: "red",
    size: "xs",
    icon: /* @__PURE__ */ React.createElement(CloseIcon3, null),
    onClick: onRemove
  })), fields);
};

// src/components/ComponentForm/GeneralTraitFormList/GeneralTraitFormList.tsx
var GeneralTraitFormList = (props) => {
  const { component, registry } = props;
  const onAddTrait = (type) => {
    const traitSpec = registry.getTraitByType(type).spec;
    const initProperties = parseTypeBox2(traitSpec.properties);
    eventBus.send("operation", new AddTraitOperation(component.id, type, initProperties));
  };
  const traitFields = component.traits.filter((t) => {
    return !ignoreTraitsList.includes(t.type);
  }).map((t, i) => {
    const onRemoveTrait = () => {
      eventBus.send("operation", new RemoveTraitOperation(component.id, i));
    };
    return /* @__PURE__ */ React.createElement(GeneralTraitForm, {
      key: i,
      component,
      trait: t,
      onRemove: onRemoveTrait,
      registry
    });
  });
  return /* @__PURE__ */ React.createElement(VStack7, {
    width: "full",
    alignItems: "start"
  }, /* @__PURE__ */ React.createElement(HStack5, {
    width: "full",
    justify: "space-between"
  }, /* @__PURE__ */ React.createElement("strong", null, "Traits"), /* @__PURE__ */ React.createElement(AddTraitButton, {
    onAddTrait,
    registry
  })), traitFields);
};

// src/components/ComponentForm/FetchTraitForm/FetchTraitForm.tsx
import {
  Box as Box6,
  FormControl as FormControl2,
  FormLabel as FormLabel2,
  HStack as HStack6,
  IconButton as IconButton7,
  Input as Input3,
  Select as Select2,
  VStack as VStack8
} from "@chakra-ui/react";
import { AddIcon as AddIcon3, CloseIcon as CloseIcon4 } from "@chakra-ui/icons";
import { useFormik as useFormik2 } from "formik";
import produce3 from "immer";
var httpMethods = ["get", "post", "put", "delete", "patch"];
var FetchTraitForm = (props) => {
  var _a;
  const { component, registry } = props;
  const fetchTrait = (_a = component.traits.find((t) => t.type === "core/v1/fetch")) == null ? void 0 : _a.properties;
  if (!fetchTrait) {
    return null;
  }
  const formik = useFormik2({
    initialValues: fetchTrait,
    onSubmit: (values) => {
      eventBus.send("operation", new ModifyTraitPropertiesOperation(component.id, "core/v1/fetch", values));
    }
  });
  const urlField = /* @__PURE__ */ React.createElement(FormControl2, null, /* @__PURE__ */ React.createElement(FormLabel2, null, "URL"), /* @__PURE__ */ React.createElement(Input3, {
    name: "url",
    onChange: formik.handleChange,
    onBlur: () => formik.submitForm(),
    value: formik.values.url
  }));
  const methodField = /* @__PURE__ */ React.createElement(FormControl2, null, /* @__PURE__ */ React.createElement(FormLabel2, null, "Method"), /* @__PURE__ */ React.createElement(Select2, {
    name: "method",
    placeholder: "Select Method",
    onChange: formik.handleChange,
    onBlur: () => formik.submitForm(),
    value: formik.values.method
  }, httpMethods.map((v) => /* @__PURE__ */ React.createElement("option", {
    key: v,
    value: v
  }, v))));
  const bodyField = /* @__PURE__ */ React.createElement(FormControl2, null, /* @__PURE__ */ React.createElement(FormLabel2, null, "Body"), /* @__PURE__ */ React.createElement(KeyValueEditor, {
    initValue: formik.values.body,
    onChange: (json) => {
      formik.setFieldValue("body", json);
      formik.submitForm();
    }
  }));
  const headersField = /* @__PURE__ */ React.createElement(FormControl2, null, /* @__PURE__ */ React.createElement(FormLabel2, null, "Headers"), /* @__PURE__ */ React.createElement(KeyValueEditor, {
    initValue: formik.values.headers,
    onChange: (json) => {
      formik.setFieldValue("headers", json);
      formik.submitForm();
    }
  }));
  const onAddHandler = () => {
    const newHandler = {
      type: "",
      componentId: "",
      method: {
        name: "",
        parameters: {}
      },
      disabled: false,
      wait: {
        type: "delay",
        time: 0
      }
    };
    formik.setFieldValue("onComplete", [...formik.values.onComplete, newHandler]);
  };
  const onCompleteField = /* @__PURE__ */ React.createElement(FormControl2, null, /* @__PURE__ */ React.createElement(HStack6, {
    width: "full",
    justify: "space-between"
  }, /* @__PURE__ */ React.createElement(FormLabel2, null, "onComplete"), /* @__PURE__ */ React.createElement(IconButton7, {
    "aria-label": "add event",
    size: "sm",
    variant: "ghost",
    colorScheme: "blue",
    icon: /* @__PURE__ */ React.createElement(AddIcon3, null),
    onClick: onAddHandler
  })), formik.values.onComplete.map((handler, i) => {
    const onChange = (handler2) => {
      const newOnComplete = produce3(formik.values.onComplete, (draft) => {
        draft[i] = handler2;
      });
      formik.setFieldValue("onComplete", newOnComplete);
      formik.submitForm();
    };
    const onRemove = () => {
      const newOnComplete = produce3(formik.values.onComplete, (draft) => {
        draft.splice(i, 1);
      });
      formik.setFieldValue("onComplete", newOnComplete);
      formik.submitForm();
    };
    return /* @__PURE__ */ React.createElement(EventHandlerForm, {
      key: i,
      eventTypes: [],
      handler,
      hideEventType: true,
      onChange,
      onRemove,
      registry
    });
  }));
  return /* @__PURE__ */ React.createElement(Box6, {
    width: "full",
    position: "relative"
  }, /* @__PURE__ */ React.createElement("strong", null, "Fetch"), /* @__PURE__ */ React.createElement(HStack6, {
    width: "full",
    justify: "space-between"
  }, /* @__PURE__ */ React.createElement(VStack8, {
    css: formWrapperCSS
  }, urlField, methodField, bodyField, headersField, onCompleteField)), /* @__PURE__ */ React.createElement(IconButton7, {
    position: "absolute",
    right: "0",
    top: "0",
    "aria-label": "remove event handler",
    variant: "ghost",
    colorScheme: "red",
    size: "xs",
    icon: /* @__PURE__ */ React.createElement(CloseIcon4, null),
    onClick: () => {
      const i = component.traits.findIndex((t) => t.type === "core/v1/fetch");
      eventBus.send("operation", new RemoveTraitOperation(component.id, i));
    }
  }));
};

// src/components/ComponentForm/ComponentForm.tsx
var renderField = (properties) => {
  const { value, type, fullKey, selectedId } = properties;
  if (typeof value !== "object") {
    const ref = React5.createRef();
    const onBlur = () => {
      var _a, _b;
      const operation = type ? new ModifyTraitPropertyOperation(selectedId, type, fullKey, (_a = ref.current) == null ? void 0 : _a.value) : new ModifyComponentPropertyOperation(selectedId, fullKey, (_b = ref.current) == null ? void 0 : _b.value);
      eventBus.send("operation", operation);
    };
    return /* @__PURE__ */ React5.createElement(FormControl3, {
      key: `${selectedId}-${fullKey}`
    }, /* @__PURE__ */ React5.createElement(FormLabel3, null, fullKey), /* @__PURE__ */ React5.createElement(Textarea, {
      ref,
      onBlur,
      defaultValue: value
    }));
  } else {
    const fieldArray = flatten(Object.keys(value || []).map((childKey) => {
      const childValue = value[childKey];
      return renderField({
        key: childKey,
        value: childValue,
        type,
        fullKey: `${fullKey}.${childKey}`,
        selectedId
      });
    }));
    return fieldArray;
  }
};
var ComponentForm = (props) => {
  const { selectedId, app, registry } = props;
  const selectedComponent = app.spec.components.find((c) => c.id === selectedId);
  if (!selectedComponent) {
    return /* @__PURE__ */ React5.createElement("div", null, "cannot find component with id: ", selectedId);
  }
  const { version, name } = parseType(selectedComponent.type);
  const cImpl = registry.getComponent(version, name);
  const properties = Object.assign(parseTypeBox3(cImpl.spec.properties), selectedComponent.properties);
  const propertyFields = Object.keys(properties || []).map((key) => {
    const value = properties[key];
    return renderField({ key, value, fullKey: key, selectedId });
  });
  const changeComponentId = (selectedId2, value) => {
    eventBus.send("operation", new ModifyComponentIdOperation(selectedId2, value));
  };
  const propertyForm = /* @__PURE__ */ React5.createElement(VStack9, {
    width: "full",
    alignItems: "start"
  }, /* @__PURE__ */ React5.createElement("strong", null, "Properties"), /* @__PURE__ */ React5.createElement(VStack9, {
    width: "full",
    padding: "4",
    background: "white",
    border: "1px solid",
    borderColor: "gray.200",
    borderRadius: "4"
  }, propertyFields));
  return /* @__PURE__ */ React5.createElement(VStack9, {
    p: 4,
    spacing: "4",
    background: "gray.50"
  }, /* @__PURE__ */ React5.createElement(FormControl3, null, /* @__PURE__ */ React5.createElement(FormLabel3, null, /* @__PURE__ */ React5.createElement("strong", null, "Component ID")), /* @__PURE__ */ React5.createElement(Input4, {
    key: selectedComponent == null ? void 0 : selectedComponent.id,
    defaultValue: selectedComponent == null ? void 0 : selectedComponent.id,
    background: "white",
    onBlur: (e) => changeComponentId(selectedComponent == null ? void 0 : selectedComponent.id, e.target.value)
  })), propertyFields.length > 0 ? propertyForm : null, /* @__PURE__ */ React5.createElement(EventTraitForm, {
    component: selectedComponent,
    registry
  }), /* @__PURE__ */ React5.createElement(FetchTraitForm, {
    component: selectedComponent,
    registry
  }), /* @__PURE__ */ React5.createElement(GeneralTraitFormList, {
    component: selectedComponent,
    registry
  }));
};

// src/components/ComponentsList/ComponentList.tsx
import React6 from "react";
import {
  Tabs,
  TabList,
  Tab,
  TabPanels,
  TabPanel,
  SimpleGrid,
  Flex,
  Box as Box7
} from "@chakra-ui/react";
import { encodeDragDataTransfer, DROP_EXAMPLE_SIZE_PREFIX } from "@meta-ui/runtime";
var ComponentList = ({ registry }) => {
  return /* @__PURE__ */ React6.createElement(Tabs, null, /* @__PURE__ */ React6.createElement(TabList, null, Array.from(registry.components.keys()).map((version) => /* @__PURE__ */ React6.createElement(Tab, {
    key: version
  }, version))), /* @__PURE__ */ React6.createElement(TabPanels, null, Array.from(registry.components.keys()).map((version) => /* @__PURE__ */ React6.createElement(TabPanel, {
    key: version,
    overflow: "auto"
  }, /* @__PURE__ */ React6.createElement(SimpleGrid, {
    columns: 4,
    spacing: 1
  }, Array.from(registry.components.get(version).values()).map((c) => {
    const onDragStart = (e) => {
      e.dataTransfer.setData("component", `${c.version}/${c.metadata.name}`);
      e.dataTransfer.setData(encodeDragDataTransfer(`${DROP_EXAMPLE_SIZE_PREFIX}${JSON.stringify(c.metadata.exampleSize)}`), "");
    };
    const cEle = /* @__PURE__ */ React6.createElement(Flex, {
      key: c.metadata.name,
      flexDirection: "column",
      align: "center",
      justify: "start"
    }, /* @__PURE__ */ React6.createElement(Flex, {
      className: "droppable-element",
      background: "gray.100",
      width: "60px",
      height: "60px",
      borderRadius: "md",
      align: "center",
      justify: "center",
      transition: "ease 0.2s",
      _hover: {
        transform: "scale(1.05)",
        background: "gray.200"
      },
      p: 2,
      draggable: true,
      unselectable: "on",
      onDragStart
    }, /* @__PURE__ */ React6.createElement("svg", {
      viewBox: "0 0 1024 1024",
      version: "1.1",
      xmlns: "http://www.w3.org/2000/svg",
      "p-id": "2693",
      width: "30",
      height: "30"
    }, /* @__PURE__ */ React6.createElement("path", {
      d: "M972.09863 1016.986301H259.506849c-19.638356 0-35.068493-15.430137-35.068493-35.068493V768.70137c-8.416438 5.610959-18.235616 9.819178-28.054794 12.624657h-1.40274c-12.624658 4.208219-26.652055 5.610959-39.276712 5.610959-77.150685 0-138.871233-63.123288-138.871233-138.871233 0-77.150685 63.123288-138.871233 138.871233-138.871232 14.027397 0 28.054795 2.805479 42.082191 7.013698 1.40274 0 2.805479 1.40274 4.20822 1.40274 7.013699 2.805479 14.027397 5.610959 19.638356 8.416438l2.805479 1.40274V269.326027c0-19.638356 15.430137-35.068493 35.068493-35.068493h228.646576l-4.20822-8.416438c-7.013699-11.221918-12.624658-22.443836-15.430137-35.068493v-1.40274c-4.208219-12.624658-5.610959-26.652055-5.610958-39.276712C462.90411 72.942466 526.027397 11.221918 601.775342 11.221918c77.150685 0 138.871233 63.123288 138.871233 138.871233 0 14.027397-2.805479 28.054795-7.013698 42.082191 0 1.40274-1.40274 2.805479-1.40274 4.20822-2.805479 7.013699-5.610959 14.027397-8.416438 19.638356l-7.013699 16.832877h255.29863c19.638356 0 35.068493 15.430137 35.068493 35.068493v314.213698c0 11.221918-5.610959 22.443836-15.430137 29.457535-9.819178 7.013699-22.443836 7.013699-33.665753 2.805479L897.753425 587.747945c-1.40274 0-1.40274-1.40274-2.80548-1.40274-2.805479-1.40274-7.013699-4.208219-11.221918-5.610958h-1.402739c-7.013699-2.805479-14.027397-2.805479-21.041096-2.80548-37.873973 0-68.734247 30.860274-68.734247 68.734247s30.860274 68.734247 68.734247 68.734246c7.013699 0 14.027397-1.40274 19.638356-2.805479 7.013699-1.40274 12.624658-5.610959 18.235616-8.416439 1.40274-1.40274 2.805479-1.40274 4.20822-2.805479l53.304109-25.249315c11.221918-5.610959 23.846575-4.208219 33.665754 1.40274s16.832877 18.235616 16.832876 29.457534V981.917808c0 19.638356-15.430137 35.068493-35.068493 35.068493z m-677.523288-70.136986h642.454795v-182.356164h-1.40274c-11.221918 7.013699-22.443836 12.624658-35.068493 16.832876h-1.40274c-12.624658 4.208219-26.652055 5.610959-39.276712 5.610959-77.150685 0-138.871233-63.123288-138.871233-138.871233 0-77.150685 63.123288-138.871233 138.871233-138.871232 14.027397 0 28.054795 2.805479 42.082192 7.013698 1.40274 0 2.805479 1.40274 4.208219 1.40274 7.013699 2.805479 14.027397 5.610959 19.638356 8.416438l9.819178 4.208219v-224.438356H662.093151c-11.221918 0-22.443836-5.610959-29.457535-15.430137-7.013699-9.819178-7.013699-22.443836-2.805479-33.665753l29.457534-67.331507c0-1.40274 1.40274-1.40274 1.40274-2.805479 1.40274-2.805479 4.208219-7.013699 5.610959-11.221918v-1.40274c2.805479-7.013699 2.805479-14.027397 2.805479-21.041096 0-37.873973-30.860274-68.734247-68.734246-68.734246s-68.734247 30.860274-68.734247 68.734246c0 7.013699 1.40274 14.027397 2.80548 19.638356 1.40274 7.013699 5.610959 12.624658 8.416438 18.235617 1.40274 1.40274 1.40274 2.805479 2.805479 4.208219l28.054795 60.317808c5.610959 11.221918 4.208219 23.846575-1.40274 33.665754s-18.235616 16.832877-29.457534 16.832876H294.575342v274.936987c0 11.221918-5.610959 22.443836-15.430137 29.457534-9.819178 7.013699-22.443836 7.013699-33.665753 2.805479L192.175342 589.150685c-1.40274 0-1.40274-1.40274-2.805479-1.40274-2.805479-1.40274-7.013699-4.208219-11.221918-5.610959h-1.40274c-7.013699-2.805479-14.027397-2.805479-21.041095-2.805479-37.873973 0-68.734247 30.860274-68.734247 68.734246s30.860274 68.734247 68.734247 68.734247c7.013699 0 14.027397-1.40274 19.638356-2.805479 7.013699-1.40274 12.624658-5.610959 18.235616-8.416439 1.40274-1.40274 2.805479-1.40274 4.208219-2.805479l46.290411-22.443836c11.221918-5.610959 23.846575-4.208219 33.665754 1.40274 9.819178 7.013699 16.832877 18.235616 16.832876 29.457534v235.660274z",
      "p-id": "2694"
    }))), /* @__PURE__ */ React6.createElement(Box7, {
      p: 2,
      whiteSpace: "pre-wrap",
      textAlign: "center",
      fontSize: "x-small"
    }, c.metadata.displayName));
    return cEle;
  }))))));
};

// src/components/EditorHeader/EditorHeader.tsx
import React7 from "react";
import { Flex as Flex2, Button as Button2, Box as Box8 } from "@chakra-ui/react";
var EditorHeader = ({ scale, setScale, onPreview }) => {
  return /* @__PURE__ */ React7.createElement(Flex2, {
    p: 2,
    borderBottomWidth: "2px",
    borderColor: "gray.200",
    align: "center"
  }, /* @__PURE__ */ React7.createElement(Flex2, {
    flex: "1"
  }), /* @__PURE__ */ React7.createElement(Flex2, {
    flex: "1",
    align: "center",
    justify: "center"
  }, /* @__PURE__ */ React7.createElement(Button2, {
    size: "sm",
    disabled: scale <= 50,
    onClick: () => setScale(scale - 10)
  }, "-"), /* @__PURE__ */ React7.createElement(Box8, {
    fontSize: "sm",
    mx: "2",
    width: 10,
    textAlign: "center"
  }, scale, "%"), /* @__PURE__ */ React7.createElement(Button2, {
    size: "sm",
    disabled: scale >= 100,
    onClick: () => setScale(scale + 10)
  }, "+")), /* @__PURE__ */ React7.createElement(Flex2, {
    flex: "1",
    justify: "end"
  }, /* @__PURE__ */ React7.createElement(Button2, {
    colorScheme: "blue",
    onClick: onPreview
  }, "preview")));
};

// src/components/PreviewModal/PreviewModal.tsx
import React8 from "react";
import {
  Modal,
  ModalOverlay,
  ModalHeader,
  ModalContent,
  ModalCloseButton,
  ModalBody
} from "@chakra-ui/react";
var PreviewModal = ({
  onClose,
  children
}) => {
  return /* @__PURE__ */ React8.createElement(Modal, {
    onClose,
    size: "full",
    isOpen: true
  }, /* @__PURE__ */ React8.createElement(ModalOverlay, null), /* @__PURE__ */ React8.createElement(ModalContent, null, /* @__PURE__ */ React8.createElement(ModalHeader, null, "Preview App"), /* @__PURE__ */ React8.createElement(ModalCloseButton, null), /* @__PURE__ */ React8.createElement(ModalBody, null, children)));
};

// src/components/KeyboardEventWrapper.tsx
import { css as css2 } from "@emotion/react";
import React9 from "react";
var KeyboardEventWrapper = (props) => {
  const style = css2`
    &:focus {
      outline: none;
    }

    width: 100%;
    height: 100%;
  `;
  const onKeyDown = (e) => {
    if (e.target instanceof Element && e.target.id !== "keyboard-event-wrapper")
      return false;
    switch (e.key) {
      case "Delete":
      case "Backspace":
        eventBus.send("operation", new RemoveComponentOperation(props.selectedComponentId));
        break;
      case "z":
        if (e.metaKey) {
          eventBus.send("undo");
        }
    }
  };
  return /* @__PURE__ */ React9.createElement("div", {
    id: "keyboard-event-wrapper",
    css: style,
    onKeyDown,
    tabIndex: -1
  }, props.children);
};

// src/components/ComponentWrapper.tsx
import React10, { useEffect as useEffect3, useState as useState6 } from "react";
import { css as css3 } from "@emotion/react";
var fullHeightList = ["core/v1/grid_layout"];
var inlineList = ["chakra_ui/v1/checkbox", "chakra_ui/v1/radio"];
var ComponentWrapper = (props) => {
  const { component, parentType } = props;
  const [selectedComponentId, setSelectedComponentId] = useState6("");
  const [hoverComponentId, setHoverComponentId] = useState6("");
  useEffect3(() => {
    const handler = (event, payload) => {
      switch (event) {
        case SelectComponentEvent:
          setSelectedComponentId(payload);
          break;
        case HoverComponentEvent:
          setHoverComponentId(payload);
          break;
      }
    };
    eventBus.on("*", handler);
    return () => eventBus.off("*", handler);
  }, [setSelectedComponentId, setHoverComponentId]);
  const isHover = hoverComponentId === component.id;
  const isSelected = selectedComponentId === component.id;
  let borderColor = "transparent";
  if (isSelected) {
    borderColor = "red";
  } else if (isHover) {
    borderColor = "black";
  }
  const style = css3`
    display: ${inlineList.includes(component.type) ? "inline-block" : "block"};
    height: ${fullHeightList.includes(parentType) ? "100%" : "auto"};
    position: relative;
    &:after {
      content: '';
      position: absolute;
      top: -4px;
      bottom: -4px;
      left: -4px;
      right: -4px;
      border: 1px solid ${borderColor};
      pointer-events: none;
    }
  `;
  const onClickWrapper = (e) => {
    e.stopPropagation();
    eventBus.send(SelectComponentEvent, component.id);
  };
  const onMouseEnterWrapper = (e) => {
    e.stopPropagation();
    eventBus.send(HoverComponentEvent, component.id);
  };
  const onMouseLeaveWrapper = (e) => {
    e.stopPropagation();
    eventBus.send(HoverComponentEvent, "");
  };
  return /* @__PURE__ */ React10.createElement("div", {
    onClick: onClickWrapper,
    onMouseEnter: onMouseEnterWrapper,
    onMouseLeave: onMouseLeaveWrapper,
    css: style
  }, props.children);
};

// src/components/CodeEditor/StateEditor.tsx
import React11, { useEffect as useEffect4, useRef } from "react";
import CodeMirror from "codemirror";
import { Box as Box9 } from "@chakra-ui/react";
import { css as css4 } from "@emotion/react";
import "codemirror/mode/javascript/javascript";
import "codemirror/addon/fold/brace-fold";
import "codemirror/addon/fold/foldgutter";
import "codemirror/addon/fold/foldgutter.css";
import "codemirror/lib/codemirror.css";
import "codemirror/theme/duotone-dark.css";
var StateEditor = ({ code }) => {
  const style = css4`
    .CodeMirror {
      height: 100%;
    }
  `;
  const wrapperEl = useRef(null);
  const cm = useRef(null);
  useEffect4(() => {
    if (!wrapperEl.current) {
      return;
    }
    if (!cm.current) {
      cm.current = CodeMirror(wrapperEl.current, {
        value: code,
        mode: {
          name: "javascript",
          json: true
        },
        readOnly: true,
        foldGutter: true,
        lineWrapping: true,
        lineNumbers: true,
        gutters: ["CodeMirror-linenumbers", "CodeMirror-foldgutter"],
        foldOptions: {
          widget: () => {
            return "...";
          }
        }
      });
    } else {
      cm.current.setValue(code);
    }
  }, [code]);
  return /* @__PURE__ */ React11.createElement(Box9, {
    css: style,
    ref: wrapperEl,
    height: "100%"
  });
};

// src/components/Editor.tsx
var Editor = ({
  App,
  registry,
  stateStore,
  appModelManager
}) => {
  var _a;
  const { app } = useAppModel();
  const [selectedComponentId, setSelectedComponentId] = useState7(((_a = app.spec.components[0]) == null ? void 0 : _a.id) || "");
  const [scale, setScale] = useState7(100);
  const [preview, setPreview] = useState7(false);
  useEffect5(() => {
    eventBus.on(SelectComponentEvent, (id) => {
      setSelectedComponentId(id);
    });
  }, [setSelectedComponentId]);
  const gridCallbacks = useMemo4(() => {
    return {
      onDragStop(id, layout) {
        eventBus.send("operation", new ModifyComponentPropertyOperation(id, "layout", layout));
      },
      onDrop(id, layout, _, e) {
        var _a2;
        const component = ((_a2 = e.dataTransfer) == null ? void 0 : _a2.getData("component")) || "";
        const componentId = appModelManager.genId(component);
        eventBus.send("operation", new CreateComponentOperation(component, id, "content"));
        const newLayout = produce4(layout, (draft) => {
          draft.forEach((l) => {
            if (l.i === "__dropping-elem__") {
              l.i = componentId;
            }
          });
        }).filter((v) => !!v);
        eventBus.send("operation", new ModifyComponentPropertyOperation(id, "layout", newLayout));
      }
    };
  }, []);
  const appComponent = useMemo4(() => {
    return /* @__PURE__ */ React.createElement(App, {
      options: app,
      debugEvent: false,
      debugStore: false,
      gridCallbacks,
      componentWrapper: ComponentWrapper
    });
  }, [app, gridCallbacks]);
  return /* @__PURE__ */ React.createElement(KeyboardEventWrapper, {
    selectedComponentId
  }, /* @__PURE__ */ React.createElement(Box10, {
    display: "flex",
    height: "100%",
    width: "100%",
    flexDirection: "column"
  }, /* @__PURE__ */ React.createElement(EditorHeader, {
    scale,
    setScale,
    onPreview: () => setPreview(true)
  }), /* @__PURE__ */ React.createElement(Box10, {
    display: "flex",
    flex: "1",
    overflow: "auto"
  }, /* @__PURE__ */ React.createElement(Box10, {
    width: "280px",
    borderRightWidth: "1px",
    borderColor: "gray.200"
  }, /* @__PURE__ */ React.createElement(Tabs2, {
    align: "center",
    height: "100%",
    display: "flex",
    flexDirection: "column",
    textAlign: "left",
    isLazy: true
  }, /* @__PURE__ */ React.createElement(TabList2, {
    background: "gray.50"
  }, /* @__PURE__ */ React.createElement(Tab2, null, "UI Tree"), /* @__PURE__ */ React.createElement(Tab2, null, "State")), /* @__PURE__ */ React.createElement(TabPanels2, {
    flex: "1",
    overflow: "auto"
  }, /* @__PURE__ */ React.createElement(TabPanel2, {
    p: 0
  }, /* @__PURE__ */ React.createElement(StructureTree, {
    app,
    selectedComponentId,
    onSelectComponent: (id) => setSelectedComponentId(id),
    registry
  })), /* @__PURE__ */ React.createElement(TabPanel2, {
    p: 0,
    height: "100%"
  }, /* @__PURE__ */ React.createElement(StateEditor, {
    code: JSON.stringify(stateStore, null, 2)
  }))))), /* @__PURE__ */ React.createElement(Box10, {
    flex: "1",
    background: "gray.50",
    p: 4
  }, /* @__PURE__ */ React.createElement(Box10, {
    width: "100%",
    height: "100%",
    background: "white",
    transform: `scale(${scale / 100})`
  }, /* @__PURE__ */ React.createElement(Box10, {
    id: DIALOG_CONTAINER_ID,
    width: "full",
    height: "full",
    position: "absolute"
  }), appComponent)), /* @__PURE__ */ React.createElement(Box10, {
    width: "320px",
    borderLeftWidth: "1px",
    borderColor: "gray.200",
    overflow: "auto"
  }, /* @__PURE__ */ React.createElement(Tabs2, {
    align: "center",
    textAlign: "left",
    height: "100%",
    display: "flex",
    flexDirection: "column"
  }, /* @__PURE__ */ React.createElement(TabList2, {
    background: "gray.50"
  }, /* @__PURE__ */ React.createElement(Tab2, null, "Inspect"), /* @__PURE__ */ React.createElement(Tab2, null, "Insert")), /* @__PURE__ */ React.createElement(TabPanels2, {
    flex: "1",
    overflow: "auto"
  }, /* @__PURE__ */ React.createElement(TabPanel2, {
    p: 0
  }, /* @__PURE__ */ React.createElement(ComponentForm, {
    app,
    selectedId: selectedComponentId,
    registry
  })), /* @__PURE__ */ React.createElement(TabPanel2, {
    p: 0
  }, /* @__PURE__ */ React.createElement(ComponentList, {
    registry
  }))))))), preview && /* @__PURE__ */ React.createElement(PreviewModal, {
    onClose: () => setPreview(false)
  }, /* @__PURE__ */ React.createElement(Box10, {
    width: "100%",
    height: "100%"
  }, /* @__PURE__ */ React.createElement(App, {
    options: JSON.parse(JSON.stringify(app)),
    debugEvent: false,
    debugStore: false
  }))));
};

// src/operations/AppModelManager.ts
import { parseType as parseType2 } from "@meta-ui/runtime";
import { produce as produce5 } from "immer";
import { set, isEqual } from "lodash-es";
function genSlotTrait(parentId, slot) {
  return {
    type: "core/v1/slot",
    properties: {
      container: {
        id: parentId,
        slot
      }
    }
  };
}
function genComponent(registry, type, id, parentId, slot) {
  const { version, name } = parseType2(type);
  const cImpl = registry.getComponent(version, name);
  const traits = parentId && slot ? [genSlotTrait(parentId, slot)] : [];
  const initProperties = cImpl.metadata.exampleProperties;
  return {
    id,
    type,
    properties: initProperties,
    traits
  };
}
var AppModelManager = class {
  constructor(app, registry) {
    this.undoStack = [];
    const appFromLS = localStorage.getItem("schema");
    if (appFromLS) {
      this.app = JSON.parse(appFromLS);
    } else {
      this.app = app;
    }
    this.registry = registry;
    eventBus.on("undo", () => this.undo());
    eventBus.on("operation", (o) => this.apply(o));
    this.updateApp(this.app);
  }
  getApp() {
    return this.app;
  }
  genId(componentType) {
    const { name } = parseType2(componentType);
    const componentsCount = this.app.spec.components.filter((c) => c.type === componentType).length;
    return `${name}${componentsCount + 1}`;
  }
  updateApp(app) {
    eventBus.send("appChange", app);
    localStorage.setItem("schema", JSON.stringify(app));
    this.app = app;
  }
  undo() {
    if (this.undoStack.length === 0) {
      return this.app;
    }
    const o = this.undoStack.pop();
    this.apply(o, true);
  }
  apply(o, noEffect = false) {
    var _a;
    let newApp = this.app;
    switch (o.kind) {
      case "createComponent":
        const createO = o;
        const newComponent = genComponent(this.registry, createO.componentType, createO.componentId || this.genId(createO.componentType), createO.parentId, createO.slot);
        if (!noEffect) {
          const undoOperation = new RemoveComponentOperation(newComponent.id);
          this.undoStack.push(undoOperation);
        }
        newApp = produce5(this.app, (draft) => {
          draft.spec.components.push(newComponent);
        });
        break;
      case "removeComponent":
        const removeO = o;
        newApp = produce5(this.app, (draft) => {
          const i2 = draft.spec.components.findIndex((c) => c.id === removeO.componentId);
          draft.spec.components.splice(i2, 1);
        });
        break;
      case "modifyComponentProperty":
        const mo = o;
        newApp = produce5(this.app, (draft) => {
          return draft.spec.components.forEach((c) => {
            if (c.id === mo.componentId) {
              set(c.properties, mo.propertyKey, mo.propertyValue);
            }
          });
        });
        if (!noEffect) {
          const oldValue2 = (_a = this.app.spec.components.find((c) => c.id === mo.componentId)) == null ? void 0 : _a.properties[mo.propertyKey];
          const undoOperation = new ModifyComponentPropertyOperation(mo.componentId, mo.propertyKey, oldValue2);
          this.undoStack.push(undoOperation);
        }
        break;
      case "modifyComponentId":
        const mIdo = o;
        newApp = produce5(this.app, (draft) => {
          return draft.spec.components.forEach((c) => {
            if (c.id === mIdo.componentId) {
              c.id = mIdo.value;
            }
          });
        });
        if (!noEffect) {
          const undoOperation = new ModifyComponentIdOperation(mIdo.value, mIdo.componentId);
          this.undoStack.push(undoOperation);
        }
        break;
      case "modifyTraitProperty":
        const mto = o;
        let oldValue;
        newApp = produce5(this.app, (draft) => {
          draft.spec.components.forEach((c) => {
            if (c.id === mto.componentId) {
              c.traits.forEach((t) => {
                if (t.type === mto.traitType) {
                  oldValue = t.properties[mto.propertyKey];
                  set(t.properties, mto.propertyKey, mto.propertyValue);
                }
              });
            }
          });
        });
        if (!noEffect) {
          const undoOperation = new ModifyTraitPropertyOperation(mto.componentId, mto.traitType, mto.propertyKey, oldValue);
          this.undoStack.push(undoOperation);
        }
        break;
      case "modifyTraitProperties":
        const mtpo = o;
        let oldProperties;
        newApp = produce5(this.app, (draft) => {
          draft.spec.components.forEach((c) => {
            if (c.id === mtpo.componentId) {
              c.traits.forEach((t) => {
                if (t.type === mtpo.traitType) {
                  oldProperties = t.properties;
                  t.properties = mtpo.properties;
                }
              });
            }
          });
        });
        if (!noEffect) {
          const undoOperation = new ModifyTraitPropertiesOperation(mtpo.componentId, mtpo.traitType, oldProperties || {});
          this.undoStack.push(undoOperation);
        }
        break;
      case "addTraitOperation":
        const ato = o;
        let i = 0;
        newApp = produce5(this.app, (draft) => {
          draft.spec.components.forEach((c) => {
            if (c.id === ato.componentId) {
              c.traits.push({
                type: ato.traitType,
                properties: ato.properties
              });
              i = c.traits.length - 1;
            }
          });
        });
        if (!noEffect) {
          const removeTraitOperation = new RemoveTraitOperation(ato.componentId, i);
          this.undoStack.push(removeTraitOperation);
        }
        break;
      case "removeTraitOperation":
        const rto = o;
        newApp = produce5(this.app, (draft) => {
          draft.spec.components.forEach((c) => {
            if (c.id === rto.componentId) {
              c.traits.splice(rto.traitIndex, 1);
            }
          });
        });
        break;
      case "sortComponent":
        const sortO = o;
        newApp = produce5(this.app, (draft) => {
          const iIndex = draft.spec.components.findIndex((c) => c.id === sortO.componentId);
          const iComponent = this.app.spec.components[iIndex];
          const iSlotTrait = iComponent.traits.find((t) => t.type === "core/v1/slot");
          if (!iSlotTrait)
            return;
          const findArray = sortO.direction === "up" ? this.app.spec.components.slice(0, iIndex).reverse() : this.app.spec.components.slice(iIndex + 1);
          const jComponent = findArray.find((c) => {
            const jSlotTrait = c.traits.find((t) => t.type === "core/v1/slot");
            if (jSlotTrait) {
              return isEqual(jSlotTrait, iSlotTrait);
            }
          });
          if (!jComponent)
            return;
          const jIndex = this.app.spec.components.findIndex((c) => c.id === jComponent.id);
          if (jIndex > -1) {
            [draft.spec.components[iIndex], draft.spec.components[jIndex]] = [
              draft.spec.components[jIndex],
              draft.spec.components[iIndex]
            ];
          }
        });
        break;
    }
    this.updateApp(newApp);
  }
};

// src/main.tsx
function renderApp(app = DefaultAppSchema, options = {}) {
  const metaUI = initMetaUI2();
  const App = metaUI.App;
  const registry = metaUI.registry;
  const apiService = metaUI.apiService;
  const stateStore = metaUI.stateManager.store;
  const appModelManager = new AppModelManager(app, registry);
  const { components = [], traits = [], modules = [] } = options;
  components.forEach((c) => registry.registerComponent(c));
  traits.forEach((t) => registry.registerTrait(t));
  modules.forEach((m) => registry.registerModule(m));
  ReactDOM.render(/* @__PURE__ */ React.createElement(StrictMode, null, /* @__PURE__ */ React.createElement(ChakraProvider, null, /* @__PURE__ */ React.createElement(Editor, {
    App,
    registry,
    stateStore,
    appModelManager,
    apiService
  }))), document.getElementById("root"));
}
export {
  renderApp as default
};
//# sourceMappingURL=main.js.map
