aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/client/apis/youtube/.YoutubeBox.scss.icloudbin0 -> 165 bytes
-rw-r--r--src/client/apis/youtube/.YoutubeBox.tsx.icloudbin0 -> 162 bytes
-rw-r--r--src/client/util/Scripting.ts2
-rw-r--r--src/client/views/collections/CollectionCarouselView.tsx13
-rw-r--r--src/client/views/linking/.LinkRelationshipSearch.tsx.icloudbin0 -> 176 bytes
-rw-r--r--src/client/views/nodes/.FaceRectangles.tsx.icloudbin0 -> 168 bytes
-rw-r--r--src/client/views/nodes/.LinkAnchorBox.tsx.icloudbin0 -> 167 bytes
-rw-r--r--src/client/views/nodes/AudioBox.tsx19
-rw-r--r--src/client/views/nodes/ComparisonBox.tsx317
-rw-r--r--src/client/views/nodes/ImageBox.tsx49
-rw-r--r--src/client/views/nodes/LabelBigText.js270
-rw-r--r--src/typings/index.d.ts2
12 files changed, 494 insertions, 178 deletions
diff --git a/src/client/apis/youtube/.YoutubeBox.scss.icloud b/src/client/apis/youtube/.YoutubeBox.scss.icloud
new file mode 100644
index 000000000..44b9557bd
--- /dev/null
+++ b/src/client/apis/youtube/.YoutubeBox.scss.icloud
Binary files differ
diff --git a/src/client/apis/youtube/.YoutubeBox.tsx.icloud b/src/client/apis/youtube/.YoutubeBox.tsx.icloud
new file mode 100644
index 000000000..bb5d12d7c
--- /dev/null
+++ b/src/client/apis/youtube/.YoutubeBox.tsx.icloud
Binary files differ
diff --git a/src/client/util/Scripting.ts b/src/client/util/Scripting.ts
index c63d3d7cb..47d85a723 100644
--- a/src/client/util/Scripting.ts
+++ b/src/client/util/Scripting.ts
@@ -1,7 +1,7 @@
// export const ts = (window as any).ts;
// import * as typescriptlib from '!!raw-loader!../../../node_modules/typescript/lib/lib.d.ts'
// import * as typescriptes5 from '!!raw-loader!../../../node_modules/typescript/lib/lib.es5.d.ts'
-import typescriptlib from 'type_decls.d';
+// import typescriptlib from 'type_decls.d';
import * as ts from 'typescript';
import { Doc, FieldType } from '../../fields/Doc';
import { RefField } from '../../fields/RefField';
diff --git a/src/client/views/collections/CollectionCarouselView.tsx b/src/client/views/collections/CollectionCarouselView.tsx
index b6c3744e6..108cdbdb4 100644
--- a/src/client/views/collections/CollectionCarouselView.tsx
+++ b/src/client/views/collections/CollectionCarouselView.tsx
@@ -262,15 +262,6 @@ export class CollectionCarouselView extends CollectionSubView() {
addFlashcard() {
const newDoc = Docs.Create.ComparisonDocument('', { _layout_isFlashcard: true, _width: 300, _height: 300 });
this.addDocument?.(newDoc);
- // DocUtils.copyDragFactory(newDoc);
- // this._props.addDocument?.();
- // newDoc.layout = this.layoutDoc;
- // newDoc.data = this.dataDoc;
- // Doc.AddDocToList()
- // this._props.parent._props.addDocument();
- // this.childLayoutPairs.push({ newDoc.layout, newDoc.data});
- // this._props.addDocument?.(newDoc);
- // console.log('HERE');
}
@computed get buttons() {
@@ -290,7 +281,7 @@ export class CollectionCarouselView extends CollectionSubView() {
<div key="fwd" className="carouselView-fwd" onClick={this.advance}>
<FontAwesomeIcon icon="chevron-right" size="2x" />
</div>
- {this.practiceMode ? (
+ {this.practiceMode == practiceMode.PRACTICE ? (
<div>
<Tooltip title="Incorrect. View again later.">
<div key="remove" className="carouselView-remove" onClick={e => this.setPracticeVal(e, practiceVal.MISSED)}>
@@ -321,7 +312,7 @@ export class CollectionCarouselView extends CollectionSubView() {
const curDoc = this.carouselItems?.[this.carouselIndex];
return (
<div className="carouselView-menu">
- {!this.filterDoc ? (null) : (
+ {!this.filterDoc ? null : (
<div style={{ height: this.filterHeight(), width: this.filterHeight() }}>
<DocumentView
{...this._props}
diff --git a/src/client/views/linking/.LinkRelationshipSearch.tsx.icloud b/src/client/views/linking/.LinkRelationshipSearch.tsx.icloud
new file mode 100644
index 000000000..6e73d1bd0
--- /dev/null
+++ b/src/client/views/linking/.LinkRelationshipSearch.tsx.icloud
Binary files differ
diff --git a/src/client/views/nodes/.FaceRectangles.tsx.icloud b/src/client/views/nodes/.FaceRectangles.tsx.icloud
new file mode 100644
index 000000000..14c960022
--- /dev/null
+++ b/src/client/views/nodes/.FaceRectangles.tsx.icloud
Binary files differ
diff --git a/src/client/views/nodes/.LinkAnchorBox.tsx.icloud b/src/client/views/nodes/.LinkAnchorBox.tsx.icloud
new file mode 100644
index 000000000..2b5650f75
--- /dev/null
+++ b/src/client/views/nodes/.LinkAnchorBox.tsx.icloud
Binary files differ
diff --git a/src/client/views/nodes/AudioBox.tsx b/src/client/views/nodes/AudioBox.tsx
index 63a126aec..8056ced1e 100644
--- a/src/client/views/nodes/AudioBox.tsx
+++ b/src/client/views/nodes/AudioBox.tsx
@@ -300,10 +300,29 @@ export class AudioBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
console.log('RESPONSE: ' + response.data['transcription']);
};
+ youtubeUpload = async () => {
+ console.log('Here');
+ const audio = {
+ file: 'Cd2ch4XV84s&t=373s',
+ };
+ const response = await axios.post('http://localhost:105/youtube/', audio, {
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ });
+ console.log('RESPONSE: ' + response.data['transcription']);
+ };
+
// context menu
specificContextMenu = (): void => {
const funcs: ContextMenuProps[] = [];
// funcs.push({ description: 'Push info', event: this.pushInfo, icon: 'redo-alt' });
+
+ funcs.push({
+ description: 'Youtube',
+ event: this.youtubeUpload, // prettier-ignore
+ icon: 'expand-arrows-alt',
+ });
funcs.push({
description: (this.layoutDoc.hideAnchors ? "Don't hide" : 'Hide') + ' anchors',
event: () => { this.layoutDoc.hideAnchors = !this.layoutDoc.hideAnchors; }, // prettier-ignore
diff --git a/src/client/views/nodes/ComparisonBox.tsx b/src/client/views/nodes/ComparisonBox.tsx
index 5ca4d048e..8fbcb74cb 100644
--- a/src/client/views/nodes/ComparisonBox.tsx
+++ b/src/client/views/nodes/ComparisonBox.tsx
@@ -1,34 +1,41 @@
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import { MathJax, MathJaxContext } from 'better-react-mathjax';
import { Tooltip } from '@mui/material';
-import axios from 'axios';
-import { IReactionDisposer, action, computed, makeObservable, observable, reaction } from 'mobx';
+import { action, computed, makeObservable, observable, reaction } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
-import ReactLoading from 'react-loading';
import { returnFalse, returnNone, returnTrue, returnZero, setupMoveUpEvents } from '../../../ClientUtils';
import { emptyFunction } from '../../../Utils';
import { Doc, Opt } from '../../../fields/Doc';
import { DocData } from '../../../fields/DocSymbols';
-import { Id } from '../../../fields/FieldSymbols';
import { RichTextField } from '../../../fields/RichTextField';
import { DocCast, NumCast, RTFCast, StrCast, toList } from '../../../fields/Types';
-import { nullAudio } from '../../../fields/URLField';
import { GPTCallType, gptAPICall, gptImageLabel } from '../../apis/gpt/GPT';
-import { DocUtils, FollowLinkScript } from '../../documents/DocUtils';
-import { CollectionViewType, DocumentType } from '../../documents/DocumentTypes';
+import '../pdf/GPTPopup/GPTPopup.scss';
+import { DocUtils } from '../../documents/DocUtils';
+import { DocumentType } from '../../documents/DocumentTypes';
import { Docs } from '../../documents/Documents';
import { DragManager } from '../../util/DragManager';
import { dropActionType } from '../../util/DropActionTypes';
import { undoable } from '../../util/UndoManager';
-import { ContextMenu } from '../ContextMenu';
import { ViewBoxAnnotatableComponent } from '../DocComponent';
import { PinDocView, PinProps } from '../PinFuncs';
import { StyleProp } from '../StyleProp';
-import '../pdf/GPTPopup/GPTPopup.scss';
import './ComparisonBox.scss';
import { DocumentView } from './DocumentView';
import { FieldView, FieldViewProps } from './FieldView';
import { FormattedTextBox } from './formattedText/FormattedTextBox';
+import ReactLoading from 'react-loading';
+import { ContextMenu } from '../ContextMenu';
+import { ContextMenuProps } from '../ContextMenuItem';
+import { tickStep } from 'd3';
+import { CollectionCarouselView } from '../collections/CollectionCarouselView';
+import { FollowLinkScript } from '../../documents/DocUtils';
+import { schema } from '../nodes/formattedText/schema_rts';
+import { Id } from '../../../fields/FieldSymbols';
+import axios from 'axios';
+import ReactMarkdown from 'react-markdown';
+import { WebField, nullAudio } from '../../../fields/URLField';
const API_URL = 'https://api.unsplash.com/search/photos';
@@ -37,47 +44,46 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
public static LayoutString(fieldKey: string) {
return FieldView.LayoutString(ComparisonBox, fieldKey);
}
- private _reactDisposer: IReactionDisposer | undefined;
private _disposers: (DragManager.DragDropDisposer | undefined)[] = [undefined, undefined];
- private _closeRef = React.createRef<HTMLDivElement>();
-
- SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
-
- protected createDropTarget = (ele: HTMLDivElement | null, fieldKey: string, disposerId: number) => {
- this._disposers[disposerId]?.();
- if (ele) {
- this._disposers[disposerId] = DragManager.MakeDropTarget(ele, (e, dropEvent) => this.internalDrop(e, dropEvent, fieldKey), this.layoutDoc);
- }
- };
-
constructor(props: FieldViewProps) {
super(props);
makeObservable(this);
this.setListening();
}
- @observable private _mathJaxConfig = { loader: { load: ['input/asciimath'] } }; // prettier-ignore
- @observable private _transcriptElement = '';
@observable private _inputValue = '';
@observable private _outputValue = '';
@observable private _loading = false;
@observable private _isEmpty = false;
@observable private _audio: Doc = Docs.Create.TextDocument('');
- @observable private _childActive = false; // whether pointer events pass through comparison box to its contents or not
- @observable private _animating = '';
+ @observable childActive = false;
+ @observable _yRelativeToTop: boolean = true;
+ @observable _animating = '';
+ @observable mathJaxConfig = {
+ loader: { load: ['input/asciimath'] },
+ };
@observable private _listening = false;
- @observable private _frontSide = false;
- @observable private _recognition = new this.SpeechRecognition();
+ @observable transcriptElement = '';
+ @observable private frontSide = false;
+ SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
+ @observable recognition = new this.SpeechRecognition();
+ _closeRef = React.createRef<HTMLDivElement>();
- @computed get revealOpKey() {
- return `_${this.fieldKey}_revealOp`;
+ get revealOp() {
+ return this.layoutDoc[`_${this._props.fieldKey}_revealOp`];
}
- @computed get clipHeightKey() { return '_' + this.fieldKey + '_clipHeight'; } // prettier-ignore
- @computed get clipWidthKey() { return '_' + this.fieldKey + '_clipWidth'; } // prettier-ignore
- @computed get revealOp() { return this.layoutDoc[`_${this.fieldKey}_revealOp`]; } // prettier-ignore
+ get clipHeightKey() {
+ return '_' + this._props.fieldKey + '_clipHeight';
+ }
+
+ get clipWidthKey() {
+ return '_' + this._props.fieldKey + '_clipWidth';
+ }
+
@computed get clipWidth() {
return NumCast(this.layoutDoc[this.clipWidthKey], 50);
}
+
@computed get clipHeight() {
return NumCast(this.layoutDoc[this.clipHeightKey], 200);
}
@@ -95,8 +101,8 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
})
}
style={{
- background: this.revealOp === 'hover' ? 'gray' : this._frontSide ? 'white' : 'black',
- color: this.revealOp === 'hover' ? 'black' : this._frontSide ? 'black' : 'white',
+ background: this.revealOp === 'hover' ? 'gray' : this.frontSide ? 'white' : 'black',
+ color: this.revealOp === 'hover' ? 'black' : this.frontSide ? 'black' : 'white',
display: 'inline-block',
}}>
<div key="alternate" className="formattedTextBox-flip">
@@ -111,8 +117,8 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
return (
<div>
<Tooltip
- title={this._frontSide ? <div className="dash-tooltip">Flip to front side to use GPT</div> : <div className="dash-tooltip">Ask GPT to create an answer on the back side of the flashcard based on your question on the front</div>}>
- <div style={{ position: 'absolute', bottom: '3px', right: '50px', cursor: 'pointer' }} onPointerDown={e => (!this._frontSide ? this.findImageTags() : null)}>
+ title={this.frontSide ? <div className="dash-tooltip">Flip to front side to use GPT</div> : <div className="dash-tooltip">Ask GPT to create an answer on the back side of the flashcard based on your question on the front</div>}>
+ <div style={{ position: 'absolute', bottom: '3px', right: '50px', cursor: 'pointer' }} onPointerDown={e => (!this.frontSide ? this.findImageTags() : null)}>
<FontAwesomeIcon icon="lightbulb" size="xl" />
</div>
</Tooltip>
@@ -139,57 +145,65 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
);
}
- componentDidMount() {
- this._props.setContentViewBox?.(this);
- this._reactDisposer = reaction(
- () => this._props.isSelected(), // when this reaction should update
- selected => !selected && (this._childActive = false) // what it should update to
- );
- }
- componentWillUnmount() {
- this._disposers.forEach(d => d?.());
- this._reactDisposer?.();
- }
-
@action handleHover = () => {
if (this.revealOp === 'hover') {
- this.layoutDoc[this.revealOpKey] = 'flip';
+ this.layoutDoc[`_${this._props.fieldKey}_revealOp`] = 'flip';
this.Document.forceActive = false;
} else {
- this.layoutDoc[this.revealOpKey] = 'hover';
+ this.layoutDoc[`_${this._props.fieldKey}_revealOp`] = 'hover';
this.Document.forceActive = true;
}
};
- handleInputChange = action((e: React.ChangeEvent<HTMLTextAreaElement>) => {
+ @action handleInputChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
this._inputValue = e.target.value;
- });
+ console.log(this._inputValue);
+ };
+
+ @action activateContent = () => {
+ this.childActive = true;
+ };
- handleRenderClick = action(() => {
- this._frontSide = !this._frontSide;
- });
+ @action handleRenderClick = () => {
+ this.frontSide = !this.frontSide;
+ };
- handleRenderGPTClick = action(() => {
- console.log('Phonetic transcription: ' + DocCast(this.Document.audio).phoneticTranscription);
- const phonTrans = DocCast(this.Document.audio).phoneticTranscription;
+ @action handleRenderGPTClick = async () => {
+ const phonTrans = DocCast(this.Document.audio) ? DocCast(this.Document.audio).phoneticTranscription : undefined;
if (phonTrans) {
this._inputValue = StrCast(phonTrans);
console.log('INPUT:' + this._inputValue);
this.askGPTPhonemes(this._inputValue);
} else if (this._inputValue) this.askGPT(GPTCallType.QUIZ);
- this._frontSide = false;
+ this.frontSide = false;
this._outputValue = '';
- });
+ };
- onPointerMove = ({ movementX }: PointerEvent) => {
+ @action
+ private onPointerMove = ({ movementX }: PointerEvent) => {
const width = movementX * this.ScreenToLocalBoxXf().Scale + (this.clipWidth / 100) * this._props.PanelWidth();
- if (width < this._props.PanelWidth()) {
- this.layoutDoc[this.clipWidthKey] = (Math.max(0, width) * 100) / this._props.PanelWidth();
+ if (width && width > 5 && width < this._props.PanelWidth()) {
+ this.layoutDoc[this.clipWidthKey] = (width * 100) / this._props.PanelWidth();
}
return false;
};
- internalDrop = undoable((e: Event, dropEvent: DragManager.DropEvent, fieldKey: string) => {
+ componentDidMount() {
+ this._props.setContentViewBox?.(this);
+ reaction(
+ () => this._props.isSelected(), // when this reaction should update
+ selected => !selected && (this.childActive = false) // what it should update to
+ );
+ }
+
+ protected createDropTarget = (ele: HTMLDivElement | null, fieldKey: string, disposerId: number) => {
+ this._disposers[disposerId]?.();
+ if (ele) {
+ this._disposers[disposerId] = DragManager.MakeDropTarget(ele, (e, dropEvent) => this.internalDrop(e, dropEvent, fieldKey), this.layoutDoc);
+ }
+ };
+
+ private internalDrop = undoable((e: Event, dropEvent: DragManager.DropEvent, fieldKey: string) => {
if (dropEvent.complete.docDragData) {
const { droppedDocuments } = dropEvent.complete.docDragData;
const added = dropEvent.complete.docDragData.moveDocument?.(droppedDocuments, this.Document, (doc: Doc | Doc[]) => this.addDoc(toList(doc).lastElement(), fieldKey));
@@ -232,10 +246,10 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
remDoc = (doc: Doc, which: string) => {
if (this.dataDoc[which] === doc) {
this._isEmpty = true;
- // this.dataDoc[which] = 'empty';
this.dataDoc[which] = undefined;
return true;
}
+ console.log('FALSE');
return false;
};
@@ -274,7 +288,7 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
emptyFunction,
action((moveEv, doubleTap) => {
if (doubleTap) {
- this._childActive = true;
+ this.childActive = true;
if (!this.dataDoc[this.fieldKey + '_1'] && !this.dataDoc[this.fieldKey]) this.dataDoc[this.fieldKey + '_1'] = DocUtils.copyDragFactory(Doc.UserDoc().emptyNote as Doc);
if (!this.dataDoc[this.fieldKey + '_2'] && !this.dataDoc[this.fieldKey + '_alternate']) this.dataDoc[this.fieldKey + '_2'] = DocUtils.copyDragFactory(Doc.UserDoc().emptyNote as Doc);
}
@@ -282,13 +296,17 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
false,
undefined,
action(() => {
- if (!this._childActive) {
- this._animating = 'all 200ms';
- // on click, animate slider movement to the targetWidth
- this.layoutDoc[this.clipWidthKey] = (targetWidth * 100) / this._props.PanelWidth();
- // this.layoutDoc[this.clipHeightKey] = (targetWidth * 100) / this._props.PanelHeight();
- setTimeout(action(() => { this._animating = ''; }), 200); // prettier-ignore
- }
+ if (this.childActive) return;
+ this._animating = 'all 200ms';
+ // on click, animate slider movement to the targetWidth
+ this.layoutDoc[this.clipWidthKey] = (targetWidth * 100) / this._props.PanelWidth();
+
+ setTimeout(
+ action(() => {
+ this._animating = '';
+ }),
+ 200
+ );
})
);
}
@@ -297,31 +315,31 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
setListening = () => {
const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
if (SpeechRecognition) {
- this._recognition.continuous = true;
- this._recognition.interimResults = true;
- this._recognition.lang = 'en-US';
- this._recognition.onresult = this.handleResult.bind(this);
+ this.recognition.continuous = true;
+ this.recognition.interimResults = true;
+ this.recognition.lang = 'en-US';
+ this.recognition.onresult = this.handleResult.bind(this);
}
ContextMenu.Instance.setLangIndex(0);
};
startListening = () => {
- this._recognition.start();
+ this.recognition.start();
this._listening = true;
};
stopListening = () => {
- this._recognition.stop();
+ this.recognition.stop();
this._listening = false;
};
setLanguage = (language: string, ind: number) => {
- this._recognition.lang = language;
+ this.recognition.lang = language;
ContextMenu.Instance.setLangIndex(ind);
};
convertAbr = () => {
- switch (this._recognition.lang) {
+ switch (this.recognition.lang) {
case 'en-US': return 'English'; //prettier-ignore
case 'es-ES': return 'Spanish'; //prettier-ignore
case 'fr-FR': return 'French'; //prettier-ignore
@@ -360,18 +378,40 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
},
});
this.Document.phoneticTranscription = response.data['transcription'];
+ console.log('RESPONSE: ' + response.data['transcription']);
+ };
+
+ getYouTubeVideoId = (url: string) => {
+ const regExp = /^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|\&v=|\?v=)([^#\&\?]*).*/;
+ const match = url.match(regExp);
+ return match && match[2].length === 11 ? match[2] : null;
+ };
+
+ youtubeUpload = async () => {
+ const audio = {
+ file: this.getYouTubeVideoId(StrCast(RTFCast(DocCast(this.dataDoc[this.fieldKey + '_1']).text)?.Text)),
+ };
+ const response = await axios.post('http://localhost:105/youtube/', audio, {
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ });
+ return response.data['transcription'];
};
createFlashcardPile(collectionArr: Doc[], gpt: boolean) {
const newCol = Docs.Create.CarouselDocument(collectionArr, {
- _width: NumCast(this.layoutDoc['_' + this.fieldKey + '_width'], 250) + 50,
- _height: NumCast(this.layoutDoc['_' + this.fieldKey + '_width'], 200) + 50,
+ _width: NumCast(this.layoutDoc['_' + this._props.fieldKey + '_width'], 250) + 50,
+ _height: NumCast(this.layoutDoc['_' + this._props.fieldKey + '_width'], 200) + 50,
_layout_fitWidth: false,
_layout_autoHeight: true,
});
- newCol.x = this.layoutDoc.x;
- newCol.y = NumCast(this.layoutDoc.y) + 50;
- newCol.type_collection = CollectionViewType.Carousel;
+ newCol['x'] = this.layoutDoc['x'];
+ newCol['y'] = NumCast(this.layoutDoc['y']) + 50;
+ newCol.type_collection = 'carousel';
+ for (var i = 0; i < collectionArr.length; i++) {
+ DocCast(collectionArr[i])[DocData].embedContainer = newCol;
+ }
if (gpt) {
this._props.DocumentView?.()._props.addDocument?.(newCol);
@@ -383,10 +423,13 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
}
}
+ /**
+ * Transfers the content of flashcards into a flashcard pile.
+ */
gptFlashcardPile = async () => {
- let text = await this.askGPT(GPTCallType.STACK);
- let senArr = text?.split('Question: ');
- let collectionArr: Doc[] = [];
+ var text = await this.askGPT(GPTCallType.STACK);
+ var senArr = text?.split('Question: ');
+ var collectionArr: Doc[] = [];
for (let i = 1; i < senArr?.length!; i++) {
const newDoc = Docs.Create.ComparisonDocument(senArr![i], { _layout_isFlashcard: true, _width: 300, _height: 300 });
@@ -419,17 +462,28 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
DocCast(newDoc)[DocData][this.fieldKey + '_1'] = textDoc1;
DocCast(newDoc)[DocData][this.fieldKey + '_0'] = Docs.Create.TextDocument(question[0].includes('Answer: ') ? question[0].split('Answer: ')[1] : question[1]);
}
+
collectionArr.push(newDoc);
}
this.createFlashcardPile(collectionArr, true);
};
+ /**
+ * Calls GPT for each flashcard type.
+ */
askGPT = async (callType: GPTCallType): Promise<string | undefined> => {
- const questionText = 'Question: ' + StrCast(RTFCast(DocCast(this.dataDoc[this.fieldKey + '_1']).text)?.Text);
+ let questionText = 'Question: ' + StrCast(RTFCast(DocCast(this.dataDoc[this.fieldKey + '_1']).text)?.Text);
const rubricText = ' Rubric: ' + StrCast(RTFCast(DocCast(this.dataDoc[this.fieldKey + '_0']).text)?.Text);
const queryText = questionText + ' UserAnswer: ' + this._inputValue + '. ' + rubricText;
this._loading = true;
const doc = DocCast(this.dataDoc[this.props.fieldKey + '_0']);
+
+ // if (true) {
+ // const s = await this.youtubeUpload();
+
+ // questionText = 'Question: ' + s;
+ // }
+
if (callType == GPTCallType.CHATCARD) {
if (StrCast(RTFCast(DocCast(this.dataDoc[this.fieldKey + '_1']).text)?.Text) === '') {
this._loading = false;
@@ -439,7 +493,7 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
}
try {
console.log(queryText);
- const res = await gptAPICall(callType == GPTCallType.QUIZ ? queryText : questionText, callType);
+ const res = await gptAPICall(questionText, GPTCallType.FLASHCARD);
if (!res) {
console.error('GPT call failed');
return;
@@ -448,6 +502,7 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
DocCast(this.dataDoc[this.props.fieldKey + '_0'])[DocData].text = res;
} else if (callType == GPTCallType.QUIZ) {
console.log(this._inputValue);
+ this.frontSide = true;
this._outputValue = res.replace(/UserAnswer/g, "user's answer").replace(/Rubric/g, 'rubric');
} else if (callType === GPTCallType.FLASHCARD) {
this._loading = false;
@@ -461,7 +516,6 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
}
this._loading = false;
};
-
layoutWidth = () => NumCast(this.layoutDoc.width, 200);
layoutHeight = () => NumCast(this.layoutDoc.height, 200);
@@ -470,7 +524,8 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
if (c?.length === 0) await this.askGPT(GPTCallType.CHATCARD);
if (c) {
this._loading = true;
- for (const i of c) {
+ for (let i of c) {
+ console.log(i);
if (i.className !== 'ProseMirror-separator') await this.getImageDesc(i.src);
}
this._loading = false;
@@ -508,11 +563,17 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
this.convertAbr() +
' speech and they are not allophones of the same phoneme and they are far away from each on the ipa vowel chat and that pronunciation is not normal for the meaning of the word, note this difference and explain how it is supposed to sound. Just so you know, "i" sounds like "ee" as in "bee", not "ih" as an "lick". Interpret "ɹ" as the same as "r". Interpret "ʌ" as the same as "ə". Do not make "θ" and "f" interchangable. Do not make "n" and "ɲ" interchangable. Do not make "e" and "i" interchangable. If "ɚ", "ɔː", and "ɔ" are options for pronunciation, do not choose "ɚ". Ignore differences with colons. Ignore redundant letters and words and sounds and the splitting of words; do not mention this since there could be repeated words in the sentence. Provide a response like this: "Lets work on improving the pronunciation of "coffee." You said "cawffee," which is close, but we need to adjust the vowel sound. In American English, "coffee" is pronounced /ˈkɔːfi/, with a long "aw" sound. Try saying "kah-fee." Your intonation is good, but try putting a bit more stress on "like" in the sentence "I would like a coffee with milk." This will make your speech sound more natural. Keep practicing, and lets try saying the whole sentence again!"';
- switch (this._recognition.lang) {
- case 'en-US': this._outputValue = await gptAPICall(promptEng, GPTCallType.PRONUNCIATION); break;
- case 'es-ES': this._outputValue = await gptAPICall(promptSpa, GPTCallType.PRONUNCIATION); break;
- default: this._outputValue = await gptAPICall(promptAll, GPTCallType.PRONUNCIATION); break;
- } // prettier-ignore
+ switch (this.recognition.lang) {
+ case 'en-US':
+ this._outputValue = await gptAPICall(promptEng, GPTCallType.PRONUNCIATION);
+ break;
+ case 'es-ES':
+ this._outputValue = await gptAPICall(promptSpa, GPTCallType.PRONUNCIATION);
+ break;
+ default:
+ this._outputValue = await gptAPICall(promptAll, GPTCallType.PRONUNCIATION);
+ break;
+ }
};
handleResult = (e: SpeechRecognitionEvent) => {
@@ -543,8 +604,8 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
_height: 150,
title: '--snapshot' + NumCast(this.layoutDoc._layout_currentTimecode) + ' image-',
});
- imageSnapshot.x = this.layoutDoc.x;
- imageSnapshot.y = this.layoutDoc.y;
+ imageSnapshot['x'] = this.layoutDoc['x'];
+ imageSnapshot['y'] = this.layoutDoc['y'];
return imageSnapshot;
} catch (error) {
console.log(error);
@@ -553,7 +614,8 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
static imageUrlToBase64 = async (imageUrl: string): Promise<string> => {
try {
- const blob = await fetch(imageUrl).then(response => response.blob());
+ const response = await fetch(imageUrl);
+ const blob = await response.blob();
return new Promise((resolve, reject) => {
const reader = new FileReader();
@@ -574,16 +636,17 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
DocCast(this.dataDoc[this.props.fieldKey + '_0'])[DocData].text = response;
} catch (error) {
- console.log('Error', error);
+ console.log('Error');
}
};
- flipFlashcard = action(() => {
- this._frontSide = !this._frontSide;
- });
+ @action
+ flipFlashcard = () => {
+ this.frontSide = !this.frontSide;
+ };
hoverFlip = (side: boolean) => {
- if (this.revealOp === 'hover') this.layoutDoc[`_${this._props.fieldKey}_usePath`] = side;
+ if (this.revealOp === 'hover') this.frontSide = side;
};
testForTextFields = (whichSlot: string) => {
@@ -616,7 +679,6 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
const clearButton = (which: string) => (
<Tooltip title={<div className="dash-tooltip">remove</div>}>
<div
- // style={{ position: 'relative', top: '0px', left: '10px' }}
ref={this._closeRef}
className={`clear-button ${which}`}
onPointerDown={e => this.closeDown(e, which)} // prevent triggering slider movement in registerSliding
@@ -629,19 +691,14 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
const whichDoc = DocCast(this.dataDoc[whichSlot]);
const targetDoc = DocCast(whichDoc?.annotationOn, whichDoc);
const layoutString = targetDoc ? '' : this.testForTextFields(whichSlot);
- // whichDoc['backgroundColor'] = this.layoutDoc['backgroundColor'];
return targetDoc || layoutString ? (
- // <MathJaxContext config={this._mathJaxConfig}>
- // <MathJax>
<>
<DocumentView
// eslint-disable-next-line react/jsx-props-no-spreading
{...this._props}
showTags={undefined}
fitWidth={undefined}
- NativeHeight={returnZero}
- NativeWidth={returnZero}
ignoreUsePath={layoutString ? true : undefined}
renderDepth={this.props.renderDepth + 1}
LayoutTemplateString={layoutString}
@@ -649,17 +706,16 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
containerViewPath={this._props.docViewPath}
moveDocument={whichSlot.endsWith('1') ? this.moveDoc1 : this.moveDoc2}
removeDocument={whichSlot.endsWith('1') ? this.remDoc1 : this.remDoc2}
- isContentActive={() => this._childActive}
+ NativeWidth={this.layoutWidth}
+ NativeHeight={this.layoutHeight}
+ isContentActive={() => this.childActive}
isDocumentActive={returnFalse}
dontSelect={returnTrue}
whenChildContentsActiveChanged={this.whenChildContentsActiveChanged}
- styleProvider={this._childActive ? this._props.styleProvider : this.docStyleProvider}
+ styleProvider={this.childActive ? this._props.styleProvider : this.docStyleProvider}
hideLinkButton
- pointerEvents={this._childActive ? undefined : returnNone}
+ pointerEvents={this.childActive ? undefined : returnNone}
/>
- {/* </MathJax> */}
- {/* <div style={{ position: 'absolute', top: '-5px', left: '2px' }}>{layoutString ? null : clearButton(whichSlot)}</div> */}
- {/* </MathJaxContext> // placeholder image if doc is missingleft: `${NumCast(this.layoutDoc.width, 200) - 33}px` */}
</>
) : (
<div className="placeholder">
@@ -674,19 +730,17 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
style={{ width: this._props.PanelWidth() }}
onPointerDown={e => {
this.registerSliding(e, cover);
- this._childActive = true;
+ this.activateContent();
}}
ref={ele => this.createDropTarget(ele, which, index)}>
{!this._isEmpty ? displayDoc(which) : null}
- {/* {this.dataDoc[this.fieldKey + '_0'] !== 'empty' ? displayDoc(which) : null} */}
</div>
);
if (this.Document._layout_isFlashcard) {
- const side = this._frontSide ? 1 : 0;
+ const side = this.frontSide ? 1 : 0;
// add text box to each side when comparison box is first created
- // (!this.dataDoc[this.fieldKey + '_0'] && this.dataDoc[this._props.fieldKey + '_0'] !== 'empty')
if (!this.dataDoc[this.fieldKey + '_0'] && !this._isEmpty) {
const dataSplit = StrCast(this.dataDoc.data).includes('Keyword: ') ? StrCast(this.dataDoc.data).split('Keyword: ') : StrCast(this.dataDoc.data).split('Answer: ');
const newDoc = Docs.Create.TextDocument(dataSplit[1], { _layout_autoHeight: true });
@@ -707,14 +761,14 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
<p style={{ display: text === '' ? 'flex' : 'none', color: 'white', marginLeft: '10px' }}>Return to all flashcards and add text to both sides. </p>
<div className="input-box">
<textarea
- value={this._frontSide ? this._outputValue : this._inputValue}
+ value={this.frontSide ? this._outputValue : this._inputValue}
onChange={this.handleInputChange}
onScroll={e => {
e.stopPropagation();
e.preventDefault();
}}
placeholder={!this.layoutDoc[`_${this._props.fieldKey}_usePath`] ? 'Enter a response for GPT to evaluate.' : ''}
- readOnly={this._frontSide}></textarea>
+ readOnly={this.frontSide}></textarea>
{this._loading ? (
<div className="loading-spinner" style={{ position: 'absolute' }}>
@@ -746,7 +800,7 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
Evaluate Pronunciation
</button>
- {this._frontSide ? (
+ {!this.frontSide ? (
<button className="submit-buttonsubmit" type="button" onClick={this.handleRenderGPTClick} style={{ borderRadius: '2px', marginBottom: '3px', width: '100%' }}>
Submit
</button>
@@ -766,8 +820,12 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
<div
className={`comparisonBox${this._props.isContentActive() ? '-interactive' : ''}`} /* change className to easily disable/enable pointer events in CSS */
style={{ display: 'flex', flexDirection: 'column', overflow: 'hidden' }}
- onMouseEnter={() => this.hoverFlip(false)}
- onMouseLeave={() => this.hoverFlip(true)}>
+ onMouseEnter={() => {
+ this.hoverFlip(false);
+ }}
+ onMouseLeave={() => {
+ this.hoverFlip(true);
+ }}>
{displayBox(`${this.fieldKey}_${side === 0 ? 1 : 0}`, side, this._props.PanelWidth() - 3)}
{this._loading ? (
<div className="loading-spinner" style={{ position: 'absolute' }}>
@@ -790,11 +848,10 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
<div
className="slide-bar"
style={{
- left: `min(100% - 3px, calc(${this.clipWidth + '%'}))`,
- transition: this._animating,
+ left: `calc(${this.clipWidth + '%'} - 0.5px)`,
cursor: this.clipWidth < 5 ? 'e-resize' : this.clipWidth / 100 > (this._props.PanelWidth() - 5) / this._props.PanelWidth() ? 'w-resize' : undefined,
}}
- onPointerDown={e => this.registerSliding(e, this._props.PanelWidth() / 2)} /* if clicked, return slide-bar to center */
+ onPointerDown={e => !this.childActive && this.registerSliding(e, this._props.PanelWidth() / 2)} /* if clicked, return slide-bar to center */
>
<div className="slide-handle" />
</div>
diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx
index 29887f162..91e51d24e 100644
--- a/src/client/views/nodes/ImageBox.tsx
+++ b/src/client/views/nodes/ImageBox.tsx
@@ -168,11 +168,12 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
Object.values(this._disposers).forEach(disposer => disposer?.());
}
+ /**
+ * Find images from the unsplash api to add to flashcards.
+ */
fetchImages = async () => {
try {
const { data } = await axios.get(`${API_URL}?query=${this._searchInput}&page=1&per_page=${1}&client_id=${process.env.VITE_API_KEY}`);
- console.log('data', data);
- console.log(data.results);
const imageSnapshot = Docs.Create.ImageDocument(data.results[0].urls.small, {
_nativeWidth: Doc.NativeWidth(this.layoutDoc),
_nativeHeight: Doc.NativeHeight(this.layoutDoc),
@@ -326,8 +327,6 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
if (ctx) {
this._imageRef && ctx.drawImage(this._imageRef, NumCast(this._marqueeref.current?.left) * scaling, NumCast(this._marqueeref.current?.top) * scaling, w, h, 0, 0, w, h);
}
- // canvas.style.zIndex = '2000000';
- // document.body.appendChild(canvas);
const blob = await ImageUtility.canvasToBlob(canvas);
return ImageBox.selectUrlToBase64(blob);
};
@@ -350,7 +349,6 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
Doc.SetNativeHeight(imageSnapshot[DocData], Doc.NativeHeight(this.layoutDoc));
this._props.addDocument?.(imageSnapshot);
DocUtils.MakeLink(imageSnapshot, this.getAnchor(true), { link_relationship: 'video snapshot' });
- // link && (DocCast(link.link_anchor_2)[DocData].timecodeToHide = NumCast(DocCast(link.link_anchor_2).timecodeToShow) + 3); // do we need to set an end time? should default to +0.1
setTimeout(() => downX !== undefined && downY !== undefined && DocumentView.getFirstDocumentView(imageSnapshot)?.startDragging(downX, downY, dropActionType.move, true));
};
@@ -371,7 +369,6 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
pushInfo = async (quiz: quizMode, i?: string) => {
this._quizMode = quiz;
this._loading = true;
- console.log('JHSDKFJHKSDJFHKSJDHFKJSDHFKJHSDKF');
const img = {
file: i ? i : this.paths[0],
@@ -383,10 +380,6 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
'Content-Type': 'application/json',
},
});
-
- console.log('RESPONSE:');
- console.log(response.data['boxes']);
- console.log(response.data['text']);
if (response.data['boxes'].length != 0) {
this.createBoxes(response.data['boxes'], response.data['text']);
} else {
@@ -394,6 +387,11 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
}
};
+ /**
+ * Creates label boxes over text on the image to be filled in.
+ * @param boxes
+ * @param texts
+ */
createBoxes = (boxes: [[[number, number]]], texts: [string]) => {
const nscale = NumCast(this._props.PanelWidth()) * NumCast(this.layoutDoc._freeform_scale, 1);
const nw = nscale / NumCast(this.dataDoc[this.fieldKey + '_nativeWidth']);
@@ -405,17 +403,13 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
const newCol = Docs.Create.LabelDocument({
_width: width,
- //width * NumCast(this.dataDoc[this.fieldKey + '_nativeWidth']),
_height: height,
- //height * NumCast(this.dataDoc[this.fieldKey + '_nativeHeight']),
_layout_fitWidth: true,
title: '',
- // _layout_autoHeight: true,
});
const scaling = 1 / (this._props.NativeDimScaling?.() || 1);
newCol.x = coords[0][0] + NumCast(this._marqueeref.current?.left) * scaling;
newCol.y = coords[0][1] + NumCast(this._marqueeref.current?.top) * scaling;
- // newCol[DocData].text_fontSize = height + 'px';
newCol.zIndex = 1000;
newCol.forceActive = true;
@@ -428,12 +422,14 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
}
};
+ /**
+ * Create flashcards from an image.
+ */
getImageDesc = async () => {
this._loading = true;
try {
const hrefBase64 = await this.createCanvas();
const response = await gptImageLabel(hrefBase64, 'Make flashcards out of this image with each question and answer labeled as "question" and "answer". Do not label each flashcard and do not include asterisks: ');
- console.log(response);
AnchorMenu.Instance.transferToFlashcard(response, NumCast(this.layoutDoc['x']), NumCast(this.layoutDoc['y']));
} catch (error) {
console.log('Error');
@@ -535,15 +531,16 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
}
};
+ /**
+ * Check whether the contents of the label boxes on an image are correct.
+ */
check = () => {
this._loading = true;
this._quizBoxes.forEach(async doc => {
const input = StrCast(doc[DocData].title);
- console.log('INP: ' + StrCast(input) + '; DOC: ' + StrCast(doc.quiz));
if (this._quizMode == quizMode.SMART && input) {
const questionText = 'Question: What was labeled in this image?';
const rubricText = ' Rubric: ' + StrCast(doc.quiz);
- // const queryText = 'RealAnswer: ' + StrCast(doc.quiz) + '. UserAnswer: ' + input + '.';
const queryText =
questionText +
' UserAnswer: ' +
@@ -553,7 +550,6 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
'. One sentence and evaluate based on meaning, not wording. Provide a hex color at the beginning with a period after it on a scale of green (minor details missed) to red (big error) for how correct the answer is. Example: "#FFFFFF. Pasta is delicious."';
const response = await gptAPICall(queryText, GPTCallType.QUIZ);
const hexSent = this.extractHexAndSentences(response);
- console.log(hexSent.hexNumber);
doc.quiz = hexSent.sentences?.replace(/UserAnswer/g, "user's answer").replace(/Rubric/g, 'rubric');
doc.backgroundColor = '#' + hexSent.hexNumber;
} else {
@@ -561,7 +557,6 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
doc.backgroundColor = match ? '#11c249' : '#eb2d2d';
}
doc.showQuiz = true;
- // console.log(this.compareWords(input, StrCast(doc.quiz)) ? 'Match' : 'No Match');
});
this._loading = false;
};
@@ -577,8 +572,6 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
exitQuizMode = () => {
this._quizMode = quizMode.NONE;
this._quizBoxes.forEach(doc => {
- // this._props.removeDocument?.(DocCast(doc));
- // this._props.DocumentView?.()._props.removeDocument?.(doc);
this.removeDocument?.(doc);
});
this._quizBoxes = [];
@@ -595,7 +588,6 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
if (field) {
const funcs: ContextMenuProps[] = [];
const quizes: ContextMenuProps[] = [];
- // funcs.push({ description: 'Create ai flashcards', event: () => this.getImageDesc(), icon: 'id-card' });
quizes.push({
description: 'Smart Check',
event: this._quizMode == quizMode.NONE ? () => this.pushInfo(quizMode.SMART) : this.exitQuizMode,
@@ -606,19 +598,6 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
event: this._quizMode == quizMode.NONE ? () => this.pushInfo(quizMode.NORMAL) : this.exitQuizMode,
icon: 'pencil',
});
- // funcs.push({ description: 'Quiz Mode', subitems: optionItems, icon: 'eye' });
- // funcs.push({
- // description: 'Quiz Mode',
- // event: !this._quizMode
- // ? () => this.pushInfo(false)
- // : () => {
- // this._quizMode = false;
- // },
- // icon: 'redo-alt',
- // });
- // funcs.push({ description: 'Get Text', event: this.check, icon: 'redo-alt' });
- // funcs.push({ description: 'Get Labels2', event: this.getImageLabels2, icon: 'redo-alt' });
- // funcs.push({ description: 'Get Labels', event: this.getImageLabels, icon: 'redo-alt' });
funcs.push({ description: 'Rotate Clockwise 90', event: this.rotate, icon: 'redo-alt' });
funcs.push({ description: `Show ${this.layoutDoc._showFullRes ? 'Dynamic Res' : 'Full Res'}`, event: this.resolution, icon: 'expand' });
funcs.push({ description: 'Set Native Pixel Size', event: this.setNativeSize, icon: 'expand-arrows-alt' });
diff --git a/src/client/views/nodes/LabelBigText.js b/src/client/views/nodes/LabelBigText.js
new file mode 100644
index 000000000..290152cd0
--- /dev/null
+++ b/src/client/views/nodes/LabelBigText.js
@@ -0,0 +1,270 @@
+/*
+Brorlandi/big-text.js v1.0.0, 2017
+Adapted from DanielHoffmann/jquery-bigtext, v1.3.0, May 2014
+And from Jetroid/bigtext.js v1.0.0, September 2016
+
+Usage:
+BigText("#myElement",{
+ rotateText: {Number}, (null)
+ fontSizeFactor: {Number}, (0.8)
+ maximumFontSize: {Number}, (null)
+ limitingDimension: {String}, ("both")
+ horizontalAlign: {String}, ("center")
+ verticalAlign: {String}, ("center")
+ textAlign: {String}, ("center")
+ whiteSpace: {String}, ("nowrap")
+});
+
+
+Original Projects:
+https://github.com/DanielHoffmann/jquery-bigtext
+https://github.com/Jetroid/bigtext.js
+
+Options:
+
+rotateText: Rotates the text inside the element by X degrees.
+
+fontSizeFactor: This option is used to give some vertical spacing for letters that overflow the line-height (like 'g', 'Á' and most other accentuated uppercase letters). This does not affect the font-size if the limiting factor is the width of the parent div. The default is 0.8
+
+maximumFontSize: maximum font size to use.
+
+minimumFontSize: minimum font size to use. if font is calculated smaller than this, text will be rendered at this size and wrapped
+
+limitingDimension: In which dimension the font size should be limited. Possible values: "width", "height" or "both". Defaults to both. Using this option with values different than "both" overwrites the element parent width or height.
+
+horizontalAlign: Where to align the text horizontally. Possible values: "left", "center", "right". Defaults to "center".
+
+verticalAlign: Where to align the text vertically. Possible values: "top", "center", "bottom". Defaults to "center".
+
+textAlign: Sets the text align of the element. Possible values: "left", "center", "right". Defaults to "center". This option is only useful if there are linebreaks (<br> tags) inside the text.
+
+whiteSpace: Sets whitespace handling. Possible values: "nowrap", "pre". Defaults to "nowrap". (Can also be set to enable wrapping but this doesn't work well.)
+
+Bruno Orlandi - 2017
+
+Copyright (C) 2013 Daniel Hoffmann Bernardes, Ícaro Technologies
+Copyright (C) 2016 Jet Holt
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+function _calculateInnerDimensions(computedStyle) {
+ //Calculate the inner width and height
+ var innerWidth;
+ var innerHeight;
+
+ var width = parseInt(computedStyle.getPropertyValue("width"));
+ var height = parseInt(computedStyle.getPropertyValue("height"));
+ var paddingLeft = parseInt(computedStyle.getPropertyValue("padding-left"));
+ var paddingRight = parseInt(computedStyle.getPropertyValue("padding-right"));
+ var paddingTop = parseInt(computedStyle.getPropertyValue("padding-top"));
+ var paddingBottom = parseInt(computedStyle.getPropertyValue("padding-bottom"));
+ var borderLeft = parseInt(computedStyle.getPropertyValue("border-left-width"));
+ var borderRight = parseInt(computedStyle.getPropertyValue("border-right-width"));
+ var borderTop = parseInt(computedStyle.getPropertyValue("border-top-width"));
+ var borderBottom = parseInt(computedStyle.getPropertyValue("border-bottom-width"));
+
+ //If box-sizing is border-box, we need to subtract padding and border.
+ var parentBoxSizing = computedStyle.getPropertyValue("box-sizing");
+ if (parentBoxSizing == "border-box") {
+ innerWidth = width - (paddingLeft + paddingRight + borderLeft + borderRight);
+ innerHeight = height - (paddingTop + paddingBottom + borderTop + borderBottom);
+ } else {
+ innerWidth = width;
+ innerHeight = height;
+ }
+ var obj = {};
+ obj["width"] = innerWidth;
+ obj["height"] = innerHeight;
+ return obj;
+}
+
+export default function BigText(element, options) {
+
+ if (typeof element === 'string') {
+ element = document.querySelector(element);
+ } else if (element.length) {
+ // Support for array based queries (such as jQuery)
+ element = element[0];
+ }
+
+ var defaultOptions = {
+ rotateText: null,
+ fontSizeFactor: 0.8,
+ maximumFontSize: null,
+ limitingDimension: "both",
+ horizontalAlign: "center",
+ verticalAlign: "center",
+ textAlign: "center",
+ whiteSpace: "nowrap",
+ singleLine: true
+ };
+
+ //Merge provided options and default options
+ options = options || {};
+ for (var opt in defaultOptions)
+ if (defaultOptions.hasOwnProperty(opt) && !options.hasOwnProperty(opt))
+ options[opt] = defaultOptions[opt];
+
+ //Get variables which we will reference frequently
+ var style = element.style;
+ var parent = element.parentNode;
+ var parentStyle = parent.style;
+ var parentComputedStyle = document.defaultView.getComputedStyle(parent);
+
+ //hides the element to prevent "flashing"
+ style.visibility = "hidden";
+ //Set some properties
+ style.display = "inline-block";
+ style.clear = "both";
+ style.float = "left";
+ var fontSize = options.maximumFontSize;
+ if (options.singleLine) {
+ style.fontSize = (fontSize * options.fontSizeFactor) + "px";
+ style.lineHeight = fontSize + "px";
+ } else {
+ for (; fontSize > options.minimumFontSize; fontSize = fontSize - Math.min(fontSize / 2, Math.max(0, fontSize - 48) + 2)) {
+ style.fontSize = (fontSize * options.fontSizeFactor) + "px";
+ style.lineHeight = "1";
+ if (element.offsetHeight <= +parentComputedStyle.height.replace("px", "")) {
+ break;
+ }
+ }
+ }
+ style.whiteSpace = options.whiteSpace;
+ style.textAlign = options.textAlign;
+ style.position = "relative";
+ style.padding = 0;
+ style.margin = 0;
+ style.left = "50%";
+ style.top = "50%";
+ var computedStyle = document.defaultView.getComputedStyle(element);
+
+ //Get properties of parent to allow easier referencing later.
+ var parentPadding = {
+ top: parseInt(parentComputedStyle.getPropertyValue("padding-top")),
+ right: parseInt(parentComputedStyle.getPropertyValue("padding-right")),
+ bottom: parseInt(parentComputedStyle.getPropertyValue("padding-bottom")),
+ left: parseInt(parentComputedStyle.getPropertyValue("padding-left")),
+ };
+ var parentBorder = {
+ top: parseInt(parentComputedStyle.getPropertyValue("border-top")),
+ right: parseInt(parentComputedStyle.getPropertyValue("border-right")),
+ bottom: parseInt(parentComputedStyle.getPropertyValue("border-bottom")),
+ left: parseInt(parentComputedStyle.getPropertyValue("border-left")),
+ };
+
+ //Calculate the parent inner width and height
+ var parentInnerDimensions = _calculateInnerDimensions(parentComputedStyle);
+ var parentInnerWidth = parentInnerDimensions["width"];
+ var parentInnerHeight = parentInnerDimensions["height"];
+
+ var box = {
+ width: element.offsetWidth, //Note: This is slightly larger than the jQuery version
+ height: element.offsetHeight,
+ };
+ if (!box.width || !box.height) return element;
+
+
+ if (options.rotateText !== null) {
+ if (typeof options.rotateText !== "number")
+ throw "bigText error: rotateText value must be a number";
+ var rotate = "rotate(" + options.rotateText + "deg)";
+ style.webkitTransform = rotate;
+ style.msTransform = rotate;
+ style.MozTransform = rotate;
+ style.OTransform = rotate;
+ style.transform = rotate;
+ //calculating bounding box of the rotated element
+ var sine = Math.abs(Math.sin(options.rotateText * Math.PI / 180));
+ var cosine = Math.abs(Math.cos(options.rotateText * Math.PI / 180));
+ box.width = element.offsetWidth * cosine + element.offsetHeight * sine;
+ box.height = element.offsetWidth * sine + element.offsetHeight * cosine;
+ }
+
+ var parentWidth = (parentInnerWidth - parentPadding.left - parentPadding.right);
+ var parentHeight = (parentInnerHeight - parentPadding.top - parentPadding.bottom);
+ var widthFactor = parentWidth / box.width;
+ var heightFactor = parentHeight / box.height;
+ var lineHeight;
+
+ if (options.limitingDimension.toLowerCase() === "width") {
+ lineHeight = Math.floor(widthFactor * fontSize);
+ } else if (options.limitingDimension.toLowerCase() === "height") {
+ lineHeight = Math.floor(heightFactor * fontSize);
+ } else if (widthFactor < heightFactor)
+ lineHeight = Math.floor(widthFactor * fontSize);
+ else if (widthFactor >= heightFactor)
+ lineHeight = Math.floor(heightFactor * fontSize);
+
+ var fontSize = lineHeight * options.fontSizeFactor;
+ if (fontSize < options.minimumFontSize) {
+ parentStyle.display = "flex";
+ parentStyle.alignItems = "center";
+ style.textAlign = "center";
+ style.visibility = "";
+ style.fontSize = options.minimumFontSize + "px";
+ style.lineHeight = "";
+ style.overflow = "hidden";
+ style.textOverflow = "ellipsis";
+ style.top = "";
+ style.left = "";
+ style.margin = "";
+ return element;
+ }
+ if (options.maximumFontSize && fontSize > options.maximumFontSize) {
+ fontSize = options.maximumFontSize;
+ lineHeight = fontSize / options.fontSizeFactor;
+ }
+
+ style.fontSize = Math.floor(fontSize) + "px";
+ style.lineHeight = Math.ceil(lineHeight) + "px";
+ style.marginBottom = "0px";
+ style.marginRight = "0px";
+
+ // if (options.limitingDimension.toLowerCase() === "height") {
+ // //this option needs the font-size to be set already so computedStyle.getPropertyValue("width") returns the right size
+ // //this +4 is to compensate the rounding erros that can occur due to the calls to Math.floor in the centering code
+ // parentStyle.width = (parseInt(computedStyle.getPropertyValue("width")) + 4) + "px";
+ // }
+
+ //Calculate the inner width and height
+ var innerDimensions = _calculateInnerDimensions(computedStyle);
+ var innerWidth = innerDimensions["width"];
+ var innerHeight = innerDimensions["height"];
+
+ switch (options.verticalAlign.toLowerCase()) {
+ case "top":
+ style.top = "0%";
+ break;
+ case "bottom":
+ style.top = "100%";
+ style.marginTop = Math.floor(-innerHeight) + "px";
+ break;
+ default:
+ style.marginTop = Math.ceil((-innerHeight / 2)) + "px";
+ break;
+ }
+
+ switch (options.horizontalAlign.toLowerCase()) {
+ case "left":
+ style.left = "0%";
+ break;
+ case "right":
+ style.left = "100%";
+ style.marginLeft = Math.floor(-innerWidth) + "px";
+ break;
+ default:
+ style.marginLeft = Math.ceil((-innerWidth / 2)) + "px";
+ break;
+ }
+
+ //shows the element after the work is done
+ style.visibility = "visible";
+
+ return element;
+}
diff --git a/src/typings/index.d.ts b/src/typings/index.d.ts
index bee79a38d..fea88cdcb 100644
--- a/src/typings/index.d.ts
+++ b/src/typings/index.d.ts
@@ -12,7 +12,7 @@ declare module 'fit-curve';
declare module 'iink-js';
declare module 'pdfjs-dist/web/pdf_viewer';
declare module 'react-jsx-parser';
-declare module 'type_decls.d';
+// declare module 'type_decls.d';
declare module '@react-pdf/renderer' {
import * as React from 'react';