@zzish/math-rich-input 0.1.58 → 0.1.59
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 +22 -0
- package/dist/index.js +20 -35
- package/dist/standalone.js +1 -1
- package/package.json +7 -2
- package/scripts/build-katex-stylesheet.js +40 -0
- package/src/katexHelper.js +20 -38
- package/src/katexStylesheet.generated.js +3 -0
- package/src/standalone.js +48 -5
package/src/standalone.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { createRoot } from "react-dom/client";
|
|
3
|
+
import { flushSync } from "react-dom";
|
|
3
4
|
import { MathRichInput } from "./index.js";
|
|
5
|
+
import { setupKatex } from "./katexHelper";
|
|
4
6
|
|
|
5
7
|
// Import CSS files
|
|
6
8
|
import "./MathRichInput.css";
|
|
@@ -31,6 +33,8 @@ class MathRichInputElement extends HTMLElement {
|
|
|
31
33
|
this.lastRenderTime = 0;
|
|
32
34
|
this.renderThrottleMs = 16; // ~60fps throttle
|
|
33
35
|
this.isDuringDrag = false;
|
|
36
|
+
/** The element waiting for the first, synchronous render (`drawFirstRender`); null once drawn. */
|
|
37
|
+
this.firstElement = null;
|
|
34
38
|
/** Pending teardown, cancelled when a disconnect turns out to have been a move. */
|
|
35
39
|
this.teardownTimeout = null;
|
|
36
40
|
|
|
@@ -376,6 +380,38 @@ class MathRichInputElement extends HTMLElement {
|
|
|
376
380
|
}
|
|
377
381
|
}
|
|
378
382
|
|
|
383
|
+
/**
|
|
384
|
+
* DRAW THE FIRST RENDER BEFORE THE PAGE CAN PAINT.
|
|
385
|
+
*
|
|
386
|
+
* `root.render()` is not synchronous. React picks its priority from `window.event`: inside a discrete
|
|
387
|
+
* event such as a click it is drawn at once, anywhere else it is scheduled and drawn in slices with the
|
|
388
|
+
* browser painting in between. A host that connects fields outside an event — a framework flushing its
|
|
389
|
+
* DOM in a microtask, or this bundle arriving and upgrading fields already on the page — showed every
|
|
390
|
+
* field empty, then filled them one at a time while the layout around them grew (the Notebook's Studio,
|
|
391
|
+
* WORK-491). The first render is therefore flushed synchronously.
|
|
392
|
+
*
|
|
393
|
+
* In a microtask rather than here, because a field can be connected while React is committing (a
|
|
394
|
+
* React host renders `<math-rich-input>` in its own tree), and `flushSync` cannot flush from inside a
|
|
395
|
+
* commit: it warns and does nothing. A microtask runs once the commit has finished and still before the
|
|
396
|
+
* browser paints — React's own documented pattern for this case. A render asked for again before then
|
|
397
|
+
* replaces the element, so what is drawn is the latest.
|
|
398
|
+
*/
|
|
399
|
+
drawFirstRender(root, element) {
|
|
400
|
+
const pending = this.firstElement;
|
|
401
|
+
this.firstElement = element;
|
|
402
|
+
if (pending) return;
|
|
403
|
+
queueMicrotask(() => {
|
|
404
|
+
const latest = this.firstElement;
|
|
405
|
+
this.firstElement = null;
|
|
406
|
+
if (this.root !== root || !latest) return;
|
|
407
|
+
try {
|
|
408
|
+
flushSync(() => root.render(latest));
|
|
409
|
+
} catch (error) {
|
|
410
|
+
console.error("❌ MathRichInput: First render failed:", error);
|
|
411
|
+
}
|
|
412
|
+
});
|
|
413
|
+
}
|
|
414
|
+
|
|
379
415
|
render() {
|
|
380
416
|
// Check if this is a force render (bypass all safety checks)
|
|
381
417
|
const isForceRender = globalDragState.forceRenderQueue.has(this);
|
|
@@ -423,9 +459,11 @@ class MathRichInputElement extends HTMLElement {
|
|
|
423
459
|
}
|
|
424
460
|
|
|
425
461
|
// Create React root if it doesn't exist
|
|
462
|
+
let firstRender = false;
|
|
426
463
|
if (!this.root) {
|
|
427
464
|
try {
|
|
428
465
|
this.root = createRoot(container);
|
|
466
|
+
firstRender = true;
|
|
429
467
|
} catch (error) {
|
|
430
468
|
console.error(
|
|
431
469
|
"❌ MathRichInput: Failed to create React root:",
|
|
@@ -441,9 +479,7 @@ class MathRichInputElement extends HTMLElement {
|
|
|
441
479
|
return;
|
|
442
480
|
}
|
|
443
481
|
|
|
444
|
-
|
|
445
|
-
this.root.render(
|
|
446
|
-
React.createElement(MathRichInput, {
|
|
482
|
+
const element = React.createElement(MathRichInput, {
|
|
447
483
|
value: value,
|
|
448
484
|
placeholder: placeholder,
|
|
449
485
|
readOnly: readonly,
|
|
@@ -482,8 +518,10 @@ class MathRichInputElement extends HTMLElement {
|
|
|
482
518
|
console.error("❌ MathRichInput: onChange error:", error);
|
|
483
519
|
}
|
|
484
520
|
},
|
|
485
|
-
})
|
|
486
|
-
|
|
521
|
+
});
|
|
522
|
+
|
|
523
|
+
if (firstRender || this.firstElement) this.drawFirstRender(this.root, element);
|
|
524
|
+
else this.root.render(element);
|
|
487
525
|
|
|
488
526
|
// Render completed successfully
|
|
489
527
|
} catch (error) {
|
|
@@ -503,6 +541,11 @@ class MathRichInputElement extends HTMLElement {
|
|
|
503
541
|
}
|
|
504
542
|
}
|
|
505
543
|
|
|
544
|
+
// KaTeX's stylesheet goes on the page when the element is defined, not when the first field mounts: a
|
|
545
|
+
// host that loads this bundle ahead of its first field (the Notebook does, at idle) then has the
|
|
546
|
+
// stylesheet and its fonts in place before any field is drawn. Same stylesheet, same id; see katexHelper.
|
|
547
|
+
setupKatex();
|
|
548
|
+
|
|
506
549
|
// Define the web component
|
|
507
550
|
customElements.define("math-rich-input", MathRichInputElement);
|
|
508
551
|
|