diff --git a/tldraw/apps/tldraw-logseq/src/components/StatusBar/StatusBar.tsx b/tldraw/apps/tldraw-logseq/src/components/StatusBar/StatusBar.tsx index 898b0c164f..45cda55530 100644 --- a/tldraw/apps/tldraw-logseq/src/components/StatusBar/StatusBar.tsx +++ b/tldraw/apps/tldraw-logseq/src/components/StatusBar/StatusBar.tsx @@ -32,7 +32,7 @@ export const StatusBar = observer(function StatusBar() {
{app.selectedTool.id} | {app.selectedTool.currentState.id}
-
+
) }) diff --git a/tldraw/apps/tldraw-logseq/src/lib/preview-manager.tsx b/tldraw/apps/tldraw-logseq/src/lib/preview-manager.tsx index 2374b718b0..062e957e87 100644 --- a/tldraw/apps/tldraw-logseq/src/lib/preview-manager.tsx +++ b/tldraw/apps/tldraw-logseq/src/lib/preview-manager.tsx @@ -33,7 +33,7 @@ export class PreviewManager { }) } - generatePreviewJsx(viewport?: TLViewport) { + generatePreviewJsx(viewport?: TLViewport, ratio?: number) { const allBounds = [...(this.shapes ?? []).map(s => s.getRotatedBounds())] const vBounds = viewport?.currentView if (vBounds) { @@ -47,7 +47,7 @@ export class PreviewManager { commonBounds = BoundsUtils.expandBounds(commonBounds, SVG_EXPORT_PADDING) // make sure commonBounds is of ratio 4/3 (should we have another ratio setting?) - commonBounds = viewport ? BoundsUtils.ensureRatio(commonBounds, 4 / 3) : commonBounds + commonBounds = ratio ? BoundsUtils.ensureRatio(commonBounds, ratio) : commonBounds const translatePoint = (p: [number, number]): [string, string] => { return [(p[0] - commonBounds.minX).toFixed(2), (p[1] - commonBounds.minY).toFixed(2)] @@ -123,8 +123,8 @@ export class PreviewManager { return svgElement } - exportAsSVG() { - const svgElement = this.generatePreviewJsx() + exportAsSVG(ratio: number) { + const svgElement = this.generatePreviewJsx(undefined, ratio) return svgElement ? ReactDOMServer.renderToString(svgElement) : '' } } @@ -134,12 +134,12 @@ export class PreviewManager { * * @param serializedApp */ -export function generateSVGFromApp(serializedApp: TLDocumentModel) { +export function generateSVGFromApp(serializedApp: TLDocumentModel, ratio = 4 / 3) { const preview = new PreviewManager(serializedApp) - return preview.exportAsSVG() + return preview.exportAsSVG(ratio) } -export function generateJSXFromApp(serializedApp: TLDocumentModel) { +export function generateJSXFromApp(serializedApp: TLDocumentModel, ratio = 4 / 3) { const preview = new PreviewManager(serializedApp) - return preview.generatePreviewJsx() + return preview.generatePreviewJsx(undefined, ratio) } diff --git a/tldraw/demo/src/App.jsx b/tldraw/demo/src/App.jsx index 4734271772..9ad4027de6 100644 --- a/tldraw/demo/src/App.jsx +++ b/tldraw/demo/src/App.jsx @@ -1,7 +1,7 @@ import { uniqueId, fileToBase64 } from '@tldraw/core' import React from 'react' import ReactDOM from 'react-dom' -import { App as TldrawApp } from '@tldraw/logseq' +import { App as TldrawApp, generateJSXFromApp } from '@tldraw/logseq' const storingKey = 'playground.index' @@ -83,16 +83,17 @@ const PageNameLink = props => { ) } -const ThemeSwitcher = ({ theme, setTheme }) => { +const StatusBarSwitcher = ({ label, onClick }) => { const [anchor, setAnchor] = React.useState(null) React.useEffect(() => { if (anchor) { return } - let el = document.querySelector('#theme-switcher') + const id = 'status-bar-switcher-' + uniqueId() + let el = document.getElementById(id) if (!el) { el = document.createElement('div') - el.id = 'theme-switcher' + el.id = id let timer = setInterval(() => { const statusBarAnchor = document.querySelector('#tl-statusbar-anchor') if (statusBarAnchor) { @@ -104,26 +105,76 @@ const ThemeSwitcher = ({ theme, setTheme }) => { } }) - React.useEffect(() => { - document.documentElement.setAttribute('data-theme', theme) - }, [theme]) - if (!anchor) { return null } return ReactDOM.createPortal( , anchor ) } +const ThemeSwitcher = () => { + const [theme, setTheme] = React.useState('light') + + React.useEffect(() => { + document.documentElement.setAttribute('data-theme', theme) + }, [theme]) + + return ( + { + setTheme(t => (t === 'dark' ? 'light' : 'dark')) + }} + /> + ) +} + +const PreviewButton = ({ model }) => { + const [show, setShow] = React.useState(false) + + const [[w, h], setSize] = React.useState([window.innerWidth, window.innerHeight]) + + React.useEffect(() => { + const onResize = () => { + setSize([window.innerWidth, window.innerHeight]) + } + window.addEventListener('resize', onResize) + return () => window.removeEventListener('resize', onResize) + }, []) + + const preview = React.useMemo(() => { + return generateJSXFromApp(model, w / h) + }, [model, w, h]) + + return ( + <> + {show ? ( +
+
{preview}
+
+ ) : null} + { + setShow(s => !s) + }} + /> + + ) +} + const searchHandler = q => { return Promise.resolve({ pages: ['foo', 'bar', 'asdf'].filter(p => p.includes(q)), @@ -136,8 +187,6 @@ const searchHandler = q => { } export default function App() { - const [theme, setTheme] = React.useState('light') - const [model, setModel] = React.useState(documentModel) // Mimic external reload event @@ -153,7 +202,8 @@ export default function App() { return (
- + + a, }} model={model} - onPersist={onPersist} + onPersist={app => { + onPersist(app) + setModel(app.serialized) + }} />
)