fix: sync whiteboard theme with app mode
This commit is contained in:
@@ -1,11 +1,18 @@
|
||||
import { render, screen } from '@testing-library/react'
|
||||
import { describe, expect, it, vi } from 'vitest'
|
||||
import { act, cleanup, render, screen, waitFor } from '@testing-library/react'
|
||||
import { afterEach, describe, expect, it, vi } from 'vitest'
|
||||
import type { Editor } from 'tldraw'
|
||||
import { TldrawWhiteboard } from './TldrawWhiteboard'
|
||||
|
||||
interface MockTldrawProps {
|
||||
assetUrls: MockAssetUrls
|
||||
onMount: (editor: Editor) => () => void
|
||||
user?: MockTldrawUser
|
||||
}
|
||||
|
||||
interface MockTldrawUser {
|
||||
userPreferences: {
|
||||
get: () => { colorScheme?: string }
|
||||
}
|
||||
}
|
||||
|
||||
interface MockAssetUrls {
|
||||
@@ -64,8 +71,18 @@ vi.mock('tldraw', async () => {
|
||||
createTLStore: vi.fn(() => ({
|
||||
listen: vi.fn(() => vi.fn()),
|
||||
})),
|
||||
defaultUserPreferences: {
|
||||
colorScheme: 'light',
|
||||
locale: 'en',
|
||||
},
|
||||
getSnapshot: vi.fn(() => ({ document: {} })),
|
||||
loadSnapshot: vi.fn(),
|
||||
useTldrawUser: vi.fn(({ userPreferences }: { userPreferences: { colorScheme: string } }) => ({
|
||||
setUserPreferences: vi.fn(),
|
||||
userPreferences: {
|
||||
get: () => userPreferences,
|
||||
},
|
||||
})),
|
||||
}
|
||||
})
|
||||
|
||||
@@ -76,7 +93,7 @@ function renderedTldrawAssetUrls(): MockAssetUrls {
|
||||
}
|
||||
|
||||
function renderedTldrawProps(): MockTldrawProps {
|
||||
const props = tldrawMock.Tldraw.mock.calls[0]?.[0] as MockTldrawProps
|
||||
const props = tldrawMock.Tldraw.mock.lastCall?.[0] as MockTldrawProps
|
||||
expect(props).toBeDefined()
|
||||
return props
|
||||
}
|
||||
@@ -125,6 +142,13 @@ function expectBundledTldrawAssetUrls(assetUrls: MockAssetUrls) {
|
||||
}
|
||||
|
||||
describe('TldrawWhiteboard', () => {
|
||||
afterEach(() => {
|
||||
cleanup()
|
||||
document.documentElement.removeAttribute('data-theme')
|
||||
document.documentElement.classList.remove('dark')
|
||||
vi.clearAllMocks()
|
||||
})
|
||||
|
||||
it('uses bundled tldraw assets instead of CDN URLs', () => {
|
||||
render(
|
||||
<TldrawWhiteboard
|
||||
@@ -142,6 +166,50 @@ describe('TldrawWhiteboard', () => {
|
||||
expectBundledTldrawAssetUrls(renderedTldrawAssetUrls())
|
||||
})
|
||||
|
||||
it('passes Tolaria dark mode to tldraw', () => {
|
||||
document.documentElement.setAttribute('data-theme', 'dark')
|
||||
document.documentElement.classList.add('dark')
|
||||
|
||||
render(
|
||||
<TldrawWhiteboard
|
||||
boardId="board-1"
|
||||
height="520"
|
||||
snapshot=""
|
||||
width=""
|
||||
onSizeChange={vi.fn()}
|
||||
onSnapshotChange={vi.fn()}
|
||||
/>
|
||||
)
|
||||
|
||||
expect(renderedTldrawProps().user?.userPreferences.get().colorScheme).toBe('dark')
|
||||
})
|
||||
|
||||
it('updates the tldraw color scheme when Tolaria theme changes', async () => {
|
||||
document.documentElement.setAttribute('data-theme', 'light')
|
||||
|
||||
render(
|
||||
<TldrawWhiteboard
|
||||
boardId="board-1"
|
||||
height="520"
|
||||
snapshot=""
|
||||
width=""
|
||||
onSizeChange={vi.fn()}
|
||||
onSnapshotChange={vi.fn()}
|
||||
/>
|
||||
)
|
||||
|
||||
expect(renderedTldrawProps().user?.userPreferences.get().colorScheme).toBe('light')
|
||||
|
||||
act(() => {
|
||||
document.documentElement.setAttribute('data-theme', 'dark')
|
||||
document.documentElement.classList.add('dark')
|
||||
})
|
||||
|
||||
await waitFor(() => {
|
||||
expect(renderedTldrawProps().user?.userPreferences.get().colorScheme).toBe('dark')
|
||||
})
|
||||
})
|
||||
|
||||
it('installs the text measurement guard when the canvas mounts', () => {
|
||||
render(
|
||||
<TldrawWhiteboard
|
||||
|
||||
@@ -9,20 +9,26 @@ import {
|
||||
TldrawUiMenuContextProvider,
|
||||
Tldraw,
|
||||
createTLStore,
|
||||
defaultUserPreferences,
|
||||
getSnapshot,
|
||||
loadSnapshot,
|
||||
react as reactToTldrawSignal,
|
||||
useDialogs,
|
||||
useTldrawUser,
|
||||
useTranslation,
|
||||
type Editor,
|
||||
type TLEventInfo,
|
||||
type TLUiDialog,
|
||||
type TLStoreSnapshot,
|
||||
type TLUserPreferences,
|
||||
} from 'tldraw'
|
||||
import 'tldraw/tldraw.css'
|
||||
import { useDocumentThemeMode } from '../hooks/useDocumentThemeMode'
|
||||
import type { ResolvedThemeMode } from '../lib/themeMode'
|
||||
import { installTldrawTextMeasurementGuard } from './tldrawTextMeasurementGuard'
|
||||
|
||||
const EMPTY_TLDRAW_TRANSLATION_URL = 'data:application/json;base64,e30K'
|
||||
const TOLARIA_TLDRAW_USER_ID = 'tolaria-whiteboard'
|
||||
|
||||
function resolveTldrawAssetUrl(assetUrl: string | undefined): string {
|
||||
return assetUrl ?? EMPTY_TLDRAW_TRANSLATION_URL
|
||||
@@ -89,6 +95,18 @@ function cssSize({ height, width }: PixelSize): CSSProperties {
|
||||
} as CSSProperties
|
||||
}
|
||||
|
||||
function tldrawUserPreferences(themeMode: ResolvedThemeMode): TLUserPreferences {
|
||||
return {
|
||||
...defaultUserPreferences,
|
||||
id: TOLARIA_TLDRAW_USER_ID,
|
||||
colorScheme: themeMode,
|
||||
}
|
||||
}
|
||||
|
||||
function ignoreTldrawUserPreferencesUpdate(preferences: TLUserPreferences) {
|
||||
void preferences
|
||||
}
|
||||
|
||||
function parseSnapshot(source: string): TLStoreSnapshot | null {
|
||||
if (!source.trim()) return null
|
||||
|
||||
@@ -387,6 +405,12 @@ export function TldrawWhiteboard({
|
||||
const persistedSize = useMemo(() => normalizeSize({ height, width }), [height, width])
|
||||
const [resizingSize, setResizingSize] = useState<PixelSize | null>(null)
|
||||
const visibleSize = resizingSize ?? persistedSize
|
||||
const themeMode = useDocumentThemeMode()
|
||||
const userPreferences = useMemo(() => tldrawUserPreferences(themeMode), [themeMode])
|
||||
const tldrawUser = useTldrawUser({
|
||||
setUserPreferences: ignoreTldrawUserPreferencesUpdate,
|
||||
userPreferences,
|
||||
})
|
||||
|
||||
useEffect(() => {
|
||||
onSnapshotChangeRef.current = onSnapshotChange
|
||||
@@ -483,6 +507,7 @@ export function TldrawWhiteboard({
|
||||
components={tldrawUiComponents}
|
||||
onMount={installWhiteboardRuntimeGuards}
|
||||
store={store}
|
||||
user={tldrawUser}
|
||||
/>
|
||||
<div
|
||||
aria-label="Resize whiteboard width"
|
||||
|
||||
Reference in New Issue
Block a user