import { observer } from 'mobx-react'; import * as React from 'react'; import { DateField } from '../../../fields/DateField'; import { Doc, Field, Opt } from '../../../fields/Doc'; import { List } from '../../../fields/List'; import { ScriptField } from '../../../fields/ScriptField'; import { WebField } from '../../../fields/URLField'; import { dropActionType } from '../../util/DragManager'; import { Transform } from '../../util/Transform'; import { ViewBoxInterface } from '../DocComponent'; import { CollectionFreeFormDocumentView } from './CollectionFreeFormDocumentView'; import { DocumentView, OpenWhere } from './DocumentView'; import { PinProps } from './trails'; import { computed } from 'mobx'; export interface FocusViewOptions { willPan?: boolean; // determines whether to pan to target document willZoomCentered?: boolean; // determines whether to zoom in on target document. if zoomScale is 0, this just centers the document zoomScale?: number; // percent of containing frame to zoom into document zoomTime?: number; didMove?: boolean; // whether a document was changed during the showDocument process docTransform?: Transform; // when a document can't be panned and zoomed within its own container (say a group), then we need to continue to move up the render hierarchy to find something that can pan and zoom. when this happens the docTransform must accumulate all the transforms of each level of the hierarchy instant?: boolean; // whether focus should happen instantly (as opposed to smooth zoom) preview?: boolean; // whether changes should be previewed by the componentView or written to the document effect?: Doc; // animation effect for focus noSelect?: boolean; // whether target should be selected after focusing playAudio?: boolean; // whether to play audio annotation on focus playMedia?: boolean; // whether to play start target videos openLocation?: OpenWhere; // where to open a missing document zoomTextSelections?: boolean; // whether to display a zoomed overlay of anchor text selections toggleTarget?: boolean; // whether to toggle target on and off anchorDoc?: Doc; // doc containing anchor info to apply at end of focus to target doc easeFunc?: 'linear' | 'ease'; // transition method for scrolling } export type FocusFuncType = (doc: Doc, options: FocusViewOptions) => Opt; export type StyleProviderFuncType = (doc: Opt, props: Opt, property: string) => any; // // these properties get assigned through the render() method of the DocumentView when it creates this node. // However, that only happens because the properties are "defined" in the markup for the field view. // See the LayoutString method on each field view : ImageBox, FormattedTextBox, etc. // export interface FieldViewSharedProps { Document: Doc; TemplateDataDocument?: Doc; LayoutTemplateString?: string; LayoutTemplate?: () => Opt; renderDepth: number; scriptContext?: any; // can be assigned anything and will be passed as 'scriptContext' to any OnClick script that executes on this document xPadding?: number; yPadding?: number; dontRegisterView?: boolean; dropAction?: dropActionType; dragAction?: dropActionType; forceAutoHeight?: boolean; ignoreAutoHeight?: boolean; disableBrushing?: boolean; // should highlighting for this view be disabled when same document in another view is hovered over. hideClickBehaviors?: boolean; // whether to suppress menu item options for changing click behaviors ignoreUsePath?: boolean; // ignore the usePath field for selecting the fieldKey (eg., on text docs) CollectionFreeFormDocumentView?: () => CollectionFreeFormDocumentView; containerViewPath?: () => DocumentView[]; fitContentsToBox?: () => boolean; // used by freeformview to fit its contents to its panel. corresponds to _freeform_fitContentsToBox property on a Document isGroupActive?: () => string | undefined; // is this document part of a group that is active setContentViewBox?: (view: ViewBoxInterface) => any; // called by rendered field's viewBox so that DocumentView can make direct calls to the viewBox PanelWidth: () => number; PanelHeight: () => number; isDocumentActive?: () => boolean | undefined; // whether a document should handle pointer events isContentActive: () => boolean | undefined; // whether document contents should handle pointer events childFilters: () => string[]; childFiltersByRanges: () => string[]; styleProvider: Opt; setTitleFocus?: () => void; focus: FocusFuncType; onClickScript?: () => ScriptField; onDoubleClickScript?: () => ScriptField; onPointerDownScript?: () => ScriptField; onPointerUpScript?: () => ScriptField; onBrowseClickScript?: () => ScriptField | undefined; onKey?: (e: React.KeyboardEvent, fieldProps: FieldViewProps) => boolean | undefined; layout_fitWidth?: (doc: Doc) => boolean | undefined; searchFilterDocs: () => Doc[]; layout_showTitle?: () => string; whenChildContentsActiveChanged: (isActive: boolean) => void; rootSelected?: () => boolean; // whether the root of a template has been selected addDocTab: (doc: Doc, where: OpenWhere) => boolean; filterAddDocument?: (doc: Doc[]) => boolean; // allows a document that renders a Collection view to filter or modify any documents added to the collection (see PresBox for an example) addDocument?: (doc: Doc | Doc[], annotationKey?: string) => boolean; removeDocument?: (doc: Doc | Doc[], annotationKey?: string) => boolean; moveDocument?: (doc: Doc | Doc[], targetCollection: Doc | undefined, addDocument: (document: Doc | Doc[], annotationKey?: string) => boolean) => boolean; pinToPres: (document: Doc, pinProps: PinProps) => void; ScreenToLocalTransform: () => Transform; bringToFront?: (doc: Doc, sendToBack?: boolean) => void; waitForDoubleClickToClick?: () => 'never' | 'always' | undefined; defaultDoubleClick?: () => 'default' | 'ignore' | undefined; pointerEvents?: () => Opt; suppressSetHeight?: boolean; } /** * FieldView specific props that are not shared with DocumentView props * */ export interface FieldViewProps extends FieldViewSharedProps { DocumentView?: () => DocumentView; fieldKey: string; isSelected: () => boolean; select: (ctrlPressed: boolean, shiftPress?: boolean) => void; docViewPath: () => DocumentView[]; setHeight?: (height: number) => void; NativeDimScaling?: () => number; // scaling the DocumentView does to transform its contents into its panel & needed by ScreenToLocal // properties intended to be used from within layout strings (otherwise use the function equivalents that work more efficiently with React) // See currentUserUtils headerTemplate for examples of creating text boxes from html which set some of these fields // Also, see InkingStroke for examples of creating text boxes from render() methods which set some of these fields backgroundColor?: string; color?: string; height?: number; width?: number; dontSelectOnLoad?: boolean; // suppress selecting (e.g.,. text box) when loaded (and mark as not being associated with scrollTop document field) noSidebar?: boolean; dontScale?: boolean; } @observer export class FieldView extends React.Component { public static LayoutString(fieldType: { name: string }, fieldStr: string) { return `<${fieldType.name} {...props} fieldKey={'${fieldStr}'}/>`; //e.g., "" } @computed get fieldval() { return this.props.Document[this.props.fieldKey]; } render() { const field = this.fieldval; // prettier-ignore if (field instanceof Doc) return

{field.title?.toString()}

; if (field === undefined) return

{''}

; if (field instanceof DateField) return

{field.date.toLocaleString()}

; if (field instanceof List) return
{field.map(f => Field.toString(f)).join(', ')}
; if (field instanceof WebField) return

{Field.toString(field.url.href)}

; if (!(field instanceof Promise)) return

{Field.toString(field)}

; return

{'Waiting for server...'}

; } }