codemirror-editor.ts 1.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253
  1. import { useMemo, useRef } from 'react';
  2. import { useSWRStatic } from '@growi/core/dist/swr';
  3. import type { ReactCodeMirrorProps, UseCodeMirror } from '@uiw/react-codemirror';
  4. import type { SWRResponse } from 'swr';
  5. import deepmerge from 'ts-deepmerge';
  6. import type { UseCodeMirrorEditor } from '../services';
  7. import { useCodeMirrorEditor } from '../services';
  8. const isValid = (u: UseCodeMirrorEditor) => {
  9. return u.state != null && u.view != null;
  10. };
  11. const isDeepEquals = <T extends object>(obj1: T, obj2: T): boolean => {
  12. const typedKeys = Object.keys(obj1) as (keyof typeof obj1)[];
  13. return typedKeys.every(key => obj1[key] === obj2[key]);
  14. };
  15. export const useCodeMirrorEditorIsolated = (
  16. key: string | null, container?: HTMLDivElement | null, props?: ReactCodeMirrorProps,
  17. ): SWRResponse<UseCodeMirrorEditor> => {
  18. const ref = useRef<UseCodeMirrorEditor>();
  19. const currentData = ref.current;
  20. const swrKey = key != null ? `codeMirrorEditor_${key}` : null;
  21. const mergedProps = useMemo<UseCodeMirror>(() => {
  22. return deepmerge(
  23. props ?? {},
  24. {
  25. container,
  26. },
  27. );
  28. }, [container, props]);
  29. const newData = useCodeMirrorEditor(mergedProps);
  30. const shouldUpdate = swrKey != null && container != null && props != null && (
  31. currentData == null
  32. || (isValid(newData) && !isDeepEquals(currentData, newData))
  33. );
  34. if (shouldUpdate) {
  35. ref.current = newData;
  36. // eslint-disable-next-line no-console
  37. console.info('Initializing codemirror for main');
  38. }
  39. return useSWRStatic(swrKey, shouldUpdate ? newData : undefined);
  40. };