|
@@ -1,6 +1,12 @@
|
|
|
import {
|
|
import {
|
|
|
- type ReactNode, type JSX,
|
|
|
|
|
- memo, useCallback, useEffect, useMemo, useRef, useState,
|
|
|
|
|
|
|
+ type JSX,
|
|
|
|
|
+ type ReactNode,
|
|
|
|
|
+ memo,
|
|
|
|
|
+ useCallback,
|
|
|
|
|
+ useEffect,
|
|
|
|
|
+ useMemo,
|
|
|
|
|
+ useRef,
|
|
|
|
|
+ useState,
|
|
|
} from 'react';
|
|
} from 'react';
|
|
|
|
|
|
|
|
import { debounce } from 'throttle-debounce';
|
|
import { debounce } from 'throttle-debounce';
|
|
@@ -9,35 +15,36 @@ import type { IGraphViewerGlobal } from '..';
|
|
|
import { generateMxgraphData } from '../utils/embed';
|
|
import { generateMxgraphData } from '../utils/embed';
|
|
|
import { isGraphViewerGlobal } from '../utils/global';
|
|
import { isGraphViewerGlobal } from '../utils/global';
|
|
|
|
|
|
|
|
-
|
|
|
|
|
import styles from './DrawioViewer.module.scss';
|
|
import styles from './DrawioViewer.module.scss';
|
|
|
|
|
|
|
|
-
|
|
|
|
|
declare global {
|
|
declare global {
|
|
|
// eslint-disable-next-line vars-on-top, no-var
|
|
// eslint-disable-next-line vars-on-top, no-var
|
|
|
var GraphViewer: IGraphViewerGlobal;
|
|
var GraphViewer: IGraphViewerGlobal;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-
|
|
|
|
|
export type DrawioViewerProps = {
|
|
export type DrawioViewerProps = {
|
|
|
- diagramIndex: number,
|
|
|
|
|
- bol: number,
|
|
|
|
|
- eol: number,
|
|
|
|
|
- children?: ReactNode,
|
|
|
|
|
- onRenderingStart?: () => void,
|
|
|
|
|
- onRenderingUpdated?: (mxfile: string | null) => void,
|
|
|
|
|
-}
|
|
|
|
|
|
|
+ diagramIndex: number;
|
|
|
|
|
+ bol: number;
|
|
|
|
|
+ eol: number;
|
|
|
|
|
+ children?: ReactNode;
|
|
|
|
|
+ onRenderingStart?: () => void;
|
|
|
|
|
+ onRenderingUpdated?: (mxfile: string | null) => void;
|
|
|
|
|
+};
|
|
|
|
|
|
|
|
export type DrawioEditByViewerProps = {
|
|
export type DrawioEditByViewerProps = {
|
|
|
- bol: number,
|
|
|
|
|
- eol: number,
|
|
|
|
|
- drawioMxFile: string,
|
|
|
|
|
-}
|
|
|
|
|
|
|
+ bol: number;
|
|
|
|
|
+ eol: number;
|
|
|
|
|
+ drawioMxFile: string;
|
|
|
|
|
+};
|
|
|
|
|
|
|
|
export const DrawioViewer = memo((props: DrawioViewerProps): JSX.Element => {
|
|
export const DrawioViewer = memo((props: DrawioViewerProps): JSX.Element => {
|
|
|
const {
|
|
const {
|
|
|
- diagramIndex, bol, eol, children,
|
|
|
|
|
- onRenderingStart, onRenderingUpdated,
|
|
|
|
|
|
|
+ diagramIndex,
|
|
|
|
|
+ bol,
|
|
|
|
|
+ eol,
|
|
|
|
|
+ children,
|
|
|
|
|
+ onRenderingStart,
|
|
|
|
|
+ onRenderingUpdated,
|
|
|
} = props;
|
|
} = props;
|
|
|
|
|
|
|
|
const drawioContainerRef = useRef<HTMLDivElement>(null);
|
|
const drawioContainerRef = useRef<HTMLDivElement>(null);
|
|
@@ -56,7 +63,9 @@ export const DrawioViewer = memo((props: DrawioViewerProps): JSX.Element => {
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- const mxgraphs = drawioContainerRef.current.getElementsByClassName('mxgraph') as HTMLCollectionOf<HTMLElement>;
|
|
|
|
|
|
|
+ const mxgraphs = drawioContainerRef.current.getElementsByClassName(
|
|
|
|
|
+ 'mxgraph',
|
|
|
|
|
+ ) as HTMLCollectionOf<HTMLElement>;
|
|
|
if (mxgraphs.length > 0) {
|
|
if (mxgraphs.length > 0) {
|
|
|
// This component should have only one '.mxgraph' element
|
|
// This component should have only one '.mxgraph' element
|
|
|
const div = mxgraphs[0];
|
|
const div = mxgraphs[0];
|
|
@@ -73,15 +82,17 @@ export const DrawioViewer = memo((props: DrawioViewerProps): JSX.Element => {
|
|
|
GraphViewer.prototype.lightboxZIndex = 1055; // set $zindex-modal
|
|
GraphViewer.prototype.lightboxZIndex = 1055; // set $zindex-modal
|
|
|
GraphViewer.prototype.toolbarZIndex = 1055; // set $zindex-modal
|
|
GraphViewer.prototype.toolbarZIndex = 1055; // set $zindex-modal
|
|
|
GraphViewer.createViewerForElement(div);
|
|
GraphViewer.createViewerForElement(div);
|
|
|
- }
|
|
|
|
|
- catch (err) {
|
|
|
|
|
|
|
+ } catch (err) {
|
|
|
setError(err);
|
|
setError(err);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}, []);
|
|
}, []);
|
|
|
|
|
|
|
|
- const renderDrawioWithDebounce = useMemo(() => debounce(200, renderDrawio), [renderDrawio]);
|
|
|
|
|
|
|
+ const renderDrawioWithDebounce = useMemo(
|
|
|
|
|
+ () => debounce(200, renderDrawio),
|
|
|
|
|
+ [renderDrawio],
|
|
|
|
|
+ );
|
|
|
|
|
|
|
|
const mxgraphHtml = useMemo(() => {
|
|
const mxgraphHtml = useMemo(() => {
|
|
|
setError(undefined);
|
|
setError(undefined);
|
|
@@ -90,17 +101,16 @@ export const DrawioViewer = memo((props: DrawioViewerProps): JSX.Element => {
|
|
|
return '';
|
|
return '';
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- const code = children instanceof Array
|
|
|
|
|
|
|
+ const code = Array.isArray(children)
|
|
|
? children
|
|
? children
|
|
|
- .filter(elem => (typeof elem === 'string')) // omit non-string elements (e.g. br element generated by line-breaks option)
|
|
|
|
|
- .join('')
|
|
|
|
|
|
|
+ .filter((elem) => typeof elem === 'string') // omit non-string elements (e.g. br element generated by line-breaks option)
|
|
|
|
|
+ .join('')
|
|
|
: children.toString();
|
|
: children.toString();
|
|
|
|
|
|
|
|
- let mxgraphData;
|
|
|
|
|
|
|
+ let mxgraphData: string | undefined;
|
|
|
try {
|
|
try {
|
|
|
mxgraphData = generateMxgraphData(code);
|
|
mxgraphData = generateMxgraphData(code);
|
|
|
- }
|
|
|
|
|
- catch (err) {
|
|
|
|
|
|
|
+ } catch (err) {
|
|
|
setError(err);
|
|
setError(err);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -125,8 +135,8 @@ export const DrawioViewer = memo((props: DrawioViewerProps): JSX.Element => {
|
|
|
const container = drawioContainerRef.current;
|
|
const container = drawioContainerRef.current;
|
|
|
if (container == null) return;
|
|
if (container == null) return;
|
|
|
|
|
|
|
|
- const observerCallback = (mutationRecords:MutationRecord[]) => {
|
|
|
|
|
- mutationRecords.forEach((record:MutationRecord) => {
|
|
|
|
|
|
|
+ const observerCallback = (mutationRecords: MutationRecord[]) => {
|
|
|
|
|
+ for (const record of mutationRecords) {
|
|
|
const target = record.target as HTMLElement;
|
|
const target = record.target as HTMLElement;
|
|
|
|
|
|
|
|
const mxgraphData = target.dataset.mxgraph;
|
|
const mxgraphData = target.dataset.mxgraph;
|
|
@@ -134,7 +144,7 @@ export const DrawioViewer = memo((props: DrawioViewerProps): JSX.Element => {
|
|
|
const mxgraph = JSON.parse(mxgraphData);
|
|
const mxgraph = JSON.parse(mxgraphData);
|
|
|
onRenderingUpdated?.(mxgraph.xml);
|
|
onRenderingUpdated?.(mxgraph.xml);
|
|
|
}
|
|
}
|
|
|
- });
|
|
|
|
|
|
|
+ }
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
const observer = new MutationObserver(observerCallback);
|
|
const observer = new MutationObserver(observerCallback);
|
|
@@ -152,11 +162,11 @@ export const DrawioViewer = memo((props: DrawioViewerProps): JSX.Element => {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
const observer = new ResizeObserver((entries) => {
|
|
const observer = new ResizeObserver((entries) => {
|
|
|
- entries.forEach(() => {
|
|
|
|
|
- // setElementWidth(el.contentRect.width);
|
|
|
|
|
|
|
+ for (const entry of entries) {
|
|
|
|
|
+ // setElementWidth(entry.contentRect.width);
|
|
|
onRenderingStart?.();
|
|
onRenderingStart?.();
|
|
|
renderDrawioWithDebounce();
|
|
renderDrawioWithDebounce();
|
|
|
- });
|
|
|
|
|
|
|
+ }
|
|
|
});
|
|
});
|
|
|
observer.observe(drawioContainerRef.current);
|
|
observer.observe(drawioContainerRef.current);
|
|
|
return () => {
|
|
return () => {
|
|
@@ -174,18 +184,18 @@ export const DrawioViewer = memo((props: DrawioViewerProps): JSX.Element => {
|
|
|
data-end-line-number-of-markdown={eol}
|
|
data-end-line-number-of-markdown={eol}
|
|
|
>
|
|
>
|
|
|
{/* show error */}
|
|
{/* show error */}
|
|
|
- { error != null && (
|
|
|
|
|
|
|
+ {error != null && (
|
|
|
<span className="text-muted">
|
|
<span className="text-muted">
|
|
|
<span className="material-symbols-outlined me-1">error</span>
|
|
<span className="material-symbols-outlined me-1">error</span>
|
|
|
{error.name && <strong>{error.name}: </strong>}
|
|
{error.name && <strong>{error.name}: </strong>}
|
|
|
{error.message}
|
|
{error.message}
|
|
|
</span>
|
|
</span>
|
|
|
- ) }
|
|
|
|
|
|
|
+ )}
|
|
|
|
|
|
|
|
- { error == null && (
|
|
|
|
|
- // eslint-disable-next-line react/no-danger
|
|
|
|
|
|
|
+ {error == null && (
|
|
|
|
|
+ // biome-ignore lint/security/noDangerouslySetInnerHtml: ignore
|
|
|
<div dangerouslySetInnerHTML={{ __html: mxgraphHtml }} />
|
|
<div dangerouslySetInnerHTML={{ __html: mxgraphHtml }} />
|
|
|
- ) }
|
|
|
|
|
|
|
+ )}
|
|
|
</div>
|
|
</div>
|
|
|
);
|
|
);
|
|
|
});
|
|
});
|