codemirror-editor.ts 1.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950
  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, useCodeMirrorEditor } from '../services';
  7. const isValid = (u: UseCodeMirrorEditor) => {
  8. return u.state != null && u.view != null;
  9. };
  10. const isDeepEquals = <T extends object>(obj1: T, obj2: T): boolean => {
  11. const typedKeys = Object.keys(obj1) as (keyof typeof obj1)[];
  12. return typedKeys.every(key => obj1[key] === obj2[key]);
  13. };
  14. export const useCodeMirrorEditorIsolated = (
  15. key: string | null, container?: HTMLDivElement | null, props?: ReactCodeMirrorProps,
  16. ): SWRResponse<UseCodeMirrorEditor> => {
  17. const ref = useRef<UseCodeMirrorEditor>();
  18. const currentData = ref.current;
  19. const swrKey = key != null ? `codeMirrorEditor_${key}` : null;
  20. const mergedProps = useMemo<UseCodeMirror>(() => {
  21. return deepmerge(
  22. props ?? {},
  23. {
  24. container,
  25. },
  26. );
  27. }, [container, props]);
  28. const newData = useCodeMirrorEditor(mergedProps);
  29. const shouldUpdate = swrKey != null && container != null && props != null && (
  30. currentData == null
  31. || (isValid(newData) && !isDeepEquals(currentData, newData))
  32. );
  33. if (shouldUpdate) {
  34. ref.current = newData;
  35. }
  36. return useSWRStatic(swrKey, shouldUpdate ? newData : undefined);
  37. };