[FRONT COMPONENTS] Navigate from the remote (#17762)
## PR Description This PR: - Introduces a `FrontComponentHostCommunicationApi`, which allows us to pass functions to be executed from the worker - Exposes a navigate function from the host to the front component remote workers, enabling SDK components to trigger in-app navigation - Gets rid of `useSyncExternalStore` and makes the execution context reactive without it - Refactors and improves the `esbuild` plugin system ## Video https://github.com/user-attachments/assets/7b26a1c2-f85f-4898-a71d-f60c70e61711
This commit is contained in:
@@ -1,107 +1,29 @@
|
||||
/* eslint-disable */
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
const mockFrontComponentCode = `
|
||||
// react-globals:react
|
||||
var useState = globalThis.React.useState;
|
||||
var useEffect = globalThis.React.useEffect;
|
||||
var useSyncExternalStore = globalThis.React.useSyncExternalStore;
|
||||
var navigate = /* @__PURE__ */ (() => globalThis.TwentySdk.navigate)();
|
||||
|
||||
// react-globals:react/jsx-runtime
|
||||
var jsx = globalThis.jsx;
|
||||
var jsxs = globalThis.jsxs;
|
||||
var Fragment = globalThis.React.Fragment;
|
||||
var AppPath = /* @__PURE__ */ (() => globalThis.TwentyShared["types"].AppPath)();
|
||||
|
||||
var Button = /* @__PURE__ */ (() => globalThis.RemoteComponents.TwentyUiButton)();
|
||||
|
||||
var jsx = /* @__PURE__ */ (() => globalThis.jsx)();
|
||||
|
||||
// src/tata/test-component.front-component.tsx
|
||||
var RemoteComponents = globalThis.RemoteComponents;
|
||||
var getStore = () => {
|
||||
const store = globalThis.frontComponentExecutionContextStore;
|
||||
if (store === void 0) {
|
||||
throw new Error(
|
||||
"frontComponentExecutionContextStore not found on globalThis. This hook must be used within a front component running in the worker."
|
||||
);
|
||||
}
|
||||
return store;
|
||||
};
|
||||
var useFrontComponentExecutionContext = () => {
|
||||
const store = getStore();
|
||||
return useSyncExternalStore(store.subscribe, store.getSnapshot);
|
||||
};
|
||||
var TestComponent = () => {
|
||||
const [count, setCount] = useState(0);
|
||||
const [timer, setTimer] = useState(0);
|
||||
const context = useFrontComponentExecutionContext();
|
||||
useEffect(() => {
|
||||
const interval = setInterval(() => {
|
||||
setTimer((prevTimer) => prevTimer + 1);
|
||||
}, 1e3);
|
||||
return () => clearInterval(interval);
|
||||
}, []);
|
||||
return /* @__PURE__ */ jsxs(
|
||||
RemoteComponents.HtmlDiv,
|
||||
return /* @__PURE__ */ jsx(
|
||||
Button,
|
||||
{
|
||||
style: {
|
||||
padding: "20px",
|
||||
fontFamily: "Arial, sans-serif",
|
||||
maxWidth: "400px",
|
||||
margin: "0 auto",
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
alignItems: "center"
|
||||
},
|
||||
children: [
|
||||
/* @__PURE__ */ jsx(RemoteComponents.HtmlH1, { style: { color: "#333", marginBottom: "20px", fontSize: "24px" }, children: "Test Component" }),
|
||||
/* @__PURE__ */ jsxs(RemoteComponents.HtmlP, { style: { fontSize: "18px", marginBottom: "10px", color: "#666" }, children: [
|
||||
"Count: ",
|
||||
count
|
||||
] }),
|
||||
/* @__PURE__ */ jsxs(RemoteComponents.HtmlP, { style: { fontSize: "18px", marginBottom: "20px", color: "#666" }, children: [
|
||||
"Timer: ",
|
||||
timer,
|
||||
"s"
|
||||
] }),
|
||||
/* @__PURE__ */ jsxs(RemoteComponents.HtmlP, { style: { fontSize: "18px", marginBottom: "20px", color: "#666" }, children: [
|
||||
"User ID: ",
|
||||
context?.userId
|
||||
] }),
|
||||
/* @__PURE__ */ jsx(
|
||||
RemoteComponents.HtmlButton,
|
||||
{
|
||||
onClick: () => setCount(count + 1),
|
||||
style: {
|
||||
padding: "10px 20px",
|
||||
fontSize: "16px",
|
||||
backgroundColor: "#007bff",
|
||||
color: "white",
|
||||
border: "none",
|
||||
borderRadius: "5px",
|
||||
cursor: "pointer",
|
||||
transition: "all 0.3s ease",
|
||||
boxShadow: "0 2px 4px rgba(0, 0, 0, 0.2)"
|
||||
},
|
||||
onMouseEnter: (e) => {
|
||||
e.currentTarget.style.backgroundColor = "#0056b3";
|
||||
e.currentTarget.style.transform = "translateY(-2px)";
|
||||
e.currentTarget.style.boxShadow = "0 4px 8px rgba(0, 0, 0, 0.3)";
|
||||
},
|
||||
onMouseLeave: (e) => {
|
||||
e.currentTarget.style.backgroundColor = "#007bff";
|
||||
e.currentTarget.style.transform = "translateY(0)";
|
||||
e.currentTarget.style.boxShadow = "0 2px 4px rgba(0, 0, 0, 0.2)";
|
||||
},
|
||||
children: "Increment"
|
||||
}
|
||||
)
|
||||
]
|
||||
title: "Navigate to people index page",
|
||||
onClick: () => navigate?.(AppPath.RecordIndexPage, {
|
||||
objectNamePlural: "people"
|
||||
})
|
||||
}
|
||||
);
|
||||
};
|
||||
var test_component_front_component_default = globalThis.jsx(TestComponent, {});
|
||||
export {
|
||||
test_component_front_component_default as default,
|
||||
useFrontComponentExecutionContext
|
||||
test_component_front_component_default as default
|
||||
};
|
||||
//# sourceMappingURL=test-component.front-component.mjs.map
|
||||
`;
|
||||
|
||||
let cachedMockBlobUrl: string | null = null;
|
||||
|
||||
Reference in New Issue
Block a user