diff options
-rw-r--r-- | src/client/util/CurrentUserUtils.ts | 11 | ||||
-rw-r--r-- | src/client/views/collections/CollectionNoteTakingView.tsx | 103 | ||||
-rw-r--r-- | src/client/views/collections/CollectionNoteTakingViewColumn.tsx | 12 | ||||
-rw-r--r-- | src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx | 18 | ||||
-rw-r--r-- | src/client/views/nodes/CollectionFreeFormDocumentView.tsx | 10 | ||||
-rw-r--r-- | src/client/views/nodes/DocumentView.scss | 3 | ||||
-rw-r--r-- | src/fields/SchemaHeaderField.ts | 2 | ||||
-rw-r--r-- | src/fields/ScriptField.ts | 10 |
8 files changed, 79 insertions, 90 deletions
diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 99a8c895f..2321d18ee 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -597,14 +597,17 @@ export class CurrentUserUtils { /// initializes the required buttons in the expanding button menu at the bottom of the Dash window static setupDockedButtons(doc: Doc, field="myDockedBtns") { const dockedBtns = DocCast(doc[field]); - const dockBtn = (opts: DocumentOptions, scripts: {[key:string]:string}) => + const dockBtn = (opts: DocumentOptions, scripts: {[key:string]:string}, funcs?: {[key:string]:string}) => DocUtils.AssignScripts(DocUtils.AssignOpts(DocListCast(dockedBtns?.data)?.find(doc => doc.title === opts.title), opts) ?? - CurrentUserUtils.createToolButton(opts), scripts); + CurrentUserUtils.createToolButton(opts), scripts, funcs); const btnDescs = [// setup reactions to change the highlights on the undo/redo buttons -- would be better to encode this in the undo/redo buttons, but the undo/redo stacks are not wired up that way yet { scripts: { onClick: "undo()"}, opts: { title: "undo", icon: "undo-alt", toolTip: "Click to undo" }}, - { scripts: { onClick: "redo()"}, opts: { title: "redo", icon: "redo-alt", toolTip: "Click to redo" }} - ]; + { scripts: { onClick: "redo()"}, opts: { title: "redo", icon: "redo-alt", toolTip: "Click to redo" }}, + // { scripts: { onClick: 'prevKeyFrame(_readOnly_)'}, opts: { title: "Back", icon: "chevron-left", toolTip: "Prev Animation Frame", btnType: ButtonType.ClickButton, width: 20}}, + // { scripts: { onClick:""}, opts: { title: "Num", icon: "", toolTip: "Frame Number", btnType: ButtonType.TextButton, width: 20}, funcs: { buttonText: 'selectedDocs()?.lastElement()?.currentFrame.toString()'}}, + // { scripts: { onClick: 'nextKeyFrame(_readOnly_)'}, opts:{title: "Fwd", icon: "chevron-right", toolTip: "Next Animation Frame", btnType: ButtonType.ClickButton, width: 20,} }, + ]; const btns = btnDescs.map(desc => dockBtn({_width: 30, _height: 30, dontUndo: true, _stayInCollection: true, ...desc.opts}, desc.scripts)); const dockBtnsReqdOpts = { title: "docked buttons", _height: 40, flexGap: 0, linearViewFloating: true, diff --git a/src/client/views/collections/CollectionNoteTakingView.tsx b/src/client/views/collections/CollectionNoteTakingView.tsx index b359ef420..5a6d899ef 100644 --- a/src/client/views/collections/CollectionNoteTakingView.tsx +++ b/src/client/views/collections/CollectionNoteTakingView.tsx @@ -11,7 +11,7 @@ import { BoolCast, Cast, NumCast, ScriptCast, StrCast } from '../../../fields/Ty import { TraceMobx } from '../../../fields/util'; import { emptyFunction, returnEmptyDoclist, returnFalse, returnTrue, returnZero, smoothScroll, Utils } from '../../../Utils'; import { Docs, DocUtils } from '../../documents/Documents'; -import { CollectionViewType, DocumentType } from '../../documents/DocumentTypes'; +import { DocumentType } from '../../documents/DocumentTypes'; import { DragManager, dropActionType } from '../../util/DragManager'; import { SnappingManager } from '../../util/SnappingManager'; import { Transform } from '../../util/Transform'; @@ -19,7 +19,6 @@ import { undoBatch } from '../../util/UndoManager'; import { ContextMenu } from '../ContextMenu'; import { ContextMenuProps } from '../ContextMenuItem'; import { LightboxView } from '../LightboxView'; -import { CollectionFreeFormDocumentView } from '../nodes/CollectionFreeFormDocumentView'; import { DocFocusOptions, DocumentView, DocumentViewProps, ViewAdjustment } from '../nodes/DocumentView'; import { FieldViewProps } from '../nodes/FieldView'; import { FormattedTextBox } from '../nodes/formattedText/FormattedTextBox'; @@ -30,13 +29,6 @@ import { CollectionNoteTakingViewDivider } from './CollectionNoteTakingViewDivid import { CollectionSubView } from './CollectionSubView'; const _global = (window /* browser */ || global) /* node */ as any; -export type collectionNoteTakingViewProps = { - chromeHidden?: boolean; - viewType?: CollectionViewType; - NativeWidth?: () => number; - NativeHeight?: () => number; -}; - /** * CollectionNoteTakingView is a column-based view for displaying documents. In this view, the user can (1) * add and remove columns (2) change column sizes and (3) move documents within and between columns. This @@ -45,28 +37,32 @@ export type collectionNoteTakingViewProps = { * the rest of Dash, so it may be worthwhile to transition the headers to simple documents. */ @observer -export class CollectionNoteTakingView extends CollectionSubView<Partial<collectionNoteTakingViewProps>>() { +export class CollectionNoteTakingView extends CollectionSubView() { _disposers: { [key: string]: IReactionDisposer } = {}; _masonryGridRef: HTMLDivElement | null = null; _draggerRef = React.createRef<HTMLDivElement>(); + notetakingCategoryField = 'NotetakingCategory'; + dividerWidth = 16; @observable docsDraggedRowCol: number[] = []; @observable _cursor: CursorProperty = 'grab'; @observable _scroll = 0; @computed get chromeHidden() { - return this.props.chromeHidden || BoolCast(this.layoutDoc.chromeHidden); + return BoolCast(this.layoutDoc.chromeHidden); } // columnHeaders returns the list of SchemaHeaderFields currently being used by the layout doc to render the columns @computed get columnHeaders() { const columnHeaders = Cast(this.dataDoc.columnHeaders, listSpec(SchemaHeaderField), null); - const needsUnsetCategory = this.childDocs.some(d => !d[this.notetakingCategoryField] && !columnHeaders.find(sh => sh.heading === 'unset')); + const needsUnsetCategory = this.childDocs.some(d => !d[this.notetakingCategoryField] && !columnHeaders?.find(sh => sh.heading === 'unset')); if (needsUnsetCategory) { - setTimeout(() => columnHeaders.push(new SchemaHeaderField('unset', undefined, undefined, 1))); + setTimeout(() => { + const needsUnsetCategory = this.childDocs.some(d => !d[this.notetakingCategoryField] && !columnHeaders?.find(sh => sh.heading === 'unset')); + if (needsUnsetCategory) { + if (columnHeaders) columnHeaders.push(new SchemaHeaderField('unset', undefined, undefined, 1)); + else this.dataDoc.columnHeaders = new List<SchemaHeaderField>(); + } + }); } - return columnHeaders; - } - // notetakingCategoryField returns the key to accessing a document's column value - @computed get notetakingCategoryField() { - return 'NotetakingCategory'; + return columnHeaders ?? ([] as SchemaHeaderField[]); } @computed get headerMargin() { return this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.HeaderMargin); @@ -74,10 +70,6 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti @computed get xMargin() { return NumCast(this.layoutDoc._xMargin, 2 * Math.min(this.gridGap, 0.05 * this.props.PanelWidth())); } - // dividerWidth returns the width of a CollectionNoteTakingViewDivider - @computed get dividerWidth() { - return 32; - } @computed get yMargin() { return this.props.yPadding || NumCast(this.layoutDoc._yMargin, 5); } @@ -99,19 +91,10 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti // availableWidth is the total amount of non-divider width. Since widths are stored relatively, // we use availableWidth to convert from a percentage to a pixel count. @computed get availableWidth() { - const numDividers = this.columnHeaders.length - 1; + const numDividers = this.numGroupColumns - 1; return this.maxColWidth - numDividers * this.dividerWidth; } - // Documents should NOT have column category fields until entering this view, so the contructor creates the 'New Column' - // category for the user to then edit later. - constructor(props: any) { - super(props); - if (this.columnHeaders === undefined) { - this.dataDoc.columnHeaders = new List<SchemaHeaderField>([new SchemaHeaderField('New Column', undefined, undefined, 1)]); - } - } - // children is passed as a prop to the NoteTakingField, which uses this function // to render the docs you see within an individual column. children = (docs: Doc[]) => { @@ -149,7 +132,7 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti } }); // now we add back in the docs that we're dragging - if (rowCol.length) { + if (rowCol.length && columnHeaders.length > rowCol[1]) { const offset = 0; sections.get(columnHeaders[rowCol[1]])?.splice(rowCol[0] - offset, 0, ...DragManager.docsBeingDragged); } @@ -236,9 +219,6 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti if (this.props.childOpacity) { return this.props.childOpacity(); } - if (this.Document._currentFrame !== undefined) { - return CollectionFreeFormDocumentView.getValues(doc, NumCast(this.Document._currentFrame))?.opacity; - } } return this.props.styleProvider?.(doc, props, property); }; @@ -392,17 +372,19 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti }); // we alter the pivot fields of the docs in case they are moved to a new column. const colIndex = this.getColumnFromXCoord(xCoord); - const colHeader = StrCast(this.columnHeaders[colIndex].heading); + const colHeader = colIndex === undefined ? 'unset' : StrCast(this.columnHeaders[colIndex].heading); DragManager.docsBeingDragged.forEach(d => (d[this.notetakingCategoryField] = colHeader)); // used to notify sections to re-render this.docsDraggedRowCol.length = 0; - this.docsDraggedRowCol.push(dropInd, this.getColumnFromXCoord(xCoord)); + const columnFromCoord = this.getColumnFromXCoord(xCoord); + columnFromCoord !== undefined && this.docsDraggedRowCol.push(dropInd, columnFromCoord); } }; // getColumnFromXCoord returns the column index for a given x-coordinate (currently always the client's mouse coordinate). // This function is used to know which document a column SHOULD be in while it is being dragged. - getColumnFromXCoord = (xCoord: number): number => { + getColumnFromXCoord = (xCoord: number): number | undefined => { + let colIndex: number | undefined = undefined; const numColumns = this.columnHeaders.length; const coords = []; let colStartXCoord = 0; @@ -411,7 +393,6 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti colStartXCoord += this.columnHeaders[i].width * this.availableWidth + this.dividerWidth; } coords.push(this.PanelWidth); - let colIndex = 0; for (let i = 0; i < numColumns; i++) { if (xCoord > coords[i] && xCoord < coords[i + 1]) { colIndex = i; @@ -423,20 +404,16 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti // getDocsFromXCoord returns the docs of a column based on the x-coordinate provided. getDocsFromXCoord = (xCoord: number): Doc[] => { - const colIndex = this.getColumnFromXCoord(xCoord); - const colHeader = StrCast(this.columnHeaders[colIndex].heading); - // const docs = this.childDocList - const docs = this.childDocs; const docsMatchingHeader: Doc[] = []; - if (docs) { - docs.map(d => { - if (d instanceof Promise) return; - const sectionValue = (d[this.notetakingCategoryField] as object) ?? 'unset'; - if (sectionValue.toString() == colHeader) { - docsMatchingHeader.push(d); - } - }); - } + const colIndex = this.getColumnFromXCoord(xCoord); + const colHeader = colIndex === undefined ? 'unset' : StrCast(this.columnHeaders[colIndex].heading); + this.childDocs?.map(d => { + if (d instanceof Promise) return; + const sectionValue = (d[this.notetakingCategoryField] as object) ?? 'unset'; + if (sectionValue.toString() == colHeader) { + docsMatchingHeader.push(d); + } + }); return docsMatchingHeader; }; @@ -511,7 +488,7 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti this.onPointerMove(true, e.clientX, e.clientY); docus?.map((doc: Doc) => this.addDocument(doc)); const newDoc = this.childDocs.lastElement(); - const colHeader = StrCast(this.columnHeaders[colInd].heading); + const colHeader = colInd === undefined ? 'unset' : StrCast(this.columnHeaders[colInd].heading); newDoc[this.notetakingCategoryField] = colHeader; const docs = this.childDocList; if (docs && targInd !== -1) { @@ -570,9 +547,9 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti maxColWidth={this.maxColWidth} availableWidth={this.availableWidth} PanelWidth={this.PanelWidth} - key={heading?.heading ?? ''} + key={heading?.heading ?? 'unset'} headings={this.headings} - heading={heading?.heading ?? ''} + heading={heading?.heading ?? 'unset'} headingObject={heading} docList={docList} yMargin={this.yMargin} @@ -589,10 +566,12 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti @undoBatch @action addGroup = (value: string) => { - for (const header of this.columnHeaders) { - if (header.heading == value) { - alert('You cannot use an existing column name. Please try a new column name'); - return value; + if (this.columnHeaders) { + for (const header of this.columnHeaders) { + if (header.heading == value) { + alert('You cannot use an existing column name. Please try a new column name'); + return value; + } } } const columnHeaders = Cast(this.props.Document.columnHeaders, listSpec(SchemaHeaderField), null); @@ -678,10 +657,10 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti } @computed get nativeWidth() { - return this.props.NativeWidth?.() ?? Doc.NativeWidth(this.layoutDoc); + return Doc.NativeWidth(this.layoutDoc); } @computed get nativeHeight() { - return this.props.NativeHeight?.() ?? Doc.NativeHeight(this.layoutDoc); + return Doc.NativeHeight(this.layoutDoc); } @computed get scaling() { diff --git a/src/client/views/collections/CollectionNoteTakingViewColumn.tsx b/src/client/views/collections/CollectionNoteTakingViewColumn.tsx index 4610da4e3..c57677683 100644 --- a/src/client/views/collections/CollectionNoteTakingViewColumn.tsx +++ b/src/client/views/collections/CollectionNoteTakingViewColumn.tsx @@ -3,7 +3,7 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { action, computed, observable } from 'mobx'; import { observer } from 'mobx-react'; import { Doc, DocListCast, Opt } from '../../../fields/Doc'; -import { Id } from '../../../fields/FieldSymbols'; +import { Copy, Id } from '../../../fields/FieldSymbols'; import { RichTextField } from '../../../fields/RichTextField'; import { listSpec } from '../../../fields/Schema'; import { SchemaHeaderField } from '../../../fields/SchemaHeaderField'; @@ -22,6 +22,8 @@ import { ContextMenuProps } from '../ContextMenuItem'; import { EditableView } from '../EditableView'; import { FormattedTextBox } from '../nodes/formattedText/FormattedTextBox'; import './CollectionNoteTakingView.scss'; +import { List } from '../../../fields/List'; +import { Field } from '../../util/ProsemirrorCopy/prompt'; const higflyout = require('@hig/flyout'); export const { anchorPoints } = higflyout; export const Flyout = higflyout.default; @@ -148,15 +150,17 @@ export class CollectionNoteTakingViewColumn extends React.Component<CSVFieldColu @undoBatch @action deleteColumn = () => { - const columnHeaders = Cast(this.props.Document.columnHeaders, listSpec(SchemaHeaderField), null); - if (columnHeaders && this.props.headingObject) { - const index = columnHeaders.indexOf(this.props.headingObject); + const acolumnHeaders = Cast(this.props.Document.columnHeaders, listSpec(SchemaHeaderField), null); + if (acolumnHeaders && this.props.headingObject) { + const index = acolumnHeaders.indexOf(this.props.headingObject); + const columnHeaders = new List<SchemaHeaderField>(acolumnHeaders.map(header => header[Copy]())); // needed for undo to work properly. otherwise we end up changing field values in the undo stack since they are shared by reference const newColIndex = index > 0 ? index - 1 : 1; const newColHeader = this.props.columnHeaders ? this.props.columnHeaders[newColIndex] : undefined; const newHeading = newColHeader ? newColHeader.heading : 'unset'; this.props.docList.forEach(d => (d[this.props.pivotField] = newHeading)); const colWidth = this.props.columnHeaders ? this.props.columnHeaders[index].width : 0; columnHeaders.splice(index, 1); + Doc.GetProto(this.props.Document).columnHeaders = columnHeaders; this.props.resizeColumns(false, colWidth, index); } }; diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 052cbd3bb..c44b33ed0 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -44,7 +44,6 @@ import { PresBox } from '../../nodes/trails/PresBox'; import { VideoBox } from '../../nodes/VideoBox'; import { CreateImage } from '../../nodes/WebBoxRenderer'; import { StyleProp } from '../../StyleProvider'; -import { CollectionDockingView } from '../CollectionDockingView'; import { CollectionSubView } from '../CollectionSubView'; import { TreeViewType } from '../CollectionTreeView'; import { TabDocView } from '../TabDocView'; @@ -233,11 +232,11 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection const newBoxes = newBox instanceof Doc ? [newBox] : newBox; for (const newBox of newBoxes) { if (newBox.activeFrame !== undefined) { - const vals = CollectionFreeFormDocumentView.animFields.map(field => newBox[field]); - CollectionFreeFormDocumentView.animFields.forEach(field => delete newBox[`${field}-indexed`]); - CollectionFreeFormDocumentView.animFields.forEach(field => delete newBox[field]); + const vals = CollectionFreeFormDocumentView.animFields.map(field => newBox[field.key]); + CollectionFreeFormDocumentView.animFields.forEach(field => delete newBox[`${field.key}-indexed`]); + CollectionFreeFormDocumentView.animFields.forEach(field => delete newBox[field.key]); delete newBox.activeFrame; - CollectionFreeFormDocumentView.animFields.forEach((field, i) => field !== 'opacity' && (newBox[field] = vals[i])); + CollectionFreeFormDocumentView.animFields.forEach((field, i) => field.key !== 'opacity' && (newBox[field.key] = vals[i])); } } if (this.Document._currentFrame !== undefined && !this.props.isAnnotationOverlay) { @@ -275,10 +274,11 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection const layoutDoc = Doc.Layout(d); if (this.Document._currentFrame !== undefined) { CollectionFreeFormDocumentView.setupKeyframes([d], NumCast(this.Document._currentFrame), false); - const vals = CollectionFreeFormDocumentView.getValues(d, NumCast(d.activeFrame, 1000)); - vals.x = x + NumCast(vals.x) - dropPos[0]; - vals.y = y + NumCast(vals.y) - dropPos[1]; - vals._scrollTop = this.Document.editScrollProgressivize ? vals._scrollTop : undefined; + const pvals = CollectionFreeFormDocumentView.getValues(d, NumCast(d.activeFrame, 1000)); // get filled in values (uses defaults when not value is specified) for position + const vals = CollectionFreeFormDocumentView.getValues(d, NumCast(d.activeFrame, 1000), false); // get non-default values for everything else + vals.x = x + NumCast(pvals.x) - dropPos[0]; + vals.y = y + NumCast(pvals.y) - dropPos[1]; + vals._scrollTop = this.Document.editScrollProgressivize ? pvals._scrollTop : undefined; CollectionFreeFormDocumentView.setValues(NumCast(this.Document._currentFrame), d, vals); } else { d.x = x + NumCast(d.x) - dropPos[0]; diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx index 86566ac6a..efaecb8d2 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx @@ -36,7 +36,7 @@ export interface CollectionFreeFormDocumentViewProps extends DocumentViewProps { @observer export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeFormDocumentViewProps>() { - public static animFields = ['_height', '_width', 'x', 'y', '_scrollTop', 'opacity']; // fields that are configured to be animatable using animation frames + public static animFields: { key: string; val?: number }[] = [{ key: '_height' }, { key: '_width' }, { key: 'x' }, { key: 'y' }, { key: '_scrollTop' }, { key: 'opacity', val: 1 }, { key: 'viewScale', val: 1 }, { key: 'panX' }, { key: 'panY' }]; // fields that are configured to be animatable using animation frames public static animStringFields = ['backgroundColor', 'color']; // fields that are configured to be animatable using animation frames public static animDataFields = ['data', 'text']; // fields that are configured to be animatable using animation frames @observable _animPos: number[] | undefined = undefined; @@ -88,9 +88,9 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF return this.props.styleProvider?.(doc, props, property); }; - public static getValues(doc: Doc, time: number) { + public static getValues(doc: Doc, time: number, fillIn: boolean = true) { return CollectionFreeFormDocumentView.animFields.reduce((p, val) => { - p[val] = Cast(`${val}-indexed`, listSpec('number'), [NumCast(doc[val])]).reduce((p, v, i) => ((i <= Math.round(time) && v !== undefined) || p === undefined ? v : p), undefined as any as number); + p[val.key] = Cast(`${val}-indexed`, listSpec('number'), fillIn ? [NumCast(doc[val.key], val.val)] : []).reduce((p, v, i) => ((i <= Math.round(time) && v !== undefined) || p === undefined ? v : p), undefined as any as number); return p; }, {} as { [val: string]: Opt<number> }); } @@ -117,7 +117,7 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF action(doc => { doc._viewTransition = doc.dataTransition = 'all 1s'; CollectionFreeFormDocumentView.animFields.forEach(val => { - const findexed = Cast(doc[`${val}-indexed`], listSpec('number'), null); + const findexed = Cast(doc[`${val.key}-indexed`], listSpec('number'), null); findexed?.length <= timecode + 1 && findexed.push(undefined as any as number); }); CollectionFreeFormDocumentView.animStringFields.forEach(val => { @@ -174,7 +174,7 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF // opacity is unlike other fields because it's value should not be undefined before it appears to enable it to fade-in doc['opacity-indexed'] = new List<number>(numberRange(currTimecode + 1).map(t => (!doc.z && makeAppear && t < NumCast(doc.appearFrame) ? 0 : 1))); } - CollectionFreeFormDocumentView.animFields.forEach(val => (doc[val] = ComputedField.MakeInterpolatedNumber(val, 'activeFrame', doc, currTimecode))); + CollectionFreeFormDocumentView.animFields.forEach(val => (doc[val.key] = ComputedField.MakeInterpolatedNumber(val.key, 'activeFrame', doc, currTimecode, val.val))); CollectionFreeFormDocumentView.animStringFields.forEach(val => (doc[val] = ComputedField.MakeInterpolatedString(val, 'activeFrame', doc, currTimecode))); CollectionFreeFormDocumentView.animDataFields.forEach(val => (Doc.GetProto(doc)[val] = ComputedField.MakeInterpolatedDataField(val, 'activeFrame', Doc.GetProto(doc), currTimecode))); const targetDoc = doc.type === DocumentType.RTF ? Doc.GetProto(doc) : doc; // data fields, like rtf 'text' exist on the data doc, so diff --git a/src/client/views/nodes/DocumentView.scss b/src/client/views/nodes/DocumentView.scss index 9aaaf1e68..ab7116150 100644 --- a/src/client/views/nodes/DocumentView.scss +++ b/src/client/views/nodes/DocumentView.scss @@ -2,6 +2,7 @@ .documentView-effectsWrapper { border-radius: inherit; + transition: inherit; } // documentViews have a docView-hack tag which is replaced by this tag when capturing bitmaps (when the dom is converted to an html string) @@ -212,10 +213,12 @@ display: flex; width: 100%; height: 100%; + transition: inherit; .contentFittingDocumentView-previewDoc { position: relative; display: inline; + transition: inherit; } .contentFittingDocumentView-input { diff --git a/src/fields/SchemaHeaderField.ts b/src/fields/SchemaHeaderField.ts index 1321bc327..0b51db70b 100644 --- a/src/fields/SchemaHeaderField.ts +++ b/src/fields/SchemaHeaderField.ts @@ -115,7 +115,7 @@ export class SchemaHeaderField extends ObjectField { } [ToScriptString]() { - return `header(${this.heading},${this.type}})`; + return `header(${this.heading},${this.type},${this.width}})`; } [ToString]() { return `SchemaHeaderField`; diff --git a/src/fields/ScriptField.ts b/src/fields/ScriptField.ts index 48d5c5563..d38a019b3 100644 --- a/src/fields/ScriptField.ts +++ b/src/fields/ScriptField.ts @@ -189,13 +189,13 @@ export class ComputedField extends ScriptField { const compiled = ScriptField.CompileScript(script, params, true, capturedVariables); return compiled.compiled ? new ComputedField(compiled) : undefined; } - public static MakeInterpolatedNumber(fieldKey: string, interpolatorKey: string, doc: Doc, curTimecode: number) { + public static MakeInterpolatedNumber(fieldKey: string, interpolatorKey: string, doc: Doc, curTimecode: number, defaultVal: Opt<number>) { if (!doc[`${fieldKey}-indexed`]) { const flist = new List<number>(numberRange(curTimecode + 1).map(i => undefined) as any as number[]); - flist[curTimecode] = NumCast(doc[fieldKey]); + flist[curTimecode] = Cast(doc[fieldKey], 'number', null); doc[`${fieldKey}-indexed`] = flist; } - const getField = ScriptField.CompileScript(`getIndexVal(self['${fieldKey}-indexed'], self.${interpolatorKey})`, {}, true, {}); + const getField = ScriptField.CompileScript(`getIndexVal(self['${fieldKey}-indexed'], self.${interpolatorKey}, ${defaultVal})`, {}, true, {}); const setField = ScriptField.CompileScript(`setIndexVal(self['${fieldKey}-indexed'], self.${interpolatorKey}, value)`, { value: 'any' }, true, {}); return getField.compiled ? new ComputedField(getField, setField?.compiled ? setField : undefined) : undefined; } @@ -260,8 +260,8 @@ ScriptingGlobals.add( ); ScriptingGlobals.add( - function getIndexVal(list: any[], index: number) { - return list?.reduce((p, x, i) => ((i <= index && x !== undefined) || p === undefined ? x : p), undefined as any); + function getIndexVal(list: any[], index: number, defaultVal: Opt<number> = undefined) { + return list?.reduce((p, x, i) => ((i <= index && x !== undefined) || p === undefined ? x : p), defaultVal); }, 'returns the value at a given index of a list', '(list: any[], index: number)' |