aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/Utils.ts3
-rw-r--r--src/client/util/CurrentUserUtils.ts4
-rw-r--r--src/client/views/EditableView.tsx5
-rw-r--r--src/client/views/GestureOverlay.tsx4
-rw-r--r--src/client/views/InkTranscription.tsx182
-rw-r--r--src/client/views/InkingStroke.tsx2
-rw-r--r--src/client/views/LightboxView.tsx3
-rw-r--r--src/client/views/MainView.tsx36
-rw-r--r--src/client/views/UndoStack.tsx3
-rw-r--r--src/client/views/animationtimeline/Timeline.tsx3
-rw-r--r--src/client/views/collections/CollectionNoteTakingView.tsx3
-rw-r--r--src/client/views/collections/CollectionStackingView.tsx10
-rw-r--r--src/client/views/collections/CollectionStackingViewFieldColumn.tsx12
-rw-r--r--src/client/views/collections/CollectionTreeView.tsx3
-rw-r--r--src/client/views/collections/TreeView.tsx3
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx53
-rw-r--r--src/client/views/collections/collectionFreeForm/FaceCollectionBox.tsx3
-rw-r--r--src/client/views/collections/collectionFreeForm/MarqueeView.tsx39
-rw-r--r--src/client/views/collections/collectionLinear/CollectionLinearView.tsx5
-rw-r--r--src/client/views/collections/collectionSchema/CollectionSchemaView.tsx24
-rw-r--r--src/client/views/collections/collectionSchema/SchemaCellField.tsx4
-rw-r--r--src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx9
-rw-r--r--src/client/views/collections/collectionSchema/SchemaTableCell.tsx3
-rw-r--r--src/client/views/global/globalScripts.ts2
-rw-r--r--src/client/views/nodes/DataVizBox/DataVizBox.tsx7
-rw-r--r--src/client/views/nodes/DataVizBox/DocCreatorMenu/DocCreatorMenu.tsx3
-rw-r--r--src/client/views/nodes/DataVizBox/components/Histogram.tsx11
-rw-r--r--src/client/views/nodes/DataVizBox/components/LineChart.tsx11
-rw-r--r--src/client/views/nodes/DataVizBox/components/PieChart.tsx15
-rw-r--r--src/client/views/nodes/DiagramBox.tsx6
-rw-r--r--src/client/views/nodes/DocumentContentsView.tsx4
-rw-r--r--src/client/views/nodes/DocumentView.tsx22
-rw-r--r--src/client/views/nodes/EquationBox.tsx3
-rw-r--r--src/client/views/nodes/FunctionPlotBox.tsx3
-rw-r--r--src/client/views/nodes/LabelBox.tsx38
-rw-r--r--src/client/views/nodes/LinkBox.tsx23
-rw-r--r--src/client/views/nodes/LinkDocPreview.tsx9
-rw-r--r--src/client/views/nodes/ScreenshotBox.tsx18
-rw-r--r--src/client/views/nodes/calendarBox/CalendarBox.tsx35
-rw-r--r--src/client/views/nodes/chatbot/chatboxcomponents/ChatBox.tsx14
-rw-r--r--src/client/views/nodes/formattedText/FormattedTextBox.tsx8
-rw-r--r--src/client/views/nodes/trails/PresBox.tsx51
-rw-r--r--src/client/views/pdf/GPTPopup/GPTPopup.tsx3
-rw-r--r--src/fields/InkField.ts1
44 files changed, 358 insertions, 345 deletions
diff --git a/src/Utils.ts b/src/Utils.ts
index 724725c23..e96b8e231 100644
--- a/src/Utils.ts
+++ b/src/Utils.ts
@@ -202,6 +202,9 @@ export function aggregateBounds(boundsList: { x: number; y: number; width?: numb
export function intersectRect(r1: { left: number; top: number; width: number; height: number }, r2: { left: number; top: number; width: number; height: number }) {
return !(r2.left > r1.left + r1.width || r2.left + r2.width < r1.left || r2.top > r1.top + r1.height || r2.top + r2.height < r1.top);
}
+export function rectContains(r1: { left: number; top: number; width: number; height: number }, r2: { left: number; top: number; width: number; height: number }) {
+ if (r1.left < r2.left && r1.left + r1.width > r2.left + r2.width && r1.top < r2.top && r1.top + r1.height > r2.top + r2.height) return true;
+}
export function stringHash(s?: string) {
return !s ? undefined : Math.abs(s.split('').reduce((a, b) => (n => n & n)((a << 5) - a + b.charCodeAt(0)), 0));
diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index 45feb0b2f..9fbc82bef 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -796,6 +796,7 @@ pie title Minerals in my tap water
{ title: "Pen", toolTip: "Pen (Ctrl+P)", btnType: ButtonType.ToggleButton, icon: "pen-nib", toolType: InkInkTool.Pen, ignoreClick: true, scripts: {onClick:'{ return setActiveTool(this.toolType, true, _readOnly_);}' }},
{ title: "Highlight",toolTip: "Highlight (Ctrl+H)", btnType: ButtonType.ToggleButton, icon: "highlighter", toolType: InkInkTool.Highlight, ignoreClick: true, scripts: {onClick:'{ return setActiveTool(this.toolType, true, _readOnly_);}' }},
{ title: "Write", toolTip: "Write (Ctrl+Shift+P)", btnType: ButtonType.ToggleButton, icon: "pen", toolType: InkInkTool.Write, ignoreClick: true, scripts: {onClick:'{ return setActiveTool(this.toolType, true, _readOnly_);}' }, funcs: {hidden:"IsNoviceMode()" }},
+ { title: "Math", toolTip: "Math", btnType: ButtonType.ToggleButton, icon: "calculator", toolType: InkInkTool.Math, ignoreClick: true, scripts: {onClick:'{ return setActiveTool(this.toolType, true, _readOnly_);}' }, funcs: {hidden:"IsNoviceMode()" }},
]},
{ title: "Width", toolTip: "Stroke width", btnType: ButtonType.NumberSliderButton, toolType: InkProperty.StrokeWidth,ignoreClick: true, scripts: {script: '{ return setInkProperty(this.toolType, value, _readOnly_);}'}, funcs: {hidden:"!activeInkTool()"}, numBtnMin: 1, linearView_btnWidth:40},
{ title: "Color", toolTip: "Stroke color", btnType: ButtonType.ColorButton, icon: "pen", toolType: InkProperty.StrokeColor,ignoreClick: true, scripts: {script: '{ return setInkProperty(this.toolType, value, _readOnly_);}'}, funcs: {hidden:"!activeInkTool()"}},
@@ -1032,6 +1033,9 @@ pie title Minerals in my tap water
doc[`active${InkInkTool.Write}Color`] ?? (doc[`active${InkInkTool.Write}Color`] = "rgb(255, 0, 0)");
doc[`active${InkInkTool.Write}Width`] ?? (doc[`active${InkInkTool.Write}Width`] = 1);
doc[`active${InkInkTool.Write}Bezier`] ?? (doc[`active${InkInkTool.Write}Bezier`] = "0");
+ doc[`active${InkInkTool.Math}Color`] ?? (doc[`active${InkInkTool.Math}Color`] = "rgb(0, 0, 255)");
+ doc[`active${InkInkTool.Math}Width`] ?? (doc[`active${InkInkTool.Math}Width`] = 1);
+ doc[`active${InkInkTool.Math}Bezier`] ?? (doc[`active${InkInkTool.Math}Bezier`] = "0");
doc[`active${InkInkTool.Highlight}Color`] ?? (doc[`active${InkInkTool.Highlight}Color`] = 'transparent');
doc[`active${InkInkTool.Highlight}Width`] ?? (doc[`active${InkInkTool.Highlight}Width`] = 20);
doc[`active${InkInkTool.Highlight}Bezier`] ?? (doc[`active${InkInkTool.Highlight}Bezier`] = "0");
diff --git a/src/client/views/EditableView.tsx b/src/client/views/EditableView.tsx
index d9447b7ec..deeabaa28 100644
--- a/src/client/views/EditableView.tsx
+++ b/src/client/views/EditableView.tsx
@@ -236,6 +236,7 @@ export class EditableView extends ObservableReactComponent<EditableProps> {
return this._editing;
};
+ setInputRef = (r: HTMLInputElement | HTMLTextAreaElement | null) => (this._inputref = r);
renderEditor() {
return this._props.autosuggestProps ? (
<Autosuggest
@@ -255,7 +256,7 @@ export class EditableView extends ObservableReactComponent<EditableProps> {
) : this._props.oneLine !== false && this._props.GetValue()?.toString().indexOf('\n') === -1 ? (
<input
className="editableView-input"
- ref={r => { this._inputref = r; }} // prettier-ignore
+ ref={this.setInputRef}
style={{ display: this._props.display, overflow: 'auto', fontSize: this._props.fontSize, minWidth: 20, background: this._props.background }}
placeholder={this._props.placeholder}
onBlur={e => this.finalizeEdit(e.currentTarget.value, false, true, false)}
@@ -270,7 +271,7 @@ export class EditableView extends ObservableReactComponent<EditableProps> {
) : (
<textarea
className="editableView-input"
- ref={r => { this._inputref = r; }} // prettier-ignore
+ ref={this.setInputRef}
style={{ display: this._props.display, overflow: 'auto', fontSize: this._props.fontSize, minHeight: `min(100%, ${(this._props.GetValue()?.split('\n').length || 1) * 15})`, minWidth: 20, background: this._props.background }}
placeholder={this._props.placeholder}
onBlur={e => this.finalizeEdit(e.currentTarget.value, false, true, false)}
diff --git a/src/client/views/GestureOverlay.tsx b/src/client/views/GestureOverlay.tsx
index 777a34ebc..8488c5293 100644
--- a/src/client/views/GestureOverlay.tsx
+++ b/src/client/views/GestureOverlay.tsx
@@ -3,7 +3,7 @@ import { action, computed, makeObservable, observable, runInAction } from 'mobx'
import { observer } from 'mobx-react';
import * as React from 'react';
import { setupMoveUpEvents } from '../../ClientUtils';
-import { emptyFunction, intersectRect } from '../../Utils';
+import { emptyFunction, intersectRect, rectContains } from '../../Utils';
import { Doc } from '../../fields/Doc';
import { InkData, InkField, InkTool } from '../../fields/InkField';
import { NumCast } from '../../fields/Types';
@@ -166,7 +166,7 @@ export class GestureOverlay extends ObservableReactComponent<React.PropsWithChil
*/
docsInBoundingBox = (boundingBox: { topLeft: number[]; bottomRight: number[] }, childDocs: Doc[]): Doc[] => {
const rect = { left: boundingBox.topLeft[0], top: boundingBox.topLeft[1], width: boundingBox.bottomRight[0] - boundingBox.topLeft[0], height: boundingBox.bottomRight[1] - boundingBox.topLeft[1] };
- return childDocs.filter(doc => intersectRect(rect, { left: NumCast(doc.x), top: NumCast(doc.y), width: NumCast(doc._width), height: NumCast(doc._height) }));
+ return childDocs.filter(doc => rectContains(rect, { left: NumCast(doc.x), top: NumCast(doc.y), width: NumCast(doc._width), height: NumCast(doc._height) }));
};
/**
* Determines if what the array of cusp/intersection data corresponds to a scribble.
diff --git a/src/client/views/InkTranscription.tsx b/src/client/views/InkTranscription.tsx
index 6220033d4..32ca5f56b 100644
--- a/src/client/views/InkTranscription.tsx
+++ b/src/client/views/InkTranscription.tsx
@@ -32,7 +32,7 @@ export class InkTranscription extends React.Component {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
@observable _iinkEditor: any = undefined;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
- private lastJiix: any;
+ @observable _iinkMathEditor: any = undefined;
private currGroup?: Doc;
private collectionFreeForm?: CollectionFreeFormView;
@@ -44,7 +44,7 @@ export class InkTranscription extends React.Component {
@action
// eslint-disable-next-line @typescript-eslint/no-explicit-any
setMathRef = async (r: any) => {
- if (!this._textRegister && r) {
+ if (!this._mathRegister && r) {
const options = {
configuration: {
server: {
@@ -55,19 +55,17 @@ export class InkTranscription extends React.Component {
protocol: 'WEBSOCKET',
},
recognition: {
- type: 'TEXT',
- lang: 'en_US',
- text: {
- mimeTypes: ['application/vnd.myscript.jiix'] as 'application/vnd.myscript.jiix'[],
+ type: 'MATH',
+ math: {
+ mimeTypes: ['application/x-latex'] as unknown as 'application/vnd.myscript.jiix'[],
},
},
},
};
- await iink.Editor.load(r, 'INKV2', options);
-
- this._textRegister = r;
+ this._iinkMathEditor = await iink.Editor.load(r, 'INKV2', options);
+ this._mathRegister = r;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
- r?.addEventListener('exported', (e: any) => this.exportInk(e, this._textRef));
+ r?.addEventListener('exported', (e: any) => this.exportInk(e));
return (this._textRef = r);
}
@@ -97,12 +95,14 @@ export class InkTranscription extends React.Component {
this._iinkEditor = await iink.Editor.load(r, 'INKV2', options);
this._textRegister = r;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
- r?.addEventListener('exported', (e: any) => this.exportInk(e, this._textRef));
+ r?.addEventListener('exported', (e: any) => this.exportInk(e));
return (this._textRef = r);
}
};
+ _ffview: CollectionFreeFormView | undefined;
+
/**
* Handles processing Dash Doc data for ink transcription.
*
@@ -110,7 +110,7 @@ export class InkTranscription extends React.Component {
* @param inkDocs the ink docs contained within the selected group
* @param math boolean whether to do math transcription or not
*/
- transcribeInk = (groupDoc: Doc | undefined, inkDocs: Doc[], math: boolean) => {
+ transcribeInk = (ffview: CollectionFreeFormView, groupDoc: Doc | undefined, inkDocs: Doc[], math: boolean) => {
if (!groupDoc) return;
const validInks = inkDocs.filter(s => s.type === DocumentType.INK);
@@ -126,13 +126,10 @@ export class InkTranscription extends React.Component {
strokes.push(d.inkData.map(pd => inkStroke.ptToScreen({ X: pd.X, Y: pd.Y })));
times.push(authorTime);
});
+ this._ffview = ffview;
this.currGroup = groupDoc;
const pointerData = strokes.map((stroke, i) => this.inkJSON(stroke, times[i]));
- if (math) {
- this._iinkEditor.importPointEvents(pointerData);
- } else {
- this._iinkEditor.importPointEvents(pointerData);
- }
+ (math ? this._iinkMathEditor : this._iinkEditor).importPointEvents(pointerData);
};
convertPointsToString(points: InkData[]): string {
return points[0].map(point => `new Point(${point.X}, ${point.Y})`).join(',');
@@ -204,83 +201,92 @@ export class InkTranscription extends React.Component {
* @param ref the ref to the editor
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
- exportInk = async (e: any, ref: any) => {
- const exports = e.detail['application/vnd.myscript.jiix'];
- if (exports) {
- if (exports['type'] == 'Math') {
- const latex = exports['application/x-latex'];
- if (this.currGroup) {
- this.currGroup.text = latex;
- this.currGroup.title = latex;
- }
+ exportInk = (e: { detail: { [key: string]: string } }) => {
+ const exports = e.detail;
+ if (exports['application/x-latex']) {
+ const latex = exports['application/x-latex'];
+ if (this.currGroup) {
+ this.currGroup.text = latex;
+ this.currGroup.title = latex;
+ }
- ref.editor.clear();
- } else if (exports['type'] == 'Text') {
- if (exports['application/vnd.myscript.jiix']) {
- this.lastJiix = JSON.parse(exports['application/vnd.myscript.jiix']);
- // map timestamp to strokes
- const timestampWord = new Map<number, string>();
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- this.lastJiix.words.map((word: any) => {
- if (word.items) {
- word.items.forEach((i: { id: string; timestamp: string; X: Array<number>; Y: Array<number>; F: Array<number> }) => {
- const ms = Date.parse(i.timestamp);
- timestampWord.set(ms, word.label);
- });
- }
+ this._ffview?.addDocument(
+ Docs.Create.EquationDocument(latex, {
+ title: '',
+ x: this.currGroup?.x as number,
+ y: (this.currGroup?.y as number) + (this.currGroup?.height as number),
+ nativeHeight: 40,
+ _height: 50,
+ nativeWidth: 40,
+ _width: 50,
+ })
+ );
+ // this.showRecogBox(latex as string);
+ this._iinkMathEditor.clear();
+ } else if (exports['application/vnd.myscript.jiix']) {
+ const lastJiix = exports['application/vnd.myscript.jiix'] as unknown as { words: string[]; label: string };
+ // map timestamp to strokes
+ const timestampWord = new Map<number, string>();
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ lastJiix.words.map((word: any) => {
+ if (word.items) {
+ word.items.forEach((i: { id: string; timestamp: string; X: Array<number>; Y: Array<number>; F: Array<number> }) => {
+ const ms = Date.parse(i.timestamp);
+ timestampWord.set(ms, word.label);
});
-
- const wordInkDocMap = new Map<string, Doc[]>();
- if (this.currGroup) {
- const docList = DocListCast(this.currGroup.data);
- docList.forEach((inkDoc: Doc) => {
- // just having the times match up and be a unique value (actual timestamp doesn't matter)
- const ms = (DateCast(inkDoc.author_date)?.getDate().getTime() ?? 0) + 14400000;
- const word = timestampWord.get(ms);
- if (!word) {
- return;
- }
- const entry = wordInkDocMap.get(word);
- if (entry) {
- entry.push(inkDoc);
- wordInkDocMap.set(word, entry);
- } else {
- const newEntry = [inkDoc];
- wordInkDocMap.set(word, newEntry);
- }
- });
- if (this.lastJiix.words.length > 1) this.subgroupsTranscriptions(wordInkDocMap);
- }
}
- const text = exports['label'];
+ });
- if (this.currGroup && text) {
- DocumentView.getDocumentView(this.currGroup)?.ComponentView?.updateIcon?.();
- const image = await this.getIcon();
- const { href } = (image as URLField).url;
- const hrefParts = href.split('.');
- const hrefComplete = `${hrefParts[0]}_o.${hrefParts[1]}`;
- let response;
- try {
- const hrefBase64 = await imageUrlToBase64(hrefComplete);
- response = await gptHandwriting(hrefBase64);
- } catch {
- console.error('Error getting image');
- }
- const textBoxText = 'iink: ' + text + '\n' + '\n' + 'ChatGPT: ' + response;
- this.currGroup.transcription = response;
- this.currGroup.title = response;
- if (!this.currGroup.hasTextBox) {
- const newDoc = Docs.Create.TextDocument(textBoxText, { title: '', x: this.currGroup.x as number, y: (this.currGroup.y as number) + (this.currGroup.height as number) });
- newDoc.height = 200;
- this.collectionFreeForm?.addDocument(newDoc);
- this.currGroup.hasTextBox = true;
+ const wordInkDocMap = new Map<string, Doc[]>();
+ if (this.currGroup) {
+ DocListCast(this.currGroup.data).forEach((inkDoc: Doc) => {
+ // just having the times match up and be a unique value (actual timestamp doesn't matter)
+ const ms = (DateCast(inkDoc.author_date)?.getDate().getTime() ?? 0) + 14400000;
+ const word = timestampWord.get(ms);
+ if (word) {
+ const entry = wordInkDocMap.get(word);
+ if (entry) {
+ entry.push(inkDoc);
+ wordInkDocMap.set(word, entry);
+ } else {
+ const newEntry = [inkDoc];
+ wordInkDocMap.set(word, newEntry);
+ }
}
- ref.editor.clear();
- }
+ });
+ if (lastJiix.words.length > 1) this.subgroupsTranscriptions(wordInkDocMap);
}
+ this.showRecogBox(lastJiix.label);
+ this._iinkEditor.clear();
}
};
+ private showRecogBox(text: string) {
+ if (this.currGroup) {
+ let response;
+ // DocumentView.getDocumentView(this.currGroup)?.ComponentView?.updateIcon?.();
+ // const image = await this.getIcon();
+ // const { href } = (image as URLField).url;
+ // const hrefParts = href.split('.');
+ // const hrefComplete = `${hrefParts[0]}_o.${hrefParts[1]}`;
+ // try {
+ // const hrefBase64 = await imageUrlToBase64(hrefComplete);
+ // response = await gptHandwriting(hrefBase64);
+ // } catch {
+ // console.error('Error getting image');
+ // }
+ const textBoxText = 'iink: ' + text + '\n' + '\n' + 'ChatGPT: ' + response;
+
+ this.currGroup.transcription = response;
+ this.currGroup.title = response;
+ if (!this.currGroup.hasTextBox) {
+ const newDoc = Docs.Create.TextDocument(textBoxText, { title: '', x: this.currGroup.x as number, y: (this.currGroup.y as number) + (this.currGroup.height as number) });
+ newDoc.height = 200;
+ this.collectionFreeForm?.addDocument(newDoc);
+ this.currGroup.hasTextBox = true;
+ }
+ }
+ }
+
/**
* gets the icon of the collection that was just made
* @returns the image of the collection
@@ -299,7 +305,7 @@ export class InkTranscription extends React.Component {
*/
createInkGroup() {
// TODO nda - if document being added to is a inkGrouping then we can just add to that group
- if (Doc.ActiveTool === InkTool.Ink && Doc.ActiveInk === InkInkTool.Write) {
+ if (Doc.ActiveTool === InkTool.Ink && [InkInkTool.Write, InkInkTool.Math].includes(Doc.ActiveInk)) {
CollectionFreeFormView.collectionsWithUnprocessedInk.forEach(ffView => {
// TODO: nda - will probably want to go through ffView unprocessed docs and then see if any of the inksToGroup docs are in it and only use those
const selected = ffView.unprocessedDocs;
@@ -309,7 +315,7 @@ export class InkTranscription extends React.Component {
);
ffView.unprocessedDocs = [];
- InkTranscription.Instance.transcribeInk(newCollection, selected, false);
+ InkTranscription.Instance.transcribeInk(ffView, newCollection, selected, Doc.ActiveInk === InkInkTool.Math);
});
}
CollectionFreeFormView.collectionsWithUnprocessedInk.clear();
diff --git a/src/client/views/InkingStroke.tsx b/src/client/views/InkingStroke.tsx
index 253db08de..4b651af7d 100644
--- a/src/client/views/InkingStroke.tsx
+++ b/src/client/views/InkingStroke.tsx
@@ -124,7 +124,7 @@ export class InkingStroke extends ViewBoxAnnotatableComponent<FieldViewProps>()
);
ffView.unprocessedDocs = [];
- InkTranscription.Instance.transcribeInk(newCollection, selected, false);
+ InkTranscription.Instance.transcribeInk(ffView, newCollection, selected, false);
}
};
diff --git a/src/client/views/LightboxView.tsx b/src/client/views/LightboxView.tsx
index 0eb21b943..62b1180ec 100644
--- a/src/client/views/LightboxView.tsx
+++ b/src/client/views/LightboxView.tsx
@@ -244,6 +244,7 @@ export class LightboxView extends ObservableReactComponent<LightboxViewProps> {
</div>
</div>
);
+ setStickerRef = (r: StickerPalette | null) => (this._annoPaletteView = r);
render() {
let downx = 0;
let downy = 0;
@@ -317,7 +318,7 @@ export class LightboxView extends ObservableReactComponent<LightboxViewProps> {
</GestureOverlay>
</div>
- {this._showPalette && <StickerPalette ref={r => (this._annoPaletteView = r)} Doc={DocCast(Doc.UserDoc().myLightboxDrawings)} />}
+ {this._showPalette && DocCast(Doc.UserDoc().myLightboxDrawings) && <StickerPalette ref={this.setStickerRef} Doc={DocCast(Doc.UserDoc().myLightboxDrawings)!} />}
{this.renderNavBtn(0, undefined, this._props.PanelHeight / 2 - 12.5, 'chevron-left', this._doc && this._history.length ? true : false, this.previous)}
{this.renderNavBtn(
this._props.PanelWidth - Math.min(this._props.PanelWidth / 4, this._props.maxBorder[0]),
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 13b14617c..867a5a304 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -921,19 +921,19 @@ export class MainView extends ObservableReactComponent<object> {
);
}
+ setMainDashRef = (r: HTMLDivElement | null) =>
+ r &&
+ new ResizeObserver(
+ action(() => {
+ this._dashUIWidth = r.getBoundingClientRect().width;
+ this._dashUIHeight = r.getBoundingClientRect().height;
+ })
+ ).observe(r);
@computed get mainDashboardArea() {
return !this.userDoc ? null : (
<div
className="mainView-dashboardArea"
- ref={r => {
- r &&
- new ResizeObserver(
- action(() => {
- this._dashUIWidth = r.getBoundingClientRect().width;
- this._dashUIHeight = r.getBoundingClientRect().height;
- })
- ).observe(r);
- }}
+ ref={this.setMainDashRef}
style={{
color: 'black',
height: `calc(100% - ${this.topOfDashUI + this.topMenuHeight()}px)`,
@@ -1072,6 +1072,14 @@ export class MainView extends ObservableReactComponent<object> {
};
lightboxMaxBorder = [200, 50];
+ setMainViewRef = (r: HTMLDivElement | null) =>
+ r &&
+ new ResizeObserver(
+ action(() => {
+ this._windowWidth = r.getBoundingClientRect().width;
+ this._windowHeight = r.getBoundingClientRect().height;
+ })
+ ).observe(r);
render() {
return (
<div
@@ -1085,15 +1093,7 @@ export class MainView extends ObservableReactComponent<object> {
ele.scrollTop = ele.scrollLeft = 0;
})(document.getElementById('root')!)
}
- ref={r => {
- r &&
- new ResizeObserver(
- action(() => {
- this._windowWidth = r.getBoundingClientRect().width;
- this._windowHeight = r.getBoundingClientRect().height;
- })
- ).observe(r);
- }}>
+ ref={this.setMainViewRef}>
{this.inkResources}
<DictationOverlay />
<SharingManager />
diff --git a/src/client/views/UndoStack.tsx b/src/client/views/UndoStack.tsx
index 067020a62..3755b1ec1 100644
--- a/src/client/views/UndoStack.tsx
+++ b/src/client/views/UndoStack.tsx
@@ -9,6 +9,7 @@ import './UndoStack.scss';
@observer
export class UndoStack extends React.Component<object> {
+ setRef = (r: HTMLDivElement | null) => r?.scroll({ behavior: 'auto', top: (r?.scrollHeight ?? 0) + 20 });
render() {
const background = UndoManager.batchCounter.get() ? 'yellow' : SettingsManager.userVariantColor;
const color = UndoManager.batchCounter.get() ? 'black' : SettingsManager.userColor;
@@ -25,7 +26,7 @@ export class UndoStack extends React.Component<object> {
popup={
<div
className="undoStack-commandsContainer"
- ref={r => r?.scroll({ behavior: 'auto', top: (r?.scrollHeight ?? 0) + 20 })}
+ ref={this.setRef}
style={{
background,
color,
diff --git a/src/client/views/animationtimeline/Timeline.tsx b/src/client/views/animationtimeline/Timeline.tsx
index 814e9a7a0..c2bd01334 100644
--- a/src/client/views/animationtimeline/Timeline.tsx
+++ b/src/client/views/animationtimeline/Timeline.tsx
@@ -533,6 +533,7 @@ export class Timeline extends ObservableReactComponent<FieldViewProps & { Doc: D
this._totalLength = RegionHelpers.convertPixelTime(this._time, 'mili', 'pixel', this._tickSpacing, this._tickIncrement);
};
+ setTrackRef = (r: Track) => this.mapOfTracks.push(r);
/**
* if you have any question here, just shoot me an email or text.
* basically the only thing you need to edit besides render methods in track (individual track lines) and keyframe (green region)
@@ -554,7 +555,7 @@ export class Timeline extends ObservableReactComponent<FieldViewProps & { Doc: D
{[...this.children, this._props.Doc].map(doc => (
<Track
key={doc[Id]}
- ref={ref => this.mapOfTracks.push(ref)}
+ ref={this.setTrackRef}
timeline={this}
animatedDoc={doc}
currentBarX={this._currentBarX}
diff --git a/src/client/views/collections/CollectionNoteTakingView.tsx b/src/client/views/collections/CollectionNoteTakingView.tsx
index 7f639a11e..7a4408931 100644
--- a/src/client/views/collections/CollectionNoteTakingView.tsx
+++ b/src/client/views/collections/CollectionNoteTakingView.tsx
@@ -256,9 +256,10 @@ export class CollectionNoteTakingView extends CollectionSubView() {
const height = () => this.getDocHeight(doc);
let dref: Opt<DocumentView>;
const noteTakingDocTransform = () => this.getDocTransform(doc, dref);
+ const setRef = (r: DocumentView | null) => (dref = r || undefined);
return (
<DocumentView
- ref={r => (dref = r || undefined)}
+ ref={setRef}
Document={doc}
TemplateDataDocument={doc.isTemplateDoc || doc.isTemplateForField ? this._props.TemplateDataDocument : undefined}
pointerEvents={this.blockPointerEventsWhenDragging}
diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx
index bdeb7d944..fbdd23315 100644
--- a/src/client/views/collections/CollectionStackingView.tsx
+++ b/src/client/views/collections/CollectionStackingView.tsx
@@ -1,6 +1,6 @@
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import * as CSS from 'csstype';
-import { action, computed, IReactionDisposer, makeObservable, observable, ObservableMap, reaction, runInAction } from 'mobx';
+import { action, computed, IReactionDisposer, makeObservable, observable, ObservableMap, reaction } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
import { ClientUtils, DivHeight, returnNone, returnZero, setupMoveUpEvents, smoothScroll } from '../../../ClientUtils';
@@ -391,10 +391,8 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection
});
// This following three functions must be from the view Mehek showed
- columnDividerDown = (e: React.PointerEvent) => {
- runInAction(() => {
- this._cursor = 'grabbing';
- });
+ columnDividerDown = action((e: React.PointerEvent) => {
+ this._cursor = 'grabbing';
const batch = UndoManager.StartBatch('stacking width');
setupMoveUpEvents(
this,
@@ -406,7 +404,7 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection
}),
emptyFunction
);
- };
+ });
@action
onDividerMove = (e: PointerEvent) => {
this.Document._layout_columnWidth = Math.max(10, (this._props.DocumentView?.().screenToViewTransform().transformPoint(e.clientX, 0)[0] ?? 0) - this.xMargin);
diff --git a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
index 8c535534a..b5efa7a72 100644
--- a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
+++ b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
@@ -304,6 +304,12 @@ export class CollectionStackingViewFieldColumn extends ObservableReactComponent<
ContextMenu.Instance.displayMenu(pt[0], pt[1], undefined, true);
};
+ setRef = (r: HTMLDivElement | null) => {
+ if (this._headerRef && this._props.colHeaderRefs.includes(this._headerRef)) this._props.colHeaderRefs.splice(this._props.colStackRefs.indexOf(this._headerRef), 1);
+ r && this._props.colHeaderRefs.push(r);
+ this._headerRef = r;
+ };
+
@computed get innards() {
TraceMobx();
const key = this._props.pivotField;
@@ -315,11 +321,7 @@ export class CollectionStackingViewFieldColumn extends ObservableReactComponent<
<div
key={heading}
className="collectionStackingView-sectionHeader"
- ref={r => {
- if (this._headerRef && this._props.colHeaderRefs.includes(this._headerRef)) this._props.colHeaderRefs.splice(this._props.colStackRefs.indexOf(this._headerRef), 1);
- r && this._props.colHeaderRefs.push(r);
- this._headerRef = r;
- }}
+ ref={this.setRef}
style={{
marginTop: 0,
marginBottom: this._props.gridGap,
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index bee5d016d..4625965b4 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -407,6 +407,7 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
remAnnotationDocument = (doc: Doc | Doc[]) => this.removeDocument(doc, `${this._props.fieldKey}_annotations`) || false;
moveAnnotationDocument = (doc: Doc | Doc[], targetCollection: Doc | undefined, addDocument: (document: Doc | Doc[], annotationKey?: string) => boolean) => this.moveDocument(doc, targetCollection, addDocument) || false;
+ setRef = (r: HTMLDivElement | null) => !this.Document.treeView_HasOverlay && r && this.createTreeDropTarget(r);
@observable _headerHeight = 0;
@computed get content() {
const background = () => this._props.styleProvider?.(this.Document, this._props, StyleProp.BackgroundColor) as string;
@@ -428,7 +429,7 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
<div
className="collectionTreeView-contents"
key="tree"
- ref={r => !this.Document.treeView_HasOverlay && r && this.createTreeDropTarget(r)}
+ ref={this.setRef}
style={{
...(!titleBar ? { marginLeft: this.marginX(), paddingTop: this.marginTop() } : {}),
color: color(),
diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx
index 5b2f1ff81..f84c7d3c0 100644
--- a/src/client/views/collections/TreeView.tsx
+++ b/src/client/views/collections/TreeView.tsx
@@ -1294,6 +1294,7 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> {
return null;
}
+ const setRef = (r: TreeView | null) => treeViewRefs.set(child, r || undefined);
const dentDoc = (editTitle: boolean, newParent: Doc, addAfter: Doc | undefined, parent: TreeView | CollectionTreeView | undefined) => {
if (parent instanceof TreeView && parent._props.treeView.fileSysMode && !newParent.isFolder) return;
const fieldKey = Doc.LayoutDataKey(newParent);
@@ -1317,7 +1318,7 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> {
return (
<TreeView
key={child[Id]}
- ref={r => treeViewRefs.set(child, r || undefined)}
+ ref={setRef}
Document={pair.layout}
dataDoc={pair.data}
treeViewParent={treeViewParent}
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 32ace463d..6e9e503f4 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -562,7 +562,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
const B = this.screenToFreeformContentsXf.transformBounds(ge.bounds.left, ge.bounds.top, ge.bounds.width, ge.bounds.height);
const inkDoc = this.createInkDoc(points, B);
if (Doc.ActiveInk === InkInkTool.Highlight) inkDoc.$backgroundColor = 'transparent';
- if (Doc.ActiveInk === InkInkTool.Write) {
+ if ([InkInkTool.Write, InkInkTool.Math].includes(Doc.ActiveInk)) {
this.unprocessedDocs.push(inkDoc);
CollectionFreeFormView.collectionsWithUnprocessedInk.add(this);
}
@@ -2220,18 +2220,41 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
);
};
+ @computed get inkEraser() {
+ return (
+ Doc.ActiveTool === InkTool.Eraser &&
+ Doc.ActiveEraser === InkEraserTool.Radius &&
+ this._showEraserCircle && (
+ <div
+ onPointerMove={this.onCursorMove}
+ style={{
+ position: 'fixed',
+ left: this._eraserX,
+ top: this._eraserY,
+ width: (ActiveEraserWidth() + 5) * 2,
+ height: (ActiveEraserWidth() + 5) * 2,
+ borderRadius: '50%',
+ border: '1px solid gray',
+ transform: 'translate(-50%, -50%)',
+ }}
+ />
+ )
+ );
+ }
+
+ setRef = (r: HTMLDivElement | null) => {
+ this.createDashEventsTarget(r);
+ this.fixWheelEvents(r, this._props.isContentActive, this.onPassiveWheel);
+ r?.addEventListener('mouseleave', this.onMouseLeave);
+ r?.addEventListener('mouseenter', this.onMouseEnter);
+ };
render() {
TraceMobx();
return (
<div
className="collectionfreeformview-container"
id={this._paintedId}
- ref={r => {
- this.createDashEventsTarget(r);
- this.fixWheelEvents(r, this._props.isContentActive, this.onPassiveWheel);
- r?.addEventListener('mouseleave', this.onMouseLeave);
- r?.addEventListener('mouseenter', this.onMouseEnter);
- }}
+ ref={this.setRef}
onWheel={this.onPointerWheel}
onClick={this.onClick}
onPointerDown={this.onPointerDown}
@@ -2246,21 +2269,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
width: `${100 / this.nativeDimScaling}%`,
height: this._props.getScrollHeight?.() ?? `${100 / this.nativeDimScaling}%`,
}}>
- {Doc.ActiveTool === InkTool.Eraser && Doc.ActiveEraser === InkEraserTool.Radius && this._showEraserCircle && (
- <div
- onPointerMove={this.onCursorMove}
- style={{
- position: 'fixed',
- left: this._eraserX,
- top: this._eraserY,
- width: (ActiveEraserWidth() + 5) * 2,
- height: (ActiveEraserWidth() + 5) * 2,
- borderRadius: '50%',
- border: '1px solid gray',
- transform: 'translate(-50%, -50%)',
- }}
- />
- )}
+ {this.inkEraser}
{this.paintFunc ? (
<FormattedTextBox {...this.props} /> // need this so that any live dashfieldviews will update the underlying text that the code eval reads
) : this._lightboxDoc ? (
diff --git a/src/client/views/collections/collectionFreeForm/FaceCollectionBox.tsx b/src/client/views/collections/collectionFreeForm/FaceCollectionBox.tsx
index 142085e14..c31558dff 100644
--- a/src/client/views/collections/collectionFreeForm/FaceCollectionBox.tsx
+++ b/src/client/views/collections/collectionFreeForm/FaceCollectionBox.tsx
@@ -150,6 +150,7 @@ export class UniqueFaceBox extends ViewBoxBaseComponent<FieldViewProps>() {
FaceRecognitionHandler.UniqueFaceRemoveFaceImage(imgDoc, this.Document);
}, 'remove doc from face');
+ setRef = (r: HTMLDivElement | null) => this.fixWheelEvents(r, this._props.isContentActive);
render() {
return (
<div className="face-document-item" ref={ele => this.createDropTarget(ele!)}>
@@ -176,7 +177,7 @@ export class UniqueFaceBox extends ViewBoxBaseComponent<FieldViewProps>() {
style={{
pointerEvents: this._props.isContentActive() ? undefined : 'none',
}}
- ref={r => this.fixWheelEvents(r, this._props.isContentActive)}>
+ ref={this.setRef}>
{FaceRecognitionHandler.UniqueFaceImages(this.Document).map((doc, i) => {
const [name, type] = ImageCastToNameType(doc?.[Doc.LayoutDataKey(doc)]) ?? ['-missing-', '.png'];
return (
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index ff78b332a..4191aaca8 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -762,29 +762,26 @@ export class MarqueeView extends ObservableReactComponent<SubCollectionViewProps
}
e.stopPropagation();
};
+ setRef = (r: HTMLDivElement | null) => {
+ r?.addEventListener('dashDragMovePause', this.onDragMovePause as EventListenerOrEventListenerObject);
+ this.MarqueeRef = r;
+ };
render() {
return (
- <>
- <div
- className="marqueeView"
- ref={r => {
- r?.addEventListener('dashDragMovePause', this.onDragMovePause as EventListenerOrEventListenerObject);
- this.MarqueeRef = r;
- }}
- style={{
- overflow: StrCast(this._props.Document._overflow),
- cursor: Doc.ActiveTool === InkTool.Ink || this._visible ? 'crosshair' : 'pointer',
- }}
- onDragOver={e => e.preventDefault()}
- onScroll={e => {
- e.currentTarget.scrollTop = e.currentTarget.scrollLeft = 0;
- }}
- onClick={this.onClick}
- onPointerDown={this.onPointerDown}>
- {this._visible ? this.marqueeDiv : null}
- {this.props.children}
- </div>
- </>
+ <div
+ className="marqueeView"
+ ref={this.setRef}
+ style={{
+ overflow: StrCast(this._props.Document._overflow),
+ cursor: Doc.ActiveTool === InkTool.Ink || this._visible ? 'crosshair' : 'pointer',
+ }}
+ onDragOver={e => e.preventDefault()}
+ onScroll={e => (e.currentTarget.scrollTop = (e.currentTarget.scrollLeft = 0))} // prettier-ignore
+ onClick={this.onClick}
+ onPointerDown={this.onPointerDown}>
+ {this._visible ? this.marqueeDiv : null}
+ {this.props.children}
+ </div>
);
}
}
diff --git a/src/client/views/collections/collectionLinear/CollectionLinearView.tsx b/src/client/views/collections/collectionLinear/CollectionLinearView.tsx
index d0a1e6f0d..435f618d9 100644
--- a/src/client/views/collections/collectionLinear/CollectionLinearView.tsx
+++ b/src/client/views/collections/collectionLinear/CollectionLinearView.tsx
@@ -158,14 +158,13 @@ export class CollectionLinearView extends CollectionSubView() {
let dref: Opt<HTMLDivElement>;
const docXf = () => this.getTransform(dref);
+ const setRef = (r: HTMLDivElement | null) => (dref = r || undefined);
// const scalable = pair.layout.onClick || pair.layout.onDragStart;
return hidden ? null : (
<div
className={preview ? 'preview' : `collectionLinearView-docBtn`}
key={doc[Id]}
- ref={r => {
- dref = r || undefined;
- }}
+ ref={setRef}
style={{
pointerEvents: 'all',
width: NumCast(doc._width),
diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
index 6442385c0..2576bdf9b 100644
--- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
+++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
@@ -1043,17 +1043,16 @@ export class CollectionSchemaView extends CollectionSubView() {
if (!this._oldKeysWheel?.scrollTop && e.deltaY <= 0) e.preventDefault();
e.stopPropagation();
};
+ setRef = (r: HTMLDivElement | null) => {
+ this._oldKeysWheel?.removeEventListener('wheel', this.onKeysPassiveWheel);
+ this._oldKeysWheel = r;
+ r?.addEventListener('wheel', this.onKeysPassiveWheel, { passive: false });
+ };
_oldKeysWheel: HTMLDivElement | null = null;
@computed get keysDropdown() {
return (
<div className="schema-key-search">
- <div
- className="schema-key-list"
- ref={r => {
- this._oldKeysWheel?.removeEventListener('wheel', this.onKeysPassiveWheel);
- this._oldKeysWheel = r;
- r?.addEventListener('wheel', this.onKeysPassiveWheel, { passive: false });
- }}>
+ <div className="schema-key-list" ref={this.setRef}>
{this._menuKeys.map(key => (
<div
key={key}
@@ -1294,6 +1293,9 @@ export class CollectionSchemaView extends CollectionSubView() {
screenToLocal = () => this.ScreenToLocalBoxXf().translate(-this.tableWidth, 0);
previewWidthFunc = () => this.previewWidth;
displayedDocsFunc = () => this.docsWithDrag.docs;
+ setColHdrRef = (r: SchemaColumnHeader | null) => r && this._headerRefs.push(r);
+ setPreviewRef = (r: HTMLDivElement | null) => (this._previewRef = r);
+
render() {
return (
<div
@@ -1331,7 +1333,7 @@ export class CollectionSchemaView extends CollectionSubView() {
{this.columnKeys.map((key, index) => (
<SchemaColumnHeader
//cleanupField={this.cleanupComputedField}
- ref={r => r && this._headerRefs.push(r)}
+ ref={this.setColHdrRef}
keysDropdown={this.keysDropdown}
schemaView={this}
columnWidth={() => CollectionSchemaView._minColWidth} //TODO: update
@@ -1379,11 +1381,7 @@ export class CollectionSchemaView extends CollectionSubView() {
</div>
{this.previewWidth > 0 && <div className="schema-preview-divider" style={{ width: CollectionSchemaView._previewDividerWidth }} onPointerDown={this.onDividerDown} />}
{this.previewWidth > 0 && (
- <div
- style={{ width: `${this.previewWidth}px` }}
- ref={ref => {
- this._previewRef = ref;
- }}>
+ <div style={{ width: `${this.previewWidth}px` }} ref={this.setPreviewRef}>
{Array.from(this._selectedDocs).lastElement() && (
<DocumentView
Document={Array.from(this._selectedDocs).lastElement()}
diff --git a/src/client/views/collections/collectionSchema/SchemaCellField.tsx b/src/client/views/collections/collectionSchema/SchemaCellField.tsx
index 9ad94cb31..412daa105 100644
--- a/src/client/views/collections/collectionSchema/SchemaCellField.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaCellField.tsx
@@ -341,12 +341,14 @@ export class SchemaCellField extends ObservableReactComponent<SchemaCellFieldPro
return <span className="editableView-static">{this._props.fieldContents ? <FieldView {...this._props.fieldContents} /> : ''}</span>;
};
+ setRef = (r: HTMLDivElement | null) => (this._inputref = r);
+
renderEditor = () => {
return (
<div
contentEditable
className="schemaField-editing"
- ref={r => (this._inputref = r)}
+ ref={this.setRef}
style={{ minHeight: `min(100%, ${(this._props.GetValue()?.split('\n').length || 1) * 15})`, minWidth: 20 }}
onBlur={() => (this._props.refSelectModeInfo.enabled ? setTimeout(() => this.setIsFocused(true), 1000) : this.finalizeEdit(false, true, false))}
onInput={this.onChange}
diff --git a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx
index 134f2ed31..64bfab856 100644
--- a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx
@@ -118,6 +118,10 @@ export class SchemaColumnHeader extends ObservableReactComponent<SchemaColumnHea
return { color, fieldProps, cursor };
};
+ setRef = (r: EditableView | null) => {
+ this._inputRef = r;
+ this._props.autoFocus && r?.setIsFocused(true);
+ };
@computed get editableView() {
const { color, fieldProps } = this.renderProps(this._props);
@@ -133,10 +137,7 @@ export class SchemaColumnHeader extends ObservableReactComponent<SchemaColumnHea
width: '100%',
}}>
<EditableView
- ref={r => {
- this._inputRef = r;
- this._props.autoFocus && r?.setIsFocused(true);
- }}
+ ref={this.setRef}
oneLine={true}
allowCRs={false}
contents={''}
diff --git a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx
index 8b34b4139..02e0d8100 100644
--- a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx
@@ -185,6 +185,7 @@ export class SchemaTableCell extends ObservableReactComponent<SchemaTableCellPro
return eqSymbol + modField;
};
+ setRef = (r: SchemaCellField | null) => selectedCell(this._props) && this._props.autoFocus && r?.setIsFocused(true);
@computed get defaultCellContent() {
const { color, textDecoration, fieldProps, pointerEvents } = SchemaTableCell.renderProps(this._props);
@@ -204,7 +205,7 @@ export class SchemaTableCell extends ObservableReactComponent<SchemaTableCellPro
Doc={this._props.Doc}
highlightCells={(text: string) => this._props.highlightCells(this.adjustSelfReference(text))}
getCells={(text: string) => this._props.eqHighlightFunc(this.adjustSelfReference(text))}
- ref={r => selectedCell(this._props) && this._props.autoFocus && r?.setIsFocused(true)}
+ ref={this.setRef}
oneLine={this._props.oneLine}
contents={undefined}
fieldContents={fieldProps}
diff --git a/src/client/views/global/globalScripts.ts b/src/client/views/global/globalScripts.ts
index cb3adae10..e098d50d8 100644
--- a/src/client/views/global/globalScripts.ts
+++ b/src/client/views/global/globalScripts.ts
@@ -408,7 +408,7 @@ function setActiveTool(tool: InkTool | InkEraserTool | InkInkTool | Gestures, ke
}
runInAction(() => {
const eraserTool = tool === InkTool.Eraser ? Doc.ActiveEraser : [InkEraserTool.Stroke, InkEraserTool.Radius, InkEraserTool.Segment].includes(tool as InkEraserTool) ? (tool as InkEraserTool) : undefined;
- const inkTool = tool === InkTool.Ink ? Doc.ActiveInk : [InkInkTool.Pen, InkInkTool.Write, InkInkTool.Highlight].includes(tool as InkInkTool) ? (tool as InkInkTool) : undefined;
+ const inkTool = tool === InkTool.Ink ? Doc.ActiveInk : [InkInkTool.Pen, InkInkTool.Write, InkInkTool.Math, InkInkTool.Highlight].includes(tool as InkInkTool) ? (tool as InkInkTool) : undefined;
if (GestureOverlay.Instance) {
SnappingManager.SetKeepGestureMode(keepPrim);
}
diff --git a/src/client/views/nodes/DataVizBox/DataVizBox.tsx b/src/client/views/nodes/DataVizBox/DataVizBox.tsx
index 9369ff98a..0b7033e57 100644
--- a/src/client/views/nodes/DataVizBox/DataVizBox.tsx
+++ b/src/client/views/nodes/DataVizBox/DataVizBox.tsx
@@ -420,6 +420,7 @@ export class DataVizBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
}
};
+ setRef = (r: LineChart | Histogram | PieChart | null) => (this._vizRenderer = r ?? undefined);
// toggles for user to decide which chart type to view the data in
@computed get renderVizView() {
const scale = this._props.NativeDimScaling?.() || 1;
@@ -437,9 +438,9 @@ export class DataVizBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
if (!this.records.length) return 'no data/visualization';
switch (this.dataVizView) {
case DataVizView.TABLE: return <TableBox {...sharedProps} Doc={this.Document} specHighlightedRow={this._specialHighlightedRow} docView={this.DocumentView} selectAxes={this.selectAxes} selectTitleCol={this.selectTitleCol}/>;
- case DataVizView.LINECHART: return <LineChart {...sharedProps} Doc={this.Document} dataDoc={this.dataDoc} fieldKey={this.fieldKey} ref={r => {this._vizRenderer = r ?? undefined;}} vizBox={this} />;
- case DataVizView.HISTOGRAM: return <Histogram {...sharedProps} Doc={this.Document} dataDoc={this.dataDoc} fieldKey={this.fieldKey} ref={r => {this._vizRenderer = r ?? undefined;}} />;
- case DataVizView.PIECHART: return <PieChart {...sharedProps} Doc={this.Document} dataDoc={this.dataDoc} fieldKey={this.fieldKey} ref={r => {this._vizRenderer = r ?? undefined;}}
+ case DataVizView.LINECHART: return <LineChart {...sharedProps} Doc={this.Document} dataDoc={this.dataDoc} fieldKey={this.fieldKey} ref={this.setRef} vizBox={this} />;
+ case DataVizView.HISTOGRAM: return <Histogram {...sharedProps} Doc={this.Document} dataDoc={this.dataDoc} fieldKey={this.fieldKey} ref={this.setRef} />;
+ case DataVizView.PIECHART: return <PieChart {...sharedProps} Doc={this.Document} dataDoc={this.dataDoc} fieldKey={this.fieldKey} ref={this.setRef}
margin={{ top: 10, right: 15, bottom: 15, left: 15 }} />;
default:
} // prettier-ignore
diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu/DocCreatorMenu.tsx b/src/client/views/nodes/DataVizBox/DocCreatorMenu/DocCreatorMenu.tsx
index fb083ea75..8f6ecab57 100644
--- a/src/client/views/nodes/DataVizBox/DocCreatorMenu/DocCreatorMenu.tsx
+++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu/DocCreatorMenu.tsx
@@ -540,6 +540,7 @@ export class DocCreatorMenu extends ObservableReactComponent<DocCreateMenuProps>
]; //prettier-ignore
}
+ setRef = (r: HTMLDivElement) => (this._ref = r);
render() {
const topButton = (icon: string, opt: string, func: () => void, tag: string) => (
<div className={`top-button-container ${tag} ${opt === this._menuContent ? 'selected' : ''}`}>
@@ -558,7 +559,7 @@ export class DocCreatorMenu extends ObservableReactComponent<DocCreateMenuProps>
{!this._shouldDisplay ? undefined : (
<div
className="docCreatorMenu-cont"
- ref={r => (this._ref = r)}
+ ref={this.setRef}
style={{
display: '',
left: this._pageX,
diff --git a/src/client/views/nodes/DataVizBox/components/Histogram.tsx b/src/client/views/nodes/DataVizBox/components/Histogram.tsx
index a7c4a00b0..f51683991 100644
--- a/src/client/views/nodes/DataVizBox/components/Histogram.tsx
+++ b/src/client/views/nodes/DataVizBox/components/Histogram.tsx
@@ -413,6 +413,10 @@ export class Histogram extends ObservableReactComponent<HistogramProps> {
});
};
+ setChartRef = (r: HTMLDivElement | null) => {
+ this._histogramRef = r;
+ r && this.drawChart(this._histogramData, this.width, this.height);
+ };
render() {
if (!this.selectedBins) this.layoutDoc.dataViz_histogram_selectedBins = new List<string>();
@@ -446,12 +450,7 @@ export class Histogram extends ObservableReactComponent<HistogramProps> {
size={Size.XSMALL}
/>
</div>
- <div
- ref={r => {
- this._histogramRef = r;
- r && this.drawChart(this._histogramData, this.width, this.height);
- }}
- />
+ <div ref={this.setChartRef} />
{selected !== 'none' ? (
<div className="selected-data">
Selected: {selected}
diff --git a/src/client/views/nodes/DataVizBox/components/LineChart.tsx b/src/client/views/nodes/DataVizBox/components/LineChart.tsx
index 80fadf178..732681e05 100644
--- a/src/client/views/nodes/DataVizBox/components/LineChart.tsx
+++ b/src/client/views/nodes/DataVizBox/components/LineChart.tsx
@@ -347,6 +347,10 @@ export class LineChart extends ObservableReactComponent<LineChartProps> {
.style('pointer-events', 'none')
.style('transform', `translate(${xScale(d0.x) - this.width}px,${yScale(d0.y)}px)`);
}
+ setLineRef = (r: HTMLDivElement | null) => {
+ this._lineChartRef = r;
+ this.drawChart([this._lineChartData], this.rangeVals, this.width, this.height);
+ };
render() {
const selectedPt = this._currSelected ? `{ ${this._props.axes[0]}: ${this._currSelected.x} ${this._props.axes[1]}: ${this._currSelected.y} }` : 'none';
@@ -378,12 +382,7 @@ export class LineChart extends ObservableReactComponent<LineChartProps> {
fillWidth
/>
</div>
- <div
- ref={r => {
- this._lineChartRef = r;
- this.drawChart([this._lineChartData], this.rangeVals, this.width, this.height);
- }}
- />
+ <div ref={this.setLineRef} />
{selectedPt !== 'none' ? (
<div className="selected-data">
{`Selected: ${selectedPt}`}
diff --git a/src/client/views/nodes/DataVizBox/components/PieChart.tsx b/src/client/views/nodes/DataVizBox/components/PieChart.tsx
index 0ae70786f..cf476b8d0 100644
--- a/src/client/views/nodes/DataVizBox/components/PieChart.tsx
+++ b/src/client/views/nodes/DataVizBox/components/PieChart.tsx
@@ -373,10 +373,10 @@ export class PieChart extends ObservableReactComponent<PieChartProps> {
const sliceName = StrCast(sliceTitle) ? StrCast(sliceTitle).replace(/\$/g, '').replace(/%/g, '').replace(/#/g, '').replace(/</g, '') : sliceTitle;
const sliceColors = Cast(this._props.layoutDoc.dataViz_pie_sliceColors, listSpec('string'), null);
- sliceColors.forEach(each => {
+ sliceColors?.forEach(each => {
if (each.split('::')[0] === sliceName) sliceColors.splice(sliceColors.indexOf(each), 1);
});
- sliceColors.push(StrCast(sliceName + '::' + color));
+ sliceColors?.push(StrCast(sliceName + '::' + color));
};
@action changeHistogramCheckBox = () => {
@@ -384,6 +384,10 @@ export class PieChart extends ObservableReactComponent<PieChartProps> {
this.drawChart(this._pieChartData, this.width, this.height);
};
+ setChartRef = (r: HTMLDivElement | null) => {
+ this._piechartRef = r;
+ this.drawChart(this._pieChartData, this.width, this.height);
+ };
render() {
let titleAccessor = 'dataViz_pie_title';
if (this._props.axes.length === 2) titleAccessor = titleAccessor + this._props.axes[0] + '-' + this._props.axes[1];
@@ -443,12 +447,7 @@ export class PieChart extends ObservableReactComponent<PieChartProps> {
Organize data as histogram
</div>
) : null}
- <div
- ref={r => {
- this._piechartRef = r;
- this.drawChart(this._pieChartData, this.width, this.height);
- }}
- />
+ <div ref={this.setChartRef} />
{selected !== 'none' ? (
<div className="selected-data">
Selected: {selected}
diff --git a/src/client/views/nodes/DiagramBox.tsx b/src/client/views/nodes/DiagramBox.tsx
index 7cfccf0dc..6a31f64ce 100644
--- a/src/client/views/nodes/DiagramBox.tsx
+++ b/src/client/views/nodes/DiagramBox.tsx
@@ -185,6 +185,8 @@ export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
return '( )';
};
+ setRef = (r: HTMLDivElement | null) => this.fixWheelEvents(r, this._props.isContentActive);
+ setDiagramBoxRef = (r: HTMLDivElement | null) => r && this.renderMermaidAsync.call(this, this.removeWords(this.mermaidcode), r);
render() {
return (
<div
@@ -192,7 +194,7 @@ export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
style={{
pointerEvents: this._props.isContentActive() ? undefined : 'none',
}}
- ref={r => this.fixWheelEvents(r, this._props.isContentActive)}>
+ ref={this.setRef}>
<div className="DIYNodeBox-searchbar">
<input type="text" value={this._inputValue} onKeyDown={action(e => e.key === 'Enter' && this.generateMermaidCode())} onChange={action(e => (this._inputValue = e.target.value))} />
<button type="button" onClick={this.generateMermaidCode}>
@@ -208,7 +210,7 @@ export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
) : this._generating ? (
<div className="loading-circle" />
) : (
- <div className="diagramBox" ref={r => r && this.renderMermaidAsync.call(this, this.removeWords(this.mermaidcode), r)}>
+ <div className="diagramBox" ref={this.setDiagramBoxRef}>
{this._errorMessage || 'Type a prompt to generate a diagram'}
</div>
)}
diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx
index 504c1491e..32741a0fe 100644
--- a/src/client/views/nodes/DocumentContentsView.tsx
+++ b/src/client/views/nodes/DocumentContentsView.tsx
@@ -261,9 +261,7 @@ export class DocumentContentsView extends ObservableReactComponent<DocumentConte
jsx={layoutFrame}
showWarnings
// eslint-disable-next-line @typescript-eslint/no-explicit-any
- onError={(test: any) => {
- console.log('DocumentContentsView:' + test, bindings, layoutFrame);
- }}
+ onError={(test: any) => console.log('DocumentContentsView:' + test, bindings, layoutFrame)}
/>
);
}
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index fe95f15af..bd71115db 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -701,16 +701,18 @@ export class DocumentViewInternal extends DocComponent<DocumentViewProps & Field
aiContentsWidth = () => (this.aiContentsHeight() * (this._props.NativeWidth?.() || 1)) / (this._props.NativeHeight?.() || 1);
aiContentsHeight = () => Math.max(10, this._props.PanelHeight() - (this._aiWinHeight + (this.tagsOverlayFunc() ? 22 : 0)) * this.uiBtnScaling);
+ setAiRef = action((r: HTMLDivElement | null) => this.historyRef(this._oldHistoryWheel, (this._oldHistoryWheel = r)));
+
@computed get aiEditor() {
return (
<div
className="documentView-editorView"
+ ref={this.setAiRef}
style={{
background: SnappingManager.userVariantColor,
width: `${100 / this.uiBtnScaling}%`, //
transform: `scale(${this.uiBtnScaling})`,
- }}
- ref={r => this.historyRef(this._oldHistoryWheel, (this._oldHistoryWheel = r))}>
+ }}>
<div className="documentView-editorView-resizer" />
{this._componentView?.componentAIView?.() ?? null}
{this._props.DocumentView?.() ? <TagsView background={this.backgroundBoxColor} Views={[this._props.DocumentView?.()]} /> : null}
@@ -1507,18 +1509,16 @@ export class DocumentView extends DocComponent<DocumentViewProps>() {
.translate(-(this._docViewInternal?.aiShift() ?? 0), 0)
.scale((this._docViewInternal?.aiScale() ?? 1) / this.nativeScaling);
+ setHtmlOverlayRef = (r: HTMLDivElement | null) => {
+ const val = r?.style.display !== 'none'; // if the outer overlay has been displayed, trigger the innner div to start it's opacity fade in transition
+ if (r && val !== this._enableHtmlOverlayTransitions) {
+ setTimeout(action(() => (this._enableHtmlOverlayTransitions = val)));
+ }
+ };
htmlOverlay = () => {
const effect = StrCast(this._htmlOverlayEffect?.presentation_effect, StrCast(this._htmlOverlayEffect?.followLinkAnimEffect));
return (
- <div
- className="documentView-htmlOverlay"
- ref={r => {
- const val = r?.style.display !== 'none'; // if the outer overlay has been displayed, trigger the innner div to start it's opacity fade in transition
- if (r && val !== this._enableHtmlOverlayTransitions) {
- setTimeout(action(() => (this._enableHtmlOverlayTransitions = val)));
- }
- }}
- style={{ display: !this._htmlOverlayText ? 'none' : undefined }}>
+ <div className="documentView-htmlOverlay" ref={this.setHtmlOverlayRef} style={{ display: !this._htmlOverlayText ? 'none' : undefined }}>
<div className="documentView-htmlOverlayInner" style={{ transition: `all 500ms`, opacity: this._enableHtmlOverlayTransitions ? 0.9 : 0 }}>
{DocumentViewInternal.AnimationEffect(
<div className="webBox-textHighlight">
diff --git a/src/client/views/nodes/EquationBox.tsx b/src/client/views/nodes/EquationBox.tsx
index e0ab04692..2ce24b688 100644
--- a/src/client/views/nodes/EquationBox.tsx
+++ b/src/client/views/nodes/EquationBox.tsx
@@ -116,12 +116,13 @@ export class EquationBox extends ViewBoxBaseComponent<FieldViewProps>() {
this.layoutDoc._nativeHeight = mathHeight;
}
};
+ setRef = (r: HTMLDivElement) => r && this._ref.current?.element.current && this.updateSize(this._ref.current?.element.current);
render() {
TraceMobx();
const scale = this._props.NativeDimScaling?.() || 1;
return (
<div
- ref={r => r && this._ref.current?.element.current && this.updateSize(this._ref.current?.element.current)}
+ ref={this.setRef}
className="equationBox-cont"
onKeyDown={e => e.stopPropagation()}
onPointerDown={e => !e.ctrlKey && e.stopPropagation()}
diff --git a/src/client/views/nodes/FunctionPlotBox.tsx b/src/client/views/nodes/FunctionPlotBox.tsx
index 8e4b64851..e4d37e006 100644
--- a/src/client/views/nodes/FunctionPlotBox.tsx
+++ b/src/client/views/nodes/FunctionPlotBox.tsx
@@ -121,11 +121,12 @@ export class FunctionPlotBox extends ViewBoxAnnotatableComponent<FieldViewProps>
}
// if (this.layout_autoHeight) this.tryUpdateScrollHeight();
};
+ setRef = (r: HTMLDivElement | null) => r && this.createGraph(r);
@computed get theGraph() {
return (
<div
id={`${this._plotId}`}
- ref={r => r && this.createGraph(r)}
+ ref={this.setRef}
style={{ position: 'absolute', width: '100%', height: '100%' }}
onPointerDown={e => {
e.stopPropagation();
diff --git a/src/client/views/nodes/LabelBox.tsx b/src/client/views/nodes/LabelBox.tsx
index e1ecc2018..c5948cbbd 100644
--- a/src/client/views/nodes/LabelBox.tsx
+++ b/src/client/views/nodes/LabelBox.tsx
@@ -169,6 +169,25 @@ export class LabelBox extends ViewBoxBaseComponent<FieldViewProps>() {
}
};
+ setRef = (r: HTMLDivElement | null) => {
+ this._divRef?.removeEventListener('beforeinput', this.beforeInput);
+ this._divRef = r;
+ if (this._divRef) {
+ this._divRef.addEventListener('beforeinput', this.beforeInput);
+
+ if (DocumentView.SelectOnLoad === this.Document) {
+ DocumentView.SetSelectOnLoad(undefined);
+ this._liveTextUndo = FormattedTextBox.LiveTextUndo;
+ FormattedTextBox.LiveTextUndo = undefined;
+ this._divRef.focus();
+ }
+ this.fitTextToBox(this._divRef);
+ if (this.Title) {
+ this.resetCursor();
+ }
+ } else this._timeout && clearTimeout(this._timeout);
+ };
+
render() {
TraceMobx();
const boxParams = this.fitTextToBox(undefined); // this causes mobx to trigger re-render when data changes
@@ -228,24 +247,7 @@ export class LabelBox extends ViewBoxBaseComponent<FieldViewProps>() {
__html: `<span class="textFitted textFitAlignVert" style="display: inline-block; text-align: center; font-size: 100px; height: 0px;">${this.Title?.startsWith('#') ? '' : (this.Title ?? '')}</span>`,
}}
contentEditable={this._props.onClickScript?.() ? undefined : true}
- ref={r => {
- this._divRef?.removeEventListener('beforeinput', this.beforeInput);
- this._divRef = r;
- if (this._divRef) {
- this._divRef.addEventListener('beforeinput', this.beforeInput);
-
- if (DocumentView.SelectOnLoad === this.Document) {
- DocumentView.SetSelectOnLoad(undefined);
- this._liveTextUndo = FormattedTextBox.LiveTextUndo;
- FormattedTextBox.LiveTextUndo = undefined;
- this._divRef.focus();
- }
- this.fitTextToBox(this._divRef);
- if (this.Title) {
- this.resetCursor();
- }
- } else this._timeout && clearTimeout(this._timeout);
- }}
+ ref={this.setRef}
/>
</div>
</div>
diff --git a/src/client/views/nodes/LinkBox.tsx b/src/client/views/nodes/LinkBox.tsx
index 78c8a686c..d31fadf77 100644
--- a/src/client/views/nodes/LinkBox.tsx
+++ b/src/client/views/nodes/LinkBox.tsx
@@ -99,6 +99,7 @@ export class LinkBox extends ViewBoxBaseComponent<FieldViewProps>() {
}
};
+ setRef = (r: HTMLDivElement | null) => (this._divRef = r);
render() {
TraceMobx();
@@ -149,28 +150,18 @@ export class LinkBox extends ViewBoxBaseComponent<FieldViewProps>() {
const aid = targetAhyperlinks?.find(alink => container?.contains(alink))?.id ?? targetAhyperlinks?.lastElement()?.id;
const bid = targetBhyperlinks?.find(blink => container?.contains(blink))?.id ?? targetBhyperlinks?.lastElement()?.id;
if (!aid || !bid) {
- setTimeout(
- action(() => {
- this._forceAnimate += 0.01;
- })
- );
+ setTimeout(action(() => (this._forceAnimate += 0.01)));
return null;
}
if (foundParent) {
setTimeout(
- action(() => {
- this._forceAnimate += 0.01;
- }),
+ action(() => (this._forceAnimate += 0.01)),
1
);
}
-
- if (at || bt)
- setTimeout(
- action(() => {
- this._forceAnimate += 0.01;
- })
- ); // this forces an update during a transition animation
+ if (at || bt) {
+ setTimeout(action(() => (this._forceAnimate += 0.01))); // this forces an update during a transition animation
+ }
const highlight = this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.Highlighting) as { highlightStyle: string; highlightColor: string; highlightIndex: number; highlightStroke: boolean };
const highlightColor = highlight?.highlightIndex ? highlight?.highlightColor : undefined;
const color = this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.Color) as string;
@@ -217,7 +208,7 @@ export class LinkBox extends ViewBoxBaseComponent<FieldViewProps>() {
id={this.DocumentView?.().DocUniqueId}
className="linkBox-label"
tabIndex={-1}
- ref={r => (this._divRef = r)}
+ ref={this.setRef}
onPointerDown={e => e.stopPropagation()}
onFocus={() => {
RichTextMenu.Instance?.updateMenu(undefined, undefined, undefined, this.dataDoc);
diff --git a/src/client/views/nodes/LinkDocPreview.tsx b/src/client/views/nodes/LinkDocPreview.tsx
index 5b07b303a..1d6f41c65 100644
--- a/src/client/views/nodes/LinkDocPreview.tsx
+++ b/src/client/views/nodes/LinkDocPreview.tsx
@@ -250,6 +250,10 @@ export class LinkDocPreview extends ObservableReactComponent<LinkDocPreviewProps
);
}
+ setDocViewRef = (r: DocumentView | null) => {
+ const targetanchor = this._linkDoc && this._linkSrc && Doc.getOppositeAnchor(this._linkDoc, this._linkSrc);
+ targetanchor && this._targetDoc !== targetanchor && r?._props.focus?.(targetanchor, {});
+ };
@computed get docPreview() {
return (!this._linkDoc || !this._targetDoc || !this._linkSrc) && !this._toolTipText ? null : (
<div className="linkDocPreview-inner">
@@ -279,10 +283,7 @@ export class LinkDocPreview extends ObservableReactComponent<LinkDocPreviewProps
this._toolTipText
) : (
<DocumentView
- ref={r => {
- const targetanchor = this._linkDoc && this._linkSrc && Doc.getOppositeAnchor(this._linkDoc, this._linkSrc);
- targetanchor && this._targetDoc !== targetanchor && r?._props.focus?.(targetanchor, {});
- }}
+ ref={this.setDocViewRef}
Document={this._targetDoc!}
moveDocument={returnFalse}
styleProvider={this._props.styleProvider}
diff --git a/src/client/views/nodes/ScreenshotBox.tsx b/src/client/views/nodes/ScreenshotBox.tsx
index 603dcad5c..4677e0e61 100644
--- a/src/client/views/nodes/ScreenshotBox.tsx
+++ b/src/client/views/nodes/ScreenshotBox.tsx
@@ -171,19 +171,21 @@ export class ScreenshotBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
ContextMenu.Instance.addItem({ description: 'Options...', subitems, icon: 'video' });
};
+ setRef = (r: HTMLVideoElement | null) => {
+ this._videoRef = r;
+ setTimeout(() => {
+ if (this.layoutDoc.mediaState === mediaState.PendingRecording && this._videoRef) {
+ this.toggleRecording();
+ }
+ }, 100);
+ };
+
@computed get content() {
return (
<video
className="videoBox-content"
key="video"
- ref={r => {
- this._videoRef = r;
- setTimeout(() => {
- if (this.layoutDoc.mediaState === mediaState.PendingRecording && this._videoRef) {
- this.toggleRecording();
- }
- }, 100);
- }}
+ ref={this.setRef}
autoPlay={this._screenCapture}
style={{ width: this._screenCapture ? '100%' : undefined, height: this._screenCapture ? '100%' : undefined }}
onCanPlay={this.videoLoad}
diff --git a/src/client/views/nodes/calendarBox/CalendarBox.tsx b/src/client/views/nodes/calendarBox/CalendarBox.tsx
index a4183a11a..a2fa83b5a 100644
--- a/src/client/views/nodes/calendarBox/CalendarBox.tsx
+++ b/src/client/views/nodes/calendarBox/CalendarBox.tsx
@@ -298,10 +298,9 @@ export class CalendarBox extends CollectionSubView() {
ev.preventDefault();
});
}}
-
// for dragging and dropping (mirror)
- eventDragStart={(arg) => {
+ eventDragStart={arg => {
const mirror = arg.el.cloneNode(true) as HTMLElement;
const rect = arg.el.getBoundingClientRect();
@@ -312,25 +311,24 @@ export class CalendarBox extends CollectionSubView() {
mirror.classList.add('custom-drag-mirror');
mirror.style.width = `${rect.width}px`;
mirror.style.height = `${rect.height}px`;
-
+
document.body.appendChild(mirror);
-
+
const moveListener = (ev: MouseEvent) => {
- mirror.style.left = `${ev.clientX}px`;
- mirror.style.top = `${ev.clientY}px`;
+ mirror.style.left = `${ev.clientX}px`;
+ mirror.style.top = `${ev.clientY}px`;
};
-
+
window.addEventListener('mousemove', moveListener);
// hide the actual box
arg.el.style.visibility = 'hidden';
arg.el.style.opacity = '0';
-
+
(arg.el as any)._mirrorElement = mirror;
(arg.el as any)._moveListener = moveListener;
}}
-
- eventDragStop={(arg) => {
+ eventDragStop={arg => {
const el = arg.el as any;
const mirror = el._mirrorElement;
const moveListener = el._moveListener;
@@ -338,15 +336,18 @@ export class CalendarBox extends CollectionSubView() {
// show the actual box
el.style.visibility = 'visible';
el.style.opacity = '1';
-
+
if (mirror) document.body.removeChild(mirror);
if (moveListener) window.removeEventListener('mousemove', moveListener);
}}
-
/>
);
}
+ setRef = (r: HTMLDivElement | null) => {
+ this.createDashEventsTarget(r);
+ this.fixWheelEvents(r, this._props.isContentActive);
+ };
render() {
const scale = this._props.ScreenToLocalTransform().Scale;
const scaledWidth = this._props.PanelWidth();
@@ -361,11 +362,8 @@ export class CalendarBox extends CollectionSubView() {
height: scaledHeight,
overflow: 'hidden',
position: 'relative',
- }}
- ref={r => {
- this.createDashEventsTarget(r);
- this.fixWheelEvents(r, this._props.isContentActive);
}}
+ ref={this.setRef}
onPointerDown={e => {
setTimeout(
action(() => {
@@ -383,9 +381,8 @@ export class CalendarBox extends CollectionSubView() {
transformOrigin: 'top left',
width: scaledWidth / scale,
height: scaledHeight / scale,
- }}
- >
- {this.renderCalendar}
+ }}>
+ {this.renderCalendar}
</div>
</div>
);
diff --git a/src/client/views/nodes/chatbot/chatboxcomponents/ChatBox.tsx b/src/client/views/nodes/chatbot/chatboxcomponents/ChatBox.tsx
index 6c3da8977..8043111b9 100644
--- a/src/client/views/nodes/chatbot/chatboxcomponents/ChatBox.tsx
+++ b/src/client/views/nodes/chatbot/chatboxcomponents/ChatBox.tsx
@@ -974,6 +974,8 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
};
_dictation: DictationButton | null = null;
+ setInputRef = (r: HTMLInputElement) => (this._textInputRef = r);
+ setDictationRef = (r: DictationButton) => (this._dictation = r);
/**
* Renders the chat interface, including the message list, input field, and other UI elements.
*/
@@ -1002,9 +1004,7 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
<form onSubmit={this.askGPT} className="chat-input">
<input
- ref={r => {
- this._textInputRef = r;
- }}
+ ref={this.setInputRef}
type="text"
name="messageInput"
autoComplete="off"
@@ -1023,13 +1023,7 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
</svg>
)}
</button>
- <DictationButton
- ref={r => {
- this._dictation = r;
- }}
- setInput={this.setChatInput}
- inputRef={this._textInputRef}
- />
+ <DictationButton ref={this.setDictationRef} setInput={this.setChatInput} inputRef={this._textInputRef} />
</form>
{/* Popup for citation */}
{this._citationPopup.visible && (
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index 07cb795f1..255ee1afe 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -2129,6 +2129,8 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
}
};
+ setRef = (r: HTMLDivElement | null) => this.fixWheelEvents(r, this._props.isContentActive, this.onPassiveWheel);
+ setScrollRef = (r: HTMLDivElement | null) => (this._scrollRef = r);
render() {
TraceMobx();
const scale = this.nativeScaling();
@@ -2143,7 +2145,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
) : styleFromLayout?.height === '0px' ? null : (
<div
className="formattedTextBox"
- ref={r => this.fixWheelEvents(r, this._props.isContentActive, this.onPassiveWheel)}
+ ref={this.setRef}
style={{
...(this._props.dontScale
? {}
@@ -2181,9 +2183,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
onDoubleClick={this.onDoubleClick}>
<div
className="formattedTextBox-outer"
- ref={r => {
- this._scrollRef = r;
- }}
+ ref={this.setScrollRef}
style={{
width: this.noSidebar ? '100%' : `calc(100% - ${this.sidebarWidthPercent})`,
overflow: this.layoutDoc._createDocOnCR || this.layoutDoc._layout_hideScroll ? 'hidden' : this.layout_autoHeight ? 'visible' : undefined,
diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx
index cb2a1f13f..04b312ca5 100644
--- a/src/client/views/nodes/trails/PresBox.tsx
+++ b/src/client/views/nodes/trails/PresBox.tsx
@@ -1743,6 +1743,15 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
return <div />;
}
+ setAiEffectsRef = (r: HTMLTextAreaElement | null) =>
+ setTimeout(() => {
+ if (r && !r.textContent) {
+ r.style.height = '';
+ r.style.height = r.scrollHeight + 'px';
+ }
+ });
+
+ setAnimDictationRef = (r: DictationButton | null) => (this._animationDictation = r);
/**
* This chatbox is for getting slide effect transition suggestions from gpt and visualizing them
*/
@@ -1755,14 +1764,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
<ReactTextareaAutosize
placeholder="Use AI to suggest effects. Leave blank for random results."
className="pres-chatbox"
- ref={r => {
- setTimeout(() => {
- if (r && !r.textContent) {
- r.style.height = '';
- r.style.height = r.scrollHeight + 'px';
- }
- });
- }}
+ ref={this.setAiEffectsRef}
value={this._animationChat}
onChange={e => {
e.currentTarget.style.height = '';
@@ -1784,12 +1786,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
color={SnappingManager.userVariantColor}
onClick={this.customizeAnimations}
/>
- <DictationButton
- ref={r => {
- this._animationDictation = r;
- }}
- setInput={this.setAnimationChat}
- />
+ <DictationButton ref={this.setAnimDictationRef} setInput={this.setAnimationChat} />
</div>
<div style={{ alignItems: 'center' }}>
Click a box to use the effect.
@@ -1821,6 +1818,16 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
);
}
+ setPropertiesRef = (r: HTMLTextAreaElement | null) =>
+ setTimeout(() => {
+ if (r && !r.textContent) {
+ r.style.height = '';
+ r.style.height = r.scrollHeight + 'px';
+ }
+ });
+
+ setSlideDictationRef = (r: DictationButton | null) => (this._slideDictation = r);
+
@computed get transitionDropdown() {
const { activeItem } = this;
// Retrieving spring timing properties
@@ -1855,14 +1862,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
<ReactTextareaAutosize
placeholder="Describe how to modify the slide properties."
className="pres-chatbox"
- ref={r => {
- setTimeout(() => {
- if (r && !r.textContent) {
- r.style.height = '';
- r.style.height = r.scrollHeight + 'px';
- }
- });
- }}
+ ref={this.setPropertiesRef}
value={this._chatInput}
onChange={e => {
e.currentTarget.style.height = '';
@@ -1874,12 +1874,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
e.stopPropagation();
}}
/>
- <DictationButton
- ref={r => {
- this._slideDictation = r;
- }}
- setInput={this.setChatInput}
- />
+ <DictationButton ref={this.setSlideDictationRef} setInput={this.setChatInput} />
</div>
<Button
style={{ alignSelf: 'flex-end' }}
diff --git a/src/client/views/pdf/GPTPopup/GPTPopup.tsx b/src/client/views/pdf/GPTPopup/GPTPopup.tsx
index 568e48edf..660284397 100644
--- a/src/client/views/pdf/GPTPopup/GPTPopup.tsx
+++ b/src/client/views/pdf/GPTPopup/GPTPopup.tsx
@@ -515,6 +515,7 @@ export class GPTPopup extends ObservableReactComponent<object> {
</div>
);
+ setDictationRef = (r: DictationButton | null) => (this._askDictation = r);
promptBox = (heading: string, value: string, onChange: (e: string) => string, placeholder: string) => (
<>
<div className="gptPopup-sortBox">
@@ -541,7 +542,7 @@ export class GPTPopup extends ObservableReactComponent<object> {
background={SettingsManager.userVariantColor}
onClick={() => this.callGpt(this._mode)}
/>
- <DictationButton ref={r => (this._askDictation = r)} setInput={onChange} />
+ <DictationButton ref={this.setDictationRef} setInput={onChange} />
</div>
</>
);
diff --git a/src/fields/InkField.ts b/src/fields/InkField.ts
index d1dda106a..f2c09b6b7 100644
--- a/src/fields/InkField.ts
+++ b/src/fields/InkField.ts
@@ -18,6 +18,7 @@ export enum InkInkTool {
Pen = 'Pen',
Highlight = 'Highlight',
Write = 'Write',
+ Math = 'Math',
}
export enum InkEraserTool {