import { j as jsxRuntimeExports, E as EditorViewer } from "./doenetml-cB_aZGJ5.js";
import React__default, { useState, useEffect, useRef } from "react";
import { u as useDoenetRenderer } from "./useDoenetRenderer-DN3Z9CW3.js";
import { s as sizeToCSS } from "./css-BJLDLYRJ.js";
function resolveElements(elementOrSelector, scope, selectorCache) {
  if (elementOrSelector instanceof EventTarget) {
    return [elementOrSelector];
  } else if (typeof elementOrSelector === "string") {
    let root = document;
    const elements = root.querySelectorAll(elementOrSelector);
    return elements ? Array.from(elements) : [];
  }
  return Array.from(elementOrSelector);
}
const thresholds = {
  some: 0,
  all: 1
};
function inView(elementOrSelector, onStart, { root, margin: rootMargin, amount = "some" } = {}) {
  const elements = resolveElements(elementOrSelector);
  const activeIntersections = /* @__PURE__ */ new WeakMap();
  const onIntersectionChange = (entries) => {
    entries.forEach((entry) => {
      const onEnd = activeIntersections.get(entry.target);
      if (entry.isIntersecting === Boolean(onEnd))
        return;
      if (entry.isIntersecting) {
        const newOnEnd = onStart(entry.target, entry);
        if (typeof newOnEnd === "function") {
          activeIntersections.set(entry.target, newOnEnd);
        } else {
          observer.unobserve(entry.target);
        }
      } else if (typeof onEnd === "function") {
        onEnd(entry);
        activeIntersections.delete(entry.target);
      }
    });
  };
  const observer = new IntersectionObserver(onIntersectionChange, {
    root,
    rootMargin,
    threshold: typeof amount === "number" ? amount : thresholds[amount]
  });
  elements.forEach((element) => observer.observe(element));
  return () => observer.disconnect();
}
function useInView(ref, { root, margin, amount, once = false, initial = false } = {}) {
  const [isInView, setInView] = useState(initial);
  useEffect(() => {
    if (!ref.current || once && isInView)
      return;
    const onEnter = () => {
      setInView(true);
      return once ? void 0 : () => setInView(false);
    };
    const options = {
      root: root && root.current || void 0,
      margin,
      amount
    };
    return inView(ref.current, onEnter, options);
  }, [root, ref, margin, once, amount]);
  return isInView;
}
const codeEditor = React__default.memo(function CodeEditor(props) {
  let { id, SVs, actions, ignoreUpdate, callAction, fetchExternalDoenetML } = useDoenetRenderer(props);
  CodeEditor.baseStateVariable = "immediateValue";
  const [currentValue, setCurrentValue] = useState(SVs.immediateValue);
  const currentValueRef = useRef(currentValue);
  currentValueRef.current = currentValue;
  const ref = useRef(null);
  const isInView = useInView(ref, { amount: 0 });
  useEffect(() => {
    callAction({
      action: actions.recordVisibilityChange,
      args: { isVisible: isInView }
    });
  }, [isInView]);
  const immediateDoenetmlChangeCallback = React__default.useCallback(
    (value) => {
      setCurrentValue(value);
      callAction({
        action: actions.updateImmediateValue,
        args: { text: value },
        baseVariableValue: value
      });
    },
    [actions.updateImmediateValue, callAction]
  );
  const doenetmlChangeCallback = React__default.useCallback(
    (value) => {
      callAction({
        action: actions.updateValue,
        baseVariableValue: currentValueRef.current
      });
    },
    [actions.updateValue, callAction]
  );
  useEffect(() => {
    return () => {
      callAction({
        action: actions.recordVisibilityChange,
        args: { isVisible: false }
      });
    };
  }, []);
  if (SVs.hidden) {
    return null;
  }
  if (!ignoreUpdate && SVs.immediateValue !== currentValue) {
    setCurrentValue(SVs.immediateValue);
  }
  return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { ref, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
    EditorViewer,
    {
      id,
      activityId: id,
      prefixForIds: id + "::",
      doenetML: currentValue,
      width: sizeToCSS(SVs.width),
      height: sizeToCSS(SVs.height),
      showViewer: SVs.showResults,
      viewerLocation: SVs.resultsLocation,
      showResponses: false,
      showFormatter: SVs.showFormatter,
      readOnly: SVs.readOnly,
      immediateDoenetmlChangeCallback,
      doenetmlChangeCallback,
      fetchExternalDoenetML
    }
  ) });
});
export {
  codeEditor as default
};
