mirror of
https://github.com/supabase/supabase.git
synced 2026-05-08 18:00:20 -04:00
bc8724c46e
<!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Improved rendering and visual consistency of exported database schema images by refining font handling during SVG and PNG export processes. Schema diagrams now display with better visual fidelity when exported. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
92 lines
2.8 KiB
TypeScript
92 lines
2.8 KiB
TypeScript
import { toPng, toSvg } from 'html-to-image'
|
|
import { useMemo, useState } from 'react'
|
|
import { toast } from 'sonner'
|
|
|
|
import { useStaticEffectEvent } from '@/hooks/useStaticEffectEvent'
|
|
|
|
export const useExportSchemaToImage = () => {
|
|
const [isDownloading, setIsDownloading] = useState(false)
|
|
// By doing this once and passing the result to html-to-image options, we avoid html-to-image calculating it for every node.
|
|
// This improves performance a lot. See https://github.com/bubkoo/html-to-image/issues/542#issuecomment-3249408793
|
|
const allPropertyNames = useMemo(() => getAllPropertyNames(), [])
|
|
|
|
const exportSchemaToImage = useStaticEffectEvent(
|
|
async ({
|
|
element,
|
|
projectRef,
|
|
x,
|
|
y,
|
|
zoom,
|
|
format,
|
|
}: {
|
|
element: HTMLElement
|
|
projectRef: string
|
|
x: number
|
|
y: number
|
|
zoom: number
|
|
format: 'svg' | 'png'
|
|
}) => {
|
|
setIsDownloading(true)
|
|
const width = element.clientWidth
|
|
const height = element.clientHeight
|
|
|
|
const options = {
|
|
includeStyleProperties: allPropertyNames,
|
|
backgroundColor: 'white',
|
|
width,
|
|
height,
|
|
style: {
|
|
width: width.toString(),
|
|
height: height.toString(),
|
|
transform: `translate(${x}px, ${y}px) scale(${zoom})`,
|
|
},
|
|
skipFonts: true,
|
|
}
|
|
try {
|
|
if (format === 'svg') {
|
|
const data = await toSvg(element, options)
|
|
const a = document.createElement('a')
|
|
a.setAttribute('download', `supabase-schema-${projectRef}.svg`)
|
|
a.setAttribute('href', data)
|
|
a.click()
|
|
toast.success('Successfully downloaded as SVG')
|
|
} else if (format === 'png') {
|
|
const data = await toPng(element, options)
|
|
const a = document.createElement('a')
|
|
a.setAttribute('download', `supabase-schema-${projectRef}.png`)
|
|
a.setAttribute('href', data)
|
|
a.click()
|
|
toast.success('Successfully downloaded as PNG')
|
|
}
|
|
} catch (error) {
|
|
console.error('Failed to download:', error)
|
|
toast.error(`Failed to download current view: ${(error as Error).message}`)
|
|
} finally {
|
|
setIsDownloading(false)
|
|
}
|
|
}
|
|
)
|
|
|
|
return useMemo(
|
|
() => ({ isDownloading, exportSchemaToImage }),
|
|
[isDownloading, exportSchemaToImage]
|
|
)
|
|
}
|
|
|
|
// Get all property names accessible through getComputedStyle(), excluding custom properties
|
|
export const getAllPropertyNames = () => {
|
|
if (typeof document === 'undefined' || typeof getComputedStyle === 'undefined') {
|
|
return []
|
|
}
|
|
|
|
const names = []
|
|
const style = getComputedStyle(document.documentElement)
|
|
for (let i = 0; i < style.length; i++) {
|
|
const name = style[i]
|
|
if (!name.startsWith('--')) {
|
|
names.push(name)
|
|
}
|
|
}
|
|
return names
|
|
}
|