Builder = ({ options, layout, mode }) => {
  const [showLayers, setShowLayers] = useState(true);
  const [previews, setPreviews] = useState({});
  const [uploadedFiles, setUploadedFiles] = useState([]);
  const nodekeys = useRef([]);
  const [savingState, setSavingState] = useState({ isSaving: false });
  const [isEnlarged, setIsEnlarged] = useState(false);
  const [isLeftEnlarged, setIsLeftEnlarged] = useState(false);
  const [relationsCache, setRelationsCache] = useState({});
  const { windowWidth, windowHeight } = useWindowDimensions();

  const [builderHeight, setBuilderHeight] = useState(0);
  const [builderTop, setBuilderTop] = useState(0);

  const ref = useRef(null);

  useEffect(() => {
    if (!ref.current) return;
    setBuilderHeight(ref.current.clientHeight);
    const rect = ref.current.getBoundingClientRect();
    setBuilderTop(rect.top);
  });

  const canvasHeight =
    Math.max(windowHeight - builderTop, builderHeight, 600) - 10;
  return (
    <ErrorBoundary>
      <Editor onRender={RenderNode}>
        <Provider value={options}>
          <PreviewCtx.Provider
            value={{ previews, setPreviews, uploadedFiles, setUploadedFiles }}
          >
            <RelationsCtx.Provider
              value={{
                relationsCache,
                setRelationsCache,
              }}
            >
              <StorageCtx.Provider
                value={{
                  craftToSaltcorn,
                  layoutToNodes,
                }}
              >
                <div className="row" ref={ref} style={{ marginTop: "-5px" }}>
                  <div
                    className={`col-sm-auto left-builder-col ${
                      isLeftEnlarged
                        ? "builder-left-enlarged"
                        : "builder-left-shrunk"
                    }`}
                  >
                    <div className="componets-and-library-accordion toolbox-card">
                      <InitNewElement
                        nodekeys={nodekeys}
                        setSavingState={setSavingState}
                        savingState={savingState}
                      />
                      <Accordion>
                        <div className="card mt-1" accordiontitle="Components">
                          {{
                            show: <ToolboxShow expanded={isLeftEnlarged} />,
                            list: <ToolboxList expanded={isLeftEnlarged} />,
                            edit: <ToolboxEdit expanded={isLeftEnlarged} />,
                            page: <ToolboxPage expanded={isLeftEnlarged} />,
                            filter: <ToolboxFilter expanded={isLeftEnlarged} />,
                          }[mode] || <div>Missing mode</div>}
                        </div>
                        <div accordiontitle="Library">
                          <Library expanded={isLeftEnlarged} />
                        </div>
                      </Accordion>
                    </div>
                    <div
                      className="card toolbox-card pe-0"
                      style={isLeftEnlarged ? { width: "13.4rem" } : {}}
                    >
                      <div className="card-header p-2 d-flex justify-content-between">
                        <div>Layers</div>
                        <FontAwesomeIcon
                          icon={
                            isLeftEnlarged
                              ? faCaretSquareLeft
                              : faCaretSquareRight
                          }
                          className={"float-end fa-lg"}
                          onClick={() => setIsLeftEnlarged(!isLeftEnlarged)}
                          title={isLeftEnlarged ? "Shrink" : "Enlarge"}
                        />
                      </div>
                      {showLayers && (
                        <div className="card-body p-0 builder-layers">
                          <Layers expandRootOnLoad={true} />
                        </div>
                      )}
                    </div>
                  </div>
                  <div
                    id="builder-main-canvas"
                    style={{ height: canvasHeight }}
                    className={`col builder-mode-${options.mode} ${
                      options.mode !== "list" ? "emptymsg" : ""
                    }`}
                  >
                    <div>
                      <Frame
                        resolver={{
                          Text,
                          Empty,
                          Columns,
                          JoinField,
                          Field,
                          ViewLink,
                          Action,
                          HTMLCode,
                          LineBreak,
                          Aggregation,
                          Card,
                          Image,
                          Link,
                          View,
                          SearchBar,
                          Container,
                          Column,
                          DropDownFilter,
                          DropMenu,
                          Tabs,
                          Table,
                          ToggleFilter,
                          ListColumn,
                          ListColumns,
                        }}
                      >
                        {options.mode === "list" ? (
                          <Element canvas is={ListColumns}></Element>
                        ) : (
                          <Element canvas is={Column}></Element>
                        )}
                      </Frame>
                      {options.mode === "list" ? <AddColumnButton /> : null}
                    </div>
                  </div>
                  <div className="col-sm-auto builder-sidebar">
                    <div style={{ width: isEnlarged ? "28rem" : "16rem" }}>
                      <NextButton layout={layout} />
                      <HistoryPanel />
                      <FontAwesomeIcon
                        icon={faSave}
                        className={savingState.isSaving ? "d-inline" : "d-none"}
                      />
                      <FontAwesomeIcon
                        icon={faExclamationTriangle}
                        color="#ff0033"
                        className={savingState.error ? "d-inline" : "d-none"}
                      />
                      <FontAwesomeIcon
                        icon={
                          isEnlarged ? faCaretSquareRight : faCaretSquareLeft
                        }
                        className={"float-end me-2 mt-1 fa-lg"}
                        onClick={() => setIsEnlarged(!isEnlarged)}
                        title={isEnlarged ? "Shrink" : "Enlarge"}
                      />
                      <div
                        className={` ${
                          savingState.error ? "d-block" : "d-none"
                        } my-2 fw-bold`}
                      >
                        your work is not being saved
                      </div>
                      <SettingsPanel />
                    </div>
                  </div>
                </div>
              </StorageCtx.Provider>
            </RelationsCtx.Provider>
          </PreviewCtx.Provider>
        </Provider>
        <div className="d-none preview-scratchpad"></div>
      </Editor>
      <style>
        {options.icons
          .filter((icon) => icon.startsWith("unicode-"))
          .map(
            (icon) =>
              `i.${icon}:after {content: '${String.fromCharCode(
                parseInt(icon.substring(8, 12), 16)
              )}'}`
          )
          .join("\n")}
      </style>
    </ErrorBoundary>
  );
}
@param {object} props
@param {object} props.options
@param {object} props.layout
@param {string} props.mode
@returns {ErrorBoundary}
@category saltcorn-builder
@subcategory components
@namespace