diff options
Diffstat (limited to 'src/client/views/PropertiesView.tsx')
-rw-r--r-- | src/client/views/PropertiesView.tsx | 151 |
1 files changed, 77 insertions, 74 deletions
diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx index 899cca4ec..5cfe0bd5f 100644 --- a/src/client/views/PropertiesView.tsx +++ b/src/client/views/PropertiesView.tsx @@ -1,23 +1,23 @@ -import React = require('react'); import { IconLookup } from '@fortawesome/fontawesome-svg-core'; import { faAnchor, faArrowRight, faWindowMaximize } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { Checkbox, Tooltip } from '@material-ui/core'; -import { Button, ColorPicker, Colors, EditableText, IconButton, NumberInput, Size, Slider, Type } from 'browndash-components'; +import { Checkbox, Tooltip } from '@mui/material'; +import { Colors, EditableText, IconButton, NumberInput, Size, Slider, Type } from 'browndash-components'; import { concat } from 'lodash'; -import { action, computed, IReactionDisposer, observable, reaction, trace } from 'mobx'; +import { IReactionDisposer, action, computed, makeObservable, observable, reaction } from 'mobx'; import { observer } from 'mobx-react'; -import { ColorState, SketchPicker } from 'react-color'; +import * as React from 'react'; +import { ColorResult, SketchPicker } from 'react-color'; import * as Icons from 'react-icons/bs'; //{BsCollectionFill, BsFillFileEarmarkImageFill} from "react-icons/bs" +import { Utils, emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue, setupMoveUpEvents } from '../../Utils'; import { Doc, DocListCast, Field, FieldResult, HierarchyMapping, NumListCast, Opt, ReverseHierarchyMap, StrListCast } from '../../fields/Doc'; -import { AclAdmin, DocAcl, DocData, Height, Width } from '../../fields/DocSymbols'; +import { AclAdmin, DocAcl, DocData } from '../../fields/DocSymbols'; import { Id } from '../../fields/FieldSymbols'; import { InkField } from '../../fields/InkField'; import { List } from '../../fields/List'; import { ComputedField } from '../../fields/ScriptField'; import { Cast, DocCast, NumCast, StrCast } from '../../fields/Types'; -import { GetEffectiveAcl, normalizeEmail, SharingPermissions } from '../../fields/util'; -import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue, setupMoveUpEvents, Utils } from '../../Utils'; +import { GetEffectiveAcl, SharingPermissions, normalizeEmail } from '../../fields/util'; import { CollectionViewType, DocumentType } from '../documents/DocumentTypes'; import { DocumentManager } from '../util/DocumentManager'; import { GroupManager } from '../util/GroupManager'; @@ -26,39 +26,38 @@ import { SelectionManager } from '../util/SelectionManager'; import { SettingsManager } from '../util/SettingsManager'; import { SharingManager } from '../util/SharingManager'; import { Transform } from '../util/Transform'; -import { undoable, undoBatch, UndoManager } from '../util/UndoManager'; +import { UndoManager, undoBatch, undoable } from '../util/UndoManager'; import { EditableView } from './EditableView'; import { FilterPanel } from './FilterPanel'; import { InkStrokeProperties } from './InkStrokeProperties'; -import { DocumentView, OpenWhere, StyleProviderFunc } from './nodes/DocumentView'; -import { KeyValueBox } from './nodes/KeyValueBox'; -import { PresBox, PresEffect, PresEffectDirection } from './nodes/trails'; +import { ObservableReactComponent } from './ObservableReactComponent'; import { PropertiesButtons } from './PropertiesButtons'; import { PropertiesDocBacklinksSelector } from './PropertiesDocBacklinksSelector'; import { PropertiesDocContextSelector } from './PropertiesDocContextSelector'; import { PropertiesSection } from './PropertiesSection'; import './PropertiesView.scss'; import { DefaultStyleProvider } from './StyleProvider'; -import { FaFillDrip, FaRegHeart } from 'react-icons/fa'; -import { GeneratedResponse, StyleInput, generatePalette } from '../apis/gpt/customization'; -import { ExtractColors } from './ExtractColors'; -import ReactTextareaAutosize from 'react-textarea-autosize'; +import { DocumentView, OpenWhere } from './nodes/DocumentView'; +import { StyleProviderFuncType } from './nodes/FieldView'; +import { KeyValueBox } from './nodes/KeyValueBox'; +import { PresBox, PresEffect, PresEffectDirection } from './nodes/trails'; const _global = (window /* browser */ || global) /* node */ as any; interface PropertiesViewProps { width: number; height: number; - styleProvider?: StyleProviderFunc; + styleProvider?: StyleProviderFuncType; addDocTab: (doc: Doc, where: OpenWhere) => boolean; } @observer -export class PropertiesView extends React.Component<PropertiesViewProps> { +export class PropertiesView extends ObservableReactComponent<PropertiesViewProps> { private _widthUndo?: UndoManager.Batch; public static Instance: PropertiesView | undefined; constructor(props: any) { super(props); + makeObservable(this); PropertiesView.Instance = this; } @@ -67,11 +66,15 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { } @computed get selectedDoc() { - return SelectionManager.SelectedSchemaDoc() || this.selectedDocumentView?.rootDoc || Doc.ActiveDashboard; + return SelectionManager.SelectedSchemaDoc || this.selectedDocumentView?.Document || Doc.ActiveDashboard; + } + + @computed get selectedLayoutDoc() { + return SelectionManager.SelectedSchemaDoc || this.selectedDocumentView?.layoutDoc || Doc.ActiveDashboard; } @computed get selectedDocumentView() { - if (SelectionManager.Views().length) return SelectionManager.Views()[0]; - if (PresBox.Instance?.selectedArray.size) return DocumentManager.Instance.getDocumentView(PresBox.Instance.rootDoc); + if (SelectionManager.Views.length) return SelectionManager.Views[0]; + if (PresBox.Instance?.selectedArray.size) return DocumentManager.Instance.getDocumentView(PresBox.Instance.Document); return undefined; } @computed get isPres(): boolean { @@ -175,28 +178,31 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { @computed get isInk() { return this.selectedDoc?.type === DocumentType.INK; } + @computed get isGroup() { + return this.selectedDoc?.isGroup; + } @computed get isStack() { return [CollectionViewType.Stacking, CollectionViewType.NoteTaking].includes(this.selectedDoc?.type_collection as any); } - rtfWidth = () => (!this.selectedDoc ? 0 : Math.min(this.selectedDoc?.[Width](), this.props.width - 20)); - rtfHeight = () => (!this.selectedDoc ? 0 : this.rtfWidth() <= this.selectedDoc?.[Width]() ? Math.min(this.selectedDoc?.[Height](), this.MAX_EMBED_HEIGHT) : this.MAX_EMBED_HEIGHT); + rtfWidth = () => (!this.selectedLayoutDoc ? 0 : Math.min(NumCast(this.selectedLayoutDoc?._width), this._props.width - 20)); + rtfHeight = () => (!this.selectedLayoutDoc ? 0 : this.rtfWidth() <= NumCast(this.selectedLayoutDoc?._width) ? Math.min(NumCast(this.selectedLayoutDoc?._height), this.MAX_EMBED_HEIGHT) : this.MAX_EMBED_HEIGHT); @action docWidth = () => { - if (this.selectedDoc) { - const layoutDoc = this.selectedDoc; + const layoutDoc = this.selectedLayoutDoc; + if (layoutDoc) { const aspect = Doc.NativeAspect(layoutDoc, undefined, !layoutDoc._layout_fitWidth); - if (aspect) return Math.min(layoutDoc[Width](), Math.min(this.MAX_EMBED_HEIGHT * aspect, this.props.width - 20)); - return Doc.NativeWidth(layoutDoc) ? Math.min(layoutDoc[Width](), this.props.width - 20) : this.props.width - 20; + if (aspect) return Math.min(NumCast(layoutDoc._width), Math.min(this.MAX_EMBED_HEIGHT * aspect, this._props.width - 20)); + return Doc.NativeWidth(layoutDoc) ? Math.min(NumCast(layoutDoc._width), this._props.width - 20) : this._props.width - 20; } return 0; }; @action docHeight = () => { - if (this.selectedDoc && this.dataDoc) { - const layoutDoc = this.selectedDoc; + const layoutDoc = this.selectedLayoutDoc; + if (layoutDoc && this.dataDoc) { return Math.max( 70, Math.min( @@ -204,10 +210,10 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { Doc.NativeAspect(layoutDoc, undefined, true) ? this.docWidth() / Doc.NativeAspect(layoutDoc, undefined, true) : layoutDoc._layout_fitWidth - ? !Doc.NativeHeight(this.dataDoc) - ? NumCast(this.props.height) - : Math.min((this.docWidth() * Doc.NativeHeight(layoutDoc)) / Doc.NativeWidth(layoutDoc) || NumCast(this.props.height)) - : NumCast(layoutDoc._height) || 50 + ? !Doc.NativeHeight(this.dataDoc) + ? NumCast(this._props.height) + : Math.min((this.docWidth() * Doc.NativeHeight(layoutDoc)) / Doc.NativeWidth(layoutDoc) || NumCast(this._props.height)) + : NumCast(layoutDoc._height) || 50 ) ); } @@ -218,7 +224,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { const rows: JSX.Element[] = []; if (this.dataDoc && this.selectedDoc) { const ids = new Set<string>(reqdKeys); - const docs: Doc[] = SelectionManager.Views().length < 2 ? [this.layoutFields ? Doc.Layout(this.selectedDoc) : this.dataDoc] : SelectionManager.Views().map(dv => (this.layoutFields ? dv.layoutDoc : dv.dataDoc)); + const docs: Doc[] = SelectionManager.Views.length < 2 ? [this.layoutFields ? Doc.Layout(this.selectedDoc) : this.dataDoc] : SelectionManager.Views.map(dv => (this.layoutFields ? dv.layoutDoc : dv.dataDoc)); docs.forEach(doc => Object.keys(doc).forEach(key => doc[key] !== ComputedField.undefined && ids.add(key))); // prettier-ignore @@ -267,7 +273,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { @undoBatch setKeyValue = (value: string) => { - const docs = SelectionManager.Views().length < 2 && this.selectedDoc ? [this.layoutFields ? Doc.Layout(this.selectedDoc) : this.dataDoc!] : SelectionManager.Views().map(dv => (this.layoutFields ? dv.layoutDoc : dv.dataDoc)); + const docs = SelectionManager.Views.length < 2 && this.selectedDoc ? [this.layoutFields ? Doc.Layout(this.selectedDoc) : this.dataDoc!] : SelectionManager.Views.map(dv => (this.layoutFields ? dv.layoutDoc : dv.dataDoc)); docs.forEach(doc => { if (value.indexOf(':') !== -1) { const newVal = value[0].toUpperCase() + value.substring(1, value.length); @@ -303,12 +309,12 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { }; @computed get contexts() { - return !this.selectedDoc ? null : <PropertiesDocContextSelector DocView={this.selectedDocumentView} hideTitle={true} addDocTab={this.props.addDocTab} />; + return !this.selectedDoc ? null : <PropertiesDocContextSelector DocView={this.selectedDocumentView} hideTitle={true} addDocTab={this._props.addDocTab} />; } @computed get contextCount() { if (this.selectedDocumentView) { - const target = this.selectedDocumentView.props.Document; + const target = this.selectedDocumentView.Document; const embeddings = DocListCast(target.proto_embeddings); return embeddings.length - 1; } else { @@ -318,7 +324,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { @computed get links() { const selAnchor = this.selectedDocumentView?.anchorViewDoc ?? LinkManager.currentLinkAnchor ?? this.selectedDoc; - return !selAnchor ? null : <PropertiesDocBacklinksSelector Document={selAnchor} hideTitle={true} addDocTab={this.props.addDocTab} />; + return !selAnchor ? null : <PropertiesDocBacklinksSelector Document={selAnchor} hideTitle={true} addDocTab={this._props.addDocTab} />; } @computed get linkCount() { @@ -331,7 +337,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { } @computed get layoutPreview() { - if (SelectionManager.Views().length > 1) { + if (SelectionManager.Views.length > 1) { return '-- multiple selected --'; } if (this.selectedDoc) { @@ -341,13 +347,12 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { return ( <div ref={this.propertiesDocViewRef} style={{ pointerEvents: 'none', display: 'inline-block', height: panelHeight() }} key={this.selectedDoc[Id]}> <DocumentView - Document={layoutDoc} - DataDoc={this.dataDoc} + Document={this.selectedDoc} + TemplateDataDocument={Doc.AreProtosEqual(this.dataDoc, this.selectedDoc) ? undefined : this.dataDoc} renderDepth={1} fitContentsToBox={returnTrue} - rootSelected={returnFalse} styleProvider={DefaultStyleProvider} - docViewPath={returnEmptyDoclist} + containerViewPath={returnEmptyDoclist} dontCenter={'y'} isDocumentActive={returnFalse} isContentActive={emptyFunction} @@ -366,7 +371,6 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { whenChildContentsActiveChanged={emptyFunction} addDocTab={returnFalse} pinToPres={emptyFunction} - bringToFront={returnFalse} dontRegisterView={true} /> </div> @@ -381,7 +385,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { */ @undoBatch changePermissions = (e: any, user: string) => { - const docs = (SelectionManager.Views().length < 2 ? [this.selectedDoc] : SelectionManager.Views().map(dv => dv.props.Document)).filter(doc => doc).map(doc => (this.layoutDocAcls ? doc! : DocCast(doc)[DocData])); + const docs = SelectionManager.Views.length < 2 ? [this.selectedDoc] : SelectionManager.Views.map(dv => (this.layoutDocAcls ? dv.layoutDoc : dv.dataDoc)); SharingManager.Instance.shareFromPropertiesSidebar(user, e.currentTarget.value as SharingPermissions, docs, this.layoutDocAcls); }; @@ -427,7 +431,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { color={SettingsManager.userColor} onClick={action(() => { if (this.selectedDocumentView || this.selectedDoc) { - SharingManager.Instance.open(this.selectedDocumentView?.props.Document === this.selectedDoc ? this.selectedDocumentView : undefined, this.selectedDoc); + SharingManager.Instance.open(this.selectedDocumentView?.Document === this.selectedDoc ? this.selectedDocumentView : undefined, this.selectedDoc); } })} /> @@ -499,14 +503,14 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { */ @computed get sharingTable() { // all selected docs - const docs = SelectionManager.Views().length < 2 && this.selectedDoc ? [this.selectedDoc] : SelectionManager.Views().map(docView => docView.rootDoc); + const docs = SelectionManager.Views.length < 2 && this.selectedDoc ? [this.selectedDoc] : SelectionManager.Views.map(docView => docView.Document); const target = docs[0]; const showAdmin = GetEffectiveAcl(target) == AclAdmin; const individualTableEntries = []; const usersAdded: string[] = []; // all shared users being added - organized by denormalized email - const seldoc = this.layoutDocAcls || !this.selectedDoc ? this.selectedDoc : Doc.GetProto(this.selectedDoc); + const seldoc = this.layoutDocAcls ? this.selectedLayoutDoc : this.selectedDoc?.[DocData]; // adds each user to usersAdded SharingManager.Instance.users.forEach(eachUser => { var userOnDoc = true; @@ -615,7 +619,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { @computed get editableTitle() { const titles = new Set<string>(); - SelectionManager.Views().forEach(dv => titles.add(StrCast(dv.rootDoc.title))); + SelectionManager.Views.forEach(dv => titles.add(StrCast(dv.Document.title))); const title = Array.from(titles.keys()).length > 1 ? '--multiple selected--' : StrCast(this.selectedDoc?.title); return ( <div> @@ -669,10 +673,9 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { } @undoBatch - @action setTitle = (value: string | number) => { - if (SelectionManager.Views().length > 1) { - SelectionManager.Views().map(dv => Doc.SetInPlace(dv.rootDoc, 'title', value, true)); + if (SelectionManager.Views.length > 1) { + SelectionManager.Views.map(dv => Doc.SetInPlace(dv.Document, 'title', value, true)); } else if (this.dataDoc) { if (this.selectedDoc) Doc.SetInPlace(this.selectedDoc, 'title', value, true); else KeyValueBox.SetField(this.dataDoc, 'title', value as string, true); @@ -680,13 +683,13 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { }; @undoBatch - @action rotate = (angle: number) => { const _centerPoints: { X: number; Y: number }[] = []; - if (this.selectedDoc) { - const doc = this.selectedDoc; - if (doc.type === DocumentType.INK && doc.x && doc.y && doc._width && doc._height && doc.data) { - const ink = Cast(doc.data, InkField)?.inkData; + const doc = this.selectedDoc; + const layout = this.selectedLayoutDoc; + if (doc && layout) { + if (doc.type === DocumentType.INK && doc.x && doc.y && layout._width && layout._height && doc.data) { + const ink = Cast(doc.stroke, InkField)?.inkData; if (ink) { const xs = ink.map(p => p.X); const ys = ink.map(p => p.Y); @@ -699,9 +702,9 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { } var index = 0; - if (doc.type === DocumentType.INK && doc.x && doc.y && doc._width && doc._height && doc.data) { - doc.rotation = NumCast(doc.rotation) + angle; - const inks = Cast(doc.data, InkField)?.inkData; + if (doc.type === DocumentType.INK && doc.x && doc.y && layout._width && layout._height && doc.data) { + layout.rotation = NumCast(layout.rotation) + angle; + const inks = Cast(doc.stroke, InkField)?.inkData; if (inks) { const newPoints: { X: number; Y: number }[] = []; inks.forEach(ink => { @@ -709,7 +712,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { const newY = Math.sin(angle) * (ink.X - _centerPoints[index].X) + Math.cos(angle) * (ink.Y - _centerPoints[index].Y) + _centerPoints[index].Y; newPoints.push({ X: newX, Y: newY }); }); - doc.data = new InkField(newPoints); + doc.stroke = new InkField(newPoints); const xs = newPoints.map(p => p.X); const ys = newPoints.map(p => p.Y); const left = Math.min(...xs); @@ -717,8 +720,8 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { const right = Math.max(...xs); const bottom = Math.max(...ys); - doc._height = bottom - top; - doc._width = right - left; + layout._height = bottom - top; + layout._width = right - left; } index++; } @@ -924,7 +927,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { return ( <SketchPicker onChange={undoable( - action((color: ColorState) => setter(color.hex)), + action((color: ColorResult) => setter(color.hex)), 'set stroke color property' )} presetColors={['#D0021B', '#F5A623', '#F8E71C', '#8B572A', '#7ED321', '#417505', '#9013FE', '#4A90E2', '#50E3C2', '#B8E986', '#000000', '#4A4A4A', '#9B9B9B', '#FFFFFF', '#f1efeb', 'transparent']} @@ -1106,7 +1109,6 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { } @undoBatch - @action changeDash = () => { this.dashdStk = this.dashdStk === '2' ? '0' : '2'; }; @@ -1154,6 +1156,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { <div className="transform-editor"> {!this.isStack ? null : this.getNumber('Gap', ' px', 0, 200, NumCast(this.selectedDoc!.gridGap), (val: number) => !isNaN(val) && (this.selectedDoc!.gridGap = val))} {!this.isStack ? null : this.getNumber('xMargin', ' px', 0, 500, NumCast(this.selectedDoc!.xMargin), (val: number) => !isNaN(val) && (this.selectedDoc!.xMargin = val))} + {!this.isGroup ? null : this.getNumber('Padding', ' px', 0, 500, NumCast(this.selectedDoc!.xPadding), (val: number) => !isNaN(val) && (this.selectedDoc!.xPadding = this.selectedDoc!.yPadding = val))} {this.isInk ? this.controlPointsButton : null} {this.getNumber('Width', ' px', 0, Math.max(1000, this.shapeWid), this.shapeWid, (val: number) => !isNaN(val) && (this.shapeWid = val), 1000, 1)} {this.getNumber('Height', ' px', 0, Math.max(1000, this.shapeHgt), this.shapeHgt, (val: number) => !isNaN(val) && (this.shapeHgt = val), 1000, 1)} @@ -1274,7 +1277,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { return ( <PropertiesSection title="Filters" isOpen={this.openFilters} setIsOpen={bool => (this.openFilters = bool)} onDoubleClick={() => this.CloseAll()}> <div className="propertiesView-content filters" style={{ position: 'relative', height: 'auto' }}> - <FilterPanel rootDoc={this.selectedDoc ?? Doc.ActiveDashboard!} /> + <FilterPanel Document={this.selectedDoc ?? Doc.ActiveDashboard!} /> </div> </PropertiesSection> ); @@ -1284,7 +1287,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { return ( <> <PropertiesSection title="Appearance" isOpen={this.openAppearance} setIsOpen={bool => (this.openAppearance = bool)} onDoubleClick={() => this.CloseAll()}> - {this.selectedDoc?.layout_isSvg ? this.appearanceEditor : null} + {this.selectedLayoutDoc?.layout_isSvg ? this.appearanceEditor : null} </PropertiesSection> <PropertiesSection title="Transform" isOpen={this.openTransform} setIsOpen={bool => (this.openTransform = bool)} onDoubleClick={() => this.CloseAll()}> {this.transformEditor} @@ -1820,8 +1823,8 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { const hasSelectedAnchor = LinkManager.Links(this.sourceAnchor).includes(LinkManager.currentLink!); if (!this.selectedDoc && !this.isPres) { return ( - <div className="propertiesView" style={{ width: this.props.width }}> - <div className="propertiesView-title" style={{ width: this.props.width }}> + <div className="propertiesView" style={{ width: this._props.width }}> + <div className="propertiesView-title" style={{ width: this._props.width }}> No Document Selected </div> </div> @@ -1834,11 +1837,11 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { style={{ background: SettingsManager.userBackgroundColor, color: SettingsManager.userColor, - width: this.props.width, - minWidth: this.props.width, + width: this._props.width, + minWidth: this._props.width, }}> <div className="propertiesView-propAndInfoGrouping"> - <div className="propertiesView-title" style={{ width: this.props.width }}> + <div className="propertiesView-title" style={{ width: this._props.width }}> Properties <div className="propertiesView-info" onClick={() => window.open('https://brown-dash.github.io/Dash-Documentation/properties')}> <IconButton icon={<FontAwesomeIcon icon="info-circle" />} color={SettingsManager.userColor} /> @@ -1867,8 +1870,8 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { ? (DocCast(PresBox.Instance.activeItem?.annotationOn)?.type as any as DocumentType) : PresBox.targetRenderedDoc(PresBox.Instance.activeItem)?.type; return ( - <div className="propertiesView" style={{ width: this.props.width }}> - <div className="propertiesView-sectionTitle" style={{ width: this.props.width }}> + <div className="propertiesView" style={{ width: this._props.width }}> + <div className="propertiesView-sectionTitle" style={{ width: this._props.width }}> Presentation </div> <div className="propertiesView-name" style={{ borderBottom: 0 }}> |