diff options
Diffstat (limited to 'src/client/views/nodes/formattedText/FormattedTextBox.tsx')
-rw-r--r-- | src/client/views/nodes/formattedText/FormattedTextBox.tsx | 360 |
1 files changed, 207 insertions, 153 deletions
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index 023814a9d..1dcc445e8 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -12,9 +12,11 @@ import { Fragment, Mark, Node, Slice } from 'prosemirror-model'; import { EditorState, NodeSelection, Plugin, TextSelection, Transaction } from 'prosemirror-state'; import { EditorView } from 'prosemirror-view'; import { DateField } from '../../../../fields/DateField'; -import { AclAdmin, AclAugment, AclEdit, AclSelfEdit, CssSym, Doc, DocListCast, Field, ForceServerWrite, HeightSym, Opt, StrListCast, UpdatingFromServer, WidthSym } from '../../../../fields/Doc'; +import { Doc, DocListCast, StrListCast, Field, Opt } from '../../../../fields/Doc'; +import { AclAdmin, AclAugment, AclEdit, AclSelfEdit, DocCss, Height, Width, ForceServerWrite, UpdatingFromServer } from '../../../../fields/DocSymbols'; import { Id } from '../../../../fields/FieldSymbols'; import { InkTool } from '../../../../fields/InkField'; +import { List } from '../../../../fields/List'; import { PrefetchProxy } from '../../../../fields/Proxy'; import { RichTextField } from '../../../../fields/RichTextField'; import { RichTextUtils } from '../../../../fields/RichTextUtils'; @@ -32,8 +34,8 @@ import { DictationManager } from '../../../util/DictationManager'; import { DocumentManager } from '../../../util/DocumentManager'; import { DragManager } from '../../../util/DragManager'; import { MakeTemplate } from '../../../util/DropConverter'; -import { IsFollowLinkScript } from '../../../util/LinkFollower'; import { LinkManager } from '../../../util/LinkManager'; +import { RTFMarkup } from '../../../util/RTFMarkup'; import { SelectionManager } from '../../../util/SelectionManager'; import { SnappingManager } from '../../../util/SnappingManager'; import { undoBatch, UndoManager } from '../../../util/UndoManager'; @@ -68,8 +70,6 @@ import { schema } from './schema_rts'; import { SummaryView } from './SummaryView'; import applyDevTools = require('prosemirror-dev-tools'); import React = require('react'); -import { RTFMarkup } from '../../../util/RTFMarkup'; -import { List } from '../../../../fields/List'; const translateGoogleApi = require('translate-google-api'); export const GoogleRef = 'googleDocId'; type PullHandler = (exportState: Opt<GoogleApiClientUtils.Docs.ImportResult>, dataDoc: Doc) => void; @@ -96,6 +96,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps private _scrollRef: React.RefObject<HTMLDivElement> = React.createRef(); private _editorView: Opt<EditorView>; public _applyingChange: string = ''; + private _finishingLink = false; private _searchIndex = 0; private _lastTimedMark: Mark | undefined = undefined; private _cachedLinks: Doc[] = []; @@ -131,7 +132,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps return this._showSidebar ? '20%' : StrCast(this.layoutDoc._layout_sidebarWidthPercent, '0%'); } @computed get sidebarColor() { - return StrCast(this.layoutDoc.sidebarColor, StrCast(this.layoutDoc[this.fieldKey + '_backgroundColor'], '#e4e4e4')); + return StrCast(this.layoutDoc.sidebar_color, StrCast(this.layoutDoc[this.fieldKey + '_backgroundColor'], '#e4e4e4')); } @computed get layout_autoHeight() { return (this.props.forceAutoHeight || this.layoutDoc._layout_autoHeight) && !this.props.ignoreAutoHeight; @@ -243,9 +244,11 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps getAnchor = (addAsAnnotation: boolean, pinProps?: PinProps) => { if (!pinProps && this._editorView?.state.selection.empty) return this.rootDoc; - const anchor = Docs.Create.TextanchorDocument({ annotationOn: this.rootDoc, unrendered: true }); + const anchor = Docs.Create.ConfigDocument({ title: StrCast(this.rootDoc.title), annotationOn: this.rootDoc }); this.addDocument(anchor); + this._finishingLink = true; this.makeLinkAnchor(anchor, OpenWhere.addRight, undefined, 'Anchored Selection', false, addAsAnnotation); + this._finishingLink = false; PresBox.pinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: { ...(pinProps?.pinData ?? {}), scrollable: true } }, this.rootDoc); return anchor; }; @@ -296,21 +299,21 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps }; dispatchTransaction = (tx: Transaction) => { - if (this._editorView) { + if (this._editorView && (this._editorView as any).docView) { const state = this._editorView.state.apply(tx); this._editorView.updateState(state); const dataDoc = Doc.IsDelegateField(DocCast(this.layoutDoc.proto), this.fieldKey) ? DocCast(this.layoutDoc.proto) : this.dataDoc; - const curText = state.doc.textBetween(0, state.doc.content.size, ' \n'); - const curTemp = this.layoutDoc.resolvedDataDoc ? Cast(this.layoutDoc[this.fieldKey], RichTextField) : undefined; // the actual text in the text box - const curProto = Cast(Cast(dataDoc.proto, Doc, null)?.[this.fieldKey], RichTextField, null); // the default text inherited from a prototype - const curLayout = this.rootDoc !== this.layoutDoc ? Cast(this.layoutDoc[this.fieldKey], RichTextField, null) : undefined; // the default text stored in a layout template - const json = JSON.stringify(state.toJSON()); + const newText = state.doc.textBetween(0, state.doc.content.size, ' \n'); + const newJson = JSON.stringify(state.toJSON()); + const prevData = Cast(this.layoutDoc[this.fieldKey], RichTextField, null); // the actual text in the text box + const templateData = this.rootDoc !== this.layoutDoc ? prevData : undefined; // the default text stored in a layout template + const protoData = Cast(Cast(dataDoc.proto, Doc, null)?.[this.fieldKey], RichTextField, null); // the default text inherited from a prototype const effectiveAcl = GetEffectiveAcl(dataDoc); - const removeSelection = (json: string | undefined) => (json?.indexOf('"storedMarks"') === -1 ? json?.replace(/"selection":.*/, '') : json?.replace(/"selection":"\"storedMarks\""/, '"storedMarks"')); + const removeSelection = (json: string | undefined) => json?.replace(/"selection":.*/, ''); - if ([AclEdit, AclAdmin, AclSelfEdit].includes(effectiveAcl)) { + if ([AclEdit, AclAdmin, AclSelfEdit, AclAugment].includes(effectiveAcl)) { const accumTags = [] as string[]; state.tr.doc.nodesBetween(0, state.doc.content.size, (node: any, pos: number, parent: any) => { if (node.type === schema.nodes.dashField && node.attrs.fieldKey.startsWith('#')) { @@ -320,29 +323,25 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps dataDoc.tags = accumTags.length ? new List<string>(Array.from(new Set<string>(accumTags))) : undefined; let unchanged = true; - if (this._applyingChange !== this.fieldKey && removeSelection(json) !== removeSelection(curProto?.Data)) { + if (this._applyingChange !== this.fieldKey && removeSelection(newJson) !== removeSelection(prevData?.Data)) { this._applyingChange = this.fieldKey; - const textChange = curText !== Cast(dataDoc[this.fieldKey], RichTextField)?.Text; + const textChange = newText !== prevData?.Text; textChange && (dataDoc[this.fieldKey + '_modificationDate'] = new DateField(new Date(Date.now()))); - if ((!curTemp && !curProto) || curText || json.includes('dash')) { + if ((!prevData && !protoData) || newText || (!newText && !templateData)) { // if no template, or there's text that didn't come from the layout template, write it to the document. (if this is driven by a template, then this overwrites the template text which is intended) - if (removeSelection(json) !== removeSelection(curLayout?.Data)) { + if ((this._finishingLink || this.props.isContentActive()) && removeSelection(newJson) !== removeSelection(prevData?.Data)) { const numstring = NumCast(dataDoc[this.fieldKey], null); - if (numstring !== undefined) { - dataDoc[this.fieldKey] = Number(curText); - } else { - dataDoc[this.fieldKey] = new RichTextField(json, curText); - } - dataDoc[this.fieldKey + '_noTemplate'] = true; //(curTemp?.Text || "") !== curText; // mark the data field as being split from the template if it has been edited - textChange && ScriptCast(this.layoutDoc.onTextChanged, null)?.script.run({ this: this.layoutDoc, self: this.rootDoc, text: curText }); + dataDoc[this.fieldKey] = numstring !== undefined ? Number(newText) : new RichTextField(newJson, newText); + dataDoc[this.fieldKey + '_noTemplate'] = true; // mark the data field as being split from the template if it has been edited + textChange && ScriptCast(this.layoutDoc.onTextChanged, null)?.script.run({ this: this.layoutDoc, self: this.rootDoc, text: newText }); unchanged = false; } } else { // if we've deleted all the text in a note driven by a template, then restore the template data dataDoc[this.fieldKey] = undefined; - this._editorView.updateState(EditorState.fromJSON(this.config, JSON.parse((curProto || curTemp).Data))); + this._editorView.updateState(EditorState.fromJSON(this.config, JSON.parse((protoData || prevData).Data))); dataDoc[this.fieldKey + '_noTemplate'] = undefined; // mark the data field as not being split from any template it might have - ScriptCast(this.layoutDoc.onTextChanged, null)?.script.run({ this: this.layoutDoc, self: this.rootDoc, text: curText }); + ScriptCast(this.layoutDoc.onTextChanged, null)?.script.run({ this: this.layoutDoc, self: this.rootDoc, text: newText }); unchanged = false; } this._applyingChange = ''; @@ -418,6 +417,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps DocListCast(Doc.MyPublishedDocs.data).forEach(term => (tr = this.hyperlinkTerm(tr, term, newAutoLinks))); tr = tr.setSelection(isNodeSel && false ? new NodeSelection(tr.doc.resolve(f)) : new TextSelection(tr.doc.resolve(f), tr.doc.resolve(t))); this._editorView?.dispatch(tr); + this.prepareForTyping(); } oldAutoLinks.filter(oldLink => !newAutoLinks.has(oldLink) && oldLink.link_anchor_2 !== this.rootDoc).forEach(LinkManager.Instance.deleteLink); }; @@ -460,8 +460,12 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps if (node.firstChild === null && !node.marks.find((m: Mark) => m.type.name === schema.marks.noAutoLinkAnchor.name) && node.marks.find((m: Mark) => m.type.name === schema.marks.splitter.name)) { alink = alink ?? - (LinkManager.Links(this.Document).find(link => Doc.AreProtosEqual(Cast(link.link_anchor_1, Doc, null), this.rootDoc) && Doc.AreProtosEqual(Cast(link.link_anchor_2, Doc, null), target)) || - DocUtils.MakeLink(this.props.Document, target, { link_relationship: LinkManager.AutoKeywords })!); + (LinkManager.Links(this.rootDoc).find( + link => + Doc.AreProtosEqual(Cast(link.link_anchor_1, Doc, null), this.rootDoc) && // + Doc.AreProtosEqual(Cast(link.link_anchor_2, Doc, null), target) + ) || + DocUtils.MakeLink(this.rootDoc, target, { link_relationship: LinkManager.AutoKeywords })!); newAutoLinks.add(alink); const allAnchors = [{ href: Doc.localServerPath(target), title: 'a link', anchorId: this.props.Document[Id] }]; allAnchors.push(...(node.marks.find((m: Mark) => m.type.name === schema.marks.autoLinkAnchor.name)?.attrs.allAnchors ?? [])); @@ -534,36 +538,50 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps @undoBatch @action drop = (e: Event, de: DragManager.DropEvent) => { - if (de.complete.annoDragData) de.complete.annoDragData.dropDocCreator = () => this.getAnchor(true); + if (de.complete.annoDragData) { + de.complete.annoDragData.dropDocCreator = () => this.getAnchor(true); + e.stopPropagation(); + return true; + } const dragData = de.complete.docDragData; if (dragData) { - const draggedDoc = dragData.draggedDocuments.length && dragData.draggedDocuments[0]; - // replace text contents whend dragging with Alt - if (draggedDoc && draggedDoc.type === DocumentType.RTF && !Doc.AreProtosEqual(draggedDoc, this.props.Document) && de.altKey) { - if (draggedDoc.data instanceof RichTextField) { - Doc.GetProto(this.dataDoc)[this.fieldKey] = new RichTextField(draggedDoc.data.Data, draggedDoc.data.Text); - e.stopPropagation(); - } - // embed document when dragg marked as embed - } else if (de.embedKey) { - const target = dragData.droppedDocuments[0]; - const node = schema.nodes.dashDoc.create({ - width: target[WidthSym](), - height: target[HeightSym](), - title: 'dashDoc', - docId: target[Id], - float: 'unset', - }); - if (!['embed', 'copy'].includes((dragData.dropAction ?? '') as any)) { - dragData.removeDocument?.(dragData.draggedDocuments[0]); + const dataDoc = Doc.IsDelegateField(DocCast(this.layoutDoc.proto), this.fieldKey) ? DocCast(this.layoutDoc.proto) : this.dataDoc; + const effectiveAcl = GetEffectiveAcl(dataDoc); + let added = [AclEdit, AclAdmin, AclSelfEdit].includes(effectiveAcl); + const draggedDoc = dragData.draggedDocuments.lastElement(); + if (added) { + // replace text contents when dragging with Alt + if (de.altKey) { + const fieldKey = Doc.LayoutFieldKey(draggedDoc); + if (draggedDoc[fieldKey] instanceof RichTextField && !Doc.AreProtosEqual(draggedDoc, this.props.Document)) { + Doc.GetProto(this.dataDoc)[this.fieldKey] = Field.Copy(draggedDoc[fieldKey]); + } + + // embed document when drag marked as embed + } else if (de.embedKey) { + const node = schema.nodes.dashDoc.create({ + width: draggedDoc[Width](), + height: draggedDoc[Height](), + title: 'dashDoc', + docId: draggedDoc[Id], + float: 'unset', + }); + if (!['embed', 'copy'].includes((dragData.dropAction ?? '') as any)) { + added = dragData.removeDocument?.(draggedDoc) ? true : false; + } + if (added) { + draggedDoc._freeform_fitContentsToBox = true; + Doc.SetContainer(draggedDoc, this.rootDoc); + const view = this._editorView!; + view.dispatch(view.state.tr.insert(view.posAtCoords({ left: de.x, top: de.y })!.pos, node)); + } } - target._freeform_fitContentsToBox = true; - target.embedContainer = this.rootDoc; - const view = this._editorView!; - view.dispatch(view.state.tr.insert(view.posAtCoords({ left: de.x, top: de.y })!.pos, node)); - e.stopPropagation(); } // otherwise, fall through to outer collection to handle drop + !added && e.preventDefault(); + e.stopPropagation(); + return added; } + return false; }; getNodeEndpoints(context: Node, node: Node): { from: number; to: number } | null { @@ -650,7 +668,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps const hr = Math.round(Date.now() / 1000 / 60 / 60); numberRange(10).map(i => addStyleSheetRule(FormattedTextBox._userStyleSheet, 'UM-hr-' + (hr - i), { opacity: ((10 - i - 1) / 10).toString() })); } - this.layoutDoc[CssSym] = this.layoutDoc[CssSym] + 1; // css changes happen outside of react/mobx. so we need to set a flag that will notify anyone intereted in layout changes triggered by css changes (eg., CollectionLinkView) + this.layoutDoc[DocCss] = this.layoutDoc[DocCss] + 1; // css changes happen outside of react/mobx. so we need to set a flag that will notify anyone intereted in layout changes triggered by css changes (eg., CollectionLinkView) }; @observable _showSidebar = false; @@ -667,7 +685,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps this.layoutDoc._width = !preview && this.SidebarShown ? NumCast(this.layoutDoc._width) * 2 : Math.max(20, NumCast(this.layoutDoc._width) * prevWidth); }; sidebarDown = (e: React.PointerEvent) => { - const batch = UndoManager.StartBatch('sidebar'); + const batch = UndoManager.StartBatch('toggle sidebar'); setupMoveUpEvents( this, e, @@ -686,7 +704,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps .scale(this.props.NativeDimScaling?.() || 1) .transformDirection(delta[0], delta[1]); const sidebarWidth = (NumCast(this.layoutDoc._width) * Number(this.layout_sidebarWidthPercent.replace('%', ''))) / 100; - const width = this.layoutDoc[WidthSym]() + localDelta[0]; + const width = this.layoutDoc[Width]() + localDelta[0]; this.layoutDoc._layout_sidebarWidthPercent = Math.max(0, (sidebarWidth + localDelta[0]) / width) * 100 + '%'; this.layoutDoc.width = width; this.layoutDoc._layout_showSidebar = this.layoutDoc._layout_sidebarWidthPercent !== '0%'; @@ -694,13 +712,14 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps return false; }; - @undoBatch deleteAnnotation = (anchor: Doc) => { + const batch = UndoManager.StartBatch('delete link'); LinkManager.Instance.deleteLink(LinkManager.Links(anchor)[0]); // const docAnnotations = DocListCast(this.props.dataDoc[this.fieldKey]); // this.props.dataDoc[this.fieldKey] = new List<Doc>(docAnnotations.filter(a => a !== this.annoTextRegion)); // AnchorMenu.Instance.fadeOut(true); this.props.select(false); + setTimeout(batch.end); // wait for reaction to remove link from document }; @undoBatch @@ -733,17 +752,22 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps .split(' ') .filter(h => h); const anchorDoc = Array.from(hrefs).lastElement().replace(Doc.localServerPath(), '').split('?')[0]; + const deleteMarkups = undoBatch(() => { + const sel = editor.state.selection; + editor.dispatch(editor.state.tr.removeMark(sel.from, sel.to, editor.state.schema.marks.linkAnchor)); + }); e.persist(); anchorDoc && DocServer.GetRefField(anchorDoc).then( action(anchor => { + anchor && SelectionManager.SelectSchemaViewDoc(anchor as Doc); AnchorMenu.Instance.Status = 'annotation'; - AnchorMenu.Instance.Delete = () => this.deleteAnnotation(anchor as Doc); + AnchorMenu.Instance.Delete = !anchor && editor.state.selection.empty ? returnFalse : !anchor ? deleteMarkups : () => this.deleteAnnotation(anchor as Doc); AnchorMenu.Instance.Pinned = false; - AnchorMenu.Instance.PinToPres = () => this.pinToPres(anchor as Doc); - AnchorMenu.Instance.MakeTargetToggle = () => this.makeTargetToggle(anchor as Doc); - AnchorMenu.Instance.ShowTargetTrail = () => this.showTargetTrail(anchor as Doc); - AnchorMenu.Instance.IsTargetToggler = () => this.isTargetToggler(anchor as Doc); + AnchorMenu.Instance.PinToPres = !anchor ? returnFalse : () => this.pinToPres(anchor as Doc); + AnchorMenu.Instance.MakeTargetToggle = !anchor ? returnFalse : () => this.makeTargetToggle(anchor as Doc); + AnchorMenu.Instance.ShowTargetTrail = !anchor ? returnFalse : () => this.showTargetTrail(anchor as Doc); + AnchorMenu.Instance.IsTargetToggler = !anchor ? returnFalse : () => this.isTargetToggler(anchor as Doc); AnchorMenu.Instance.jumpTo(e.clientX, e.clientY, true); }) ); @@ -808,9 +832,9 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps icon: !this.Document._layout_noSidebar ? 'eye-slash' : 'eye', }); uicontrols.push({ - description: (this.Document._layout_altContentUI ? 'Hide' : 'Show') + ' Alt Content UI', - event: () => (this.layoutDoc._layout_altContentUI = !this.layoutDoc._layout_altContentUI), - icon: !this.Document._layout_altContentUI ? 'eye-slash' : 'eye', + description: (this.Document._layout_enableAltContentUI ? 'Hide' : 'Show') + ' Alt Content UI', + event: () => (this.layoutDoc._layout_enableAltContentUI = !this.layoutDoc._layout_enableAltContentUI), + icon: !this.Document._layout_enableAltContentUI ? 'eye-slash' : 'eye', }); uicontrols.push({ description: 'Show Highlights...', noexpand: true, subitems: highlighting, icon: 'hand-point-right' }); !Doc.noviceMode && @@ -823,7 +847,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps const appearance = cm.findByDescription('Appearance...'); const appearanceItems = appearance && 'subitems' in appearance ? appearance.subitems : []; - appearanceItems.push({ description: 'Change Perspective...', noexpand: true, subitems: changeItems, icon: 'external-link-alt' }); + appearanceItems.push({ description: 'Change Style...', noexpand: true, subitems: changeItems, icon: 'external-link-alt' }); // this.rootDoc.isTemplateDoc && appearanceItems.push({ description: "Make Default Layout", event: async () => Doc.UserDoc().defaultTextLayout = new PrefetchProxy(this.rootDoc), icon: "eye" }); !Doc.noviceMode && @@ -862,11 +886,12 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps const optionItems = options && 'subitems' in options ? options.subitems : []; optionItems.push({ description: `Generate Dall-E Image`, event: () => this.generateImage(), icon: 'star' }); optionItems.push({ description: `Ask GPT-3`, event: () => this.askGPT(), icon: 'lightbulb' }); - optionItems.push({ - description: !this.Document._createDocOnCR ? 'Create New Doc on Carriage Return' : 'Allow Carriage Returns', - event: () => (this.layoutDoc._createDocOnCR = !this.layoutDoc._createDocOnCR), - icon: !this.Document._createDocOnCR ? 'grip-lines' : 'bars', - }); + this.props.renderDepth && + optionItems.push({ + description: !this.Document._createDocOnCR ? 'Create New Doc on Carriage Return' : 'Allow Carriage Returns', + event: () => (this.layoutDoc._createDocOnCR = !this.layoutDoc._createDocOnCR), + icon: !this.Document._createDocOnCR ? 'grip-lines' : 'bars', + }); !Doc.noviceMode && optionItems.push({ description: `${this.Document._layout_autoHeight ? 'Lock' : 'Auto'} Height`, @@ -906,7 +931,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps let image_url = await gptImageCall((this.dataDoc.text as RichTextField)?.Text); if (image_url) { const [result] = await Networking.PostToServer('/uploadRemoteImage', { sources: [image_url] }); - const source = Utils.prepend(result.accessPaths.agnostic.client); + const source = result.accessPaths.agnostic.client; const newDoc = Docs.Create.ImageDocument(source, { x: NumCast(this.rootDoc.x) + NumCast(this.layoutDoc._width) + 10, y: NumCast(this.rootDoc.y), @@ -915,10 +940,10 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps data_nativeWidth: result.nativeWidth, data_nativeHeight: result.nativeHeight, }); - if (DocListCast(Doc.MyOverlayDocs?.data).includes(this.rootDoc)) { + if (Doc.IsInMyOverlay(this.rootDoc)) { newDoc.overlayX = this.rootDoc.x; newDoc.overlayY = NumCast(this.rootDoc.y) + NumCast(this.rootDoc._height); - Doc.AddDocToList(Doc.MyOverlayDocs, undefined, newDoc); + Doc.AddToMyOverlay(newDoc); } else { this.props.addDocument?.(newDoc); } @@ -960,7 +985,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps if (this._editorView && this._recordingStart) { if (this._break) { const textanchorFunc = () => { - const tanch = Docs.Create.TextanchorDocument({ title: 'dictation anchor', unrendered: true }); + const tanch = Docs.Create.ConfigDocument({ title: 'dictation anchor' }); return this.addDocument(tanch) ? tanch : undefined; }; const link = DocUtils.MakeLinkToActiveAudio(textanchorFunc, false).lastElement(); @@ -998,7 +1023,13 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps const splitter = state.schema.marks.splitter.create({ id: Utils.GenerateGuid() }); let tr = state.tr.addMark(sel.from, sel.to, splitter); if (sel.from !== sel.to) { - const anchor = anchorDoc ?? Docs.Create.TextanchorDocument({ title: '#' + this._editorView?.state.doc.textBetween(sel.from, sel.to), annotationOn: this.dataDoc, unrendered: true }); + const anchor = + anchorDoc ?? + Docs.Create.ConfigDocument({ + // + title: 'text(' + this._editorView?.state.doc.textBetween(sel.from, sel.to) + ')', + annotationOn: this.dataDoc, + }); const href = targetHref ?? Doc.localServerPath(anchor); if (anchor !== anchorDoc && addAsAnnotation) this.addDocument(anchor); tr.doc.nodesBetween(sel.from, sel.to, (node: any, pos: number, parent: any) => { @@ -1014,6 +1045,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps this._editorView!.dispatch(tr.removeMark(sel.from, sel.to, splitter)); this.dataDoc[UpdatingFromServer] = this.dataDoc[ForceServerWrite] = false; anchor.text = selectedText; + anchor.title = selectedText.substring(0, 30); return anchor; } return anchorDoc ?? this.rootDoc; @@ -1022,7 +1054,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps } getView = async (doc: Doc) => { - if (DocListCast(this.rootDoc[this.SidebarKey]).find(anno => Doc.AreProtosEqual(doc.unrendered ? DocCast(doc.annotationOn) : doc, anno))) { + if (DocListCast(this.rootDoc[this.SidebarKey]).find(anno => Doc.AreProtosEqual(doc.layout_unrendered ? DocCast(doc.annotationOn) : doc, anno))) { !this.SidebarShown && this.toggleSidebar(false); setTimeout(() => this._sidebarRef?.current?.makeDocUnfiltered(doc)); } @@ -1129,11 +1161,17 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps () => ({ sidebarHeight: this.sidebarHeight, textHeight: this.textHeight, layout_autoHeight: this.layout_autoHeight, marginsHeight: this.layout_autoHeightMargins }), ({ sidebarHeight, textHeight, layout_autoHeight, marginsHeight }) => { const newHeight = this.contentScaling * (marginsHeight + Math.max(sidebarHeight, textHeight)); - if (layout_autoHeight && newHeight && newHeight !== this.rootDoc.height && !this.props.dontRegisterView) { + if ( + (!Array.from(FormattedTextBox._globalHighlights).includes('Bold Text') || this.props.isSelected()) && // + layout_autoHeight && + newHeight && + newHeight !== this.rootDoc.height && + !this.props.dontRegisterView + ) { this.props.setHeight?.(newHeight); } }, - { fireImmediately: true } + { fireImmediately: !Array.from(FormattedTextBox._globalHighlights).includes('Bold Text') } ); this._disposers.links = reaction( () => LinkManager.Links(this.dataDoc), // if a link is deleted, then remove all hyperlinks that reference it from the text's marks @@ -1155,7 +1193,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps () => { const dataDoc = Doc.IsDelegateField(DocCast(this.layoutDoc?.proto), this.fieldKey) ? DocCast(this.layoutDoc?.proto) : this?.dataDoc; const whichDoc = !this.dataDoc || !this.layoutDoc ? undefined : dataDoc?.[this.fieldKey + '_noTemplate'] || !this.layoutDoc[this.fieldKey] ? dataDoc : this.layoutDoc; - return !whichDoc ? undefined : { data: Cast(whichDoc[this.fieldKey], RichTextField, null), str: Field.toString(whichDoc[this.fieldKey]) }; + return !whichDoc ? undefined : { data: Cast(whichDoc[this.fieldKey], RichTextField, null), str: Field.toString(DocCast(whichDoc[this.fieldKey])) }; }, incomingValue => { if (this._editorView && this._applyingChange !== this.fieldKey) { @@ -1199,15 +1237,16 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps this._disposers.selected = reaction( () => this.props.isSelected(), action(selected => { + selected && this.prepareForTyping(); if (FormattedTextBox._globalHighlights.has('Bold Text')) { - this.layoutDoc[CssSym] = this.layoutDoc[CssSym] + 1; // css change happens outside of mobx/react, so this will notify anyone interested in the layout that it has changed + this.layoutDoc[DocCss] = this.layoutDoc[DocCss] + 1; // css change happens outside of mobx/react, so this will notify anyone interested in the layout that it has changed } if (RichTextMenu.Instance?.view === this._editorView && !selected) { RichTextMenu.Instance?.updateMenu(undefined, undefined, undefined); } if (this._editorView && selected) { RichTextMenu.Instance?.updateMenu(this._editorView, undefined, this.props); - this.autoLink(); + setTimeout(this.autoLink, 20); } // Accessing editor and text doc for gpt assisted text edits if (this._editorView && selected) { @@ -1474,11 +1513,11 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps } const selectOnLoad = this.rootDoc[Id] === FormattedTextBox.SelectOnLoad && (!LightboxView.LightboxDoc || LightboxView.IsLightboxDocView(this.props.docViewPath())); - if (selectOnLoad && !this.props.dontRegisterView && !this.props.dontSelectOnLoad && this.isActiveTab(this.ProseRef)) { + if (this._editorView && selectOnLoad && !this.props.dontRegisterView && !this.props.dontSelectOnLoad && this.isActiveTab(this.ProseRef)) { const selLoadChar = FormattedTextBox.SelectOnLoadChar; FormattedTextBox.SelectOnLoad = ''; this.props.select(false); - if (selLoadChar && this._editorView) { + if (selLoadChar) { const $from = this._editorView.state.selection.anchor ? this._editorView.state.doc.resolve(this._editorView.state.selection.anchor - 1) : undefined; const mark = schema.marks.user_mark.create({ userid: Doc.CurrentUserEmail, modified: Math.floor(Date.now() / 1000) }); const curMarks = this._editorView.state.storedMarks ?? $from?.marksAcross(this._editorView.state.selection.$head) ?? []; @@ -1488,30 +1527,18 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps .insertText(FormattedTextBox.SelectOnLoadChar, this._editorView.state.doc.content.size - 1, this._editorView.state.doc.content.size) .setStoredMarks(storedMarks); this._editorView.dispatch(tr.setSelection(new TextSelection(tr.doc.resolve(tr.doc.content.size)))); - } else if (this._editorView && curText && !FormattedTextBox.DontSelectInitialText) { + } else if (curText && !FormattedTextBox.DontSelectInitialText) { selectAll(this._editorView.state, this._editorView?.dispatch); - this.startUndoTypingBatch(); - } else if (this._editorView) { - this._editorView.dispatch(this._editorView.state.tr.addStoredMark(schema.marks.user_mark.create({ userid: Doc.CurrentUserEmail, modified: Math.floor(Date.now() / 1000) }))); } } selectOnLoad && this._editorView!.focus(); - // add user mark for any first character that was typed since the user mark that gets set in KeyPress won't have been called yet. + if (this.props.isContentActive()) this.prepareForTyping(); if (this._editorView) { const tr = this._editorView.state.tr; const { from, to } = tr.selection; - // for some reason, the selection is sometimes lost in the sidebar view when prosemirror syncs the seledtion with the dom, so reset the selectoin after the document has ben fully instantiated. + // for some reason, the selection is sometimes lost in the sidebar view when prosemirror syncs the seledtion with the dom, so reset the selection after the document has ben fully instantiated. if (FormattedTextBox.DontSelectInitialText) setTimeout(() => this._editorView?.dispatch(tr.setSelection(new TextSelection(tr.doc.resolve(from), tr.doc.resolve(to)))), 250); - this._editorView.state.storedMarks = [ - ...(this._editorView.state.storedMarks ?? []), - ...(!this._editorView.state.storedMarks?.some(mark => mark.type === schema.marks.user_mark) ? [schema.marks.user_mark.create({ userid: Doc.CurrentUserEmail, modified: Math.floor(Date.now() / 1000) })] : []), - ...(Doc.UserDoc().fontColor !== 'transparent' && Doc.UserDoc().fontColor ? [schema.mark(schema.marks.pFontColor, { color: StrCast(Doc.UserDoc().fontColor) })] : []), - ...(Doc.UserDoc().fontStyle === 'italics' ? [schema.mark(schema.marks.em)] : []), - ...(Doc.UserDoc().textDecoration === 'underline' ? [schema.mark(schema.marks.underline)] : []), - ...(Doc.UserDoc().fontFamily ? [schema.mark(schema.marks.pFontFamily, { family: this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.FontFamily) })] : []), - ...(Doc.UserDoc().fontSize ? [schema.mark(schema.marks.pFontSize, { fontSize: this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.FontSize) })] : []), - ...(Doc.UserDoc().fontWeight === 'bold' ? [schema.mark(schema.marks.strong)] : []), - ]; + if (FormattedTextBox.PasteOnLoad) { const pdfAnchorId = FormattedTextBox.PasteOnLoad.clipboardData?.getData('dash/pdfAnchor'); FormattedTextBox.PasteOnLoad = undefined; @@ -1521,9 +1548,31 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps FormattedTextBox.DontSelectInitialText = false; } + // add user mark for any first character that was typed since the user mark that gets set in KeyPress won't have been called yet. + prepareForTyping = () => { + this._editorView?.dispatch( + this._editorView?.state.tr.setStoredMarks([ + ...(this._editorView.state.storedMarks?.filter(mark => ![schema.marks.em, schema.marks.underline, schema.marks.pFontFamily, schema.marks.pFontSize, schema.marks.strong, schema.marks.pFontColor].includes(mark.type)) ?? []), + ...[schema.marks.user_mark.create({ userid: Doc.CurrentUserEmail, modified: Math.floor(Date.now() / 1000) })], + ...(Doc.UserDoc().fontColor !== 'transparent' && Doc.UserDoc().fontColor ? [schema.mark(schema.marks.pFontColor, { color: StrCast(Doc.UserDoc().fontColor) })] : []), + ...(Doc.UserDoc().fontStyle === 'italics' ? [schema.mark(schema.marks.em)] : []), + ...(Doc.UserDoc().textDecoration === 'underline' ? [schema.mark(schema.marks.underline)] : []), + ...(Doc.UserDoc().fontFamily ? [schema.mark(schema.marks.pFontFamily, { family: this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.FontFamily) })] : []), + ...(Doc.UserDoc().fontSize ? [schema.mark(schema.marks.pFontSize, { fontSize: this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.FontSize) })] : []), + ...(Doc.UserDoc().fontWeight === 'bold' ? [schema.mark(schema.marks.strong)] : []), + ]) + ); + }; + + @action componentWillUnmount() { + if (this._recording) { + this._recording = !this._recording; + } Object.values(this._disposers).forEach(disposer => disposer?.()); this.endUndoTypingBatch(); + FormattedTextBox.LiveTextUndo?.end(); + FormattedTextBox.LiveTextUndo = undefined; this.unhighlightSearchTerms(); this._editorView?.destroy(); RichTextMenu.Instance?.TextView === this && RichTextMenu.Instance.updateMenu(undefined, undefined, undefined); @@ -1558,8 +1607,6 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps } if (this._recording && !e.ctrlKey && e.button === 0) { this.breakupDictation(); - e.preventDefault(); - e.stopPropagation(); } this._downX = e.clientX; this._downY = e.clientY; @@ -1624,7 +1671,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps onFocused = (e: React.FocusEvent): void => { //applyDevTools.applyDevTools(this._editorView); this.ProseRef?.children[0] === e.nativeEvent.target && this._editorView && RichTextMenu.Instance?.updateMenu(this._editorView, undefined, this.props); - this.startUndoTypingBatch(); + e.stopPropagation(); }; onClick = (e: React.MouseEvent): void => { @@ -1699,13 +1746,11 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps } } startUndoTypingBatch() { - !this._undoTyping && (this._undoTyping = UndoManager.StartBatch('undoTyping')); + !this._undoTyping && (this._undoTyping = UndoManager.StartBatch('text edits on ' + this.rootDoc.title)); } public endUndoTypingBatch() { - const wasUndoing = this._undoTyping; this._undoTyping?.end(); this._undoTyping = undefined; - return wasUndoing; } @action @@ -1733,7 +1778,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps const state = this._editorView!.state; const curText = state.doc.textBetween(0, state.doc.content.size, ' \n'); - if (this.layoutDoc.sidebarViewType === 'translation' && !this.fieldKey.includes('translation') && curText.endsWith(' ') && curText !== this._lastText) { + if (this.layoutDoc.sidebar_collectionType === 'translation' && !this.fieldKey.includes('translation') && curText.endsWith(' ') && curText !== this._lastText) { try { translateGoogleApi(curText, { from: 'en', to: 'es' }).then((result1: any) => { setTimeout( @@ -1799,8 +1844,11 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps default: if (this._lastTimedMark?.attrs.userid === Doc.CurrentUserEmail) break; case ' ': - [AclEdit, AclAdmin, AclSelfEdit].includes(GetEffectiveAcl(this.dataDoc)) && - this._editorView!.dispatch(this._editorView!.state.tr.removeStoredMark(schema.marks.user_mark.create({})).addStoredMark(schema.marks.user_mark.create({ userid: Doc.CurrentUserEmail, modified: Math.floor(Date.now() / 1000) }))); + if (e.code !== 'Space') { + [AclEdit, AclAugment, AclAdmin].includes(GetEffectiveAcl(this.rootDoc)) && + this._editorView!.dispatch(this._editorView!.state.tr.removeStoredMark(schema.marks.user_mark).addStoredMark(schema.marks.user_mark.create({ userid: Doc.CurrentUserEmail, modified: Math.floor(Date.now() / 1000) }))); + } + break; } this.startUndoTypingBatch(); }; @@ -1822,17 +1870,18 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps tryUpdateScrollHeight = () => { const margins = 2 * NumCast(this.layoutDoc._yMargin, this.props.yPadding || 0); const children = this.ProseRef?.children.length ? Array.from(this.ProseRef.children[0].children) : undefined; - if (children) { + if (children && !SnappingManager.GetIsDragging()) { const toNum = (val: string) => Number(val.replace('px', '').replace('auto', '0')); const toHgt = (node: Element) => { const { height, marginTop, marginBottom } = getComputedStyle(node); return toNum(height) + Math.max(0, toNum(marginTop)) + Math.max(0, toNum(marginBottom)); }; const proseHeight = !this.ProseRef ? 0 : children.reduce((p, child) => p + toHgt(child), margins); - const scrollHeight = this.ProseRef && Math.min(NumCast(this.layoutDoc.docMaxAutoHeight, proseHeight), proseHeight); + const scrollHeight = this.ProseRef && Math.min(NumCast(this.layoutDoc.layout_maxAutoHeight, proseHeight), proseHeight); if (this.props.setHeight && scrollHeight && !this.props.dontRegisterView) { // if top === 0, then the text box is growing upward (as the overlay caption) which doesn't contribute to the height computation const setScrollHeight = () => (this.rootDoc[this.fieldKey + '_scrollHeight'] = scrollHeight); + if (this.rootDoc === this.layoutDoc || this.layoutDoc.resolvedDataDoc) { setScrollHeight(); } else { @@ -1941,25 +1990,25 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps fitContentsToBox={this.fitContentsToBox} noSidebar={true} treeViewHideTitle={true} - fieldKey={this.layoutDoc.sidebarViewType === 'translation' ? `${this.fieldKey}_translation` : `${this.fieldKey}_sidebar`} + fieldKey={this.layoutDoc.sidebar_collectionType === 'translation' ? `${this.fieldKey}_translation` : `${this.fieldKey}_sidebar`} /> </div> ); }; return ( <div className={'formattedTextBox-sidebar' + (Doc.ActiveTool !== InkTool.None ? '-inking' : '')} style={{ width: `${this.layout_sidebarWidthPercent}`, backgroundColor: `${this.sidebarColor}` }}> - {renderComponent(StrCast(this.layoutDoc.sidebarViewType))} + {renderComponent(StrCast(this.layoutDoc.sidebar_collectionType))} </div> ); } cycleAlternateText = () => { - if (this.layoutDoc._layout_altContentUI) { - const usePath = this.rootDoc[`${this.props.fieldKey}_usePath`]; + if (this.layoutDoc._layout_enableAltContentUI) { + const usePath = this.rootDoc[`_${this.props.fieldKey}_usePath`]; this.rootDoc[`_${this.props.fieldKey}_usePath`] = usePath === undefined ? 'alternate' : usePath === 'alternate' ? 'alternate:hover' : undefined; } }; @computed get overlayAlternateIcon() { - const usePath = this.rootDoc[`${this.props.fieldKey}_usePath`]; + const usePath = this.rootDoc[`_${this.props.fieldKey}_usePath`]; return ( <Tooltip title={ @@ -1995,62 +2044,69 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps return this.props.fieldKey + (usePath && (!usePath.includes(':hover') || this._isHovering) ? `_${usePath.replace(':hover', '')}` : ''); } @observable _isHovering = false; + onPassiveWheel = (e: WheelEvent) => { + // if scrollTop is 0, then don't let wheel trigger scroll on any container (which it would since onScroll won't be triggered on this) + if (this.props.isContentActive() && !this.props.allowScroll) { + if (!NumCast(this.layoutDoc._layout_scrollTop) && e.deltaY <= 0) e.preventDefault(); + e.stopPropagation(); + } + }; + _oldWheel: any; + @computed get fontColor() { + return this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.Color); + } + @computed get fontSize() { + return this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.FontSize); + } + @computed get fontFamily() { + return this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.FontFamily); + } + @computed get fontWeight() { + return this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.FontWeight); + } render() { TraceMobx(); - const active = this.props.isContentActive() || this.props.isSelected(); - const selected = active; const scale = (this.props.NativeDimScaling?.() || 1) * NumCast(this.layoutDoc._freeform_scale, 1); - const rounded = StrCast(this.layoutDoc.borderRounding) === '100%' ? '-rounded' : ''; - const interactive = (Doc.ActiveTool === InkTool.None || SnappingManager.GetIsDragging()) && (this.layoutDoc.z || !this.layoutDoc._lockedPosition); - if (!selected && FormattedTextBoxComment.textBox === this) setTimeout(FormattedTextBoxComment.Hide); - const minimal = this.props.ignoreAutoHeight; + const rounded = StrCast(this.layoutDoc.layout_borderRounding) === '100%' ? '-rounded' : ''; + setTimeout(() => !this.props.isContentActive() && FormattedTextBoxComment.textBox === this && FormattedTextBoxComment.Hide); const paddingX = NumCast(this.layoutDoc._xMargin, this.props.xPadding || 0); const paddingY = NumCast(this.layoutDoc._yMargin, this.props.yPadding || 0); - const selPad = (selected && !this.layoutDoc._createDocOnCR) || minimal ? Math.min(paddingY, Math.min(paddingX, 10)) : 0; - const selPaddingClass = selected && !this.layoutDoc._createDocOnCR && paddingY >= 10 ? '-selected' : ''; const styleFromLayoutString = Doc.styleFromLayoutString(this.rootDoc, this.layoutDoc, this.props, scale); // this converts any expressions in the format string to style props. e.g., <FormattedTextBox height='{this._headerHeight}px' > return styleFromLayoutString?.height === '0px' ? null : ( <div className="formattedTextBox" onPointerEnter={action(() => (this._isHovering = true))} onPointerLeave={action(() => (this._isHovering = false))} - ref={r => - r?.addEventListener( - 'wheel', // if scrollTop is 0, then don't let wheel trigger scroll on any container (which it would since onScroll won't be triggered on this) - (e: WheelEvent) => { - if (this.props.isContentActive() && !this.props.allowScroll) { - if (!NumCast(this.layoutDoc._layout_scrollTop) && e.deltaY <= 0) e.preventDefault(); - e.stopPropagation(); - } - }, - { passive: false } - ) - } + ref={r => { + this._oldWheel?.removeEventListener('wheel', this.onPassiveWheel); + this._oldWheel = r; + r?.addEventListener('wheel', this.onPassiveWheel, { passive: false }); + }} style={{ ...(this.props.dontScale ? {} : { transform: `scale(${scale})`, - transformOrigin: 'top left', width: `${100 / scale}%`, height: `${100 / scale}%`, }), - display: !SnappingManager.GetIsDragging() && this.props.thumbShown?.() ? 'none' : undefined, + // display: !this.props.isContentActive() && this.props.thumbShown?.() ? 'none' : undefined, transition: 'inherit', // overflowY: this.layoutDoc._layout_autoHeight ? "hidden" : undefined, - color: this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.Color), - fontSize: this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.FontSize), - fontFamily: this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.FontFamily), - fontWeight: this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.FontWeight), + color: this.fontColor, + fontSize: this.fontSize, + fontFamily: this.fontFamily, + fontWeight: this.fontWeight, ...styleFromLayoutString, }}> <div className="formattedTextBox-cont" ref={this._ref} style={{ + cursor: this.props.isContentActive() ? 'text' : undefined, overflow: this.layout_autoHeight && this.props.CollectionFreeFormDocumentView?.() ? 'hidden' : undefined, //x this breaks viewing an layout_autoHeight doc in its own tab, or in the lightbox height: this.props.height || (this.layout_autoHeight && this.props.renderDepth && !this.props.suppressSetHeight ? 'max-content' : undefined), - pointerEvents: interactive ? undefined : 'none', + pointerEvents: Doc.ActiveTool === InkTool.None && !this.props.onBrowseClick?.() ? undefined : 'none', }} onContextMenu={this.specificContextMenu} onKeyDown={this.onKeyDown} @@ -2062,32 +2118,30 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps onPointerDown={this.onPointerDown} onDoubleClick={this.onDoubleClick}> <div - className={`formattedTextBox-outer${selected ? '-selected' : ''}`} + className={`formattedTextBox-outer`} ref={this._scrollRef} style={{ width: this.props.dontSelectOnLoad ? '100%' : `calc(100% - ${this.layout_sidebarWidthPercent})`, - pointerEvents: !active && !SnappingManager.GetIsDragging() ? 'none' : undefined, overflow: this.layoutDoc._createDocOnCR ? 'hidden' : this.layoutDoc._layout_autoHeight ? 'visible' : undefined, }} onScroll={this.onScroll} onDrop={this.ondrop}> <div - className={minimal ? 'formattedTextBox-minimal' : `formattedTextBox-inner${rounded}${selPaddingClass}`} + className={`formattedTextBox-inner${rounded}`} ref={this.createDropTarget} style={{ padding: StrCast(this.layoutDoc._textBoxPadding), - paddingLeft: StrCast(this.layoutDoc._textBoxPaddingX, `${paddingX - selPad}px`), - paddingRight: StrCast(this.layoutDoc._textBoxPaddingX, `${paddingX - selPad}px`), - paddingTop: StrCast(this.layoutDoc._textBoxPaddingY, `${paddingY - selPad}px`), - paddingBottom: StrCast(this.layoutDoc._textBoxPaddingY, `${paddingY - selPad}px`), - pointerEvents: !active && !SnappingManager.GetIsDragging() ? (IsFollowLinkScript(this.layoutDoc.onClick) ? 'none' : undefined) : undefined, + paddingLeft: StrCast(this.layoutDoc._textBoxPaddingX, `${paddingX}px`), + paddingRight: StrCast(this.layoutDoc._textBoxPaddingX, `${paddingX}px`), + paddingTop: StrCast(this.layoutDoc._textBoxPaddingY, `${paddingY}px`), + paddingBottom: StrCast(this.layoutDoc._textBoxPaddingY, `${paddingY}px`), }} /> </div> {this.noSidebar || this.props.dontSelectOnLoad || !this.SidebarShown || this.layout_sidebarWidthPercent === '0%' ? null : this.sidebarCollection} {this.noSidebar || this.Document._layout_noSidebar || this.props.dontSelectOnLoad || this.Document._createDocOnCR ? null : this.sidebarHandle} {this.audioHandle} - {this.layoutDoc._layout_altContentUI ? this.overlayAlternateIcon : null} + {this.layoutDoc._layout_enableAltContentUI ? this.overlayAlternateIcon : null} </div> </div> ); |