diff options
-rw-r--r-- | src/client/views/MainView.tsx | 2 | ||||
-rw-r--r-- | src/client/views/nodes/DataVizBox/DataVizBox.tsx | 2 | ||||
-rw-r--r-- | src/client/views/nodes/DataVizBox/DocCreatorMenu/DocCreatorMenu.scss (renamed from src/client/views/nodes/DataVizBox/DocCreatorMenu.scss) | 2 | ||||
-rw-r--r-- | src/client/views/nodes/DataVizBox/DocCreatorMenu/DocCreatorMenu.tsx (renamed from src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx) | 315 | ||||
-rw-r--r-- | src/client/views/nodes/DataVizBox/DocCreatorMenu/FieldTypes.tsx | 159 |
5 files changed, 303 insertions, 177 deletions
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index fc159d96b..6ee42d256 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -58,7 +58,7 @@ import { ImageLabelHandler } from './collections/collectionFreeForm/ImageLabelHa import { MarqueeOptionsMenu } from './collections/collectionFreeForm/MarqueeOptionsMenu'; import { CollectionLinearView } from './collections/collectionLinear'; import { LinkMenu } from './linking/LinkMenu'; -import { DocCreatorMenu } from './nodes/DataVizBox/DocCreatorMenu'; +import { DocCreatorMenu } from './nodes/DataVizBox/DocCreatorMenu/DocCreatorMenu'; import { SchemaCSVPopUp } from './nodes/DataVizBox/SchemaCSVPopUp'; import { DocButtonState } from './nodes/DocumentLinksButton'; import { DocumentView, DocumentViewInternal } from './nodes/DocumentView'; diff --git a/src/client/views/nodes/DataVizBox/DataVizBox.tsx b/src/client/views/nodes/DataVizBox/DataVizBox.tsx index 896048ab3..1243831c8 100644 --- a/src/client/views/nodes/DataVizBox/DataVizBox.tsx +++ b/src/client/views/nodes/DataVizBox/DataVizBox.tsx @@ -32,7 +32,7 @@ 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 { Col, DataVizTemplateInfo, DocCreatorMenu, LayoutType, TemplateFieldSize, TemplateFieldType } from './DocCreatorMenu/DocCreatorMenu'; import { Histogram } from './components/Histogram'; import { LineChart } from './components/LineChart'; import { PieChart } from './components/PieChart'; diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss b/src/client/views/nodes/DataVizBox/DocCreatorMenu/DocCreatorMenu.scss index 4ea904b8e..4f5397cdb 100644 --- a/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss +++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu/DocCreatorMenu.scss @@ -7,7 +7,7 @@ .docCreatorMenu-cont { position: absolute; - z-index: 100000; + z-index: 1000; // box-shadow: 0px 3px 4px rgba(0, 0, 0, 30%); // background: whitesmoke; // color: black; diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx b/src/client/views/nodes/DataVizBox/DocCreatorMenu/DocCreatorMenu.tsx index 6c649bde3..91c86bef1 100644 --- a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx +++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu/DocCreatorMenu.tsx @@ -5,29 +5,29 @@ import { observer } from 'mobx-react'; import { IDisposer } from 'mobx-utils'; import * as React from 'react'; import ReactLoading from 'react-loading'; -import { ClientUtils, returnEmptyFilter, returnFalse, returnTrue, setupMoveUpEvents } from '../../../../ClientUtils'; -import { emptyFunction } from '../../../../Utils'; -import { Doc, NumListCast, StrListCast, returnEmptyDoclist } from '../../../../fields/Doc'; -import { Id } from '../../../../fields/FieldSymbols'; -import { Cast, DocCast, ImageCast, StrCast } from '../../../../fields/Types'; -import { ImageField } from '../../../../fields/URLField'; -import { Networking } from '../../../Network'; -import { GPTCallType, gptAPICall, gptImageCall } from '../../../apis/gpt/GPT'; -import { Docs } from '../../../documents/Documents'; -import { DragManager } from '../../../util/DragManager'; -import { MakeTemplate } from '../../../util/DropConverter'; -import { SnappingManager } from '../../../util/SnappingManager'; -import { UndoManager, undoable } from '../../../util/UndoManager'; -import { LightboxView } from '../../LightboxView'; -import { ObservableReactComponent } from '../../ObservableReactComponent'; -import { CollectionFreeFormView } from '../../collections/collectionFreeForm/CollectionFreeFormView'; -import { DocumentView, DocumentViewInternal } from '../DocumentView'; -import { FieldViewProps } from '../FieldView'; -import { OpenWhere } from '../OpenWhere'; -import { DataVizBox } from './DataVizBox'; +import { ClientUtils, returnEmptyFilter, returnFalse, returnTrue, setupMoveUpEvents } from '../../../../../ClientUtils'; +import { emptyFunction } from '../../../../../Utils'; +import { Doc, FieldType, NumListCast, StrListCast, returnEmptyDoclist } from '../../../../../fields/Doc'; +import { Id } from '../../../../../fields/FieldSymbols'; +import { Cast, DocCast, ImageCast, StrCast } from '../../../../../fields/Types'; +import { ImageField } from '../../../../../fields/URLField'; +import { Networking } from '../../../../Network'; +import { GPTCallType, gptAPICall, gptImageCall } from '../../../../apis/gpt/GPT'; +import { Docs, DocumentOptions } from '../../../../documents/Documents'; +import { DragManager } from '../../../../util/DragManager'; +import { MakeTemplate } from '../../../../util/DropConverter'; +import { SnappingManager } from '../../../../util/SnappingManager'; +import { UndoManager, undoable } from '../../../../util/UndoManager'; +import { LightboxView } from '../../../LightboxView'; +import { ObservableReactComponent } from '../../../ObservableReactComponent'; +import { CollectionFreeFormView } from '../../../collections/collectionFreeForm/CollectionFreeFormView'; +import { DocumentView, DocumentViewInternal } from '../../DocumentView'; +import { FieldViewProps } from '../../FieldView'; +import { OpenWhere } from '../../OpenWhere'; +import { DataVizBox } from '../DataVizBox'; import './DocCreatorMenu.scss'; -import { DefaultStyleProvider, returnEmptyDocViewList } from '../../StyleProvider'; -import { Transform } from '../../../util/Transform'; +import { DefaultStyleProvider, returnEmptyDocViewList } from '../../../StyleProvider'; +import { Transform } from '../../../../util/Transform'; import { IconProp } from '@fortawesome/fontawesome-svg-core'; export enum LayoutType { @@ -545,7 +545,7 @@ export class DocCreatorMenu extends ObservableReactComponent<FieldViewProps> { }; matchesForTemplate = (template: TemplateDocInfos, cols: Col[]): number[][] => { - const colMatchesField = (col: Col, field: Field) => { + const colMatchesField = (col: Col, field: FieldSettings) => { return field.sizes?.some(size => col.sizes?.includes(size)) && field.types?.includes(col.type); }; @@ -669,7 +669,7 @@ export class DocCreatorMenu extends ObservableReactComponent<FieldViewProps> { const assignments: { [title: string]: { number: string; content: string } } = JSON.parse(res); //console.log('assignments', GPTAssignments, 'assignment string', GPTAssignmentString, 'field content', fieldContent, 'response', res, 'assignments', assignments); Object.entries(assignments).forEach(([title, info]) => { - const field: Field = template.fields[Number(info.number)]; + const field: FieldSettings = template.fields[Number(info.number)]; const col = this.getColByTitle(title); const doc = FieldUtils.TextField( @@ -697,7 +697,7 @@ export class DocCreatorMenu extends ObservableReactComponent<FieldViewProps> { const createGeneratedImage = async (fieldNum: string, col: Col, prompt: string) => { const url = await this.generateGPTImage(prompt); - const field: Field = template.fields[Number(fieldNum)]; + const field: FieldSettings = template.fields[Number(fieldNum)]; const doc = FieldUtils.ImageField( { tl: field.tl, @@ -764,7 +764,7 @@ export class DocCreatorMenu extends ObservableReactComponent<FieldViewProps> { let fieldContent: string = ''; Object.entries(nonGPTAssignments).forEach(([f, strCol]) => { - const field: Field = template.fields[Number(f)]; + const field: FieldSettings = template.fields[Number(f)]; const col = strCol[1]; const doc = (col.type === TemplateFieldType.VISUAL ? FieldUtils.ImageField : FieldUtils.TextField)( @@ -944,7 +944,7 @@ export class DocCreatorMenu extends ObservableReactComponent<FieldViewProps> { removeDocument={returnFalse} PanelWidth={() => this._menuDimensions.width - 10} PanelHeight={() => this._menuDimensions.height - 60} - ScreenToLocalTransform={() => new Transform(-this._pageX,-this._pageY, 1)} + ScreenToLocalTransform={() => new Transform(-this._pageX - 5,-this._pageY - 35, 1)} renderDepth={5} whenChildContentsActiveChanged={emptyFunction} focus={emptyFunction} @@ -1493,13 +1493,13 @@ export class DocCreatorMenu extends ObservableReactComponent<FieldViewProps> { return [ <div className='docCreatorMenu-resizer top' onPointerDown={this.onResizePointerDown} style={{width: width, left: 0, top: -7}}/>, - <div className='docCreatorMenu-resizer right' onPointerDown={this.onResizePointerDown} style={{height: height, left: width - 3, top: 0}}/>, - <div className='docCreatorMenu-resizer bottom' onPointerDown={this.onResizePointerDown} style={{width: width, left: 0, top: height - 3}}/>, <div className='docCreatorMenu-resizer left' onPointerDown={this.onResizePointerDown} style={{height: height, left: -7, top: 0}}/>, - <div className='docCreatorMenu-resizer topRight' onPointerDown={this.onResizePointerDown} style={{left: width - 5, top: -10, cursor: 'nesw-resize'}}/>, + <div className='docCreatorMenu-resizer right' onPointerDown={this.onResizePointerDown} style={{height: height, left: width - 3, top: 0}}/>, + <div className='docCreatorMenu-resizer bottom' onPointerDown={this.onResizePointerDown} style={{width: width, left: 0, top: height - 3}}/>, <div className='docCreatorMenu-resizer topLeft' onPointerDown={this.onResizePointerDown} style={{left: -10, top: -10, cursor: 'nwse-resize'}}/>, + <div className='docCreatorMenu-resizer topRight' onPointerDown={this.onResizePointerDown} style={{left: width - 5, top: -10, cursor: 'nesw-resize'}}/>, + <div className='docCreatorMenu-resizer bottomLeft' onPointerDown={this.onResizePointerDown} style={{left: -10, top: height - 5, cursor: 'nesw-resize'}}/>, <div className='docCreatorMenu-resizer bottomRight' onPointerDown={this.onResizePointerDown} style={{left: width - 5, top: height - 5, cursor: 'nwse-resize'}}/>, - <div className='docCreatorMenu-resizer bottomLeft' onPointerDown={this.onResizePointerDown} style={{left: -10, top: height - 5, cursor: 'nesw-resize'}}/> ]; //prettier-ignore } @@ -1638,50 +1638,115 @@ export interface FieldOpts { fieldViewType?: 'freeform' | 'stacked'; } -type Field = { +type FieldSettings = { tl: [number, number]; br: [number, number]; opts: FieldOpts; subfields?: Field[]; types?: TemplateFieldType[]; sizes?: TemplateFieldSize[]; - isDecoration?: boolean; description?: string; }; -// class ContentField implements Field { -// tl: [number, number]; -// br: [number, number]; -// opts: FieldOpts; -// subfields?: Field[]; -// types?: TemplateFieldType[]; -// sizes?: TemplateFieldSize[]; -// description?: string; - -// constructor( tl: [number, number], br: [number, number], -// opts: FieldOpts, subfields?: Field[], -// types?: TemplateFieldType[], -// sizes?: TemplateFieldSize[], -// description?: string) { -// this.tl = tl; -// this.br = br; -// this.opts = opts; -// this.subfields = subfields; -// this.types = types; -// this.sizes = sizes; -// this.description = description; -// } - -// render = (content: any): Doc => { -// return new Doc; -// } -// } - -type DecorationField = Field; +interface ConstructedField { + renderToDoc: (content: FieldType, doc: Doc) => Doc; + validSubfieldGroups: () => Field[]; +} + +class Field { + settings: FieldSettings; + parent: Field; + + constructor(settings: FieldSettings, parent: Field, ) { + this.settings = settings; + this.parent = parent; + } + + private 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; + + currFontSize += 1; + } + + return currFontSize - 1; + }; + + private 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 }; + return { width, height, coord }; + }; + + private docWithBasicOpts = (factory: (children: unknown, options: DocumentOptions) => Doc, settings: FieldSettings): Doc => { + const x = settings.tl[0]; + const y = settings.tl[1]; + const height = settings. + return factory([], {...}) + } +} + +class TextField implements Field { + settings: FieldSettings; + parent: Field; + + constructor(settings: FieldSettings, parent: Field) { + this.settings = settings; + this.parent = parent; + } + + renderToDoc = (content: FieldType, doc: Doc): Doc => { + + return new Doc; + } + + validSubfieldGroups = () => { + return []; + } +} + +type DecorationField = FieldSettings; type InkDecoration = {}; -type TemplateDecorations = Field | InkDecoration; +type TemplateDecorations = FieldSettings | InkDecoration; interface TemplateOpts extends FieldOpts {} @@ -1690,8 +1755,8 @@ export interface TemplateDocInfos { height: number; width: number; opts: TemplateOpts; - fields: Field[]; - decorations: Field[]; + fields: FieldSettings[]; + decorations: FieldSettings[]; } export class TemplateLayouts { @@ -1889,66 +1954,6 @@ export class TemplateLayouts { ], }; - // public static FourField003: TemplateDocInfos = { - // title: 'fourfield3', - // width: 477, - // height: 662, - // opts: { - // backgroundColor: '#9E9C95' - // }, - // fields: [{ - // tl: [-.875, -.9], - // br: [.875, .7], - // types: [TemplateFieldType.VISUAL], - // sizes: [TemplateFieldSize.LARGE, TemplateFieldSize.HUGE], - // description: '', - // opts: { - // borderWidth: '15', - // borderColor: '#E0E0DA', - // } - // }, { - // tl: [-.95, .8], - // br: [-.1, .95], - // types: [TemplateFieldType.TEXT], - // sizes: [TemplateFieldSize.TINY, TemplateFieldSize.SMALL], - // description: '', - // opts: { - // backgroundColor: 'transparent', - // color: 'white', - // contentXCentering: 'h-right', - // } - // }, { - // tl: [.1, .8], - // br: [.95, .95], - // types: [TemplateFieldType.TEXT], - // sizes: [TemplateFieldSize.TINY, TemplateFieldSize.SMALL], - // description: '', - // opts: { - // backgroundColor: 'transparent', - // color: 'red', - // fontTransform: 'uppercase', - // contentXCentering: 'h-left' - // } - // }, { - // tl: [0, -.9], - // br: [.85, -.66], - // types: [TemplateFieldType.TEXT, TemplateFieldType.VISUAL], - // sizes: [TemplateFieldSize.MEDIUM, TemplateFieldSize.LARGE, TemplateFieldSize.HUGE], - // description: '', - // opts: { - // backgroundColor: 'transparent', - // contentXCentering: 'h-right' - // } - // }], - // decorations: [{ - // tl: [-.025, .8], - // br: [.025, .95], - // opts: { - // backgroundColor: '#E0E0DA', - // } - // }] - // }; - public static FourField004: TemplateDocInfos = { title: 'fourfield4', width: 414, @@ -2160,8 +2165,8 @@ export class TemplateLayouts { } export class FieldUtils { - public static contentFields = (fields: Field[]) => { - let toRet: Field[] = []; + public static contentFields = (fields: FieldSettings[]) => { + let toRet: FieldSettings[] = []; fields.forEach(field => { if (!field.isDecoration) { toRet.push(field); @@ -2227,9 +2232,18 @@ export class FieldUtils { return { width, height, coord }; }; + public static docWithBasicOpts = (factory: (children: unknown, options: DocumentOptions) => Doc, settings: FieldSettings): Doc => { + const x = settings.tl[0]; + const y = settings.tl[1]; + const height = settings. + return factory([], {...}) + } + 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, @@ -2311,51 +2325,4 @@ export class FieldUtils { }; } -// 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/DocCreatorMenu/FieldTypes.tsx b/src/client/views/nodes/DataVizBox/DocCreatorMenu/FieldTypes.tsx new file mode 100644 index 000000000..56902ef14 --- /dev/null +++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu/FieldTypes.tsx @@ -0,0 +1,159 @@ +import { Doc } from "../../../../../fields/Doc"; +import { FieldType } from "../../../../../fields/ObjectField"; +import { Docs, DocumentOptions } from "../../../../documents/Documents"; +import { TemplateFieldSize, TemplateFieldType } from "./DocCreatorMenu"; + +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 FieldSettings = { + tl: [number, number]; + br: [number, number]; + opts: FieldOpts; + subfields?: Field[]; + types?: TemplateFieldType[]; + sizes?: TemplateFieldSize[]; + description?: string; +}; + +interface ConstructedField { + renderedDoc: () => Doc; + validSubfieldGroups: () => Field[]; + setContent: (newContent: any) => void; + getContent: () => any; +} + +class Field { + settings: FieldSettings; + parent: Field; + dimensions: { width: number; height: number; coord: { x: number; y: number }}; + + constructor(settings: FieldSettings, parent: Field) { + this.settings = settings; + this.parent = parent; + this.dimensions = this.parent.getChildDimensions({tl: settings.tl, br: settings.br}); + } + + 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; + + 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; + + currFontSize += 1; + } + + return currFontSize - 1; + }; + + getChildDimensions = (coords: { tl: [number, number]; br: [number, number] }): { width: number; height: number; coord: { x: number; y: number } } => { + const l = (coords.tl[0] * this.dimensions.height) / 2; + const t = coords.tl[1] * this.dimensions.width / 2; //prettier-ignore + const r = (coords.br[0] * this.dimensions.height) / 2; + const b = coords.br[1] * this.dimensions.width / 2; //prettier-ignore + const width = r - l; + const height = b - t; + const coord = { x: l, y: t }; + return { width, height, coord }; + }; + + applyBasicOpts = (doc: Doc) => { + const opts = this.settings.opts; + doc.x = this.dimensions.coord.x; + doc.y = this.dimensions.coord.y; + doc._height = this.dimensions.height; + doc._width = this.dimensions.width; + doc.backgroundColor = opts.backgroundColor ?? ''; + doc._layout_borderRounding = `${opts.cornerRounding ?? 0}px`; + doc.borderColor = opts.borderColor; + doc.borderWidth = opts.borderWidth; + doc.opacity = opts.opacity; + doc._rotation = opts.rotation; + } +} + +class TextField extends Field implements ConstructedField { + content: string = ''; + + constructor(settings: FieldSettings, parent: Field) { + super(settings, parent); + } + + renderedDoc = (): Doc => { + const opts = this.settings.opts; + const doc = Docs.Create.TextDocument(this.content, { + text_fontColor: opts.color, + contentBold: opts.fontBold, + textTransform: opts.fontTransform, + color: opts.color, + }); + this.applyBasicOpts(doc); + return doc; + } + + validSubfieldGroups = () => { + return []; + } + + setContent = (newContent: any) => { + if (newContent !instanceof String){ + return; + } + + this.content = newContent; + } + + getContent = () => { + return ''; + }; +} + +type DecorationField = FieldSettings; + +type InkDecoration = {}; + +type TemplateDecorations = FieldSettings | InkDecoration; + +interface TemplateOpts extends FieldOpts {} |