Feat(Playground): Support load global js and css variables

This commit is contained in:
2024-11-02 15:27:32 +08:00
parent 451225c1cf
commit 216d3fd41c
14 changed files with 1704 additions and 39 deletions

View File

@@ -2,7 +2,6 @@ import Icon from '@ant-design/icons'
import { Background, Controls, MiniMap, Node, Panel, ReactFlow } from '@xyflow/react'
import '@xyflow/react/dist/style.css'
import { AppContext } from '@/App'
import { generateThemeCssVariable } from '@/util/common'
import useStyles from '@/components/Playground/Output/Preview/render.style'
import iframeRaw from '@/components/Playground/Output/Preview/iframe.html?raw'
import devices, { DeviceName } from '@/components/Playground/Output/Preview/devices'
@@ -12,15 +11,18 @@ interface RenderProps {
iframeKey: string
compiledCode: string
mobileMode?: boolean
globalJsVariables?: Record<string, unknown>
globalCssVariables?: string
}
interface IMessage {
type: 'LOADED' | 'ERROR' | 'UPDATE' | 'DONE' | 'THEME'
type: 'LOADED' | 'ERROR' | 'UPDATE' | 'DONE' | 'GLOBAL_VARIABLES'
msg: string
data: {
compiledCode?: string
zoom?: number
themeSrc?: string
globalJsVariables?: Record<string, unknown>
globalCssVariables?: string
}
}
@@ -30,7 +32,13 @@ const getIframeUrl = (iframeRaw: string) => {
const iframeUrl = getIframeUrl(iframeRaw)
const Render = ({ iframeKey, compiledCode, mobileMode = false }: RenderProps) => {
const Render = ({
iframeKey,
compiledCode,
mobileMode = false,
globalJsVariables,
globalCssVariables
}: RenderProps) => {
const { styles, theme } = useStyles()
const { isDarkMode } = useContext(AppContext)
const iframeRef = useRef<HTMLIFrameElement>(null)
@@ -59,11 +67,11 @@ const Render = ({ iframeKey, compiledCode, mobileMode = false }: RenderProps) =>
setIsRotate(!isRotate)
}
const loadTheme = () => {
const loadGlobalVariables = () => {
iframeRef.current?.contentWindow?.postMessage(
{
type: 'THEME',
data: { themeSrc: generateThemeCssVariable(theme).styles }
type: 'GLOBAL_VARIABLES',
data: { globalJsVariables, globalCssVariables }
} as IMessage,
'*'
)
@@ -80,15 +88,15 @@ const Render = ({ iframeKey, compiledCode, mobileMode = false }: RenderProps) =>
} as IMessage,
'*'
)
loadTheme()
loadGlobalVariables()
}, [isLoaded, compiledCode])
useEffect(() => {
if (!isLoaded) {
return
}
loadTheme()
}, [isLoaded, isDarkMode])
loadGlobalVariables()
}, [isLoaded, globalJsVariables, globalCssVariables])
return mobileMode ? (
<>

View File

@@ -4,14 +4,14 @@
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Preview</title>
<style id="theme-variable"></style>
<style id="global-css-variable"></style>
</head>
<body>
<script>
window.addEventListener("message", ({ data }) => {
if (data?.type === "UPDATE") {
// Record old styles that need to be removed
const appStyleElement = document.querySelectorAll("style:not(:is(style[id$=\"_oxygen_base_style.css\"], style[id=\"theme-variable\"]))") || [];
const appStyleElement = document.querySelectorAll("style:not(:is(style[id$=\"_oxygen_base_style.css\"], style[id=\"global-css-variable\"]))") || [];
// Remove old app
const appSrcElement = document.querySelector("#appSrc");
@@ -37,8 +37,11 @@
URL.revokeObjectURL(oldSrc);
}
if (data?.type === "THEME") {
document.querySelector("#theme-variable").textContent = data.data.themeSrc;
if (data?.type === "GLOBAL_VARIABLES") {
document.querySelector("#global-css-variable").textContent = data.data.globalCssVariables;
for (const key in data.data.globalJsVariables) {
globalThis[key] = data.data.globalJsVariables[key]
}
}
});
</script>

View File

@@ -11,6 +11,8 @@ interface PreviewProps {
preExpansionCode?: string
postExpansionCode?: string
mobileMode?: boolean
globalJsVariables?: Record<string, unknown>
globalCssVariables?: string
}
const Preview = ({
@@ -20,7 +22,9 @@ const Preview = ({
entryPoint,
preExpansionCode = '',
postExpansionCode = '',
mobileMode = false
mobileMode = false,
globalJsVariables,
globalCssVariables
}: PreviewProps) => {
const { styles } = useStyles()
const [errorMsg, setErrorMsg] = useState('')
@@ -44,7 +48,13 @@ const Preview = ({
return (
<div className={styles.root}>
<Render iframeKey={iframeKey} compiledCode={compiledCode} mobileMode={mobileMode} />
<Render
iframeKey={iframeKey}
compiledCode={compiledCode}
mobileMode={mobileMode}
globalJsVariables={globalJsVariables}
globalCssVariables={globalCssVariables}
/>
{errorMsg && <div className={styles.errorMessage}>{errorMsg}</div>}
</div>
)

View File

@@ -13,6 +13,8 @@ interface OutputProps {
preExpansionCode?: string
postExpansionCode?: string
mobileMode?: boolean
globalJsVariables?: Record<string, unknown>
globalCssVariables?: string
}
const Output = ({
@@ -23,7 +25,9 @@ const Output = ({
entryPoint,
preExpansionCode,
postExpansionCode,
mobileMode = false
mobileMode = false,
globalJsVariables,
globalCssVariables
}: OutputProps) => {
const [selectedTab, setSelectedTab] = useState('Preview')
@@ -47,6 +51,8 @@ const Output = ({
preExpansionCode={preExpansionCode}
postExpansionCode={postExpansionCode}
mobileMode={mobileMode}
globalJsVariables={globalJsVariables}
globalCssVariables={globalCssVariables}
/>
)}
{selectedTab === 'Transform' && (