codeimage icon indicating copy to clipboard operation
codeimage copied to clipboard

🐞 - Broken code mirror cursor and line numbers on scaled content

Open riccardoperra opened this issue 2 years ago • 1 comments

~Added to fix mobile editor cursor and gutter when scaling the content, should be removed since it is an experimental property~.

Edit: After an investigation, it seems that there is a browser issue with "getBoundingClientRects"that returns inconsistent values when the parent node has the transform scale property.

This could be fixed wrapping the scaled content into an iframe. This could be a possible implementation that doesn't cover these issues:

  • Stylesheet are not fully loaded. When switching a theme that uses @emotion/css the stylesheet must be loaded into the iframe.
  • Iframe position must be changered.
  • Frame handler size could be fixed

Possible implementation: create a new app package that handle only his style and the editor content

// IFrame.tsx

type IFrameProps = JSX.IntrinsicElements['iframe'] & {};

export function IFrame(props: IFrameProps): JSX.Element {
  const [ref, setRef] = createSignal<HTMLIFrameElement>();
  const [mountNode, setMountNode] = createSignal<HTMLElement>();
  const [height, setHeight] = createSignal(0);
  const [width, setWidth] = createSignal(0);

  createEffect(
    on(ref, frame => {
      if (!frame || !frame.contentWindow) return;
      const currentHead = window.document.head;
      frame.contentDocument!.head.innerHTML = currentHead.innerHTML;
      setMountNode(() => frame.contentWindow?.document.body);

      setTimeout(() => {
        const scrollHeight = ref()?.contentWindow?.document.body.scrollHeight;
        const scrollWidth = ref()?.contentWindow?.document.body.scrollWidth;
        setHeight(scrollHeight ?? 0);
        setWidth(scrollWidth ?? 0);
      });
    }),
  );

  return (
    <iframe {...props} ref={setRef} width={width()} height={height()}>
      <Show when={mountNode()}>
        {node => <Portal mount={node}>{props.children}</Portal>}
      </Show>
    </iframe>
  );
}

// FrameHandler.tsx

export function FrameHandler(
  props: PropsWithChildren<FrameHandlerProps>,
): JSXElement {
  const [internalRef, setInternalRef] = createSignal<HTMLDivElement>();
  const [canvasScale, setCanvasScale] = createSignal(1);
  const ratio = 0.1;

  createEffect(
    on([internalRef], ([frame]) => {
      setTimeout(() => {
        const scale = getScaleByRatio(
          // TODO: should be a ref (?)
          frame?.parentElement,
          frame,
          1 + ratio,
        );
        props.onScaleChange(scale);
        setCanvasScale(scale);
      });
    }),
  );

  return (
    <Box class={styles.wrapper}>
      <div
        class={styles.handler}
        style={assignInlineVars({
          [styles.frameHandlerVars.scale]: canvasScale().toString(),
        })}
        ref={createRef<'div'>(props, e => {
          setInternalRef(() => e);
        })}
      >
        <div use:exportExclude={true} class={styles.squaredBackgroundOverlay} />

        <IFrame>{props.children}</IFrame>
      </div>
    </Box>
  );
}

riccardoperra avatar Mar 10 '22 21:03 riccardoperra

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

stale[bot] avatar Jun 30 '22 08:06 stale[bot]

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

stale[bot] avatar Aug 30 '22 21:08 stale[bot]

What about Monaco Editor which powers VS Code.

KunalTanwar avatar Dec 17 '22 20:12 KunalTanwar

Monaco Editor is unusable on mobile, has a bigger bundle and currently there will be a lot of effort switching editor library 😅

This is something not blocking in my opinion then at the moment is not prioritized

riccardoperra avatar Dec 17 '22 20:12 riccardoperra

Yeah you are right for now it can work out, its just the cursor position is bothering me!! 😅

P.S - No hurry but sometime take a look at this

KunalTanwar avatar Dec 17 '22 20:12 KunalTanwar