From cebdaa4cfaa7becb7638faf1690dad719e730862 Mon Sep 17 00:00:00 2001 From: timoconnellaus Date: Wed, 22 May 2024 10:50:05 +1000 Subject: [PATCH 1/4] Feature: Editor left sidebar as a plugin --- packages/editor/src/EasyblocksEditor.tsx | 1 + packages/editor/src/EasyblocksEditorProps.ts | 15 ++++++++- packages/editor/src/EasyblocksParent.tsx | 7 ++++- packages/editor/src/Editor.tsx | 33 ++++++++++++++++++-- packages/editor/src/index.ts | 5 ++- 5 files changed, 56 insertions(+), 5 deletions(-) diff --git a/packages/editor/src/EasyblocksEditor.tsx b/packages/editor/src/EasyblocksEditor.tsx index be269fa8..733ab6df 100644 --- a/packages/editor/src/EasyblocksEditor.tsx +++ b/packages/editor/src/EasyblocksEditor.tsx @@ -62,6 +62,7 @@ export function EasyblocksEditor(props: EasyblocksEditorProps) { onExternalDataChange={props.onExternalDataChange ?? (() => ({}))} widgets={props.widgets} components={props.components} + plugins={props.plugins} /> )} diff --git a/packages/editor/src/EasyblocksEditorProps.ts b/packages/editor/src/EasyblocksEditorProps.ts index 00c69611..030b52da 100644 --- a/packages/editor/src/EasyblocksEditorProps.ts +++ b/packages/editor/src/EasyblocksEditorProps.ts @@ -7,12 +7,25 @@ import { WidgetComponentProps, } from "@easyblocks/core"; import React, { ComponentType } from "react"; +import { Form } from "./form"; +import { InternalAnyField } from "@easyblocks/core/_internals"; export type ExternalDataChangeHandler = ( externalData: RequestedExternalData, contextParams: ContextParams ) => void; +export type EditorSidebarLeftProps = { + focussedField: string[]; + form: Form; +}; + +export type EasyblocksEditorPlugins = { + components?: { + sidebarLeft?: ComponentType; + }; +}; + export type EasyblocksEditorProps = { config: Config; externalData?: ExternalData; @@ -23,6 +36,6 @@ export type EasyblocksEditorProps = { | ComponentType> | ComponentType> >; - + plugins?: EasyblocksEditorPlugins; __debug?: boolean; }; diff --git a/packages/editor/src/EasyblocksParent.tsx b/packages/editor/src/EasyblocksParent.tsx index 033e3cdd..40c28732 100644 --- a/packages/editor/src/EasyblocksParent.tsx +++ b/packages/editor/src/EasyblocksParent.tsx @@ -19,7 +19,10 @@ import { GlobalStyles } from "./tinacms/styles"; import { SpaceTokenWidget } from "./sidebar/SpaceTokenWidget"; import { parseQueryParams } from "./parseQueryParams"; import { DocumentDataWidgetComponent } from "./sidebar/DocumentDataWidget"; -import { ExternalDataChangeHandler } from "./EasyblocksEditorProps"; +import { + EasyblocksEditorPlugins, + ExternalDataChangeHandler, +} from "./EasyblocksEditorProps"; type EasyblocksParentProps = { config: Config; @@ -31,6 +34,7 @@ type EasyblocksParentProps = { | ComponentType> >; components?: Record>; + plugins?: EasyblocksEditorPlugins; }; const shouldForwardProp: ShouldForwardProp<"web"> = (propName, target) => { @@ -82,6 +86,7 @@ export function EasyblocksParent(props: EasyblocksParentProps) { ...props.widgets, }} components={props.components} + plugins={props.plugins} /> diff --git a/packages/editor/src/Editor.tsx b/packages/editor/src/Editor.tsx index 8d34002a..d0ee35fe 100644 --- a/packages/editor/src/Editor.tsx +++ b/packages/editor/src/Editor.tsx @@ -53,7 +53,10 @@ import React, { import Modal from "react-modal"; import styled from "styled-components"; import { ConfigAfterAutoContext } from "./ConfigAfterAutoContext"; -import { ExternalDataChangeHandler } from "./EasyblocksEditorProps"; +import { + EasyblocksEditorPlugins, + ExternalDataChangeHandler, +} from "./EasyblocksEditorProps"; import { EditorContext, EditorContextType } from "./EditorContext"; import { EditorExternalDataProvider } from "./EditorExternalDataProvider"; import { EditorIframe } from "./EditorIframe"; @@ -115,6 +118,19 @@ const SidebarContainer = styled.div` overflow-y: auto; `; +const SidebarContainerLeft = styled.div` + flex: 0 0 240px; + background: ${Colors.white}; + border-right: 1px solid ${Colors.black100}; + box-sizing: border-box; + + > * { + box-sizing: border-box; + } + + overflow-y: auto; +`; + const DataSaverRoot = styled.div` position: fixed; width: 100%; @@ -176,6 +192,7 @@ type EditorProps = { | ComponentType> >; components?: Record>; + plugins?: EasyblocksEditorPlugins; }; export const Editor = EditorBackendInitializer; @@ -310,6 +327,7 @@ const EditorWrapper = memo( compilationContext={compilationContext} initialDocument={props.document} initialEntry={initialEntry} + plugins={props.plugins} /> ); } @@ -320,6 +338,7 @@ type EditorContentProps = EditorProps & { initialDocument: Document | null; initialEntry: NoCodeComponentEntry; heightMode?: "viewport" | "full"; + plugins?: EasyblocksEditorPlugins; }; function parseExternalDataId(externalDataId: string): { @@ -614,7 +633,6 @@ const EditorContent = ({ useRerenderOnResize(); // re-render on resize (recalculates viewport size, active breakpoint for fit-screen etc); const compilationCache = useRef(new CompilationCache()); - const [isEditing, setEditing] = useState(true); const [componentPickerData, setComponentPickerData] = useState< | { promiseResolve: (config: NoCodeComponentEntry | undefined) => void; @@ -642,6 +660,7 @@ const EditorContent = ({ }; const sidebarNodeRef = useRef(null); + const sidebarLeftNodeRef = useRef(null); const [editableData, form] = useForm({ id: "easyblocks-editor", @@ -990,6 +1009,8 @@ const EditorContent = ({ Modal.setAppElement("#shopstory-app"); }, []); + const EditorSidebarLeft = props.plugins?.components?.sidebarLeft; + return (
{isDataSaverOverlayOpen && ( @@ -1041,6 +1062,14 @@ const EditorContent = ({ readOnly={editorContext.readOnly} /> + {isEditing && EditorSidebarLeft && ( + + + + )} { setFocussedField([]); diff --git a/packages/editor/src/index.ts b/packages/editor/src/index.ts index a1e46bea..a8ac498e 100644 --- a/packages/editor/src/index.ts +++ b/packages/editor/src/index.ts @@ -2,4 +2,7 @@ export type { EditorContextType } from "./EditorContext"; export type { EditorWindowAPI } from "./types"; export { useEditorContext } from "./EditorContext"; export { EasyblocksEditor } from "./EasyblocksEditor"; -export type { ExternalDataChangeHandler } from "./EasyblocksEditorProps"; +export type { + ExternalDataChangeHandler, + EditorSidebarLeftProps, +} from "./EasyblocksEditorProps"; From 97778d118bbcc51114babaefd7629e85f457655f Mon Sep 17 00:00:00 2001 From: timoconnellaus Date: Wed, 22 May 2024 10:58:32 +1000 Subject: [PATCH 2/4] accidentally deleted isEditing state --- packages/editor/src/Editor.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/editor/src/Editor.tsx b/packages/editor/src/Editor.tsx index d0ee35fe..c82e6dfc 100644 --- a/packages/editor/src/Editor.tsx +++ b/packages/editor/src/Editor.tsx @@ -633,6 +633,7 @@ const EditorContent = ({ useRerenderOnResize(); // re-render on resize (recalculates viewport size, active breakpoint for fit-screen etc); const compilationCache = useRef(new CompilationCache()); + const [isEditing, setEditing] = useState(true); const [componentPickerData, setComponentPickerData] = useState< | { promiseResolve: (config: NoCodeComponentEntry | undefined) => void; From 2ef02be530cf01dca34b9b87bf2d6ca3b4f3dd64 Mon Sep 17 00:00:00 2001 From: timoconnellaus Date: Wed, 22 May 2024 10:58:32 +1000 Subject: [PATCH 3/4] Feature: Editor left sidebar as a plugin accidentally deleted isEditing state --- packages/editor/src/EasyblocksEditor.tsx | 1 + packages/editor/src/EasyblocksEditorProps.ts | 15 ++++++++- packages/editor/src/EasyblocksParent.tsx | 7 ++++- packages/editor/src/Editor.tsx | 32 +++++++++++++++++++- packages/editor/src/index.ts | 5 ++- 5 files changed, 56 insertions(+), 4 deletions(-) diff --git a/packages/editor/src/EasyblocksEditor.tsx b/packages/editor/src/EasyblocksEditor.tsx index be269fa8..733ab6df 100644 --- a/packages/editor/src/EasyblocksEditor.tsx +++ b/packages/editor/src/EasyblocksEditor.tsx @@ -62,6 +62,7 @@ export function EasyblocksEditor(props: EasyblocksEditorProps) { onExternalDataChange={props.onExternalDataChange ?? (() => ({}))} widgets={props.widgets} components={props.components} + plugins={props.plugins} /> )} diff --git a/packages/editor/src/EasyblocksEditorProps.ts b/packages/editor/src/EasyblocksEditorProps.ts index 00c69611..030b52da 100644 --- a/packages/editor/src/EasyblocksEditorProps.ts +++ b/packages/editor/src/EasyblocksEditorProps.ts @@ -7,12 +7,25 @@ import { WidgetComponentProps, } from "@easyblocks/core"; import React, { ComponentType } from "react"; +import { Form } from "./form"; +import { InternalAnyField } from "@easyblocks/core/_internals"; export type ExternalDataChangeHandler = ( externalData: RequestedExternalData, contextParams: ContextParams ) => void; +export type EditorSidebarLeftProps = { + focussedField: string[]; + form: Form; +}; + +export type EasyblocksEditorPlugins = { + components?: { + sidebarLeft?: ComponentType; + }; +}; + export type EasyblocksEditorProps = { config: Config; externalData?: ExternalData; @@ -23,6 +36,6 @@ export type EasyblocksEditorProps = { | ComponentType> | ComponentType> >; - + plugins?: EasyblocksEditorPlugins; __debug?: boolean; }; diff --git a/packages/editor/src/EasyblocksParent.tsx b/packages/editor/src/EasyblocksParent.tsx index 033e3cdd..40c28732 100644 --- a/packages/editor/src/EasyblocksParent.tsx +++ b/packages/editor/src/EasyblocksParent.tsx @@ -19,7 +19,10 @@ import { GlobalStyles } from "./tinacms/styles"; import { SpaceTokenWidget } from "./sidebar/SpaceTokenWidget"; import { parseQueryParams } from "./parseQueryParams"; import { DocumentDataWidgetComponent } from "./sidebar/DocumentDataWidget"; -import { ExternalDataChangeHandler } from "./EasyblocksEditorProps"; +import { + EasyblocksEditorPlugins, + ExternalDataChangeHandler, +} from "./EasyblocksEditorProps"; type EasyblocksParentProps = { config: Config; @@ -31,6 +34,7 @@ type EasyblocksParentProps = { | ComponentType> >; components?: Record>; + plugins?: EasyblocksEditorPlugins; }; const shouldForwardProp: ShouldForwardProp<"web"> = (propName, target) => { @@ -82,6 +86,7 @@ export function EasyblocksParent(props: EasyblocksParentProps) { ...props.widgets, }} components={props.components} + plugins={props.plugins} /> diff --git a/packages/editor/src/Editor.tsx b/packages/editor/src/Editor.tsx index 8d34002a..c82e6dfc 100644 --- a/packages/editor/src/Editor.tsx +++ b/packages/editor/src/Editor.tsx @@ -53,7 +53,10 @@ import React, { import Modal from "react-modal"; import styled from "styled-components"; import { ConfigAfterAutoContext } from "./ConfigAfterAutoContext"; -import { ExternalDataChangeHandler } from "./EasyblocksEditorProps"; +import { + EasyblocksEditorPlugins, + ExternalDataChangeHandler, +} from "./EasyblocksEditorProps"; import { EditorContext, EditorContextType } from "./EditorContext"; import { EditorExternalDataProvider } from "./EditorExternalDataProvider"; import { EditorIframe } from "./EditorIframe"; @@ -115,6 +118,19 @@ const SidebarContainer = styled.div` overflow-y: auto; `; +const SidebarContainerLeft = styled.div` + flex: 0 0 240px; + background: ${Colors.white}; + border-right: 1px solid ${Colors.black100}; + box-sizing: border-box; + + > * { + box-sizing: border-box; + } + + overflow-y: auto; +`; + const DataSaverRoot = styled.div` position: fixed; width: 100%; @@ -176,6 +192,7 @@ type EditorProps = { | ComponentType> >; components?: Record>; + plugins?: EasyblocksEditorPlugins; }; export const Editor = EditorBackendInitializer; @@ -310,6 +327,7 @@ const EditorWrapper = memo( compilationContext={compilationContext} initialDocument={props.document} initialEntry={initialEntry} + plugins={props.plugins} /> ); } @@ -320,6 +338,7 @@ type EditorContentProps = EditorProps & { initialDocument: Document | null; initialEntry: NoCodeComponentEntry; heightMode?: "viewport" | "full"; + plugins?: EasyblocksEditorPlugins; }; function parseExternalDataId(externalDataId: string): { @@ -642,6 +661,7 @@ const EditorContent = ({ }; const sidebarNodeRef = useRef(null); + const sidebarLeftNodeRef = useRef(null); const [editableData, form] = useForm({ id: "easyblocks-editor", @@ -990,6 +1010,8 @@ const EditorContent = ({ Modal.setAppElement("#shopstory-app"); }, []); + const EditorSidebarLeft = props.plugins?.components?.sidebarLeft; + return (
{isDataSaverOverlayOpen && ( @@ -1041,6 +1063,14 @@ const EditorContent = ({ readOnly={editorContext.readOnly} /> + {isEditing && EditorSidebarLeft && ( + + + + )} { setFocussedField([]); diff --git a/packages/editor/src/index.ts b/packages/editor/src/index.ts index a1e46bea..a8ac498e 100644 --- a/packages/editor/src/index.ts +++ b/packages/editor/src/index.ts @@ -2,4 +2,7 @@ export type { EditorContextType } from "./EditorContext"; export type { EditorWindowAPI } from "./types"; export { useEditorContext } from "./EditorContext"; export { EasyblocksEditor } from "./EasyblocksEditor"; -export type { ExternalDataChangeHandler } from "./EasyblocksEditorProps"; +export type { + ExternalDataChangeHandler, + EditorSidebarLeftProps, +} from "./EasyblocksEditorProps"; From fb5badb64fcb916da33b4d7d138591d21666aa17 Mon Sep 17 00:00:00 2001 From: timoconnellaus Date: Fri, 5 Jul 2024 19:02:16 +1000 Subject: [PATCH 4/4] feat: Expose ValueSchemaProp type in types.ts --- packages/core/src/types.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/src/types.ts b/packages/core/src/types.ts index bdc43b1a..09c330e4 100644 --- a/packages/core/src/types.ts +++ b/packages/core/src/types.ts @@ -574,7 +574,7 @@ export type SchemaPropShared = { layout?: "row" | "column"; }; -type ValueSchemaProp< +export type ValueSchemaProp< Type extends string, ValueType, Responsiveness extends "optional" | "forced" | "never"