@doenet/doenetml-iframe 0.7.20-dev.323 → 0.7.20-dev.326
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +261 -0
- package/index.d.ts +90 -5
- package/index.js +640 -140
- package/index.js.map +1 -1
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import * as
|
|
2
|
-
import
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import React__default, { createContext, useMemo, useCallback, useLayoutEffect, useEffect, useRef, useState, useContext, isValidElement } from "react";
|
|
3
3
|
import { MathJaxBaseContext, MathJax } from "better-react-mathjax";
|
|
4
4
|
import { createRoot } from "react-dom/client";
|
|
5
5
|
import { createPortal } from "react-dom";
|
|
@@ -337,7 +337,7 @@ var DefaultContext = {
|
|
|
337
337
|
style: void 0,
|
|
338
338
|
attr: void 0
|
|
339
339
|
};
|
|
340
|
-
var IconContext =
|
|
340
|
+
var IconContext = React__default.createContext && /* @__PURE__ */ React__default.createContext(DefaultContext);
|
|
341
341
|
var _excluded = ["attr", "size", "title"];
|
|
342
342
|
function _objectWithoutProperties(e2, t4) {
|
|
343
343
|
if (null == e2) return {};
|
|
@@ -405,12 +405,12 @@ function _toPrimitive(t4, r2) {
|
|
|
405
405
|
return ("string" === r2 ? String : Number)(t4);
|
|
406
406
|
}
|
|
407
407
|
function Tree2Element(tree) {
|
|
408
|
-
return tree && tree.map((node, i2) => /* @__PURE__ */
|
|
408
|
+
return tree && tree.map((node, i2) => /* @__PURE__ */ React__default.createElement(node.tag, _objectSpread$5({
|
|
409
409
|
key: i2
|
|
410
410
|
}, node.attr), Tree2Element(node.child)));
|
|
411
411
|
}
|
|
412
412
|
function GenIcon(data) {
|
|
413
|
-
return (props) => /* @__PURE__ */
|
|
413
|
+
return (props) => /* @__PURE__ */ React__default.createElement(IconBase, _extends$2({
|
|
414
414
|
attr: _objectSpread$5({}, data.attr)
|
|
415
415
|
}, props), Tree2Element(data.child));
|
|
416
416
|
}
|
|
@@ -421,7 +421,7 @@ function IconBase(props) {
|
|
|
421
421
|
var className;
|
|
422
422
|
if (conf.className) className = conf.className;
|
|
423
423
|
if (props.className) className = (className ? className + " " : "") + props.className;
|
|
424
|
-
return /* @__PURE__ */
|
|
424
|
+
return /* @__PURE__ */ React__default.createElement("svg", _extends$2({
|
|
425
425
|
stroke: "currentColor",
|
|
426
426
|
fill: "currentColor",
|
|
427
427
|
strokeWidth: "0"
|
|
@@ -433,9 +433,9 @@ function IconBase(props) {
|
|
|
433
433
|
height: computedSize,
|
|
434
434
|
width: computedSize,
|
|
435
435
|
xmlns: "http://www.w3.org/2000/svg"
|
|
436
|
-
}), title && /* @__PURE__ */
|
|
436
|
+
}), title && /* @__PURE__ */ React__default.createElement("title", null, title), props.children);
|
|
437
437
|
};
|
|
438
|
-
return IconContext !== void 0 ? /* @__PURE__ */
|
|
438
|
+
return IconContext !== void 0 ? /* @__PURE__ */ React__default.createElement(IconContext.Consumer, null, (conf) => elem(conf)) : elem(DefaultContext);
|
|
439
439
|
}
|
|
440
440
|
function MdError(props) {
|
|
441
441
|
return GenIcon({ "attr": { "viewBox": "0 0 24 24" }, "child": [{ "tag": "path", "attr": { "fill": "none", "d": "M0 0h24v24H0z" }, "child": [] }, { "tag": "path", "attr": { "d": "M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2m1 15h-2v-2h2zm0-4h-2V7h2z" }, "child": [] }] })(props);
|
|
@@ -20232,10 +20232,10 @@ var astToFiniteField$1$1 = class astToFiniteField$12 {
|
|
|
20232
20232
|
convert(t4, n2, r2 = PRIME$1) {
|
|
20233
20233
|
return finite_field_evaluate_ast$1(t4, n2, r2);
|
|
20234
20234
|
}
|
|
20235
|
-
}, evaluation_exports$1 = __exportAll$1({ evaluate: () => evaluate$
|
|
20235
|
+
}, evaluation_exports$1 = __exportAll$1({ evaluate: () => evaluate$2, evaluate_to_constant: () => evaluate_to_constant$1, f: () => f$2, finite_field_evaluate: () => finite_field_evaluate$1 }), astToMathjs$1$1 = new astToMathjs$2$1({ mathjs: mathjs_default$1 }), astToFiniteField$2 = new astToFiniteField$1$1(), f$2 = function(t4) {
|
|
20236
20236
|
var n2 = get_tree$1(t4), r2 = factorial_to_gamma_function$1(astToMathjs$1$1.convert(log_subscript_to_two_arg_log$1(normalize_function_names$1(normalize_applied_functions$1(n2)))));
|
|
20237
20237
|
return r2.evaluate.bind(r2);
|
|
20238
|
-
}, evaluate$
|
|
20238
|
+
}, evaluate$2 = function(t4, n2) {
|
|
20239
20239
|
return f$2(t4)(n2);
|
|
20240
20240
|
}, finite_field_evaluate$1 = function(t4, n2, r2) {
|
|
20241
20241
|
return astToFiniteField$2.convert(t4.tree, n2, r2);
|
|
@@ -25618,7 +25618,7 @@ function requireCssesc$1() {
|
|
|
25618
25618
|
return cssesc_1$1;
|
|
25619
25619
|
}
|
|
25620
25620
|
requireCssesc$1();
|
|
25621
|
-
const viewerIframeJsSource = '(function() {\n "use strict";\n async function waitForStandaloneBundle(timeoutMs) {\n if (typeof window.renderDoenetViewerToContainer === "function") {\n return true;\n }\n const deadline = Date.now() + timeoutMs;\n while (Date.now() < deadline) {\n await new Promise((resolve) => setTimeout(resolve, 50));\n if (typeof window.renderDoenetViewerToContainer === "function") {\n return true;\n }\n }\n return false;\n }\n ComlinkViewer.expose(\n { renderViewerWithFunctionProps },\n ComlinkViewer.windowEndpoint(globalThis.parent)\n );\n function renderViewerWithFunctionProps(...args) {\n const augmentedDoenetViewerProps = { ...doenetViewerProps };\n augmentedDoenetViewerProps.externalVirtualKeyboardProvided = true;\n for (const propName of doenetViewerPropsSpecified) {\n if (!(propName in doenetViewerProps)
|
|
25621
|
+
const viewerIframeJsSource = '(function() {\n "use strict";\n let lastAugmentedProps = null;\n let currentFunctionProps = {};\n const functionPropDispatchers = {};\n function getFunctionPropDispatcher(key) {\n let dispatcher = functionPropDispatchers[key];\n if (!dispatcher) {\n dispatcher = (...callArgs) => currentFunctionProps[key]?.(...callArgs);\n functionPropDispatchers[key] = dispatcher;\n }\n return dispatcher;\n }\n function functionPropArgsToMap(args) {\n const map = {};\n for (let i = 0; i < args.length; i += 2) {\n const key = args[i];\n const fn = args[i + 1];\n if (typeof key === "string" && typeof fn === "function") {\n map[key] = fn;\n }\n }\n return map;\n }\n function releaseFunctionProxy(fn) {\n try {\n fn?.[ComlinkViewer.releaseProxy]?.();\n } catch (e) {\n console.warn(\n "iframe DoenetViewer: failed to release stale Comlink proxy",\n e\n );\n }\n }\n function setCurrentFunctionProps(incoming) {\n for (const [key, fn] of Object.entries(currentFunctionProps)) {\n if (incoming[key] !== fn) {\n releaseFunctionProxy(fn);\n }\n }\n currentFunctionProps = incoming;\n }\n function defaultRequestScrollTo(offset) {\n messageParentFromViewer({ type: "scrollTo", offset });\n }\n function syncAugmentedFunctionProps() {\n if (!lastAugmentedProps) {\n return;\n }\n const next = {};\n for (const [key, val] of Object.entries(lastAugmentedProps)) {\n if (typeof val !== "function") {\n next[key] = val;\n }\n }\n for (const key of Object.keys(currentFunctionProps)) {\n next[key] = getFunctionPropDispatcher(key);\n }\n if (!("requestScrollTo" in next)) {\n next.requestScrollTo = defaultRequestScrollTo;\n }\n lastAugmentedProps = next;\n }\n let currentDoenetMLSource = null;\n function resolveDoenetMLSource(root) {\n if (currentDoenetMLSource !== null) {\n return currentDoenetMLSource;\n }\n const scriptTag = root.querySelector(\'script[type="text/doenetml"]\');\n currentDoenetMLSource = scriptTag?.innerHTML ?? "";\n return currentDoenetMLSource;\n }\n async function waitForStandaloneBundle(timeoutMs) {\n if (typeof window.renderDoenetViewerToContainer === "function") {\n return true;\n }\n const deadline = Date.now() + timeoutMs;\n while (Date.now() < deadline) {\n await new Promise((resolve) => setTimeout(resolve, 50));\n if (typeof window.renderDoenetViewerToContainer === "function") {\n return true;\n }\n }\n return false;\n }\n ComlinkViewer.expose(\n {\n renderViewerWithFunctionProps,\n updateViewerProps(updatedSerializableProps) {\n if (!lastAugmentedProps) {\n console.warn(\n "iframe DoenetViewer: updateViewerProps arrived before renderViewerWithFunctionProps completed — likely a bug in the iframe wrapper\'s queue/replay sequencing."\n );\n return;\n }\n const { doenetML, ...rest } = updatedSerializableProps;\n if (typeof doenetML === "string") {\n currentDoenetMLSource = doenetML;\n }\n lastAugmentedProps = {\n ...lastAugmentedProps,\n ...rest\n };\n renderWithLastAugmentedProps();\n },\n updateViewerFunctionProps(...args) {\n if (!lastAugmentedProps) {\n console.warn(\n "iframe DoenetViewer: updateViewerFunctionProps arrived before renderViewerWithFunctionProps completed — likely a bug in the iframe wrapper\'s queue/replay sequencing."\n );\n return;\n }\n const incoming = functionPropArgsToMap(args);\n const prevKeys = Object.keys(currentFunctionProps).sort();\n const nextKeys = Object.keys(incoming).sort();\n const keysChanged = prevKeys.length !== nextKeys.length || prevKeys.some((key, i) => key !== nextKeys[i]);\n setCurrentFunctionProps(incoming);\n if (keysChanged) {\n syncAugmentedFunctionProps();\n renderWithLastAugmentedProps();\n }\n }\n },\n ComlinkViewer.windowEndpoint(globalThis.parent)\n );\n function renderViewerWithFunctionProps(...args) {\n setCurrentFunctionProps(functionPropArgsToMap(args));\n const augmentedDoenetViewerProps = { ...doenetViewerProps };\n augmentedDoenetViewerProps.externalVirtualKeyboardProvided = true;\n for (const propName of doenetViewerPropsSpecified) {\n if (!(propName in doenetViewerProps) && propName in currentFunctionProps) {\n augmentedDoenetViewerProps[propName] = getFunctionPropDispatcher(propName);\n }\n }\n if (!doenetViewerPropsSpecified.includes("requestScrollTo")) {\n augmentedDoenetViewerProps.requestScrollTo = defaultRequestScrollTo;\n }\n lastAugmentedProps = augmentedDoenetViewerProps;\n renderWithLastAugmentedProps();\n }\n function renderWithLastAugmentedProps() {\n const root = document.getElementById("root");\n window.renderDoenetViewerToContainer(\n root,\n resolveDoenetMLSource(root),\n lastAugmentedProps\n );\n }\n function installSharedCorePortProvider() {\n let coreCounter = 0;\n window.doenetGlobalConfig.createExternalCoreWorkerPort = () => {\n const coreId = `${viewerId}-core-${++coreCounter}`;\n const channel = new MessageChannel();\n window.parent.postMessage(\n { origin: viewerId, data: { type: "createSharedCore", coreId } },\n window.parent.origin,\n [channel.port2]\n );\n return {\n port: channel.port1,\n destroy: (suspectWedge) => {\n messageParentFromViewer({\n type: "destroySharedCore",\n coreId,\n suspectWedge: Boolean(suspectWedge)\n });\n }\n };\n };\n }\n (async () => {\n if (await waitForStandaloneBundle(6e4)) {\n if (typeof doenetSharedCoreWorker !== "undefined" && doenetSharedCoreWorker) {\n installSharedCorePortProvider();\n }\n messageParentFromViewer({ iframeReady: true });\n } else {\n messageParentFromViewer({\n error: "Invalid DoenetML version or DoenetML package not found"\n });\n }\n })().catch((err) => {\n console.error(\n "iframe DoenetViewer: unexpected failure while signalling iframeReady",\n err\n );\n try {\n messageParentFromViewer({\n error: "iframe viewer failed to initialize"\n });\n } catch {\n }\n });\n function messageParentFromViewer(data) {\n window.parent.postMessage(\n {\n origin: viewerId,\n data\n },\n window.parent.origin\n );\n }\n})();\n';
|
|
25622
25622
|
const editorIframeJsSource = `(function() {
|
|
25623
25623
|
"use strict";
|
|
25624
25624
|
let editorControlHandle = null;
|
|
@@ -26026,6 +26026,140 @@ function destroySharedCoresForViewer(viewerId) {
|
|
|
26026
26026
|
}
|
|
26027
26027
|
}
|
|
26028
26028
|
}
|
|
26029
|
+
const DEFAULT_MAX_LIVE_VIEWERS = 3;
|
|
26030
|
+
const DEFAULT_VISIBLE_MARGIN = "1000px";
|
|
26031
|
+
const DEFAULT_FLUSH_TIMEOUT_MS = 5e3;
|
|
26032
|
+
const DEFAULT_PARK_DELAY_MS = 2e3;
|
|
26033
|
+
const records = /* @__PURE__ */ new Map();
|
|
26034
|
+
let visibleOrderCounter = 0;
|
|
26035
|
+
let effectiveMaxLive = null;
|
|
26036
|
+
let warnedMixedBudgets = false;
|
|
26037
|
+
let evaluateTimerId = null;
|
|
26038
|
+
let evaluateTimerAt = Infinity;
|
|
26039
|
+
function registerWindowedViewer({
|
|
26040
|
+
id: id2,
|
|
26041
|
+
maxLiveViewers,
|
|
26042
|
+
parkDelayMs,
|
|
26043
|
+
canPark,
|
|
26044
|
+
requestPark
|
|
26045
|
+
}) {
|
|
26046
|
+
if (effectiveMaxLive !== null && effectiveMaxLive !== maxLiveViewers && !warnedMixedBudgets) {
|
|
26047
|
+
warnedMixedBudgets = true;
|
|
26048
|
+
console.warn(
|
|
26049
|
+
`DoenetViewer mountPolicy: viewers on this page specify different maxLiveViewers (${effectiveMaxLive} and ${maxLiveViewers}); using the smaller value.`
|
|
26050
|
+
);
|
|
26051
|
+
}
|
|
26052
|
+
effectiveMaxLive = effectiveMaxLive === null ? maxLiveViewers : Math.min(effectiveMaxLive, maxLiveViewers);
|
|
26053
|
+
records.set(id2, {
|
|
26054
|
+
id: id2,
|
|
26055
|
+
state: "live",
|
|
26056
|
+
visible: false,
|
|
26057
|
+
lastVisibleOrder: 0,
|
|
26058
|
+
invisibleSince: Date.now(),
|
|
26059
|
+
parkDelayMs,
|
|
26060
|
+
canPark,
|
|
26061
|
+
requestPark
|
|
26062
|
+
});
|
|
26063
|
+
scheduleEvaluate(parkDelayMs);
|
|
26064
|
+
return () => {
|
|
26065
|
+
records.delete(id2);
|
|
26066
|
+
scheduleEvaluate(0);
|
|
26067
|
+
};
|
|
26068
|
+
}
|
|
26069
|
+
function setViewerVisibility(id2, visible) {
|
|
26070
|
+
const record = records.get(id2);
|
|
26071
|
+
if (!record || record.visible === visible) {
|
|
26072
|
+
return;
|
|
26073
|
+
}
|
|
26074
|
+
record.visible = visible;
|
|
26075
|
+
if (visible) {
|
|
26076
|
+
record.lastVisibleOrder = ++visibleOrderCounter;
|
|
26077
|
+
scheduleEvaluate(0);
|
|
26078
|
+
} else {
|
|
26079
|
+
record.invisibleSince = Date.now();
|
|
26080
|
+
scheduleEvaluate(record.parkDelayMs);
|
|
26081
|
+
}
|
|
26082
|
+
}
|
|
26083
|
+
function notifyViewerState(id2, state) {
|
|
26084
|
+
const record = records.get(id2);
|
|
26085
|
+
if (!record || record.state === state) {
|
|
26086
|
+
return;
|
|
26087
|
+
}
|
|
26088
|
+
record.state = state;
|
|
26089
|
+
scheduleEvaluate(0);
|
|
26090
|
+
}
|
|
26091
|
+
function getViewerLifecycleStats() {
|
|
26092
|
+
let live = 0, parking = 0, parked = 0;
|
|
26093
|
+
for (const record of records.values()) {
|
|
26094
|
+
if (record.state === "live") {
|
|
26095
|
+
live++;
|
|
26096
|
+
} else if (record.state === "parking") {
|
|
26097
|
+
parking++;
|
|
26098
|
+
} else {
|
|
26099
|
+
parked++;
|
|
26100
|
+
}
|
|
26101
|
+
}
|
|
26102
|
+
return { registered: records.size, live, parking, parked };
|
|
26103
|
+
}
|
|
26104
|
+
function scheduleEvaluate(delayMs) {
|
|
26105
|
+
const at = Date.now() + delayMs;
|
|
26106
|
+
if (evaluateTimerId !== null) {
|
|
26107
|
+
if (at >= evaluateTimerAt) {
|
|
26108
|
+
return;
|
|
26109
|
+
}
|
|
26110
|
+
clearTimeout(evaluateTimerId);
|
|
26111
|
+
}
|
|
26112
|
+
evaluateTimerAt = at;
|
|
26113
|
+
evaluateTimerId = setTimeout(() => {
|
|
26114
|
+
evaluateTimerId = null;
|
|
26115
|
+
evaluateTimerAt = Infinity;
|
|
26116
|
+
evaluate$1();
|
|
26117
|
+
}, delayMs);
|
|
26118
|
+
}
|
|
26119
|
+
function evaluate$1() {
|
|
26120
|
+
if (effectiveMaxLive === null) {
|
|
26121
|
+
return;
|
|
26122
|
+
}
|
|
26123
|
+
const now = Date.now();
|
|
26124
|
+
let live = 0;
|
|
26125
|
+
for (const record of records.values()) {
|
|
26126
|
+
if (record.state === "live") {
|
|
26127
|
+
live++;
|
|
26128
|
+
}
|
|
26129
|
+
}
|
|
26130
|
+
let excess = live - effectiveMaxLive;
|
|
26131
|
+
if (excess <= 0) {
|
|
26132
|
+
return;
|
|
26133
|
+
}
|
|
26134
|
+
const candidates = [];
|
|
26135
|
+
let nextDebounceExpiry = Infinity;
|
|
26136
|
+
for (const record of records.values()) {
|
|
26137
|
+
if (record.state !== "live" || record.visible) {
|
|
26138
|
+
continue;
|
|
26139
|
+
}
|
|
26140
|
+
const eligibleAt = record.invisibleSince + record.parkDelayMs;
|
|
26141
|
+
if (eligibleAt > now) {
|
|
26142
|
+
nextDebounceExpiry = Math.min(nextDebounceExpiry, eligibleAt);
|
|
26143
|
+
continue;
|
|
26144
|
+
}
|
|
26145
|
+
if (!record.canPark()) {
|
|
26146
|
+
continue;
|
|
26147
|
+
}
|
|
26148
|
+
candidates.push(record);
|
|
26149
|
+
}
|
|
26150
|
+
candidates.sort((a2, b2) => a2.lastVisibleOrder - b2.lastVisibleOrder);
|
|
26151
|
+
for (const record of candidates) {
|
|
26152
|
+
if (excess <= 0) {
|
|
26153
|
+
break;
|
|
26154
|
+
}
|
|
26155
|
+
record.state = "parking";
|
|
26156
|
+
excess--;
|
|
26157
|
+
record.requestPark();
|
|
26158
|
+
}
|
|
26159
|
+
if (excess > 0 && nextDebounceExpiry < Infinity) {
|
|
26160
|
+
scheduleEvaluate(Math.max(0, nextDebounceExpiry - now));
|
|
26161
|
+
}
|
|
26162
|
+
}
|
|
26029
26163
|
function findNodesWithPositionInfo(nodes) {
|
|
26030
26164
|
if (typeof nodes !== "object" || nodes === null) {
|
|
26031
26165
|
return [];
|
|
@@ -34639,7 +34773,7 @@ for (const key of [
|
|
|
34639
34773
|
]) {
|
|
34640
34774
|
key.isMath = true;
|
|
34641
34775
|
}
|
|
34642
|
-
const BackspaceIcon = /* @__PURE__ */
|
|
34776
|
+
const BackspaceIcon = /* @__PURE__ */ React__default.createElement(
|
|
34643
34777
|
"svg",
|
|
34644
34778
|
{
|
|
34645
34779
|
"aria-hidden": "true",
|
|
@@ -34651,7 +34785,7 @@ const BackspaceIcon = /* @__PURE__ */ React__default__default.createElement(
|
|
|
34651
34785
|
xmlns: "http://www.w3.org/2000/svg",
|
|
34652
34786
|
viewBox: "0 0 576 512"
|
|
34653
34787
|
},
|
|
34654
|
-
/* @__PURE__ */
|
|
34788
|
+
/* @__PURE__ */ React__default.createElement(
|
|
34655
34789
|
"path",
|
|
34656
34790
|
{
|
|
34657
34791
|
fill: "currentColor",
|
|
@@ -34665,19 +34799,19 @@ function Keyboard({
|
|
|
34665
34799
|
}) {
|
|
34666
34800
|
switch (style) {
|
|
34667
34801
|
case "alpha_lower":
|
|
34668
|
-
return /* @__PURE__ */
|
|
34802
|
+
return /* @__PURE__ */ React__default.createElement("div", { className: "virtual-keyboard alpha" }, /* @__PURE__ */ React__default.createElement(Qwerty, { type: "lower", onClick }));
|
|
34669
34803
|
case "alpha_upper":
|
|
34670
|
-
return /* @__PURE__ */
|
|
34804
|
+
return /* @__PURE__ */ React__default.createElement("div", { className: "virtual-keyboard alpha" }, /* @__PURE__ */ React__default.createElement(Qwerty, { type: "upper", onClick }));
|
|
34671
34805
|
case "numeric":
|
|
34672
|
-
return /* @__PURE__ */
|
|
34806
|
+
return /* @__PURE__ */ React__default.createElement("div", { className: "virtual-keyboard numeric" }, /* @__PURE__ */ React__default.createElement(Numeric, { onClick }));
|
|
34673
34807
|
case "greek_lower":
|
|
34674
|
-
return /* @__PURE__ */
|
|
34808
|
+
return /* @__PURE__ */ React__default.createElement("div", { className: "virtual-keyboard greek" }, /* @__PURE__ */ React__default.createElement(Greek, { type: "lower", onClick }));
|
|
34675
34809
|
case "greek_upper":
|
|
34676
|
-
return /* @__PURE__ */
|
|
34810
|
+
return /* @__PURE__ */ React__default.createElement("div", { className: "virtual-keyboard greek" }, /* @__PURE__ */ React__default.createElement(Greek, { type: "upper", onClick }));
|
|
34677
34811
|
case "symbol":
|
|
34678
|
-
return /* @__PURE__ */
|
|
34812
|
+
return /* @__PURE__ */ React__default.createElement("div", { className: "virtual-keyboard symbol" }, /* @__PURE__ */ React__default.createElement(Symbol$1, { onClick }));
|
|
34679
34813
|
case "function":
|
|
34680
|
-
return /* @__PURE__ */
|
|
34814
|
+
return /* @__PURE__ */ React__default.createElement("div", { className: "virtual-keyboard composite" }, /* @__PURE__ */ React__default.createElement(Composite, { onClick }));
|
|
34681
34815
|
}
|
|
34682
34816
|
}
|
|
34683
34817
|
function Key({
|
|
@@ -34686,12 +34820,12 @@ function Key({
|
|
|
34686
34820
|
}) {
|
|
34687
34821
|
let content = keyInfo.displayName;
|
|
34688
34822
|
if (keyInfo.isMath) {
|
|
34689
|
-
content = /* @__PURE__ */
|
|
34823
|
+
content = /* @__PURE__ */ React__default.createElement("div", { style: { pointerEvents: "none" } }, /* @__PURE__ */ React__default.createElement(MathJax, null, "\\(" + content + "\\)"));
|
|
34690
34824
|
}
|
|
34691
34825
|
if (keyInfo.name === "backspace") {
|
|
34692
34826
|
content = BackspaceIcon;
|
|
34693
34827
|
}
|
|
34694
|
-
return /* @__PURE__ */
|
|
34828
|
+
return /* @__PURE__ */ React__default.createElement(
|
|
34695
34829
|
"button",
|
|
34696
34830
|
{
|
|
34697
34831
|
className: `key key-${keyInfo.name} ${keyInfo.isMath ? "math" : ""}`,
|
|
@@ -34723,7 +34857,7 @@ function Qwerty({
|
|
|
34723
34857
|
SPECIAL_KEYS.right,
|
|
34724
34858
|
SPECIAL_KEYS.enter
|
|
34725
34859
|
];
|
|
34726
|
-
return /* @__PURE__ */
|
|
34860
|
+
return /* @__PURE__ */ React__default.createElement(React__default.Fragment, null, [row1, row2, row3, row4].map((row, i2) => /* @__PURE__ */ React__default.createElement("div", { key: i2, className: "row" }, row.map((key) => /* @__PURE__ */ React__default.createElement(Key, { keyInfo: key, onClick, key: key.name })))));
|
|
34727
34861
|
}
|
|
34728
34862
|
function Numeric({ onClick }) {
|
|
34729
34863
|
const row1 = [
|
|
@@ -34747,7 +34881,7 @@ function Numeric({ onClick }) {
|
|
|
34747
34881
|
SPECIAL_KEYS.right,
|
|
34748
34882
|
SPECIAL_KEYS.enter
|
|
34749
34883
|
];
|
|
34750
|
-
return /* @__PURE__ */
|
|
34884
|
+
return /* @__PURE__ */ React__default.createElement(React__default.Fragment, null, /* @__PURE__ */ React__default.createElement("div", { className: "keyboard-region" }, Object.values(VAR_KEYS).map((key) => /* @__PURE__ */ React__default.createElement(Key, { keyInfo: key, onClick, key: key.name }))), /* @__PURE__ */ React__default.createElement("div", { className: "sub-keyboard" }, [row1, row2, row3, row4].map((row, i2) => /* @__PURE__ */ React__default.createElement("div", { key: i2, className: "row" }, row.map((key) => /* @__PURE__ */ React__default.createElement(
|
|
34751
34885
|
Key,
|
|
34752
34886
|
{
|
|
34753
34887
|
keyInfo: key,
|
|
@@ -34757,12 +34891,12 @@ function Numeric({ onClick }) {
|
|
|
34757
34891
|
))))));
|
|
34758
34892
|
}
|
|
34759
34893
|
function Symbol$1({ onClick }) {
|
|
34760
|
-
return /* @__PURE__ */
|
|
34894
|
+
return /* @__PURE__ */ React__default.createElement(React__default.Fragment, null, /* @__PURE__ */ React__default.createElement("div", { className: "keyboard-region" }, Object.values(SYMBOL_KEYS).map((key) => /* @__PURE__ */ React__default.createElement(Key, { keyInfo: key, onClick, key: key.name }))), /* @__PURE__ */ React__default.createElement("div", { className: "keyboard-region" }, Object.values(OTHER_SYMBOLS).map((key) => /* @__PURE__ */ React__default.createElement(Key, { keyInfo: key, onClick, key: key.name })), [
|
|
34761
34895
|
SPECIAL_KEYS.left,
|
|
34762
34896
|
SPECIAL_KEYS.right,
|
|
34763
34897
|
SPECIAL_KEYS.backspace,
|
|
34764
34898
|
SPECIAL_KEYS.enter
|
|
34765
|
-
].map((key) => /* @__PURE__ */
|
|
34899
|
+
].map((key) => /* @__PURE__ */ React__default.createElement(Key, { keyInfo: key, onClick, key: key.name }))));
|
|
34766
34900
|
}
|
|
34767
34901
|
function Greek({
|
|
34768
34902
|
type,
|
|
@@ -34783,15 +34917,15 @@ function Greek({
|
|
|
34783
34917
|
SPECIAL_KEYS.right,
|
|
34784
34918
|
SPECIAL_KEYS.enter
|
|
34785
34919
|
];
|
|
34786
|
-
return /* @__PURE__ */
|
|
34920
|
+
return /* @__PURE__ */ React__default.createElement(React__default.Fragment, null, [row1, row2, row3, row4].map((row, i2) => /* @__PURE__ */ React__default.createElement("div", { key: i2, className: "row" }, row.map((key) => /* @__PURE__ */ React__default.createElement(Key, { keyInfo: key, onClick, key: key.name })))));
|
|
34787
34921
|
}
|
|
34788
34922
|
function Composite({ onClick }) {
|
|
34789
|
-
return /* @__PURE__ */
|
|
34923
|
+
return /* @__PURE__ */ React__default.createElement(React__default.Fragment, null, /* @__PURE__ */ React__default.createElement("div", { className: "keyboard-region" }, Object.values(TRIG_KEYS).map((key) => /* @__PURE__ */ React__default.createElement(Key, { keyInfo: key, onClick, key: key.name }))), /* @__PURE__ */ React__default.createElement("div", { className: "keyboard-region" }, Object.values(FUNCTION_KEYS).map((key) => /* @__PURE__ */ React__default.createElement(Key, { keyInfo: key, onClick, key: key.name })), [
|
|
34790
34924
|
SPECIAL_KEYS.backspace,
|
|
34791
34925
|
SPECIAL_KEYS.left,
|
|
34792
34926
|
SPECIAL_KEYS.right,
|
|
34793
34927
|
SPECIAL_KEYS.enter
|
|
34794
|
-
].map((key) => /* @__PURE__ */
|
|
34928
|
+
].map((key) => /* @__PURE__ */ React__default.createElement(Key, { keyInfo: key, onClick, key: key.name }))));
|
|
34795
34929
|
}
|
|
34796
34930
|
const FocusableContext = createContext(true);
|
|
34797
34931
|
function flatten2DArray(array) {
|
|
@@ -35235,7 +35369,7 @@ function mergeProps(base, overrides2) {
|
|
|
35235
35369
|
}
|
|
35236
35370
|
return props;
|
|
35237
35371
|
}
|
|
35238
|
-
const _React = { ...
|
|
35372
|
+
const _React = { ...React };
|
|
35239
35373
|
const useReactId = _React.useId;
|
|
35240
35374
|
const useReactInsertionEffect = _React.useInsertionEffect;
|
|
35241
35375
|
const useSafeLayoutEffect = canUseDOM ? useLayoutEffect : useEffect;
|
|
@@ -35352,7 +35486,7 @@ function useMetadataProps(props, key, value) {
|
|
|
35352
35486
|
return [parent?.[key], { onLoadedMetadataCapture }];
|
|
35353
35487
|
}
|
|
35354
35488
|
function forwardRef(render) {
|
|
35355
|
-
const Role =
|
|
35489
|
+
const Role = React.forwardRef((props, ref) => render({
|
|
35356
35490
|
...props,
|
|
35357
35491
|
ref
|
|
35358
35492
|
}));
|
|
@@ -35360,18 +35494,18 @@ function forwardRef(render) {
|
|
|
35360
35494
|
return Role;
|
|
35361
35495
|
}
|
|
35362
35496
|
function memo(Component, propsAreEqual) {
|
|
35363
|
-
return
|
|
35497
|
+
return React.memo(Component, propsAreEqual);
|
|
35364
35498
|
}
|
|
35365
35499
|
function createElement(Type, props) {
|
|
35366
35500
|
const { wrapElement, render, ...rest2 } = props;
|
|
35367
35501
|
const mergedRef = useMergeRefs(props.ref, getRefProperty(render));
|
|
35368
35502
|
let element;
|
|
35369
|
-
if (
|
|
35503
|
+
if (React.isValidElement(render)) {
|
|
35370
35504
|
const renderProps = {
|
|
35371
35505
|
...render.props,
|
|
35372
35506
|
ref: mergedRef
|
|
35373
35507
|
};
|
|
35374
|
-
element =
|
|
35508
|
+
element = React.cloneElement(render, mergeProps(rest2, renderProps));
|
|
35375
35509
|
} else if (render) element = render(rest2);
|
|
35376
35510
|
else element = /* @__PURE__ */ jsxRuntimeExports.jsx(Type, { ...rest2 });
|
|
35377
35511
|
if (wrapElement) return wrapElement(element);
|
|
@@ -35385,17 +35519,17 @@ function createHook(useProps) {
|
|
|
35385
35519
|
return useRole;
|
|
35386
35520
|
}
|
|
35387
35521
|
function createStoreContext(providers = [], scopedProviders = []) {
|
|
35388
|
-
const context =
|
|
35389
|
-
const scopedContext =
|
|
35390
|
-
const useContext2 = () =>
|
|
35522
|
+
const context = React.createContext(void 0);
|
|
35523
|
+
const scopedContext = React.createContext(void 0);
|
|
35524
|
+
const useContext2 = () => React.useContext(context);
|
|
35391
35525
|
const useScopedContext = (onlyScoped = false) => {
|
|
35392
|
-
const scoped =
|
|
35526
|
+
const scoped = React.useContext(scopedContext);
|
|
35393
35527
|
const store = useContext2();
|
|
35394
35528
|
if (onlyScoped) return scoped;
|
|
35395
35529
|
return scoped || store;
|
|
35396
35530
|
};
|
|
35397
35531
|
const useProviderContext = () => {
|
|
35398
|
-
const scoped =
|
|
35532
|
+
const scoped = React.useContext(scopedContext);
|
|
35399
35533
|
const store = useContext2();
|
|
35400
35534
|
if (scoped && scoped === store) return;
|
|
35401
35535
|
return store;
|
|
@@ -36649,7 +36783,7 @@ var hasRequiredUseSyncExternalStoreShim_production;
|
|
|
36649
36783
|
function requireUseSyncExternalStoreShim_production() {
|
|
36650
36784
|
if (hasRequiredUseSyncExternalStoreShim_production) return useSyncExternalStoreShim_production;
|
|
36651
36785
|
hasRequiredUseSyncExternalStoreShim_production = 1;
|
|
36652
|
-
var React2 =
|
|
36786
|
+
var React2 = React__default;
|
|
36653
36787
|
function is(x2, y2) {
|
|
36654
36788
|
return x2 === y2 && (0 !== x2 || 1 / x2 === 1 / y2) || x2 !== x2 && y2 !== y2;
|
|
36655
36789
|
}
|
|
@@ -36706,7 +36840,7 @@ var shimExports = requireShim();
|
|
|
36706
36840
|
const noopSubscribe = () => () => {
|
|
36707
36841
|
};
|
|
36708
36842
|
function useStoreState(store, keyOrSelector = identity$1) {
|
|
36709
|
-
const storeSubscribe =
|
|
36843
|
+
const storeSubscribe = React.useCallback((callback) => {
|
|
36710
36844
|
if (!store) return noopSubscribe();
|
|
36711
36845
|
return subscribe(store, null, callback);
|
|
36712
36846
|
}, [store]);
|
|
@@ -36723,8 +36857,8 @@ function useStoreState(store, keyOrSelector = identity$1) {
|
|
|
36723
36857
|
return shimExports.useSyncExternalStore(storeSubscribe, getSnapshot, getSnapshot);
|
|
36724
36858
|
}
|
|
36725
36859
|
function useStoreStateObject(store, object2) {
|
|
36726
|
-
const objRef =
|
|
36727
|
-
const storeSubscribe =
|
|
36860
|
+
const objRef = React.useRef({});
|
|
36861
|
+
const storeSubscribe = React.useCallback((callback) => {
|
|
36728
36862
|
if (!store) return noopSubscribe();
|
|
36729
36863
|
return subscribe(store, null, callback);
|
|
36730
36864
|
}, [store]);
|
|
@@ -36781,10 +36915,10 @@ function useStoreProps(store, props, key, setKey) {
|
|
|
36781
36915
|
});
|
|
36782
36916
|
}
|
|
36783
36917
|
function useStore(createStore2, props) {
|
|
36784
|
-
const [store, setStore] =
|
|
36918
|
+
const [store, setStore] = React.useState(() => createStore2(props));
|
|
36785
36919
|
useSafeLayoutEffect(() => init(store), [store]);
|
|
36786
|
-
const useState2 =
|
|
36787
|
-
return [
|
|
36920
|
+
const useState2 = React.useCallback((keyOrSelector) => useStoreState(store, keyOrSelector), [store]);
|
|
36921
|
+
return [React.useMemo(() => ({
|
|
36788
36922
|
...store,
|
|
36789
36923
|
useState: useState2
|
|
36790
36924
|
}), [store, useState2]), useEvent(() => {
|
|
@@ -37626,10 +37760,10 @@ function TabProvider(props = {}) {
|
|
|
37626
37760
|
});
|
|
37627
37761
|
}
|
|
37628
37762
|
function ManagedKeyboard({ onClick }) {
|
|
37629
|
-
const [style, setStyle] =
|
|
37763
|
+
const [style, setStyle] = React__default.useState("numeric");
|
|
37630
37764
|
const store = useTabStore();
|
|
37631
37765
|
const storeState = store.useState();
|
|
37632
|
-
|
|
37766
|
+
React__default.useEffect(() => {
|
|
37633
37767
|
if (!storeState.activeId) {
|
|
37634
37768
|
return;
|
|
37635
37769
|
}
|
|
@@ -37643,7 +37777,7 @@ function ManagedKeyboard({ onClick }) {
|
|
|
37643
37777
|
setStyle(storeState.activeId);
|
|
37644
37778
|
}
|
|
37645
37779
|
}, [storeState, style]);
|
|
37646
|
-
const wrappedOnClick =
|
|
37780
|
+
const wrappedOnClick = React__default.useCallback(
|
|
37647
37781
|
(e2) => {
|
|
37648
37782
|
const firstPress = e2[0];
|
|
37649
37783
|
if (!firstPress) {
|
|
@@ -37670,7 +37804,7 @@ function ManagedKeyboard({ onClick }) {
|
|
|
37670
37804
|
},
|
|
37671
37805
|
[style]
|
|
37672
37806
|
);
|
|
37673
|
-
return /* @__PURE__ */
|
|
37807
|
+
return /* @__PURE__ */ React__default.createElement(TabProvider, null, /* @__PURE__ */ React__default.createElement(TabList, { className: "virtual-keyboard-tab-list" }, /* @__PURE__ */ React__default.createElement(Tab, { store, id: "numeric" }, "123"), /* @__PURE__ */ React__default.createElement(Tab, { store, id: "function" }, "f(x)"), /* @__PURE__ */ React__default.createElement(Tab, { store, id: "alpha_lower" }, "ABC"), /* @__PURE__ */ React__default.createElement(Tab, { store, id: "greek_lower" }, "αβγ"), /* @__PURE__ */ React__default.createElement(Tab, { store, id: "symbol" }, "$%∞")), /* @__PURE__ */ React__default.createElement(Keyboard, { style, onClick: wrappedOnClick }));
|
|
37674
37808
|
}
|
|
37675
37809
|
var classnames = { exports: {} };
|
|
37676
37810
|
var hasRequiredClassnames;
|
|
@@ -37732,7 +37866,7 @@ function requireClassnames() {
|
|
|
37732
37866
|
}
|
|
37733
37867
|
var classnamesExports = requireClassnames();
|
|
37734
37868
|
const classNames = /* @__PURE__ */ getDefaultExportFromCjs$1(classnamesExports);
|
|
37735
|
-
const KeyboardIcon = () => /* @__PURE__ */
|
|
37869
|
+
const KeyboardIcon = () => /* @__PURE__ */ React__default.createElement(
|
|
37736
37870
|
"svg",
|
|
37737
37871
|
{
|
|
37738
37872
|
stroke: "currentColor",
|
|
@@ -37745,15 +37879,15 @@ const KeyboardIcon = () => /* @__PURE__ */ React__default__default.createElement
|
|
|
37745
37879
|
width: "1em",
|
|
37746
37880
|
xmlns: "http://www.w3.org/2000/svg"
|
|
37747
37881
|
},
|
|
37748
|
-
/* @__PURE__ */
|
|
37882
|
+
/* @__PURE__ */ React__default.createElement("path", { d: "M528 448H48c-26.51 0-48-21.49-48-48V112c0-26.51 21.49-48 48-48h480c26.51 0 48 21.49 48 48v288c0 26.51-21.49 48-48 48zM128 180v-40c0-6.627-5.373-12-12-12H76c-6.627 0-12 5.373-12 12v40c0 6.627 5.373 12 12 12h40c6.627 0 12-5.373 12-12zm96 0v-40c0-6.627-5.373-12-12-12h-40c-6.627 0-12 5.373-12 12v40c0 6.627 5.373 12 12 12h40c6.627 0 12-5.373 12-12zm96 0v-40c0-6.627-5.373-12-12-12h-40c-6.627 0-12 5.373-12 12v40c0 6.627 5.373 12 12 12h40c6.627 0 12-5.373 12-12zm96 0v-40c0-6.627-5.373-12-12-12h-40c-6.627 0-12 5.373-12 12v40c0 6.627 5.373 12 12 12h40c6.627 0 12-5.373 12-12zm96 0v-40c0-6.627-5.373-12-12-12h-40c-6.627 0-12 5.373-12 12v40c0 6.627 5.373 12 12 12h40c6.627 0 12-5.373 12-12zm-336 96v-40c0-6.627-5.373-12-12-12h-40c-6.627 0-12 5.373-12 12v40c0 6.627 5.373 12 12 12h40c6.627 0 12-5.373 12-12zm96 0v-40c0-6.627-5.373-12-12-12h-40c-6.627 0-12 5.373-12 12v40c0 6.627 5.373 12 12 12h40c6.627 0 12-5.373 12-12zm96 0v-40c0-6.627-5.373-12-12-12h-40c-6.627 0-12 5.373-12 12v40c0 6.627 5.373 12 12 12h40c6.627 0 12-5.373 12-12zm96 0v-40c0-6.627-5.373-12-12-12h-40c-6.627 0-12 5.373-12 12v40c0 6.627 5.373 12 12 12h40c6.627 0 12-5.373 12-12zm-336 96v-40c0-6.627-5.373-12-12-12H76c-6.627 0-12 5.373-12 12v40c0 6.627 5.373 12 12 12h40c6.627 0 12-5.373 12-12zm288 0v-40c0-6.627-5.373-12-12-12H172c-6.627 0-12 5.373-12 12v40c0 6.627 5.373 12 12 12h232c6.627 0 12-5.373 12-12zm96 0v-40c0-6.627-5.373-12-12-12h-40c-6.627 0-12 5.373-12 12v40c0 6.627 5.373 12 12 12h40c6.627 0 12-5.373 12-12z" })
|
|
37749
37883
|
);
|
|
37750
37884
|
function KeyboardTray({
|
|
37751
37885
|
onClick,
|
|
37752
37886
|
theme
|
|
37753
37887
|
}) {
|
|
37754
|
-
const [open, setOpen] =
|
|
37888
|
+
const [open, setOpen] = React__default.useState(false);
|
|
37755
37889
|
return createPortal(
|
|
37756
|
-
/* @__PURE__ */
|
|
37890
|
+
/* @__PURE__ */ React__default.createElement(
|
|
37757
37891
|
"div",
|
|
37758
37892
|
{
|
|
37759
37893
|
id: "virtual-keyboard-tray",
|
|
@@ -37770,7 +37904,7 @@ function KeyboardTray({
|
|
|
37770
37904
|
]);
|
|
37771
37905
|
}
|
|
37772
37906
|
},
|
|
37773
|
-
/* @__PURE__ */
|
|
37907
|
+
/* @__PURE__ */ React__default.createElement(
|
|
37774
37908
|
"button",
|
|
37775
37909
|
{
|
|
37776
37910
|
className: "open-keyboard-button",
|
|
@@ -37778,9 +37912,9 @@ function KeyboardTray({
|
|
|
37778
37912
|
title: open ? "Close Keyboard" : "Open Keyboard",
|
|
37779
37913
|
"aria-label": open ? "Close Keyboard" : "Open Keyboard"
|
|
37780
37914
|
},
|
|
37781
|
-
/* @__PURE__ */
|
|
37915
|
+
/* @__PURE__ */ React__default.createElement(KeyboardIcon, null)
|
|
37782
37916
|
),
|
|
37783
|
-
/* @__PURE__ */
|
|
37917
|
+
/* @__PURE__ */ React__default.createElement("div", { className: "keyboard-container" }, /* @__PURE__ */ React__default.createElement(
|
|
37784
37918
|
"button",
|
|
37785
37919
|
{
|
|
37786
37920
|
className: "close-keyboard-button",
|
|
@@ -37789,7 +37923,7 @@ function KeyboardTray({
|
|
|
37789
37923
|
"aria-label": "Close Keyboard"
|
|
37790
37924
|
},
|
|
37791
37925
|
"×"
|
|
37792
|
-
), /* @__PURE__ */
|
|
37926
|
+
), /* @__PURE__ */ React__default.createElement(ManagedKeyboard, { onClick }))
|
|
37793
37927
|
),
|
|
37794
37928
|
document.body
|
|
37795
37929
|
);
|
|
@@ -37905,7 +38039,7 @@ function MathJaxContext({
|
|
|
37905
38039
|
});
|
|
37906
38040
|
return { version: version2, promise };
|
|
37907
38041
|
}, [config2, src, useExistingMathJax, timeoutMs, version2]);
|
|
37908
|
-
return /* @__PURE__ */
|
|
38042
|
+
return /* @__PURE__ */ React__default.createElement(MathJaxBaseContext.Provider, { value }, children);
|
|
37909
38043
|
}
|
|
37910
38044
|
var commonjsGlobal = typeof globalThis !== "undefined" ? globalThis : typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : {};
|
|
37911
38045
|
function getDefaultExportFromCjs(x2) {
|
|
@@ -63053,7 +63187,7 @@ function rerenderTray() {
|
|
|
63053
63187
|
virtualKeyboardState.keyboardReactRoot?.render(renderTray(theme));
|
|
63054
63188
|
}
|
|
63055
63189
|
function renderTray(theme) {
|
|
63056
|
-
return /* @__PURE__ */
|
|
63190
|
+
return /* @__PURE__ */ React__default.createElement(MathJaxContext, { config: mathjaxConfig, version: 4 }, /* @__PURE__ */ React__default.createElement(
|
|
63057
63191
|
KeyboardTray,
|
|
63058
63192
|
{
|
|
63059
63193
|
theme,
|
|
@@ -63068,12 +63202,12 @@ function UniqueKeyboardTray({
|
|
|
63068
63202
|
theme,
|
|
63069
63203
|
ownerRef
|
|
63070
63204
|
}) {
|
|
63071
|
-
const [id2] =
|
|
63205
|
+
const [id2] = React__default.useState(() => {
|
|
63072
63206
|
const next = virtualKeyboardState.nextRegistrationId;
|
|
63073
63207
|
virtualKeyboardState.nextRegistrationId += 1;
|
|
63074
63208
|
return next;
|
|
63075
63209
|
});
|
|
63076
|
-
|
|
63210
|
+
React__default.useEffect(() => {
|
|
63077
63211
|
if (virtualKeyboardState.count === 0) {
|
|
63078
63212
|
const keyboardDomNode = document.createElement("footer");
|
|
63079
63213
|
keyboardDomNode.id = "virtual-keyboard-dummy";
|
|
@@ -63132,7 +63266,7 @@ function UniqueKeyboardTray({
|
|
|
63132
63266
|
}
|
|
63133
63267
|
};
|
|
63134
63268
|
}, []);
|
|
63135
|
-
|
|
63269
|
+
React__default.useEffect(() => {
|
|
63136
63270
|
const registration = getRegistrationById(id2);
|
|
63137
63271
|
if (registration) {
|
|
63138
63272
|
registration.onClick = onClick;
|
|
@@ -63147,7 +63281,7 @@ function ExternalVirtualKeyboard({
|
|
|
63147
63281
|
theme,
|
|
63148
63282
|
ownerRef
|
|
63149
63283
|
}) {
|
|
63150
|
-
return /* @__PURE__ */
|
|
63284
|
+
return /* @__PURE__ */ React__default.createElement(
|
|
63151
63285
|
UniqueKeyboardTray,
|
|
63152
63286
|
{
|
|
63153
63287
|
ownerRef,
|
|
@@ -63172,7 +63306,7 @@ function ExternalVirtualKeyboard({
|
|
|
63172
63306
|
}
|
|
63173
63307
|
);
|
|
63174
63308
|
}
|
|
63175
|
-
const version = "0.7.20-dev.
|
|
63309
|
+
const version = "0.7.20-dev.326";
|
|
63176
63310
|
const latestDoenetmlVersion = version;
|
|
63177
63311
|
function subscribeToPinnedTheme() {
|
|
63178
63312
|
return () => {
|
|
@@ -63180,13 +63314,32 @@ function subscribeToPinnedTheme() {
|
|
|
63180
63314
|
}
|
|
63181
63315
|
function useResolvedTheme(setting) {
|
|
63182
63316
|
const subscribe2 = setting === "system" ? subscribeToSystemTheme : subscribeToPinnedTheme;
|
|
63183
|
-
const systemTheme =
|
|
63317
|
+
const systemTheme = React__default.useSyncExternalStore(
|
|
63184
63318
|
subscribe2,
|
|
63185
63319
|
getSystemTheme,
|
|
63186
63320
|
() => "light"
|
|
63187
63321
|
);
|
|
63188
63322
|
return setting === "system" ? systemTheme : setting;
|
|
63189
63323
|
}
|
|
63324
|
+
const LIVE_UPDATE_MIN_VERSION = [0, 7, 18];
|
|
63325
|
+
function versionSupportsLiveUpdates(version2) {
|
|
63326
|
+
const match2 = version2.replace(/^v/, "").match(/^(\d+)(?:\.(\d+))?(?:\.(\d+))?/);
|
|
63327
|
+
if (!match2) {
|
|
63328
|
+
return true;
|
|
63329
|
+
}
|
|
63330
|
+
const parts = [match2[1], match2[2], match2[3]].map(
|
|
63331
|
+
(p2) => p2 === void 0 ? Infinity : parseInt(p2, 10)
|
|
63332
|
+
);
|
|
63333
|
+
for (let i2 = 0; i2 < 3; i2++) {
|
|
63334
|
+
if (parts[i2] > LIVE_UPDATE_MIN_VERSION[i2]) {
|
|
63335
|
+
return true;
|
|
63336
|
+
}
|
|
63337
|
+
if (parts[i2] < LIVE_UPDATE_MIN_VERSION[i2]) {
|
|
63338
|
+
return false;
|
|
63339
|
+
}
|
|
63340
|
+
}
|
|
63341
|
+
return true;
|
|
63342
|
+
}
|
|
63190
63343
|
function DoenetViewer({
|
|
63191
63344
|
doenetML,
|
|
63192
63345
|
standaloneUrl: specifiedStandaloneUrl,
|
|
@@ -63194,16 +63347,53 @@ function DoenetViewer({
|
|
|
63194
63347
|
doenetmlVersion: specifiedDoenetmlVersion,
|
|
63195
63348
|
autodetectVersion = true,
|
|
63196
63349
|
useSharedCoreWorker = false,
|
|
63350
|
+
mountPolicy,
|
|
63197
63351
|
...doenetViewerProps
|
|
63198
63352
|
}) {
|
|
63199
|
-
const [id2, _2] =
|
|
63200
|
-
const ref =
|
|
63201
|
-
const
|
|
63202
|
-
const
|
|
63203
|
-
const
|
|
63353
|
+
const [id2, _2] = React__default.useState(() => Math.random().toString(36).slice(2));
|
|
63354
|
+
const ref = React__default.useRef(null);
|
|
63355
|
+
const viewerIframeRef = React__default.useRef(null);
|
|
63356
|
+
const pendingActions = React__default.useRef([]);
|
|
63357
|
+
const lastSentPropsSnapshotRef = React__default.useRef(null);
|
|
63358
|
+
const lastSentFunctionPropsRef = React__default.useRef(null);
|
|
63359
|
+
const doenetViewerPropsRef = React__default.useRef(doenetViewerProps);
|
|
63360
|
+
doenetViewerPropsRef.current = doenetViewerProps;
|
|
63361
|
+
const doenetMLRef = React__default.useRef(doenetML);
|
|
63362
|
+
doenetMLRef.current = doenetML;
|
|
63363
|
+
const windowed = mountPolicy?.mode === "windowed";
|
|
63364
|
+
const [parked, setParked] = React__default.useState(false);
|
|
63365
|
+
const [parkGeneration, setParkGeneration] = React__default.useState(0);
|
|
63366
|
+
const parkedRef = React__default.useRef(false);
|
|
63367
|
+
const parkingRef = React__default.useRef(false);
|
|
63368
|
+
const visibleRef = React__default.useRef(false);
|
|
63369
|
+
const containerRef = React__default.useRef(null);
|
|
63370
|
+
const parkFlushCounterRef = React__default.useRef(0);
|
|
63371
|
+
const parkFlushIdRef = React__default.useRef(null);
|
|
63372
|
+
const parkFlushCleanupRef = React__default.useRef(null);
|
|
63373
|
+
const lastCapturedReportRef = React__default.useRef(null);
|
|
63374
|
+
const parkedSnapshotRef = React__default.useRef(
|
|
63375
|
+
void 0
|
|
63376
|
+
);
|
|
63377
|
+
const everHadStateRef = React__default.useRef(false);
|
|
63378
|
+
const pinnedVariantIndexRef = React__default.useRef(null);
|
|
63379
|
+
if (windowed && pinnedVariantIndexRef.current === null) {
|
|
63380
|
+
pinnedVariantIndexRef.current = doenetViewerProps.requestedVariantIndex ?? Math.floor(Math.random() * 1e6) + 1;
|
|
63381
|
+
}
|
|
63382
|
+
const [height, setHeight] = React__default.useState("500px");
|
|
63383
|
+
const [inErrorState, setInErrorState] = React__default.useState(null);
|
|
63384
|
+
const [ignoreDetectedVersion, setIgnoreDetectedVersion] = React__default.useState(false);
|
|
63204
63385
|
const resolvedTheme = useResolvedTheme(
|
|
63205
63386
|
doenetViewerProps.darkMode ?? "system"
|
|
63206
63387
|
);
|
|
63388
|
+
function syncIframeBodyBackground() {
|
|
63389
|
+
const body = ref.current?.contentDocument?.body;
|
|
63390
|
+
if (body) {
|
|
63391
|
+
setIframeBodyBackground(
|
|
63392
|
+
body,
|
|
63393
|
+
doenetViewerPropsRef.current.darkMode
|
|
63394
|
+
);
|
|
63395
|
+
}
|
|
63396
|
+
}
|
|
63207
63397
|
let standaloneUrl, cssUrl;
|
|
63208
63398
|
let foundAutoVersion = false;
|
|
63209
63399
|
let detectedVersion;
|
|
@@ -63226,22 +63416,80 @@ function DoenetViewer({
|
|
|
63226
63416
|
} else {
|
|
63227
63417
|
cssUrl = `https://cdn.jsdelivr.net/npm/@doenet/standalone@${selectedDoenetmlVersion}/style.css`;
|
|
63228
63418
|
}
|
|
63229
|
-
const
|
|
63419
|
+
const usingCustomStandaloneUrl = Boolean(
|
|
63420
|
+
specifiedStandaloneUrl && !foundAutoVersion
|
|
63421
|
+
);
|
|
63422
|
+
const liveUpdatesSupported = usingCustomStandaloneUrl || versionSupportsLiveUpdates(selectedDoenetmlVersion);
|
|
63423
|
+
const standaloneUrlRef = React__default.useRef(standaloneUrl);
|
|
63230
63424
|
standaloneUrlRef.current = standaloneUrl;
|
|
63231
|
-
|
|
63232
|
-
|
|
63233
|
-
|
|
63425
|
+
const propsSnapshotStr = serializePropsSnapshot(
|
|
63426
|
+
{ doenetML },
|
|
63427
|
+
doenetViewerProps
|
|
63428
|
+
);
|
|
63429
|
+
const legacyReloadKey = liveUpdatesSupported ? "" : propsSnapshotStr;
|
|
63430
|
+
const srcDoc = React__default.useMemo(() => {
|
|
63431
|
+
let bakedProps = doenetViewerPropsRef.current;
|
|
63432
|
+
if (windowed) {
|
|
63433
|
+
bakedProps = { ...bakedProps };
|
|
63434
|
+
if (bakedProps.requestedVariantIndex === void 0) {
|
|
63435
|
+
bakedProps.requestedVariantIndex = pinnedVariantIndexRef.current;
|
|
63436
|
+
}
|
|
63437
|
+
if (parkedSnapshotRef.current !== void 0) {
|
|
63438
|
+
bakedProps.initialState = parkedSnapshotRef.current;
|
|
63439
|
+
bakedProps.flags = {
|
|
63440
|
+
...bakedProps.flags ?? {},
|
|
63441
|
+
allowLoadState: true
|
|
63442
|
+
};
|
|
63443
|
+
}
|
|
63234
63444
|
}
|
|
63445
|
+
return createHtmlForDoenetViewer(
|
|
63446
|
+
id2,
|
|
63447
|
+
doenetMLRef.current,
|
|
63448
|
+
bakedProps,
|
|
63449
|
+
standaloneUrl,
|
|
63450
|
+
cssUrl,
|
|
63451
|
+
useSharedCoreWorker
|
|
63452
|
+
);
|
|
63453
|
+
}, [
|
|
63454
|
+
id2,
|
|
63455
|
+
standaloneUrl,
|
|
63456
|
+
cssUrl,
|
|
63457
|
+
useSharedCoreWorker,
|
|
63458
|
+
legacyReloadKey,
|
|
63459
|
+
parkGeneration
|
|
63460
|
+
]);
|
|
63461
|
+
React__default.useEffect(() => {
|
|
63235
63462
|
return () => {
|
|
63236
63463
|
destroySharedCoresForViewer(id2);
|
|
63237
63464
|
};
|
|
63238
63465
|
}, []);
|
|
63239
|
-
|
|
63466
|
+
React__default.useLayoutEffect(() => {
|
|
63467
|
+
viewerIframeRef.current = null;
|
|
63468
|
+
destroySharedCoresForViewer(id2);
|
|
63469
|
+
lastSentPropsSnapshotRef.current = serializePropsSnapshot(
|
|
63470
|
+
{ doenetML: doenetMLRef.current },
|
|
63471
|
+
doenetViewerPropsRef.current
|
|
63472
|
+
);
|
|
63473
|
+
lastSentFunctionPropsRef.current = null;
|
|
63474
|
+
}, [srcDoc]);
|
|
63475
|
+
React__default.useEffect(() => {
|
|
63240
63476
|
const listener = (event) => {
|
|
63241
63477
|
if (event.origin !== window.location.origin) {
|
|
63242
63478
|
return;
|
|
63243
63479
|
}
|
|
63244
|
-
if (
|
|
63480
|
+
if (windowed && parkedRef.current && event.data.subject === "SPLICE.flushState") {
|
|
63481
|
+
const currentProps = doenetViewerPropsRef.current;
|
|
63482
|
+
window.postMessage({
|
|
63483
|
+
subject: "SPLICE.flushState.response",
|
|
63484
|
+
activity_id: currentProps.activityId ?? "a",
|
|
63485
|
+
doc_id: currentProps.docId ?? "1",
|
|
63486
|
+
message_id: event.data.message_id,
|
|
63487
|
+
success: true,
|
|
63488
|
+
hadState: everHadStateRef.current
|
|
63489
|
+
});
|
|
63490
|
+
return;
|
|
63491
|
+
}
|
|
63492
|
+
if (event.data.subject === "SPLICE.getState.response" || event.data.subject === "SPLICE.requestSolutionView.response" || event.data.subject == "SPLICE.submitAllAnswers" || event.data.subject === "SPLICE.flushState") {
|
|
63245
63493
|
ref.current?.contentWindow?.postMessage(event.data);
|
|
63246
63494
|
return;
|
|
63247
63495
|
}
|
|
@@ -63253,6 +63501,16 @@ function DoenetViewer({
|
|
|
63253
63501
|
setHeight(event.data.height + "px");
|
|
63254
63502
|
}
|
|
63255
63503
|
}
|
|
63504
|
+
if (windowed) {
|
|
63505
|
+
if (event.data.subject === "SPLICE.reportScoreAndState") {
|
|
63506
|
+
lastCapturedReportRef.current = event.data;
|
|
63507
|
+
return;
|
|
63508
|
+
}
|
|
63509
|
+
if (event.data.subject === "SPLICE.flushState.response" && event.data.message_id === parkFlushIdRef.current) {
|
|
63510
|
+
completeParkFlush(event.data);
|
|
63511
|
+
return;
|
|
63512
|
+
}
|
|
63513
|
+
}
|
|
63256
63514
|
if (event.data?.origin !== id2) {
|
|
63257
63515
|
return;
|
|
63258
63516
|
}
|
|
@@ -63288,18 +63546,29 @@ function DoenetViewer({
|
|
|
63288
63546
|
const viewerIframe = wrap$3(
|
|
63289
63547
|
windowEndpoint(ref.current.contentWindow)
|
|
63290
63548
|
);
|
|
63549
|
+
const latestProps = doenetViewerPropsRef.current;
|
|
63291
63550
|
const proxiedFunctions = [];
|
|
63292
|
-
|
|
63293
|
-
|
|
63294
|
-
)) {
|
|
63551
|
+
const registeredFunctions = {};
|
|
63552
|
+
for (const [key, prop] of Object.entries(latestProps)) {
|
|
63295
63553
|
if (typeof prop === "function") {
|
|
63554
|
+
registeredFunctions[key] = prop;
|
|
63296
63555
|
proxiedFunctions.push(key);
|
|
63297
63556
|
proxiedFunctions.push(proxy(prop));
|
|
63298
63557
|
}
|
|
63299
63558
|
}
|
|
63300
|
-
viewerIframe
|
|
63301
|
-
|
|
63559
|
+
viewerIframe.renderViewerWithFunctionProps(...proxiedFunctions).catch(
|
|
63560
|
+
logComlinkError(
|
|
63561
|
+
"DoenetViewer",
|
|
63562
|
+
"renderViewerWithFunctionProps"
|
|
63563
|
+
)
|
|
63302
63564
|
);
|
|
63565
|
+
lastSentFunctionPropsRef.current = registeredFunctions;
|
|
63566
|
+
viewerIframeRef.current = viewerIframe;
|
|
63567
|
+
const queued = pendingActions.current.splice(0);
|
|
63568
|
+
for (const action of queued) {
|
|
63569
|
+
action(viewerIframe);
|
|
63570
|
+
}
|
|
63571
|
+
syncIframeBodyBackground();
|
|
63303
63572
|
}
|
|
63304
63573
|
}
|
|
63305
63574
|
};
|
|
@@ -63310,13 +63579,208 @@ function DoenetViewer({
|
|
|
63310
63579
|
window.removeEventListener("message", listener);
|
|
63311
63580
|
};
|
|
63312
63581
|
}, []);
|
|
63582
|
+
React__default.useEffect(() => {
|
|
63583
|
+
if (!liveUpdatesSupported) {
|
|
63584
|
+
return;
|
|
63585
|
+
}
|
|
63586
|
+
if (lastSentPropsSnapshotRef.current === propsSnapshotStr) {
|
|
63587
|
+
return;
|
|
63588
|
+
}
|
|
63589
|
+
lastSentPropsSnapshotRef.current = propsSnapshotStr;
|
|
63590
|
+
const snapshot = JSON.parse(propsSnapshotStr);
|
|
63591
|
+
const action = (remote) => {
|
|
63592
|
+
remote.updateViewerProps(snapshot).catch(logComlinkError("DoenetViewer", "updateViewerProps"));
|
|
63593
|
+
};
|
|
63594
|
+
if (viewerIframeRef.current) {
|
|
63595
|
+
action(viewerIframeRef.current);
|
|
63596
|
+
} else {
|
|
63597
|
+
pendingActions.current.push(action);
|
|
63598
|
+
}
|
|
63599
|
+
}, [propsSnapshotStr, srcDoc, liveUpdatesSupported]);
|
|
63600
|
+
React__default.useEffect(() => {
|
|
63601
|
+
syncIframeBodyBackground();
|
|
63602
|
+
}, [doenetViewerProps.darkMode]);
|
|
63603
|
+
React__default.useEffect(() => {
|
|
63604
|
+
if (!liveUpdatesSupported) {
|
|
63605
|
+
return;
|
|
63606
|
+
}
|
|
63607
|
+
const prev = lastSentFunctionPropsRef.current;
|
|
63608
|
+
if (prev === null) {
|
|
63609
|
+
return;
|
|
63610
|
+
}
|
|
63611
|
+
const current = {};
|
|
63612
|
+
for (const [key, val] of Object.entries(doenetViewerPropsRef.current)) {
|
|
63613
|
+
if (typeof val === "function") {
|
|
63614
|
+
current[key] = val;
|
|
63615
|
+
}
|
|
63616
|
+
}
|
|
63617
|
+
const prevKeys = Object.keys(prev);
|
|
63618
|
+
const currKeys = Object.keys(current);
|
|
63619
|
+
let changed = prevKeys.length !== currKeys.length;
|
|
63620
|
+
if (!changed) {
|
|
63621
|
+
for (const k2 of currKeys) {
|
|
63622
|
+
if (prev[k2] !== current[k2]) {
|
|
63623
|
+
changed = true;
|
|
63624
|
+
break;
|
|
63625
|
+
}
|
|
63626
|
+
}
|
|
63627
|
+
}
|
|
63628
|
+
if (!changed) {
|
|
63629
|
+
return;
|
|
63630
|
+
}
|
|
63631
|
+
lastSentFunctionPropsRef.current = current;
|
|
63632
|
+
const proxiedFunctions = [];
|
|
63633
|
+
for (const [key, val] of Object.entries(current)) {
|
|
63634
|
+
proxiedFunctions.push(key);
|
|
63635
|
+
proxiedFunctions.push(proxy(val));
|
|
63636
|
+
}
|
|
63637
|
+
const action = (remote) => {
|
|
63638
|
+
remote.updateViewerFunctionProps(...proxiedFunctions).catch(
|
|
63639
|
+
logComlinkError(
|
|
63640
|
+
"DoenetViewer",
|
|
63641
|
+
"updateViewerFunctionProps"
|
|
63642
|
+
)
|
|
63643
|
+
);
|
|
63644
|
+
};
|
|
63645
|
+
if (viewerIframeRef.current) {
|
|
63646
|
+
action(viewerIframeRef.current);
|
|
63647
|
+
} else {
|
|
63648
|
+
pendingActions.current.push(action);
|
|
63649
|
+
}
|
|
63650
|
+
});
|
|
63651
|
+
function hasPersistencePath() {
|
|
63652
|
+
const flags = doenetViewerPropsRef.current.flags;
|
|
63653
|
+
return Boolean(flags?.allowSaveState || flags?.allowLocalState);
|
|
63654
|
+
}
|
|
63655
|
+
function canPark() {
|
|
63656
|
+
return hasPersistencePath() && Boolean(ref.current?.contentWindow);
|
|
63657
|
+
}
|
|
63658
|
+
function beginPark() {
|
|
63659
|
+
if (parkedRef.current || parkingRef.current) {
|
|
63660
|
+
return;
|
|
63661
|
+
}
|
|
63662
|
+
if (!ref.current?.contentWindow) {
|
|
63663
|
+
notifyViewerState(id2, "live");
|
|
63664
|
+
return;
|
|
63665
|
+
}
|
|
63666
|
+
parkingRef.current = true;
|
|
63667
|
+
const flushId = `__doenetParkFlush-${id2}-${++parkFlushCounterRef.current}`;
|
|
63668
|
+
parkFlushIdRef.current = flushId;
|
|
63669
|
+
const post = () => {
|
|
63670
|
+
ref.current?.contentWindow?.postMessage({
|
|
63671
|
+
subject: "SPLICE.flushState",
|
|
63672
|
+
message_id: flushId
|
|
63673
|
+
});
|
|
63674
|
+
};
|
|
63675
|
+
const retryTimer = setInterval(post, 500);
|
|
63676
|
+
const timeoutTimer = setTimeout(() => {
|
|
63677
|
+
onParkFlushTimeout();
|
|
63678
|
+
}, mountPolicy?.flushTimeoutMs ?? DEFAULT_FLUSH_TIMEOUT_MS);
|
|
63679
|
+
parkFlushCleanupRef.current = () => {
|
|
63680
|
+
clearInterval(retryTimer);
|
|
63681
|
+
clearTimeout(timeoutTimer);
|
|
63682
|
+
parkFlushCleanupRef.current = null;
|
|
63683
|
+
};
|
|
63684
|
+
post();
|
|
63685
|
+
}
|
|
63686
|
+
function endParkFlush() {
|
|
63687
|
+
if (!parkingRef.current) {
|
|
63688
|
+
return false;
|
|
63689
|
+
}
|
|
63690
|
+
parkFlushCleanupRef.current?.();
|
|
63691
|
+
parkFlushIdRef.current = null;
|
|
63692
|
+
parkingRef.current = false;
|
|
63693
|
+
if (visibleRef.current) {
|
|
63694
|
+
notifyViewerState(id2, "live");
|
|
63695
|
+
return false;
|
|
63696
|
+
}
|
|
63697
|
+
return true;
|
|
63698
|
+
}
|
|
63699
|
+
function completeParkFlush(ack) {
|
|
63700
|
+
if (!endParkFlush()) {
|
|
63701
|
+
return;
|
|
63702
|
+
}
|
|
63703
|
+
if (ack.hadState) {
|
|
63704
|
+
everHadStateRef.current = true;
|
|
63705
|
+
if (lastCapturedReportRef.current?.state) {
|
|
63706
|
+
parkedSnapshotRef.current = lastCapturedReportRef.current.state;
|
|
63707
|
+
}
|
|
63708
|
+
}
|
|
63709
|
+
finishPark();
|
|
63710
|
+
}
|
|
63711
|
+
function onParkFlushTimeout() {
|
|
63712
|
+
if (!endParkFlush()) {
|
|
63713
|
+
return;
|
|
63714
|
+
}
|
|
63715
|
+
finishPark();
|
|
63716
|
+
}
|
|
63717
|
+
function finishPark() {
|
|
63718
|
+
viewerIframeRef.current = null;
|
|
63719
|
+
destroySharedCoresForViewer(id2);
|
|
63720
|
+
parkedRef.current = true;
|
|
63721
|
+
setParked(true);
|
|
63722
|
+
notifyViewerState(id2, "parked");
|
|
63723
|
+
}
|
|
63724
|
+
function unpark() {
|
|
63725
|
+
if (!parkedRef.current) {
|
|
63726
|
+
return;
|
|
63727
|
+
}
|
|
63728
|
+
parkedRef.current = false;
|
|
63729
|
+
setParked(false);
|
|
63730
|
+
setParkGeneration((generation) => generation + 1);
|
|
63731
|
+
notifyViewerState(id2, "live");
|
|
63732
|
+
}
|
|
63733
|
+
React__default.useEffect(() => {
|
|
63734
|
+
if (!windowed || !containerRef.current) {
|
|
63735
|
+
return;
|
|
63736
|
+
}
|
|
63737
|
+
const observer = new IntersectionObserver(
|
|
63738
|
+
(entries) => {
|
|
63739
|
+
for (const entry of entries) {
|
|
63740
|
+
visibleRef.current = entry.isIntersecting;
|
|
63741
|
+
setViewerVisibility(id2, entry.isIntersecting);
|
|
63742
|
+
if (entry.isIntersecting && parkedRef.current) {
|
|
63743
|
+
unpark();
|
|
63744
|
+
}
|
|
63745
|
+
}
|
|
63746
|
+
},
|
|
63747
|
+
{
|
|
63748
|
+
rootMargin: mountPolicy?.visibleMargin ?? DEFAULT_VISIBLE_MARGIN
|
|
63749
|
+
}
|
|
63750
|
+
);
|
|
63751
|
+
observer.observe(containerRef.current);
|
|
63752
|
+
return () => {
|
|
63753
|
+
observer.disconnect();
|
|
63754
|
+
};
|
|
63755
|
+
}, [windowed]);
|
|
63756
|
+
React__default.useEffect(() => {
|
|
63757
|
+
if (!windowed) {
|
|
63758
|
+
return;
|
|
63759
|
+
}
|
|
63760
|
+
if (!hasPersistencePath()) {
|
|
63761
|
+
console.warn(
|
|
63762
|
+
"DoenetViewer mountPolicy: windowed mounting is enabled but neither flags.allowSaveState nor flags.allowLocalState is set, so parking would lose student work. This viewer will always stay live."
|
|
63763
|
+
);
|
|
63764
|
+
}
|
|
63765
|
+
const unregister = registerWindowedViewer({
|
|
63766
|
+
id: id2,
|
|
63767
|
+
maxLiveViewers: mountPolicy?.maxLiveViewers ?? DEFAULT_MAX_LIVE_VIEWERS,
|
|
63768
|
+
parkDelayMs: mountPolicy?.parkDelayMs ?? DEFAULT_PARK_DELAY_MS,
|
|
63769
|
+
canPark,
|
|
63770
|
+
requestPark: beginPark
|
|
63771
|
+
});
|
|
63772
|
+
return () => {
|
|
63773
|
+
parkFlushCleanupRef.current?.();
|
|
63774
|
+
unregister();
|
|
63775
|
+
};
|
|
63776
|
+
}, [windowed]);
|
|
63313
63777
|
if (inErrorState) {
|
|
63314
63778
|
if (foundAutoVersion) {
|
|
63315
63779
|
setIgnoreDetectedVersion(true);
|
|
63316
63780
|
setInErrorState("");
|
|
63317
63781
|
return null;
|
|
63318
63782
|
}
|
|
63319
|
-
let errorIcon = /* @__PURE__ */
|
|
63783
|
+
let errorIcon = /* @__PURE__ */ React__default.createElement(
|
|
63320
63784
|
MdError,
|
|
63321
63785
|
{
|
|
63322
63786
|
fontSize: "24pt",
|
|
@@ -63324,7 +63788,7 @@ function DoenetViewer({
|
|
|
63324
63788
|
style: { verticalAlign: "middle" }
|
|
63325
63789
|
}
|
|
63326
63790
|
);
|
|
63327
|
-
return /* @__PURE__ */
|
|
63791
|
+
return /* @__PURE__ */ React__default.createElement(
|
|
63328
63792
|
"div",
|
|
63329
63793
|
{
|
|
63330
63794
|
style: {
|
|
@@ -63344,19 +63808,28 @@ function DoenetViewer({
|
|
|
63344
63808
|
inErrorState
|
|
63345
63809
|
);
|
|
63346
63810
|
}
|
|
63347
|
-
|
|
63811
|
+
const viewerContent = parked ? (
|
|
63812
|
+
// Fixed-height placeholder holding a parked viewer's place in the
|
|
63813
|
+
// layout (the last height the iframe reported survives in state, so
|
|
63814
|
+
// parking does not shift the page).
|
|
63815
|
+
/* @__PURE__ */ React__default.createElement(
|
|
63816
|
+
"div",
|
|
63817
|
+
{
|
|
63818
|
+
"data-doenet-parked-viewer": "true",
|
|
63819
|
+
style: {
|
|
63820
|
+
width: "100%",
|
|
63821
|
+
boxSizing: "border-box",
|
|
63822
|
+
height,
|
|
63823
|
+
minHeight: 50
|
|
63824
|
+
}
|
|
63825
|
+
}
|
|
63826
|
+
)
|
|
63827
|
+
) : /* @__PURE__ */ React__default.createElement(React__default.Fragment, null, addVirtualKeyboard ? /* @__PURE__ */ React__default.createElement(ExternalVirtualKeyboard, { ownerRef: ref, theme: resolvedTheme }) : null, /* @__PURE__ */ React__default.createElement(
|
|
63348
63828
|
"iframe",
|
|
63349
63829
|
{
|
|
63350
63830
|
title: "Doenet document",
|
|
63351
63831
|
ref,
|
|
63352
|
-
srcDoc
|
|
63353
|
-
id2,
|
|
63354
|
-
doenetML,
|
|
63355
|
-
doenetViewerProps,
|
|
63356
|
-
standaloneUrl,
|
|
63357
|
-
cssUrl,
|
|
63358
|
-
useSharedCoreWorker
|
|
63359
|
-
),
|
|
63832
|
+
srcDoc,
|
|
63360
63833
|
style: {
|
|
63361
63834
|
width: "100%",
|
|
63362
63835
|
boxSizing: "border-box",
|
|
@@ -63367,13 +63840,26 @@ function DoenetViewer({
|
|
|
63367
63840
|
height
|
|
63368
63841
|
}
|
|
63369
63842
|
));
|
|
63843
|
+
if (!windowed) {
|
|
63844
|
+
return viewerContent;
|
|
63845
|
+
}
|
|
63846
|
+
return /* @__PURE__ */ React__default.createElement("div", { ref: containerRef, style: { width: "100%" } }, viewerContent);
|
|
63847
|
+
}
|
|
63848
|
+
function serializePropsSnapshot(seed, props) {
|
|
63849
|
+
const snapshot = { ...seed };
|
|
63850
|
+
for (const [key, val] of Object.entries(props)) {
|
|
63851
|
+
if (typeof val !== "function") {
|
|
63852
|
+
snapshot[key] = val;
|
|
63853
|
+
}
|
|
63854
|
+
}
|
|
63855
|
+
return JSON.stringify(snapshot);
|
|
63370
63856
|
}
|
|
63371
|
-
function logComlinkError(method) {
|
|
63857
|
+
function logComlinkError(component, method) {
|
|
63372
63858
|
return (err) => {
|
|
63373
|
-
console.warn(`iframe
|
|
63859
|
+
console.warn(`iframe ${component}: ${method} failed`, err);
|
|
63374
63860
|
};
|
|
63375
63861
|
}
|
|
63376
|
-
const DoenetEditor =
|
|
63862
|
+
const DoenetEditor = React__default.forwardRef(function DoenetEditor2({
|
|
63377
63863
|
doenetML,
|
|
63378
63864
|
standaloneUrl: specifiedStandaloneUrl,
|
|
63379
63865
|
cssUrl: specifiedCssUrl,
|
|
@@ -63383,17 +63869,17 @@ const DoenetEditor = React__default__default.forwardRef(function DoenetEditor2({
|
|
|
63383
63869
|
autodetectVersion = true,
|
|
63384
63870
|
...doenetEditorProps
|
|
63385
63871
|
}, forwardedRef) {
|
|
63386
|
-
const [id2, _2] =
|
|
63387
|
-
const ref =
|
|
63388
|
-
const editorIframeRef =
|
|
63389
|
-
const pendingActions =
|
|
63390
|
-
const lastSentPropsSnapshotRef =
|
|
63391
|
-
const lastSentFunctionPropsRef =
|
|
63392
|
-
const doenetEditorPropsRef =
|
|
63872
|
+
const [id2, _2] = React__default.useState(() => Math.random().toString(36).slice(2));
|
|
63873
|
+
const ref = React__default.useRef(null);
|
|
63874
|
+
const editorIframeRef = React__default.useRef(null);
|
|
63875
|
+
const pendingActions = React__default.useRef([]);
|
|
63876
|
+
const lastSentPropsSnapshotRef = React__default.useRef(null);
|
|
63877
|
+
const lastSentFunctionPropsRef = React__default.useRef(null);
|
|
63878
|
+
const doenetEditorPropsRef = React__default.useRef(doenetEditorProps);
|
|
63393
63879
|
doenetEditorPropsRef.current = doenetEditorProps;
|
|
63394
|
-
const [inErrorState, setInErrorState] =
|
|
63395
|
-
const [ignoreDetectedVersion, setIgnoreDetectedVersion] =
|
|
63396
|
-
const [initialDiagnostics, setInitialDiagnostics] =
|
|
63880
|
+
const [inErrorState, setInErrorState] = React__default.useState(null);
|
|
63881
|
+
const [ignoreDetectedVersion, setIgnoreDetectedVersion] = React__default.useState(false);
|
|
63882
|
+
const [initialDiagnostics, setInitialDiagnostics] = React__default.useState([]);
|
|
63397
63883
|
const resolvedTheme = useResolvedTheme(
|
|
63398
63884
|
doenetEditorProps.darkMode ?? "system"
|
|
63399
63885
|
);
|
|
@@ -63406,12 +63892,17 @@ const DoenetEditor = React__default__default.forwardRef(function DoenetEditor2({
|
|
|
63406
63892
|
);
|
|
63407
63893
|
}
|
|
63408
63894
|
}
|
|
63409
|
-
|
|
63895
|
+
React__default.useImperativeHandle(
|
|
63410
63896
|
forwardedRef,
|
|
63411
63897
|
() => ({
|
|
63412
63898
|
openDiagnosticsTab(tabId) {
|
|
63413
63899
|
const action = (remote) => {
|
|
63414
|
-
remote.openDiagnosticsTab(tabId).catch(
|
|
63900
|
+
remote.openDiagnosticsTab(tabId).catch(
|
|
63901
|
+
logComlinkError(
|
|
63902
|
+
"DoenetEditor",
|
|
63903
|
+
"openDiagnosticsTab"
|
|
63904
|
+
)
|
|
63905
|
+
);
|
|
63415
63906
|
};
|
|
63416
63907
|
if (editorIframeRef.current) {
|
|
63417
63908
|
action(editorIframeRef.current);
|
|
@@ -63421,7 +63912,12 @@ const DoenetEditor = React__default__default.forwardRef(function DoenetEditor2({
|
|
|
63421
63912
|
},
|
|
63422
63913
|
closeDiagnosticsPanel() {
|
|
63423
63914
|
const action = (remote) => {
|
|
63424
|
-
remote.closeDiagnosticsPanel().catch(
|
|
63915
|
+
remote.closeDiagnosticsPanel().catch(
|
|
63916
|
+
logComlinkError(
|
|
63917
|
+
"DoenetEditor",
|
|
63918
|
+
"closeDiagnosticsPanel"
|
|
63919
|
+
)
|
|
63920
|
+
);
|
|
63425
63921
|
};
|
|
63426
63922
|
if (editorIframeRef.current) {
|
|
63427
63923
|
action(editorIframeRef.current);
|
|
@@ -63431,7 +63927,12 @@ const DoenetEditor = React__default__default.forwardRef(function DoenetEditor2({
|
|
|
63431
63927
|
},
|
|
63432
63928
|
updateRenderedView() {
|
|
63433
63929
|
const action = (remote) => {
|
|
63434
|
-
remote.updateRenderedView().catch(
|
|
63930
|
+
remote.updateRenderedView().catch(
|
|
63931
|
+
logComlinkError(
|
|
63932
|
+
"DoenetEditor",
|
|
63933
|
+
"updateRenderedView"
|
|
63934
|
+
)
|
|
63935
|
+
);
|
|
63435
63936
|
};
|
|
63436
63937
|
if (editorIframeRef.current) {
|
|
63437
63938
|
action(editorIframeRef.current);
|
|
@@ -63442,7 +63943,7 @@ const DoenetEditor = React__default__default.forwardRef(function DoenetEditor2({
|
|
|
63442
63943
|
}),
|
|
63443
63944
|
[]
|
|
63444
63945
|
);
|
|
63445
|
-
const initialIframePropsRef =
|
|
63946
|
+
const initialIframePropsRef = React__default.useRef(null);
|
|
63446
63947
|
if (initialIframePropsRef.current === null) {
|
|
63447
63948
|
initialIframePropsRef.current = {
|
|
63448
63949
|
doenetML,
|
|
@@ -63473,7 +63974,7 @@ const DoenetEditor = React__default__default.forwardRef(function DoenetEditor2({
|
|
|
63473
63974
|
} else {
|
|
63474
63975
|
cssUrl = `https://cdn.jsdelivr.net/npm/@doenet/standalone@${selectedDoenetmlVersion}/style.css`;
|
|
63475
63976
|
}
|
|
63476
|
-
|
|
63977
|
+
React__default.useEffect(() => {
|
|
63477
63978
|
const listener = (event) => {
|
|
63478
63979
|
if (event.origin !== window.location.origin || event.data?.origin !== id2) {
|
|
63479
63980
|
return;
|
|
@@ -63497,7 +63998,10 @@ const DoenetEditor = React__default__default.forwardRef(function DoenetEditor2({
|
|
|
63497
63998
|
}
|
|
63498
63999
|
}
|
|
63499
64000
|
editorIframe?.renderEditorWithFunctionProps(...proxiedFunctions).catch(
|
|
63500
|
-
logComlinkError(
|
|
64001
|
+
logComlinkError(
|
|
64002
|
+
"DoenetEditor",
|
|
64003
|
+
"renderEditorWithFunctionProps"
|
|
64004
|
+
)
|
|
63501
64005
|
);
|
|
63502
64006
|
lastSentFunctionPropsRef.current = registeredFunctions;
|
|
63503
64007
|
editorIframeRef.current = editorIframe;
|
|
@@ -63516,7 +64020,7 @@ const DoenetEditor = React__default__default.forwardRef(function DoenetEditor2({
|
|
|
63516
64020
|
window.removeEventListener("message", listener);
|
|
63517
64021
|
};
|
|
63518
64022
|
}, []);
|
|
63519
|
-
const srcDoc =
|
|
64023
|
+
const srcDoc = React__default.useMemo(() => {
|
|
63520
64024
|
const baseProps = {
|
|
63521
64025
|
...initialIframePropsRef.current.doenetEditorProps
|
|
63522
64026
|
};
|
|
@@ -63537,36 +64041,26 @@ const DoenetEditor = React__default__default.forwardRef(function DoenetEditor2({
|
|
|
63537
64041
|
cssUrl
|
|
63538
64042
|
);
|
|
63539
64043
|
}, [id2, standaloneUrl, cssUrl, initialDiagnostics]);
|
|
63540
|
-
const
|
|
63541
|
-
|
|
63542
|
-
|
|
63543
|
-
|
|
63544
|
-
|
|
63545
|
-
}
|
|
63546
|
-
const propsSnapshotStr = JSON.stringify(propsForUpdate);
|
|
63547
|
-
React__default__default.useLayoutEffect(() => {
|
|
64044
|
+
const propsSnapshotStr = serializePropsSnapshot(
|
|
64045
|
+
{ width },
|
|
64046
|
+
doenetEditorProps
|
|
64047
|
+
);
|
|
64048
|
+
React__default.useLayoutEffect(() => {
|
|
63548
64049
|
editorIframeRef.current = null;
|
|
63549
|
-
|
|
63550
|
-
width: initialIframePropsRef.current.width
|
|
63551
|
-
};
|
|
63552
|
-
for (const [key, val] of Object.entries(
|
|
64050
|
+
lastSentPropsSnapshotRef.current = serializePropsSnapshot(
|
|
64051
|
+
{ width: initialIframePropsRef.current.width },
|
|
63553
64052
|
initialIframePropsRef.current.doenetEditorProps
|
|
63554
|
-
)
|
|
63555
|
-
if (typeof val !== "function") {
|
|
63556
|
-
baselineProps[key] = val;
|
|
63557
|
-
}
|
|
63558
|
-
}
|
|
63559
|
-
lastSentPropsSnapshotRef.current = JSON.stringify(baselineProps);
|
|
64053
|
+
);
|
|
63560
64054
|
lastSentFunctionPropsRef.current = null;
|
|
63561
64055
|
}, [srcDoc]);
|
|
63562
|
-
|
|
64056
|
+
React__default.useEffect(() => {
|
|
63563
64057
|
if (lastSentPropsSnapshotRef.current === propsSnapshotStr) {
|
|
63564
64058
|
return;
|
|
63565
64059
|
}
|
|
63566
64060
|
lastSentPropsSnapshotRef.current = propsSnapshotStr;
|
|
63567
64061
|
const snapshot = JSON.parse(propsSnapshotStr);
|
|
63568
64062
|
const action = (remote) => {
|
|
63569
|
-
remote.updateEditorProps(snapshot).catch(logComlinkError("updateEditorProps"));
|
|
64063
|
+
remote.updateEditorProps(snapshot).catch(logComlinkError("DoenetEditor", "updateEditorProps"));
|
|
63570
64064
|
};
|
|
63571
64065
|
if (editorIframeRef.current) {
|
|
63572
64066
|
action(editorIframeRef.current);
|
|
@@ -63574,10 +64068,10 @@ const DoenetEditor = React__default__default.forwardRef(function DoenetEditor2({
|
|
|
63574
64068
|
pendingActions.current.push(action);
|
|
63575
64069
|
}
|
|
63576
64070
|
}, [propsSnapshotStr, srcDoc]);
|
|
63577
|
-
|
|
64071
|
+
React__default.useEffect(() => {
|
|
63578
64072
|
syncIframeBodyBackground();
|
|
63579
64073
|
}, [doenetEditorProps.darkMode]);
|
|
63580
|
-
|
|
64074
|
+
React__default.useEffect(() => {
|
|
63581
64075
|
const prev = lastSentFunctionPropsRef.current;
|
|
63582
64076
|
if (prev === null) {
|
|
63583
64077
|
return;
|
|
@@ -63609,7 +64103,12 @@ const DoenetEditor = React__default__default.forwardRef(function DoenetEditor2({
|
|
|
63609
64103
|
proxiedFunctions.push(proxy(val));
|
|
63610
64104
|
}
|
|
63611
64105
|
const action = (remote) => {
|
|
63612
|
-
remote.updateEditorFunctionProps(...proxiedFunctions).catch(
|
|
64106
|
+
remote.updateEditorFunctionProps(...proxiedFunctions).catch(
|
|
64107
|
+
logComlinkError(
|
|
64108
|
+
"DoenetEditor",
|
|
64109
|
+
"updateEditorFunctionProps"
|
|
64110
|
+
)
|
|
64111
|
+
);
|
|
63613
64112
|
};
|
|
63614
64113
|
if (editorIframeRef.current) {
|
|
63615
64114
|
action(editorIframeRef.current);
|
|
@@ -63635,7 +64134,7 @@ const DoenetEditor = React__default__default.forwardRef(function DoenetEditor2({
|
|
|
63635
64134
|
]);
|
|
63636
64135
|
return null;
|
|
63637
64136
|
}
|
|
63638
|
-
let errorIcon = /* @__PURE__ */
|
|
64137
|
+
let errorIcon = /* @__PURE__ */ React__default.createElement(
|
|
63639
64138
|
MdError,
|
|
63640
64139
|
{
|
|
63641
64140
|
fontSize: "24pt",
|
|
@@ -63643,7 +64142,7 @@ const DoenetEditor = React__default__default.forwardRef(function DoenetEditor2({
|
|
|
63643
64142
|
style: { verticalAlign: "middle", marginRight: "5px" }
|
|
63644
64143
|
}
|
|
63645
64144
|
);
|
|
63646
|
-
return /* @__PURE__ */
|
|
64145
|
+
return /* @__PURE__ */ React__default.createElement(
|
|
63647
64146
|
"div",
|
|
63648
64147
|
{
|
|
63649
64148
|
style: {
|
|
@@ -63663,7 +64162,7 @@ const DoenetEditor = React__default__default.forwardRef(function DoenetEditor2({
|
|
|
63663
64162
|
inErrorState
|
|
63664
64163
|
);
|
|
63665
64164
|
}
|
|
63666
|
-
return /* @__PURE__ */
|
|
64165
|
+
return /* @__PURE__ */ React__default.createElement(React__default.Fragment, null, addVirtualKeyboard ? /* @__PURE__ */ React__default.createElement(ExternalVirtualKeyboard, { ownerRef: ref, theme: resolvedTheme }) : null, /* @__PURE__ */ React__default.createElement(
|
|
63667
64166
|
"iframe",
|
|
63668
64167
|
{
|
|
63669
64168
|
title: "Doenet Editor",
|
|
@@ -63686,6 +64185,7 @@ export {
|
|
|
63686
64185
|
defaultCreativeCommonsVersion$1 as defaultCreativeCommonsVersion,
|
|
63687
64186
|
getMediaLicenseDisplay,
|
|
63688
64187
|
getMediaLicenseInfo,
|
|
64188
|
+
getViewerLifecycleStats,
|
|
63689
64189
|
mathjaxConfig$1 as mathjaxConfig,
|
|
63690
64190
|
mediaLicenses$1 as mediaLicenses,
|
|
63691
64191
|
version
|