App.jsx 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. import React from 'react'
  2. import ReactDOM from 'react-dom'
  3. import { App as TldrawApp } from 'tldraw-logseq'
  4. const storingKey = 'playground.index'
  5. const onPersist = app => {
  6. console.log('onPersist', app)
  7. window.sessionStorage.setItem(storingKey, JSON.stringify(app.serialized))
  8. }
  9. const onLoad = () => {
  10. return JSON.parse(window.sessionStorage.getItem(storingKey))
  11. }
  12. const documentModel = onLoad() ?? {
  13. currentPageId: 'page1',
  14. selectedIds: ['p6bv7EfoQPIF1eZB1RRO6'],
  15. pages: [
  16. {
  17. id: 'page1',
  18. name: 'Page',
  19. shapes: [
  20. {
  21. scale: [1, 1],
  22. id: 'p6bv7EfoQPIF1eZB1RRO6',
  23. type: 'logseq-portal',
  24. parentId: 'page1',
  25. point: [769.109375, 170.5546875],
  26. size: [390.671875, 295.3671875],
  27. stroke: '#000000',
  28. fill: '#ffffff',
  29. strokeWidth: 2,
  30. opacity: 1,
  31. pageId: '',
  32. nonce: 1,
  33. },
  34. ],
  35. bindings: {},
  36. nonce: 2,
  37. },
  38. ],
  39. }
  40. const list = ['foo', 'bar']
  41. const Page = props => {
  42. const [value, setValue] = React.useState(JSON.stringify(props, null, 2))
  43. return (
  44. <textarea
  45. className="whitespace-pre w-full h-full font-mono"
  46. style={{ minHeight: '64px' }}
  47. value={value}
  48. onChange={e => setValue(e.target.value)}
  49. />
  50. )
  51. }
  52. const ThemeSwitcher = ({ theme, setTheme }) => {
  53. const [anchor, setAnchor] = React.useState(null)
  54. React.useEffect(() => {
  55. if (anchor) {
  56. return
  57. }
  58. let el = document.querySelector('#theme-switcher')
  59. if (!el) {
  60. el = document.createElement('div')
  61. el.id = 'theme-switcher'
  62. let timer = setInterval(() => {
  63. const statusBarAnchor = document.querySelector('#tl-statusbar-anchor')
  64. if (statusBarAnchor) {
  65. statusBarAnchor.appendChild(el)
  66. setAnchor(el)
  67. clearInterval(timer)
  68. }
  69. }, 50)
  70. }
  71. })
  72. React.useEffect(() => {
  73. document.documentElement.setAttribute('data-theme', theme)
  74. }, [theme])
  75. if (!anchor) {
  76. return null
  77. }
  78. return ReactDOM.createPortal(
  79. <button
  80. className="flex items-center justify-center mx-2 bg-grey"
  81. style={{ fontSize: '1em' }}
  82. onClick={() => setTheme(t => (t === 'dark' ? 'light' : 'dark'))}
  83. >
  84. {theme} theme
  85. </button>,
  86. anchor
  87. )
  88. }
  89. export default function App() {
  90. const [theme, setTheme] = React.useState('light')
  91. return (
  92. <div className={`h-screen w-screen`}>
  93. <ThemeSwitcher theme={theme} setTheme={setTheme} />
  94. <TldrawApp
  95. PageComponent={Page}
  96. searchHandler={q => (q ? list : [])}
  97. model={documentModel}
  98. onPersist={onPersist}
  99. />
  100. </div>
  101. )
  102. }