From 5b634556a49a65f5073485bc3bd47e999a2bcbac Mon Sep 17 00:00:00 2001 From: Lois Wells Date: Tue, 30 Sep 2025 14:14:07 +0100 Subject: [PATCH 1/3] spiking plugin support --- src/containers/WebComponentLoader.jsx | 6 ++++++ src/web-component.js | 8 +++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/containers/WebComponentLoader.jsx b/src/containers/WebComponentLoader.jsx index 702ac2f96..8cd07385d 100644 --- a/src/containers/WebComponentLoader.jsx +++ b/src/containers/WebComponentLoader.jsx @@ -47,6 +47,7 @@ const WebComponentLoader = (props) => { outputOnly = false, outputPanels = ["text", "visual"], outputSplitView = false, + plugins = [], projectNameEditable = false, reactAppApiEndpoint = process.env.REACT_APP_API_ENDPOINT, readOnly = false, @@ -97,6 +98,10 @@ const WebComponentLoader = (props) => { useEmbeddedMode(embedded); + useEffect(() => { + console.log("the plugins are", plugins); + }, [plugins]); + useEffect(() => { if (theme) { dispatch(disableTheming()); @@ -228,6 +233,7 @@ const WebComponentLoader = (props) => { outputSplitView={outputSplitView} editableInstructions={editableInstructions} /> + {plugins.map((plugin) => plugin.slot1())} {errorModalShowing && } {newFileModalShowing && } {renameFileModalShowing && modals.renameFile && } diff --git a/src/web-component.js b/src/web-component.js index 693862362..6cff55dd5 100644 --- a/src/web-component.js +++ b/src/web-component.js @@ -27,6 +27,7 @@ class WebComponent extends HTMLElement { mountPoint; componentAttributes = {}; componentProperties = {}; + plugins = []; connectedCallback() { if (!this.shadowRoot) { @@ -157,6 +158,11 @@ class WebComponent extends HTMLElement { }); } + setPlugins(plugins) { + this.plugins = plugins; + this.mountReactApp(); + } + reactProps() { return { ...this.componentAttributes, @@ -177,7 +183,7 @@ class WebComponent extends HTMLElement { - + , From 02f6745e513f42398eeba70448d1e8236c2aeabd Mon Sep 17 00:00:00 2001 From: Lois Wells Date: Tue, 30 Sep 2025 17:33:53 +0100 Subject: [PATCH 2/3] allowing plugins to add a new sidebar panel --- src/components/Editor/Project/Project.jsx | 3 ++- src/components/Menus/Sidebar/Sidebar.jsx | 19 ++++++++++++++++++- .../WebComponentProject.jsx | 2 ++ src/containers/WebComponentLoader.jsx | 1 + 4 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/components/Editor/Project/Project.jsx b/src/components/Editor/Project/Project.jsx index 4fa543b97..ae33818db 100644 --- a/src/components/Editor/Project/Project.jsx +++ b/src/components/Editor/Project/Project.jsx @@ -22,6 +22,7 @@ const Project = (props) => { withProjectbar = true, withSidebar = true, sidebarOptions = [], + plugins = [], } = props; const saving = useSelector((state) => state.editor.saving); const autosave = useSelector((state) => state.editor.lastSaveAutosave); @@ -59,7 +60,7 @@ const Project = (props) => { "proj-container--wc": webComponent, })} > - {withSidebar && } + {withSidebar && }
{withProjectbar && } {!loading && ( diff --git a/src/components/Menus/Sidebar/Sidebar.jsx b/src/components/Menus/Sidebar/Sidebar.jsx index 86987a52b..c3f04ae81 100644 --- a/src/components/Menus/Sidebar/Sidebar.jsx +++ b/src/components/Menus/Sidebar/Sidebar.jsx @@ -23,8 +23,9 @@ import { MOBILE_MEDIA_QUERY } from "../../../utils/mediaQueryBreakpoints"; import FileIcon from "../../../utils/FileIcon"; import DownloadPanel from "./DownloadPanel/DownloadPanel"; import InstructionsPanel from "./InstructionsPanel/InstructionsPanel"; +import SidebarPanel from "./SidebarPanel"; -const Sidebar = ({ options = [] }) => { +const Sidebar = ({ options = [], plugins = [] }) => { const { t } = useTranslation(); let menuOptions = [ @@ -79,6 +80,22 @@ const Sidebar = ({ options = [] }) => { }, ].filter((option) => options.includes(option.name)); + let pluginMenuOptions = plugins.map((plugin) => { + return { + name: plugin.name, + icon: plugin.icon, + title: plugin.title, + position: plugin.position || "top", + panel: () => ( + + {plugin.panel()} + + ), + }; + }); + + menuOptions = [...menuOptions, ...pluginMenuOptions]; + const isMobile = useMediaQuery({ query: MOBILE_MEDIA_QUERY }); const projectImages = useSelector((state) => state.editor.project.image_list); const instructionsSteps = useSelector( diff --git a/src/components/WebComponentProject/WebComponentProject.jsx b/src/components/WebComponentProject/WebComponentProject.jsx index 99051afb9..dc258b641 100644 --- a/src/components/WebComponentProject/WebComponentProject.jsx +++ b/src/components/WebComponentProject/WebComponentProject.jsx @@ -35,6 +35,7 @@ const WebComponentProject = ({ outputOnly = false, outputPanels = ["text", "visual"], outputSplitView = false, + plugins = [], }) => { const loading = useSelector((state) => state.editor.loading); const project = useSelector((state) => state.editor.project); @@ -152,6 +153,7 @@ const WebComponentProject = ({ withProjectbar={withProjectbar} withSidebar={withSidebar} sidebarOptions={sidebarOptions} + plugins={plugins} /> ))} {outputOnly && ( diff --git a/src/containers/WebComponentLoader.jsx b/src/containers/WebComponentLoader.jsx index 8cd07385d..95da4bfac 100644 --- a/src/containers/WebComponentLoader.jsx +++ b/src/containers/WebComponentLoader.jsx @@ -232,6 +232,7 @@ const WebComponentLoader = (props) => { outputPanels={outputPanels} outputSplitView={outputSplitView} editableInstructions={editableInstructions} + plugins={plugins} /> {plugins.map((plugin) => plugin.slot1())} {errorModalShowing && } From 0b0975cb4378722536a7c21c7957b1712855651e Mon Sep 17 00:00:00 2001 From: Lois Wells Date: Thu, 2 Oct 2025 16:23:40 +0100 Subject: [PATCH 3/3] passing state into the plugin component --- src/components/Menus/Sidebar/Sidebar.jsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/components/Menus/Sidebar/Sidebar.jsx b/src/components/Menus/Sidebar/Sidebar.jsx index c3f04ae81..d37298018 100644 --- a/src/components/Menus/Sidebar/Sidebar.jsx +++ b/src/components/Menus/Sidebar/Sidebar.jsx @@ -27,6 +27,9 @@ import SidebarPanel from "./SidebarPanel"; const Sidebar = ({ options = [], plugins = [] }) => { const { t } = useTranslation(); + const projectIdentifier = useSelector( + (state) => state.editor.project.identifier, + ); let menuOptions = [ { @@ -88,7 +91,7 @@ const Sidebar = ({ options = [], plugins = [] }) => { position: plugin.position || "top", panel: () => ( - {plugin.panel()} + {plugin.panel({ projectIdentifier })} ), };