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 ? (
+
+ ) : 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)
+ }}
/>
)