| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091 |
- 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', `briven-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', `briven-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
- }
|