diff options
Diffstat (limited to 'src/client/views/nodes')
| -rw-r--r-- | src/client/views/nodes/DataVizBox/DataVizBox.tsx | 177 | ||||
| -rw-r--r-- | src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx | 438 | ||||
| -rw-r--r-- | src/client/views/nodes/DataVizBox/components/TableBox.tsx | 18 | ||||
| -rw-r--r-- | src/client/views/nodes/DocumentIcon.tsx | 10 | ||||
| -rw-r--r-- | src/client/views/nodes/DocumentView.tsx | 4 | ||||
| -rw-r--r-- | src/client/views/nodes/FieldView.tsx | 5 | ||||
| -rw-r--r-- | src/client/views/nodes/LabelBox.tsx | 4 | ||||
| -rw-r--r-- | src/client/views/nodes/calendarBox/CalendarBox.tsx | 2 | ||||
| -rw-r--r-- | src/client/views/nodes/formattedText/FormattedTextBox.tsx | 17 |
9 files changed, 336 insertions, 339 deletions
diff --git a/src/client/views/nodes/DataVizBox/DataVizBox.tsx b/src/client/views/nodes/DataVizBox/DataVizBox.tsx index 12196f290..896048ab3 100644 --- a/src/client/views/nodes/DataVizBox/DataVizBox.tsx +++ b/src/client/views/nodes/DataVizBox/DataVizBox.tsx @@ -1,4 +1,3 @@ -/* eslint-disable react/jsx-props-no-spreading */ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { Checkbox } from '@mui/material'; import { Colors, Toggle, ToggleType, Type } from 'browndash-components'; @@ -8,42 +7,36 @@ import * as React from 'react'; import { ClientUtils, returnEmptyString, returnFalse, returnOne, setupMoveUpEvents } from '../../../../ClientUtils'; import { emptyFunction } from '../../../../Utils'; import { Doc, DocListCast, Field, FieldType, NumListCast, Opt, StrListCast } from '../../../../fields/Doc'; +import { AclAdmin, AclAugment, AclEdit } from '../../../../fields/DocSymbols'; import { InkTool } from '../../../../fields/InkField'; import { List } from '../../../../fields/List'; +import { PrefetchProxy } from '../../../../fields/Proxy'; import { Cast, CsvCast, DocCast, NumCast, StrCast } from '../../../../fields/Types'; import { CsvField } from '../../../../fields/URLField'; -import { GetEffectiveAcl, TraceMobx, inheritParentAcls } from '../../../../fields/util'; +import { GetEffectiveAcl, TraceMobx } from '../../../../fields/util'; +import { GPTCallType, gptAPICall } from '../../../apis/gpt/GPT'; import { DocUtils } from '../../../documents/DocUtils'; import { DocumentType } from '../../../documents/DocumentTypes'; import { Docs } from '../../../documents/Documents'; +import { LinkManager } from '../../../util/LinkManager'; import { UndoManager, undoable } from '../../../util/UndoManager'; import { ContextMenu } from '../../ContextMenu'; import { ViewBoxAnnotatableComponent } from '../../DocComponent'; import { MarqueeAnnotator } from '../../MarqueeAnnotator'; import { PinProps } from '../../PinFuncs'; import { SidebarAnnos } from '../../SidebarAnnos'; +import { CollectionFreeFormView } from '../../collections/collectionFreeForm'; import { AnchorMenu } from '../../pdf/AnchorMenu'; import { GPTPopup, GPTPopupMode } from '../../pdf/GPTPopup/GPTPopup'; import { DocumentView } from '../DocumentView'; import { FieldView, FieldViewProps } from '../FieldView'; import { FocusViewOptions } from '../FocusViewOptions'; import './DataVizBox.scss'; +import { Col, DataVizTemplateInfo, DocCreatorMenu, LayoutType, TemplateFieldSize, TemplateFieldType } from './DocCreatorMenu'; import { Histogram } from './components/Histogram'; import { LineChart } from './components/LineChart'; import { PieChart } from './components/PieChart'; import { TableBox } from './components/TableBox'; -import { LinkManager } from '../../../util/LinkManager'; -import { Col, DataVizTemplateInfo, DataVizTemplateLayout, DocCreatorMenu, TemplateFieldSize, LayoutType, TemplateFieldType } from './DocCreatorMenu'; -import { CollectionFreeFormView, MarqueeView } from '../../collections/collectionFreeForm'; -import { PrefetchProxy } from '../../../../fields/Proxy'; -import { AclAdmin, AclAugment, AclEdit } from '../../../../fields/DocSymbols'; -import { template } from 'lodash'; -import { data } from 'jquery'; -import { listSpec } from '../../../../fields/Schema'; -import { ObjectField } from '../../../../fields/ObjectField'; -import { Id } from '../../../../fields/FieldSymbols'; -import { GPTCallType, gptAPICall } from '../../../apis/gpt/GPT'; -import { TbSortDescendingShapes } from 'react-icons/tb'; export enum DataVizView { TABLE = 'table', @@ -65,7 +58,7 @@ export class DataVizBox extends ViewBoxAnnotatableComponent<FieldViewProps>() { @observable _marqueeing: number[] | undefined = undefined; @observable _savedAnnotations = new ObservableMap<number, HTMLDivElement[]>(); @observable _specialHighlightedRow: number | undefined = undefined; - @observable GPTSummary: ObservableMap<string, {desc?: string, type?: TemplateFieldType, size?: TemplateFieldSize}> | undefined = undefined; + @observable GPTSummary: ObservableMap<string, { desc?: string; type?: TemplateFieldType; size?: TemplateFieldSize }> | undefined = undefined; @observable colsInfo: ObservableMap<string, Col> = new ObservableMap(); @observable _GPTLoading: boolean = false; @@ -121,12 +114,9 @@ export class DataVizBox extends ViewBoxAnnotatableComponent<FieldViewProps>() { const records = DataVizBox.dataset.get(CsvCast(this.dataDoc[this.fieldKey]).url.href); this._urlError = false; return records?.filter(record => Object.keys(record).some(key => record[key])) ?? []; - } catch (e){ + } catch { this._urlError = true; - const data: { [key: string]: string; }[] = [ - { error: "Data not found"}, - ]; - return data; + return [{ error: 'Data not found' }] as { [key: string]: string }[]; } } @@ -153,70 +143,73 @@ export class DataVizBox extends ViewBoxAnnotatableComponent<FieldViewProps>() { @action setSpecialHighlightedRow = (row: number | undefined) => { this._specialHighlightedRow = row; - } + }; @action setColumnType = (colTitle: string, type: TemplateFieldType) => { const colInfo = this.colsInfo.get(colTitle); - if (colInfo) { + if (colInfo) { colInfo.type = type; } else { - this.colsInfo.set(colTitle, {title: colTitle, desc: '', type: type, sizes: [TemplateFieldSize.MEDIUM]}) + this.colsInfo.set(colTitle, { title: colTitle, desc: '', type: type, sizes: [TemplateFieldSize.MEDIUM] }); } - } + }; @action modifyColumnSizes = (colTitle: string, size: TemplateFieldSize, valid: boolean) => { const column = this.colsInfo.get(colTitle); - if (column) { + if (column) { if (!valid && column.sizes.includes(size)) { column.sizes.splice(column.sizes.indexOf(size), 1); } else if (valid && !column.sizes.includes(size)) { column.sizes.push(size); } } else { - this.colsInfo.set(colTitle, {title: colTitle, desc: '', type: TemplateFieldType.UNSET, sizes: [size]}) + this.colsInfo.set(colTitle, { title: colTitle, desc: '', type: TemplateFieldType.UNSET, sizes: [size] }); } - } + }; @action setColumnTitle = (colTitle: string, newTitle: string) => { const colInfo = this.colsInfo.get(colTitle); - if (colInfo) { + if (colInfo) { colInfo.title = newTitle; - console.log(colInfo.title) + console.log(colInfo.title); } else { - this.colsInfo.set(colTitle, {title: newTitle, desc: '', type: TemplateFieldType.UNSET, sizes: []}) + this.colsInfo.set(colTitle, { title: newTitle, desc: '', type: TemplateFieldType.UNSET, sizes: [] }); } - } + }; @action setColumnDesc = (colTitle: string, desc: string) => { const colInfo = this.colsInfo.get(colTitle); if (colInfo) { - if (!desc) { colInfo.desc = this.GPTSummary?.get(colTitle)?.desc ?? ''; } - else { colInfo.desc = desc; } + if (!desc) { + colInfo.desc = this.GPTSummary?.get(colTitle)?.desc ?? ''; + } else { + colInfo.desc = desc; + } } else { - this.colsInfo.set(colTitle, {title: colTitle, desc: desc, type: TemplateFieldType.UNSET, sizes: []}) + this.colsInfo.set(colTitle, { title: colTitle, desc: desc, type: TemplateFieldType.UNSET, sizes: [] }); } - } + }; @action setColumnDefault = (colTitle: string, cont: string) => { const colInfo = this.colsInfo.get(colTitle); if (colInfo) { colInfo.defaultContent = cont; } else { - this.colsInfo.set(colTitle, {title: colTitle, desc: '', type: TemplateFieldType.UNSET, sizes: [], defaultContent: cont}) + this.colsInfo.set(colTitle, { title: colTitle, desc: '', type: TemplateFieldType.UNSET, sizes: [], defaultContent: cont }); } - } + }; @action // pinned / linked anchor doc includes selected rows, graph titles, and graph colors - restoreView = (data: Doc) => { + restoreView = (viewData: Doc) => { // const changedView = data.config_dataViz && this.dataVizView !== data.config_dataViz && (this.layoutDoc._dataViz = data.config_dataViz); // const changedAxes = data.config_dataVizAxes && this.axes.join('') !== StrListCast(data.config_dataVizAxes).join('') && (this.layoutDoc._dataViz_axes = new List<string>(StrListCast(data.config_dataVizAxes))); - this.layoutDoc.dataViz_selectedRows = Field.Copy(data.dataViz_selectedRows); - this.layoutDoc.dataViz_histogram_barColors = Field.Copy(data.dataViz_histogram_barColors); - this.layoutDoc.dataViz_histogram_defaultColor = data.dataViz_histogram_defaultColor; - this.layoutDoc.dataViz_pie_sliceColors = Field.Copy(data.dataViz_pie_sliceColors); + this.layoutDoc.dataViz_selectedRows = Field.Copy(viewData.dataViz_selectedRows); + this.layoutDoc.dataViz_histogram_barColors = Field.Copy(viewData.dataViz_histogram_barColors); + this.layoutDoc.dataViz_histogram_defaultColor = viewData.dataViz_histogram_defaultColor; + this.layoutDoc.dataViz_pie_sliceColors = Field.Copy(viewData.dataViz_pie_sliceColors); Object.keys(this.layoutDoc).forEach(key => { if (key.startsWith('dataViz_histogram_title') || key.startsWith('dataViz_lineChart_title') || key.startsWith('dataViz_pieChart_title')) { - this.layoutDoc['_' + key] = data[key]; + this.layoutDoc['_' + key] = viewData[key]; } }); return true; @@ -354,7 +347,9 @@ export class DataVizBox extends ViewBoxAnnotatableComponent<FieldViewProps>() { componentDidMount() { this._props.setContentViewBox?.(this); - if (!this._urlError) { if (!DataVizBox.dataset.has(CsvCast(this.dataDoc[this.fieldKey]).url.href)) this.fetchData() }; + if (!this._urlError) { + if (!DataVizBox.dataset.has(CsvCast(this.dataDoc[this.fieldKey]).url.href)) this.fetchData(); + } this._disposers.datavis = reaction( () => { if (this.layoutDoc.dataViz_schemaLive === undefined) this.layoutDoc.dataViz_schemaLive = true; @@ -516,14 +511,14 @@ export class DataVizBox extends ViewBoxAnnotatableComponent<FieldViewProps>() { DocCreatorMenu.Instance.toggleDisplay(x, y); DocCreatorMenu.Instance.setDataViz(this); DocCreatorMenu.Instance.setTemplateDocs(this.getPossibleTemplates()); - } + }; - specificContextMenu = (x: number, y: number): void => { + specificContextMenu = (e: React.MouseEvent) => { const cm = ContextMenu.Instance; const options = cm.findByDescription('Options...'); const optionItems = options?.subitems ?? []; optionItems.push({ description: `Analyze with AI`, event: () => this.askGPT(), icon: 'lightbulb' }); - optionItems.push({ description: `Create documents`, event: () => this.openDocCreatorMenu(x, y), icon: 'table-cells' }); + optionItems.push({ description: `Create documents`, event: () => this.openDocCreatorMenu(e.pageX, e.pageY), icon: 'table-cells' }); !options && cm.addItem({ description: 'Options...', subitems: optionItems, icon: 'eye' }); }; @@ -533,19 +528,19 @@ export class DataVizBox extends ViewBoxAnnotatableComponent<FieldViewProps>() { GPTPopup.Instance.createFilteredDoc = this.createFilteredDoc; GPTPopup.Instance.setDataJson(''); GPTPopup.Instance.setMode(GPTPopupMode.DATA); - const data = DataVizBox.dataset.get(CsvCast(this.dataDoc[this.fieldKey]).url.href); - GPTPopup.Instance.setDataJson(JSON.stringify(data)); + const csvdata = DataVizBox.dataset.get(CsvCast(this.dataDoc[this.fieldKey]).url.href); + GPTPopup.Instance.setDataJson(JSON.stringify(csvdata)); GPTPopup.Instance.generateDataAnalysis(); }); getColSummary = (): string => { - let possibleIds: number[] = this.records.map((_, index) => index); + const possibleIds: number[] = this.records.map((_, index) => index); for (let i = possibleIds.length - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)); [possibleIds[i], possibleIds[j]] = [possibleIds[j], possibleIds[i]]; } - + const rowsToCheck = possibleIds.slice(0, Math.min(10, this.records.length)); let prompt: string = 'Col titles: '; @@ -553,37 +548,37 @@ export class DataVizBox extends ViewBoxAnnotatableComponent<FieldViewProps>() { const cols = Array.from(Object.keys(this.records[0])).filter(header => header !== '' && header !== undefined); cols.forEach((col, i) => { - prompt += `Col #${i}: ${col} ------` - }) + prompt += `Col #${i}: ${col} ------`; + }); - prompt += '----------- Rows: ' + prompt += '----------- Rows: '; - rowsToCheck.forEach((row, i) => { - prompt += `Row #${row}: ` + rowsToCheck.forEach(row => { + prompt += `Row #${row}: `; cols.forEach(col => { - prompt += `${col}: ${this.records[row][col]} -----` - }) - }) + prompt += `${col}: ${this.records[row][col]} -----`; + }); + }); return prompt; - } + }; updateColDefaults = () => { - let possibleIds: number[] = this.records.map((_, index) => index); + const possibleIds: number[] = this.records.map((_, index) => index); for (let i = possibleIds.length - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)); [possibleIds[i], possibleIds[j]] = [possibleIds[j], possibleIds[i]]; } - + const rowToCheck = possibleIds[0]; const cols = Array.from(Object.keys(this.records[0])).filter(header => header !== '' && header !== undefined); - cols.forEach(col => { - this.setColumnDefault(col, `${this.records[rowToCheck][col]}`) + cols.forEach(col => { + this.setColumnDefault(col, `${this.records[rowToCheck][col]}`); }); - } + }; updateGPTSummary = async () => { this._GPTLoading = true; @@ -594,15 +589,12 @@ export class DataVizBox extends ViewBoxAnnotatableComponent<FieldViewProps>() { const cols = Array.from(Object.keys(this.records[0])).filter(header => header !== '' && header !== undefined); cols.forEach(col => { - if (!this.colsInfo.get(col)) this.colsInfo.set(col, {title: col, desc: '', sizes: [], type: TemplateFieldType.UNSET}); + if (!this.colsInfo.get(col)) this.colsInfo.set(col, { title: col, desc: '', sizes: [], type: TemplateFieldType.UNSET }); }); try { - const [res1, res2] = await Promise.all([ - gptAPICall(prompt, GPTCallType.VIZSUM), - gptAPICall('Info:' + prompt, GPTCallType.VIZSUM2) - ]); - + const [res1, res2] = await Promise.all([gptAPICall(prompt, GPTCallType.VIZSUM), gptAPICall('Info:' + prompt, GPTCallType.VIZSUM2)]); + if (res1) { this.GPTSummary = new ObservableMap(); const descs: { [col: string]: string } = JSON.parse(res1); @@ -611,10 +603,10 @@ export class DataVizBox extends ViewBoxAnnotatableComponent<FieldViewProps>() { if (!this.colsInfo.get(key)?.desc) this.setColumnDesc(key, val); } } - + if (res2) { !this.GPTSummary && (this.GPTSummary = new ObservableMap()); - const info: { [col: string]: { type: TemplateFieldType, size: TemplateFieldSize } } = JSON.parse(res2); + const info: { [col: string]: { type: TemplateFieldType; size: TemplateFieldSize } } = JSON.parse(res2); for (const [key, val] of Object.entries(info)) { const colSummary = this.GPTSummary.get(key); if (colSummary) { @@ -628,30 +620,29 @@ export class DataVizBox extends ViewBoxAnnotatableComponent<FieldViewProps>() { } catch (err) { console.error(err); } - - } + }; getPossibleTemplates = (): Doc[] => { const linkedDocs: Doc[] = LinkManager.Instance.getAllRelatedLinks(this.Document).map(d => DocCast(LinkManager.getOppositeAnchor(d, this.Document))); const linkedCollections: Doc[] = linkedDocs.filter(doc => doc.type === 'config').map(doc => DocCast(doc.annotationOn)); const isColumnTitle = (title: string): boolean => { const colTitles: string[] = Object.keys(this.records[0]); - for (let i = 0; i < colTitles.length; ++i){ + for (let i = 0; i < colTitles.length; ++i) { if (colTitles[i] === title) { return true; } } return false; - } + }; const isValidTemplate = (collection: Doc) => { const childDocs = DocListCast(collection[Doc.LayoutFieldKey(collection)]); - for (let i = 0; i < childDocs.length; ++i){ + for (let i = 0; i < childDocs.length; ++i) { if (isColumnTitle(String(childDocs[i].title))) return true; } return false; - } + }; return linkedCollections.filter(col => isValidTemplate(col)); - } + }; ApplyTemplateTo = (templateDoc: Doc, target: Doc, targetKey: string, titleTarget: string | undefined) => { if (!Doc.AreProtosEqual(target[targetKey] as Doc, templateDoc)) { @@ -664,14 +655,14 @@ export class DataVizBox extends ViewBoxAnnotatableComponent<FieldViewProps>() { } } return target; - } + }; applyLayout = (templateInfo: DataVizTemplateInfo, docs: Doc[]) => { if (templateInfo.layout.type === LayoutType.Stacked) return; const columns: number = templateInfo.columns; const xGap: number = templateInfo.layout.xMargin; const yGap: number = templateInfo.layout.yMargin; - const repeat: number = templateInfo.layout.repeat; + // const repeat: number = templateInfo.layout.repeat; const startX: number = templateInfo.referencePos.x; const startY: number = templateInfo.referencePos.y; const templWidth = Number(templateInfo.doc._width); @@ -682,8 +673,8 @@ export class DataVizBox extends ViewBoxAnnotatableComponent<FieldViewProps>() { let curX: number = startX; let curY: number = startY; - while (docsChanged < docs.length){ - while (i < columns && docsChanged < docs.length){ + while (docsChanged < docs.length) { + while (i < columns && docsChanged < docs.length) { docs[docsChanged].x = curX; docs[docsChanged].y = curY; curX += templWidth + xGap; @@ -695,27 +686,29 @@ export class DataVizBox extends ViewBoxAnnotatableComponent<FieldViewProps>() { curX = startX; curY += templHeight + yGap; } - } + }; // @action addSavedLayout = (layout: DataVizTemplateLayout) => { // const saved = Cast(this.layoutDoc.dataViz_savedTemplates, listSpec('RefField')); - + // } @action createDocsFromTemplate = (templateInfo: DataVizTemplateInfo) => { if (!templateInfo.doc) return; const mainCollection = this.DocumentView?.().containerViewPath?.().lastElement()?.ComponentView as CollectionFreeFormView; - const fields: string[] = Array.from(Object.keys(this.records[0])); + const fields: string[] = Array.from(Object.keys(this.records[0])); const selectedRows = NumListCast(this.layoutDoc.dataViz_selectedRows); const docs: Doc[] = selectedRows.map(row => { - const values: String[] = []; + const values: string[] = []; fields.forEach(col => values.push(this.records[row][col])); const proto = new Doc(); proto.author = ClientUtils.CurrentUserEmail(); - values.forEach((val, i) => {proto[fields[i]] = val as FieldType}); - + values.forEach((val, i) => { + proto[fields[i]] = val as FieldType; + }); + const target = Doc.MakeDelegate(proto); const targetKey = StrCast(templateInfo.doc!.layout_fieldKey, 'layout'); const applied = this.ApplyTemplateTo(templateInfo.doc!, target, targetKey, templateInfo.doc!.title + `${row}`); @@ -728,7 +721,7 @@ export class DataVizBox extends ViewBoxAnnotatableComponent<FieldViewProps>() { docs.forEach(doc => mainCollection.addDocument(doc)); this.applyLayout(templateInfo, docs); - } + }; /** * creates a new dataviz document filter from this one @@ -783,7 +776,7 @@ export class DataVizBox extends ViewBoxAnnotatableComponent<FieldViewProps>() { transform: `scale(${scale})`, position: 'absolute', }} - onContextMenu={(e) => this.specificContextMenu(e.pageX, e.pageY)} + onContextMenu={this.specificContextMenu} onWheel={e => e.stopPropagation()} ref={this._mainCont}> <div className="datatype-button"> diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx b/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx index ad47b7848..6c649bde3 100644 --- a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx +++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx @@ -28,6 +28,7 @@ import { DataVizBox } from './DataVizBox'; import './DocCreatorMenu.scss'; import { DefaultStyleProvider, returnEmptyDocViewList } from '../../StyleProvider'; import { Transform } from '../../../util/Transform'; +import { IconProp } from '@fortawesome/fontawesome-svg-core'; export enum LayoutType { Stacked = 'stacked', @@ -1621,6 +1622,21 @@ export type Col = { type: TemplateFieldType; defaultContent?: string; }; +export interface FieldOpts { + backgroundColor?: string; + color?: string; + cornerRounding?: number; + borderWidth?: string; + borderColor?: string; + contentXCentering?: 'h-left' | 'h-center' | 'h-right'; + contentYCentering?: 'top' | 'center' | 'bottom'; + opacity?: number; + rotation?: number; + //animation?: boolean; + fontBold?: boolean; + fontTransform?: 'uppercase' | 'lowercase'; + fieldViewType?: 'freeform' | 'stacked'; +} type Field = { tl: [number, number]; @@ -1667,6 +1683,8 @@ type InkDecoration = {}; type TemplateDecorations = Field | InkDecoration; +interface TemplateOpts extends FieldOpts {} + export interface TemplateDocInfos { title: string; height: number; @@ -1676,178 +1694,6 @@ export interface TemplateDocInfos { decorations: Field[]; } -export interface FieldOpts { - backgroundColor?: string; - color?: string; - cornerRounding?: number; - borderWidth?: string; - borderColor?: string; - contentXCentering?: 'h-left' | 'h-center' | 'h-right'; - contentYCentering?: 'top' | 'center' | 'bottom'; - opacity?: number; - rotation?: number; - //animation?: boolean; - fontBold?: boolean; - fontTransform?: 'uppercase' | 'lowercase'; - fieldViewType?: 'freeform' | 'stacked'; -} - -interface TemplateOpts extends FieldOpts {} - -export class FieldUtils { - public static contentFields = (fields: Field[]) => { - let toRet: Field[] = []; - fields.forEach(field => { - if (!field.isDecoration) { - toRet.push(field); - } - toRet = toRet.concat(FieldUtils.contentFields(field.subfields ?? [])); - }); - - return toRet; - }; - - public static calculateFontSize = (contWidth: number, contHeight: number, text: string, uppercase: boolean): number => { - const words: string[] = text.split(/\s+/).filter(Boolean); - - let currFontSize = 1; - let rowsCount = 1; - let currTextHeight = currFontSize * rowsCount * 2; - - while (currTextHeight <= contHeight) { - let wordIndex = 0; - let currentRowWidth = 0; - let wordsInCurrRow = 0; - rowsCount = 1; - - while (wordIndex < words.length) { - const word = words[wordIndex]; - const wordWidth = word.length * currFontSize * 0.5; - //console.log(wordWidth) - - if (currentRowWidth + wordWidth <= contWidth) { - currentRowWidth += wordWidth; - ++wordsInCurrRow; - } else { - if (words.length !== 1 && words.length > wordsInCurrRow) { - rowsCount++; - currentRowWidth = wordWidth; - wordsInCurrRow = 1; - } else { - break; - } - } - - wordIndex++; - } - - currTextHeight = rowsCount * currFontSize * 2; - //console.log(rowsCount, currFontSize, currTextHeight) - - currFontSize += 1; - } - - return currFontSize - 1; - }; - - private static getDimensions = (coords: { tl: [number, number]; br: [number, number] }, parentWidth: number, parentHeight: number): { width: number; height: number; coord: { x: number; y: number } } => { - const l = (coords.tl[0] * parentHeight) / 2; - const t = coords.tl[1] * parentWidth / 2; //prettier-ignore - const r = (coords.br[0] * parentHeight) / 2; - const b = coords.br[1] * parentWidth / 2; //prettier-ignore - const width = r - l; - const height = b - t; - const coord = { x: l, y: t }; - //console.log(coords, parentWidth, parentHeight, height); - return { width, height, coord }; - }; - - public static FreeformField = (coords: { tl: [number, number]; br: [number, number] }, parentWidth: number, parentHeight: number, title: string, content: string, opts: FieldOpts) => { - const { width, height, coord } = FieldUtils.getDimensions(coords, parentWidth, parentHeight); - - const docWithBasicOpts = Docs.Create.FreeformDocument([], { - isDefaultTemplateDoc: true, - _height: height, - _width: width, - title: title, - x: coord.x, - y: coord.y, - backgroundColor: opts.backgroundColor ?? '', - _layout_borderRounding: `${opts.cornerRounding}px` ?? '0px', - borderColor: opts.borderColor, - borderWidth: opts.borderWidth, - opacity: opts.opacity, - hCentering: opts.contentXCentering, - _rotation: opts.rotation, - }); - - return docWithBasicOpts; - }; - - public static TextField = (coords: { tl: [number, number]; br: [number, number] }, parentWidth: number, parentHeight: number, title: string, content: string, opts: FieldOpts) => { - const { width, height, coord } = FieldUtils.getDimensions(coords, parentWidth, parentHeight); - - const bool = true; - - const docWithBasicOpts = Docs.Create.TextDocument(content, { - isDefaultTemplateDoc: true, - _height: height, - _width: width, - title: title, - x: coord.x, - y: coord.y, - _text_fontSize: `${FieldUtils.calculateFontSize(width, height, content, true)}`, - backgroundColor: opts.backgroundColor ?? '', - text_fontColor: opts.color, - contentBold: opts.fontBold, - textTransform: opts.fontTransform, - color: opts.color, - _layout_borderRounding: `${opts.cornerRounding}px` ?? '0px', - borderColor: opts.borderColor, - borderWidth: opts.borderWidth, - opacity: opts.opacity, - hCentering: opts.contentXCentering, - _rotation: opts.rotation, - }); - - docWithBasicOpts._layout_hideScroll = true; - - return docWithBasicOpts; - }; - - public static ImageField = (coords: { tl: [number, number]; br: [number, number] }, parentWidth: number, parentHeight: number, title: string, content: string, opts: FieldOpts) => { - const { width, height, coord } = FieldUtils.getDimensions(coords, parentWidth, parentHeight); - - const doc = Docs.Create.ImageDocument(content, { - isDefaultTemplateDoc: true, - _height: height, - _width: width, - title: title, - x: coord.x, - y: coord.y, - _layout_fitWidth: false, - backgroundColor: opts.backgroundColor ?? '', - _layout_borderRounding: `${opts.cornerRounding}px` ?? '0px', - borderColor: opts.borderColor, - borderWidth: opts.borderWidth, - opacity: opts.opacity, - _rotation: opts.rotation, - }); - - //setTimeout(() => {doc._height = height; doc._width = width}, 10); - - return doc; - }; - - public static CarouselField = (coords: { tl: [number, number]; br: [number, number] }, parentWidth: number, parentHeight: number, title: string, fields: Doc[]) => { - const { width, height, coord } = FieldUtils.getDimensions(coords, parentWidth, parentHeight); - - const doc = Docs.Create.Carousel3DDocument(fields, { _height: height, _width: width, title: title, x: coord.x, y: coord.y, _text_fontSize: `${height / 2}` }); - - return doc; - }; -} - export class TemplateLayouts { public static get allTemplates(): TemplateDocInfos[] { return Object.values(TemplateLayouts).filter(value => typeof value === 'object' && value !== null && 'title' in value) as TemplateDocInfos[]; @@ -2311,55 +2157,205 @@ export class TemplateLayouts { }, ], }; +} + +export class FieldUtils { + public static contentFields = (fields: Field[]) => { + let toRet: Field[] = []; + fields.forEach(field => { + if (!field.isDecoration) { + toRet.push(field); + } + toRet = toRet.concat(FieldUtils.contentFields(field.subfields ?? [])); + }); + + return toRet; + }; + + public static calculateFontSize = (contWidth: number, contHeight: number, text: string, uppercase: boolean): number => { + const words: string[] = text.split(/\s+/).filter(Boolean); + + let currFontSize = 1; + let rowsCount = 1; + let currTextHeight = currFontSize * rowsCount * 2; + + while (currTextHeight <= contHeight) { + let wordIndex = 0; + let currentRowWidth = 0; + let wordsInCurrRow = 0; + rowsCount = 1; + + while (wordIndex < words.length) { + const word = words[wordIndex]; + const wordWidth = word.length * currFontSize * 0.5; + //console.log(wordWidth) + + if (currentRowWidth + wordWidth <= contWidth) { + currentRowWidth += wordWidth; + ++wordsInCurrRow; + } else { + if (words.length !== 1 && words.length > wordsInCurrRow) { + rowsCount++; + currentRowWidth = wordWidth; + wordsInCurrRow = 1; + } else { + break; + } + } + + wordIndex++; + } + + currTextHeight = rowsCount * currFontSize * 2; + //console.log(rowsCount, currFontSize, currTextHeight) + + currFontSize += 1; + } + + return currFontSize - 1; + }; - // public static FourField002: TemplateDocInfos = { - // width: 450, - // height: 600, - // fields: [{ - // tl: [-.6, -.9], - // br: [.6, -.8], - // types: [FieldType.TEXT], - // sizes: [FieldSize.TINY] - // }, { - // tl: [-.9, -.7], - // br: [.9, .2], - // types: [FieldType.TEXT, FieldType.VISUAL], - // sizes: [FieldSize.MEDIUM, FieldSize.LARGE, FieldSize.HUGE] - // }, { - // tl: [-.9, .3], - // br: [-.05, .9], - // types: [FieldType.TEXT], - // sizes: [FieldSize.TINY] - // }, { - // tl: [.05, .3], - // br: [.9, .9], - // types: [FieldType.TEXT, FieldType.VISUAL], - // sizes: [FieldSize.MEDIUM, FieldSize.LARGE, FieldSize.HUGE] - // }] - // }; - - // public static TwoFieldPlusCarousel: TemplateDocInfos = { - // width: 500, - // height: 600, - // fields: [{ - // tl: [-.9, -.99], - // br: [.9, -.7], - // types: [FieldType.TEXT], - // sizes: [FieldSize.TINY] - // }, { - // tl: [-.9, -.65], - // br: [.9, .35], - // types: [], - // sizes: [] - // }, { - // tl: [-.9, .4], - // br: [.9, .95], - // types: [FieldType.TEXT], - // sizes: [FieldSize.TINY] - // }] - // }; + private static getDimensions = (coords: { tl: [number, number]; br: [number, number] }, parentWidth: number, parentHeight: number): { width: number; height: number; coord: { x: number; y: number } } => { + const l = (coords.tl[0] * parentHeight) / 2; + const t = coords.tl[1] * parentWidth / 2; //prettier-ignore + const r = (coords.br[0] * parentHeight) / 2; + const b = coords.br[1] * parentWidth / 2; //prettier-ignore + const width = r - l; + const height = b - t; + const coord = { x: l, y: t }; + //console.log(coords, parentWidth, parentHeight, height); + return { width, height, coord }; + }; + + public static FreeformField = (coords: { tl: [number, number]; br: [number, number] }, parentWidth: number, parentHeight: number, title: string, content: string, opts: FieldOpts) => { + const { width, height, coord } = FieldUtils.getDimensions(coords, parentWidth, parentHeight); + + const docWithBasicOpts = Docs.Create.FreeformDocument([], { + isDefaultTemplateDoc: true, + _height: height, + _width: width, + title: title, + x: coord.x, + y: coord.y, + backgroundColor: opts.backgroundColor ?? '', + _layout_borderRounding: `${opts.cornerRounding ?? 0}px`, + borderColor: opts.borderColor, + borderWidth: opts.borderWidth, + opacity: opts.opacity, + hCentering: opts.contentXCentering, + _rotation: opts.rotation, + }); + + return docWithBasicOpts; + }; + + public static TextField = (coords: { tl: [number, number]; br: [number, number] }, parentWidth: number, parentHeight: number, title: string, content: string, opts: FieldOpts) => { + const { width, height, coord } = FieldUtils.getDimensions(coords, parentWidth, parentHeight); + + const docWithBasicOpts = Docs.Create.TextDocument(content, { + isDefaultTemplateDoc: true, + _height: height, + _width: width, + title: title, + x: coord.x, + y: coord.y, + _text_fontSize: `${FieldUtils.calculateFontSize(width, height, content, true)}`, + backgroundColor: opts.backgroundColor ?? '', + text_fontColor: opts.color, + contentBold: opts.fontBold, + textTransform: opts.fontTransform, + color: opts.color, + _layout_borderRounding: `${opts.cornerRounding ?? 0}px`, + borderColor: opts.borderColor, + borderWidth: opts.borderWidth, + opacity: opts.opacity, + hCentering: opts.contentXCentering, + _rotation: opts.rotation, + }); + + docWithBasicOpts._layout_hideScroll = true; + + return docWithBasicOpts; + }; + + public static ImageField = (coords: { tl: [number, number]; br: [number, number] }, parentWidth: number, parentHeight: number, title: string, content: string, opts: FieldOpts) => { + const { width, height, coord } = FieldUtils.getDimensions(coords, parentWidth, parentHeight); + + const doc = Docs.Create.ImageDocument(content, { + isDefaultTemplateDoc: true, + _height: height, + _width: width, + title: title, + x: coord.x, + y: coord.y, + _layout_fitWidth: false, + backgroundColor: opts.backgroundColor ?? '', + _layout_borderRounding: `${opts.cornerRounding ?? 0}px`, + borderColor: opts.borderColor, + borderWidth: opts.borderWidth, + opacity: opts.opacity, + _rotation: opts.rotation, + }); + + //setTimeout(() => {doc._height = height; doc._width = width}, 10); + + return doc; + }; + + public static CarouselField = (coords: { tl: [number, number]; br: [number, number] }, parentWidth: number, parentHeight: number, title: string, fields: Doc[]) => { + const { width, height, coord } = FieldUtils.getDimensions(coords, parentWidth, parentHeight); + + const doc = Docs.Create.Carousel3DDocument(fields, { _height: height, _width: width, title: title, x: coord.x, y: coord.y, _text_fontSize: `${height / 2}` }); + + return doc; + }; } -// export class ContentField extends Field { - -// } +// public static FourField002: TemplateDocInfos = { +// width: 450, +// height: 600, +// fields: [{ +// tl: [-.6, -.9], +// br: [.6, -.8], +// types: [FieldType.TEXT], +// sizes: [FieldSize.TINY] +// }, { +// tl: [-.9, -.7], +// br: [.9, .2], +// types: [FieldType.TEXT, FieldType.VISUAL], +// sizes: [FieldSize.MEDIUM, FieldSize.LARGE, FieldSize.HUGE] +// }, { +// tl: [-.9, .3], +// br: [-.05, .9], +// types: [FieldType.TEXT], +// sizes: [FieldSize.TINY] +// }, { +// tl: [.05, .3], +// br: [.9, .9], +// types: [FieldType.TEXT, FieldType.VISUAL], +// sizes: [FieldSize.MEDIUM, FieldSize.LARGE, FieldSize.HUGE] +// }] +// }; + +// public static TwoFieldPlusCarousel: TemplateDocInfos = { +// width: 500, +// height: 600, +// fields: [{ +// tl: [-.9, -.99], +// br: [.9, -.7], +// types: [FieldType.TEXT], +// sizes: [FieldSize.TINY] +// }, { +// tl: [-.9, -.65], +// br: [.9, .35], +// types: [], +// sizes: [] +// }, { +// tl: [-.9, .4], +// br: [.9, .95], +// types: [FieldType.TEXT], +// sizes: [FieldSize.TINY] +// }] +// }; +// } + diff --git a/src/client/views/nodes/DataVizBox/components/TableBox.tsx b/src/client/views/nodes/DataVizBox/components/TableBox.tsx index 6cc773da0..fe596bc36 100644 --- a/src/client/views/nodes/DataVizBox/components/TableBox.tsx +++ b/src/client/views/nodes/DataVizBox/components/TableBox.tsx @@ -1,5 +1,3 @@ -/* eslint-disable jsx-a11y/no-noninteractive-tabindex */ -/* eslint-disable jsx-a11y/no-static-element-interactions */ import { Button, Colors, Type } from 'browndash-components'; import { IReactionDisposer, action, computed, makeObservable, observable, reaction, runInAction } from 'mobx'; import { observer } from 'mobx-react'; @@ -18,6 +16,7 @@ import { DocumentView } from '../../DocumentView'; import { DataVizView } from '../DataVizBox'; import './Chart.scss'; +// eslint-disable-next-line @typescript-eslint/no-require-imports const { DATA_VIZ_TABLE_ROW_HEIGHT } = require('../../../global/globalCssVariables.module.scss'); // prettier-ignore interface TableBoxProps { @@ -416,7 +415,7 @@ export class TableBox extends ObservableReactComponent<TableBoxProps> { ? 'darkred' : this._props.axes.length > 3 && this._props.axes[1] === col ? 'darkblue' - : this._props.axes.lastElement() === col || (this._props.axes.length > 3 && this._props.axes[2] === col) + : this._props.axes.lastElement() === col || (this._props.axes.length > 3 && this._props.axes[2] === col) ? 'darkcyan' : undefined, background: this.settingTitle @@ -427,7 +426,7 @@ export class TableBox extends ObservableReactComponent<TableBoxProps> { ? '#Fbdbdb' : this._props.axes.lastElement() === col || (this._props.axes.length > 2 && this._props.axes[1] === col) ? '#c6ebf7' - : this._props.axes.lastElement() === col || (this._props.axes.length > 3 && this._props.axes[2] === col) + : this._props.axes.lastElement() === col || (this._props.axes.length > 3 && this._props.axes[2] === col) ? '#c2f0f4' : undefined, fontWeight: 'bolder', @@ -448,8 +447,15 @@ export class TableBox extends ObservableReactComponent<TableBoxProps> { className={`tableBox-row ${this.columns[0]}`} onClick={e => this.tableRowClick(e, rowId)} style={{ - background: rowId === this._props.specHighlightedRow ? 'lightblue' : NumListCast(this._props.layoutDoc.dataViz_highlitedRows).includes(rowId) ? 'lightYellow' : NumListCast(this._props.layoutDoc.dataViz_selectedRows).includes(rowId) ? 'lightgrey' : '', - border: rowId === this._props.specHighlightedRow ? `solid 3px ${Colors.MEDIUM_BLUE}` : '' + background: + rowId === this._props.specHighlightedRow + ? 'lightblue' + : NumListCast(this._props.layoutDoc.dataViz_highlitedRows).includes(rowId) + ? 'lightYellow' + : NumListCast(this._props.layoutDoc.dataViz_selectedRows).includes(rowId) + ? 'lightgrey' + : '', + border: rowId === this._props.specHighlightedRow ? `solid 3px ${Colors.MEDIUM_BLUE}` : '', }}> {this.columns.map(col => { let colSelected = false; diff --git a/src/client/views/nodes/DocumentIcon.tsx b/src/client/views/nodes/DocumentIcon.tsx index 0b94ae4f7..9769ecb3d 100644 --- a/src/client/views/nodes/DocumentIcon.tsx +++ b/src/client/views/nodes/DocumentIcon.tsx @@ -1,5 +1,5 @@ import { Tooltip } from '@mui/material'; -import { action, makeObservable, observable } from 'mobx'; +import { makeObservable, observable } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; import { factory } from 'typescript'; @@ -18,14 +18,14 @@ interface DocumentIconProps { @observer export class DocumentIcon extends ObservableReactComponent<DocumentIconProps> { @observable _hovered = false; - constructor(props: any) { + constructor(props: DocumentIconProps) { super(props); makeObservable(this); } render() { const { view } = this._props; - const { left, top, right, bottom } = view.getBounds || { left: 0, top: 0, right: 0, bottom: 0 }; + const { left, top, bottom } = view.getBounds || { left: 0, top: 0, right: 0, bottom: 0 }; return ( <div @@ -34,7 +34,7 @@ export class DocumentIcon extends ObservableReactComponent<DocumentIconProps> { pointerEvents: 'all', position: 'absolute', background: SnappingManager.userBackgroundColor, - transform: `translate(${left}px, ${bottom - (bottom - top)/2}px)`, //**!** + transform: `translate(${left}px, ${bottom - (bottom - top) / 2}px)`, //**!** }}> <Tooltip title={<div>{StrCast(this._props.view.Document?.title)}</div>}> <p>d{this._props.index}</p> @@ -44,7 +44,7 @@ export class DocumentIcon extends ObservableReactComponent<DocumentIconProps> { } } -@observer +@observer export class DocumentIconContainer extends React.Component { public static getTransformer(): Transformer { const usedDocuments = new Set<number>(); diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 4a249838b..428fe5acb 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -1161,7 +1161,7 @@ export class DocumentView extends DocComponent<DocumentViewProps>() { return Math.max(minTextScale, this._props.PanelHeight() / (this.effectiveNativeHeight || 1)); // height-limited or unscaled } @computed private get panelWidth() { - return this.effectiveNativeWidth ? this.effectiveNativeWidth * this.nativeScaling: this._props.PanelWidth(); + return this.effectiveNativeWidth ? this.effectiveNativeWidth * this.nativeScaling : this._props.PanelWidth(); } @computed private get panelHeight() { if (this.effectiveNativeHeight && (!this.layout_fitWidth || !this.layoutDoc.layout_reflowVertical)) { @@ -1207,6 +1207,7 @@ export class DocumentView extends DocComponent<DocumentViewProps>() { public set IsSelected(val) { runInAction(() => { this._selected = val; }); } // prettier-ignore public get IsSelected() { return this._selected; } // prettier-ignore + public get IsContentActive(){ return this._docViewInternal?.isContentActive(); } // prettier-ignore public get topMost() { return this._props.renderDepth === 0; } // prettier-ignore public get ContentDiv() { return this._docViewInternal?._contentDiv; } // prettier-ignore public get ComponentView() { return this._docViewInternal?._componentView; } // prettier-ignore @@ -1472,7 +1473,6 @@ export class DocumentView extends DocComponent<DocumentViewProps>() { render() { TraceMobx(); - const borderWidth = 50/*Number(StrCast(this.layoutDoc.layout_borderWidth).replace('px', ''))*/; const xshift = Math.abs(this.Xshift) <= 0.001 ? this._props.PanelWidth() : undefined; const yshift = Math.abs(this.Yshift) <= 0.001 ? this._props.PanelHeight() : undefined; diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx index a0d69d29d..741d63909 100644 --- a/src/client/views/nodes/FieldView.tsx +++ b/src/client/views/nodes/FieldView.tsx @@ -6,7 +6,6 @@ import { DateField } from '../../../fields/DateField'; import { Doc, Field, FieldType, Opt } from '../../../fields/Doc'; import { List } from '../../../fields/List'; import { ScriptField } from '../../../fields/ScriptField'; -import { WebField } from '../../../fields/URLField'; import { dropActionType } from '../../util/DropActionTypes'; import { Transform } from '../../util/Transform'; import { PinProps } from '../PinFuncs'; @@ -14,9 +13,9 @@ import { ViewBoxInterface } from '../ViewBoxInterface'; import { DocumentView } from './DocumentView'; import { FocusViewOptions } from './FocusViewOptions'; import { OpenWhere } from './OpenWhere'; +import { WebField } from '../../../fields/URLField'; export type FocusFuncType = (doc: Doc, options: FocusViewOptions) => Opt<number>; -// eslint-disable-next-line no-use-before-define export type StyleProviderFuncType = ( doc: Opt<Doc>, // eslint-disable-next-line no-use-before-define @@ -139,7 +138,7 @@ export class FieldView extends React.Component<FieldViewProps> { const field = this.fieldval; // prettier-ignore if (field instanceof Doc) return <p> <b>{field.title?.toString()}</b></p>; - if (field === undefined) return <p>{''}</p>; + if (field === undefined) return <p />; if (field instanceof DateField) return <p>{field.date.toLocaleString()}</p>; if (field instanceof List) return <div> {field.map(f => Field.toString(f)).join(', ')} </div>; if (field instanceof WebField) return <p>{Field.toString(field.url.href)}</p>; diff --git a/src/client/views/nodes/LabelBox.tsx b/src/client/views/nodes/LabelBox.tsx index cfcf76b12..8974cccaf 100644 --- a/src/client/views/nodes/LabelBox.tsx +++ b/src/client/views/nodes/LabelBox.tsx @@ -2,7 +2,7 @@ import { Property } from 'csstype'; import { action, computed, makeObservable } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; -//import * as textfit from 'textfit'; +import * as textfit from 'textfit'; import { Field, FieldType } from '../../../fields/Doc'; import { BoolCast, NumCast, StrCast } from '../../../fields/Types'; import { TraceMobx } from '../../../fields/util'; @@ -96,7 +96,7 @@ export class LabelBox extends ViewBoxBaseComponent<FieldViewProps>() { this._timeout = setTimeout(() => this.fitTextToBox(r)); return textfitParams; } - //textfit(r, textfitParams); + textfit(r, textfitParams); } return textfitParams; }; diff --git a/src/client/views/nodes/calendarBox/CalendarBox.tsx b/src/client/views/nodes/calendarBox/CalendarBox.tsx index 678b7dd0b..d38cb5423 100644 --- a/src/client/views/nodes/calendarBox/CalendarBox.tsx +++ b/src/client/views/nodes/calendarBox/CalendarBox.tsx @@ -1,4 +1,4 @@ -import { Calendar, DateInput, EventClickArg, EventSourceInput } from '@fullcalendar/core'; +import { Calendar, EventClickArg, EventSourceInput } from '@fullcalendar/core'; import dayGridPlugin from '@fullcalendar/daygrid'; import multiMonthPlugin from '@fullcalendar/multimonth'; import timeGrid from '@fullcalendar/timegrid'; diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index 730c57794..0d7914a82 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -1195,6 +1195,10 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB if (nh) this.layoutDoc._nativeHeight = scrollHeight; }; + @computed get tagsHeight() { + return this.DocumentView?.().showTags ? Math.max(0, 20 - Math.max(this._props.yPadding ?? 0, NumCast(this.layoutDoc._yMargin))) * this.ScreenToLocalBoxXf().Scale : 0; + } + @computed get contentScaling() { return Doc.NativeAspect(this.Document, this.dataDoc, false) ? this._props.NativeDimScaling?.() || 1 : 1; } @@ -1222,9 +1226,9 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB ); this._disposers.componentHeights = reaction( // set the document height when one of the component heights changes and layout_autoHeight is on - () => ({ sidebarHeight: this.sidebarHeight, textHeight: this.textHeight, layoutAutoHeight: this.layout_autoHeight, marginsHeight: this.layout_autoHeightMargins }), - ({ sidebarHeight, textHeight, layoutAutoHeight, marginsHeight }) => { - const newHeight = this.contentScaling * (marginsHeight + Math.max(sidebarHeight, textHeight)); + () => ({ sidebarHeight: this.sidebarHeight, textHeight: this.textHeight, layoutAutoHeight: this.layout_autoHeight, marginsHeight: this.layout_autoHeightMargins, tagsHeight: this.tagsHeight }), + ({ sidebarHeight, textHeight, layoutAutoHeight, marginsHeight, tagsHeight }) => { + const newHeight = this.contentScaling * (tagsHeight + marginsHeight + Math.max(sidebarHeight, textHeight)); if ( (!Array.from(FormattedTextBox._globalHighlights).includes('Bold Text') || this._props.isSelected()) && // layoutAutoHeight && @@ -1494,7 +1498,6 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB pdfAnchorId && this.addPdfReference(pdfAnchorId); } if (this._props.autoFocus) setTimeout(() => this._editorView!.focus()); // not sure why setTimeout is needed but editing dashFieldView's doesn't work without it. - } // 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. @@ -2005,8 +2008,8 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB const scale = this._props.NativeDimScaling?.() || 1; 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 paddingX = Math.max(this._props.xPadding ?? 0, NumCast(this.layoutDoc._xMargin)); + const paddingY = Math.max(this._props.yPadding ?? 0, NumCast(this.layoutDoc._yMargin)); const styleFromLayout = styleFromLayoutString(this.Document, this._props, scale); // this converts any expressions in the format string to style props. e.g., <FormattedTextBox height='{this._header_height}px' > return styleFromLayout?.height === '0px' ? null : ( <div @@ -2025,6 +2028,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB height: `${100 / scale}%`, }), transition: 'inherit', + paddingBottom: this.tagsHeight, // overflowY: this.layoutDoc._layout_autoHeight ? "hidden" : undefined, color: this.fontColor, fontSize: this.fontSize, @@ -2082,7 +2086,6 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB </div> </div> ); - } } |
