diff options
Diffstat (limited to 'src/client/views/StyleProvider.tsx')
-rw-r--r-- | src/client/views/StyleProvider.tsx | 286 |
1 files changed, 152 insertions, 134 deletions
diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx index dcec2fe3d..3842f930a 100644 --- a/src/client/views/StyleProvider.tsx +++ b/src/client/views/StyleProvider.tsx @@ -1,3 +1,6 @@ +/* eslint-disable jsx-a11y/alt-text */ +/* eslint-disable jsx-a11y/no-static-element-interactions */ +/* eslint-disable jsx-a11y/click-events-have-key-events */ import { IconProp } from '@fortawesome/fontawesome-svg-core'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { Tooltip } from '@mui/material'; @@ -7,54 +10,23 @@ import { extname } from 'path'; import * as React from 'react'; import { BsArrowDown, BsArrowDownUp, BsArrowUp } from 'react-icons/bs'; import { FaFilter } from 'react-icons/fa'; +import { ClientUtils, DashColor, lightOrDark } from '../../ClientUtils'; import { Doc, Opt, StrListCast } from '../../fields/Doc'; -import { DocViews } from '../../fields/DocSymbols'; +import { Id } from '../../fields/FieldSymbols'; +import { ScriptField } from '../../fields/ScriptField'; import { BoolCast, Cast, DocCast, ImageCast, NumCast, ScriptCast, StrCast } from '../../fields/Types'; -import { DashColor, lightOrDark, Utils } from '../../Utils'; +import { AudioAnnoState } from '../../server/SharedMediaTypes'; import { CollectionViewType, DocumentType } from '../documents/DocumentTypes'; -import { DocFocusOrOpen, DocumentManager } from '../util/DocumentManager'; -import { IsFollowLinkScript } from '../util/LinkFollower'; -import { LinkManager } from '../util/LinkManager'; -import { SettingsManager } from '../util/SettingsManager'; +import { IsFollowLinkScript } from '../documents/DocUtils'; import { SnappingManager } from '../util/SnappingManager'; import { undoBatch, UndoManager } from '../util/UndoManager'; -import { CollectionSchemaView } from './collections/collectionSchema/CollectionSchemaView'; import { TreeSort } from './collections/TreeSort'; import { Colors } from './global/globalEnums'; -import { DocumentViewProps } from './nodes/DocumentView'; +import { DocumentView, DocumentViewProps } from './nodes/DocumentView'; import { FieldViewProps } from './nodes/FieldView'; -import { KeyValueBox } from './nodes/KeyValueBox'; -import { PropertiesView } from './PropertiesView'; +import { StyleProp } from './StyleProp'; import './StyleProvider.scss'; - -export enum StyleProp { - TreeViewIcon = 'treeView_Icon', - TreeViewSortings = 'treeView_Sortings', // options for how to sort tree view items - DocContents = 'docContents', // when specified, the JSX returned will replace the normal rendering of the document view - Opacity = 'opacity', // opacity of the document view - BoxShadow = 'boxShadow', // box shadow - used for making collections standout and for showing clusters in free form views - BorderRounding = 'borderRounding', // border radius of the document view - Color = 'color', // foreground color of Document view items - BackgroundColor = 'backgroundColor', // background color of a document view - FillColor = 'fillColor', // fill color of an ink stroke or shape - WidgetColor = 'widgetColor', // color to display UI widgets on a document view -- used for the sidebar divider dragger on a text note - PointerEvents = 'pointerEvents', // pointer events for DocumentView -- inherits pointer events if not specified - Decorations = 'decorations', // additional decoration to display above a DocumentView -- currently only used to display a Lock for making things background - HeaderMargin = 'headerMargin', // margin at top of documentview, typically for displaying a title -- doc contents will start below that - ShowCaption = 'layout_showCaption', - TitleHeight = 'titleHeight', // Height of Title area - ShowTitle = 'layout_showTitle', // whether to display a title on a Document (optional :hover suffix) - BorderPath = 'customBorder', // border path for document view - FontSize = 'fontSize', // size of text font - FontFamily = 'fontFamily', // font family of text - FontWeight = 'fontWeight', // font weight of text - Highlighting = 'highlighting', // border highlighting -} - -export enum AudioAnnoState { - stopped = 'stopped', - playing = 'playing', -} +import { emptyPath } from '../../Utils'; function toggleLockedPosition(doc: Doc) { UndoManager.RunInBatch(() => Doc.toggleLockedPosition(doc), 'toggleBackground'); @@ -70,6 +42,19 @@ function togglePaintView(e: React.MouseEvent, doc: Opt<Doc>, props: Opt<FieldVie ScriptCast(doc?.onPaint)?.script.run(scriptProps); } +export function styleFromLayoutString(doc: Doc, props: FieldViewProps, scale: number) { + const style: { [key: string]: any } = {}; + const divKeys = ['width', 'height', 'fontSize', 'transform', 'left', 'backgroundColor', 'left', 'right', 'top', 'bottom', 'pointerEvents', 'position']; + const replacer = (match: any, expr: string) => + // bcz: this executes a script to convert a property expression string: { script } into a value + ScriptField.MakeFunction(expr, { this: Doc.name, scale: 'number' })?.script.run({ this: doc, scale }).result?.toString() ?? ''; + divKeys.forEach((prop: string) => { + const p = (props as any)[prop]; + typeof p === 'string' && (style[prop] = p?.replace(/{([^.'][^}']+)}/g, replacer)); + }); + return style; +} + export function wavyBorderPath(pw: number, ph: number, inset: number = 0.05) { return `M ${pw * 0.5} ${ph * inset} C ${pw * 0.6} ${ph * inset} ${pw * (1 - 2 * inset)} 0 ${pw * (1 - inset)} ${ph * inset} C ${pw} ${ph * (2 * inset)} ${pw * (1 - inset)} ${ph * 0.25} ${pw * (1 - inset)} ${ph * 0.3} C ${ pw * (1 - inset) @@ -80,6 +65,11 @@ export function wavyBorderPath(pw: number, ph: number, inset: number = 0.05) { } ${ph * inset}`; } +let _filterOpener: () => void; +export function SetFilterOpener(func: () => void) { + _filterOpener = func; +} + // a preliminary implementation of a dash style sheet for setting rendering properties of documents nested within a Tab // export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<FieldViewProps & DocumentViewProps>, property: string): any { @@ -90,38 +80,61 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<FieldViewProps & const isNonTransparentLevel = isNonTransparent ? Number(property.replace(/.*:nonTransparent([0-9]+).*/, '$1')) : 0; // property.includes(':nonTransparent'); const isAnnotated = property.includes(':annotated'); const layoutDoc = doc ? Doc.Layout(doc) : doc; - const isInk = () => layoutDoc?._layout_isSvg && !props?.LayoutTemplateString; - const isOpen = property.includes(':open'); - const isEmpty = property.includes(':empty'); - const boxBackground = property.includes(':box'); - const fieldKey = props?.fieldKey ? props.fieldKey + '_' : isCaption ? 'caption_' : ''; + const isOpen = property.includes(':treeOpen'); + const boxBackground = property.includes(':docView'); // background color of docView's bounds can be different than the background of contents -- eg FontIconBox + const { + DocumentView: docView, + fieldKey: fieldKeyProp, + styleProvider, + pointerEvents, + isGroupActive, + isDocumentActive, + containerViewPath, + childFilters, + hideCaptions, + showTitle, + childFiltersByRanges, + renderDepth, + docViewPath, + LayoutTemplateString, + disableBrushing, + NativeDimScaling, + PanelWidth, + PanelHeight, + isSelected, + } = props || {}; // extract props that are not shared between fieldView and documentView props. + const componentView = docView?.()?.ComponentView; + const fieldKey = fieldKeyProp ? fieldKeyProp + '_' : isCaption ? 'caption_' : ''; + const isInk = () => layoutDoc?._layout_isSvg && !LayoutTemplateString; const lockedPosition = () => doc && BoolCast(doc._lockedPosition); - const titleHeight = () => props?.styleProvider?.(doc, props, StyleProp.TitleHeight); - const backgroundCol = () => props?.styleProvider?.(doc, props, StyleProp.BackgroundColor + ':nonTransparent' + (isNonTransparentLevel + 1)); - const color = () => props?.styleProvider?.(doc, props, StyleProp.Color); - const opacity = () => props?.styleProvider?.(doc, props, StyleProp.Opacity); - const layout_showTitle = () => props?.styleProvider?.(doc, props, StyleProp.ShowTitle); + const titleHeight = () => styleProvider?.(doc, props, StyleProp.TitleHeight); + const backgroundCol = () => styleProvider?.(doc, props, StyleProp.BackgroundColor + ':nonTransparent' + (isNonTransparentLevel + 1)); + const color = () => styleProvider?.(doc, props, StyleProp.Color); + const opacity = () => styleProvider?.(doc, props, StyleProp.Opacity); + const layoutShowTitle = () => styleProvider?.(doc, props, StyleProp.ShowTitle); // prettier-ignore switch (property.split(':')[0]) { - case StyleProp.TreeViewIcon: - const img = ImageCast(doc?.icon, ImageCast(doc?.data)); + case StyleProp.TreeViewIcon: { + const img = ImageCast(doc?.icon ?? doc?.[doc ? Doc.LayoutFieldKey(doc) : ""]); if (img) { const ext = extname(img.url.href); const url = doc?.icon ? img.url.href : img.url.href.replace(ext, '_s' + ext); return <img src={url} width={20} height={15} style={{ margin: 'auto', display: 'block', objectFit: 'contain' }} />; } return Doc.toIcon(doc, isOpen); - case StyleProp.TreeViewSortings: + } + case StyleProp.TreeViewSortings: { const allSorts: { [key: string]: { color: string; icon: JSX.Element | string } | undefined } = {}; allSorts[TreeSort.AlphaDown] = { color: Colors.MEDIUM_BLUE, icon: <BsArrowDown/> }; allSorts[TreeSort.AlphaUp] = { color: 'crimson', icon: <BsArrowUp/> }; if (doc?._type_collection === CollectionViewType.Freeform) allSorts[TreeSort.Zindex] = { color: 'green', icon: 'Z' }; allSorts[TreeSort.WhenAdded] = { color: 'darkgray', icon: <BsArrowDownUp/> }; return allSorts; + } case StyleProp.Highlighting: if (doc && (Doc.IsSystem(doc) || doc.type === DocumentType.FONTICON)) return undefined; - if (doc && !doc.layout_disableBrushing && !props?.disableBrushing) { - const selected = Array.from(doc?.[DocViews]??[]).filter(dv => dv.IsSelected).length; + if (doc && !doc.layout_disableBrushing && !disableBrushing) { + const selected = DocumentView.getViews(doc).filter(dv => dv.IsSelected).length; const highlightIndex = Doc.GetBrushHighlightStatus(doc) || (selected ? Doc.DocBrushStatus.selfBrushed : 0); const highlightColor = ['transparent', 'rgb(68, 118, 247)', selected ? "black" : 'rgb(68, 118, 247)', 'orange', 'lightBlue'][highlightIndex]; const highlightStyle = ['solid', 'dashed', 'solid', 'solid', 'solid'][highlightIndex]; @@ -135,71 +148,74 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<FieldViewProps & } } return undefined; - case StyleProp.DocContents:return undefined; - case StyleProp.WidgetColor:return isAnnotated ? Colors.LIGHT_BLUE : 'dimgrey'; - case StyleProp.Opacity: return props?.LayoutTemplateString?.includes(KeyValueBox.name) ? 1 : doc?.text_inlineAnnotations ? 0 : Cast(doc?._opacity, "number", Cast(doc?.opacity, 'number', null)); - case StyleProp.FontSize: return StrCast(doc?.[fieldKey + 'fontSize'], StrCast(Doc.UserDoc().fontSize)); - case StyleProp.FontFamily: return StrCast(doc?.[fieldKey + 'fontFamily'], StrCast(Doc.UserDoc().fontFamily)); - case StyleProp.FontWeight: return StrCast(doc?.[fieldKey + 'fontWeight'], StrCast(Doc.UserDoc().fontWeight)); - case StyleProp.FillColor: return StrCast(doc?._fillColor, StrCast(doc?.fillColor, StrCast(doc?.backgroundColor, 'transparent'))); - case StyleProp.ShowCaption:return props?.hideCaptions || doc?._type_collection === CollectionViewType.Carousel ? undefined: StrCast(doc?._layout_showCaption); - case StyleProp.TitleHeight:return Math.min(4,(props?.DocumentView?.().screenToViewTransform().Scale ?? 1)) * NumCast(Doc.UserDoc().headerHeight,30); + case StyleProp.DocContents: return undefined; + case StyleProp.WidgetColor: return isAnnotated ? Colors.LIGHT_BLUE : 'dimgrey'; + case StyleProp.Opacity: return componentView?.isUnstyledView?.() ? 1 : Cast(doc?._opacity, "number", Cast(doc?.opacity, 'number', null)); + case StyleProp.FontColor: return StrCast(doc?.[fieldKey + 'fontColor'], StrCast(Doc.UserDoc().fontColor, color())); + case StyleProp.FontSize: return StrCast(doc?.[fieldKey + 'fontSize'], StrCast(Doc.UserDoc().fontSize)); + case StyleProp.FontFamily: return StrCast(doc?.[fieldKey + 'fontFamily'], StrCast(Doc.UserDoc().fontFamily)); + case StyleProp.FontWeight: return StrCast(doc?.[fieldKey + 'fontWeight'], StrCast(Doc.UserDoc().fontWeight)); + case StyleProp.FillColor: return StrCast(doc?._fillColor, StrCast(doc?.fillColor, StrCast(doc?.backgroundColor, 'transparent'))); + case StyleProp.ShowCaption: return hideCaptions || doc?._type_collection === CollectionViewType.Carousel ? undefined: StrCast(doc?._layout_showCaption); + case StyleProp.TitleHeight: return Math.min(4,(docView?.().screenToViewTransform().Scale ?? 1)) * NumCast(Doc.UserDoc().headerHeight,30); case StyleProp.ShowTitle: return ( (doc && - !(props?.DocumentView?.().ComponentView instanceof CollectionSchemaView) && - !props?.LayoutTemplateString && + !componentView?.isUnstyledView?.() && + !LayoutTemplateString && !doc.presentation_targetDoc && - !props?.LayoutTemplateString?.includes(KeyValueBox.name) && - props?.layout_showTitle?.() !== '' && + showTitle?.() !== '' && StrCast( doc._layout_showTitle, - props?.layout_showTitle?.() || + showTitle?.() || (!Doc.IsSystem(doc) && [DocumentType.COL, DocumentType.FUNCPLOT, DocumentType.LABEL, DocumentType.RTF, DocumentType.IMG, DocumentType.VID].includes(doc.type as any) - ? doc.author === Doc.CurrentUserEmail + ? doc.author === ClientUtils.CurrentUserEmail() ? StrCast(Doc.UserDoc().layout_showTitle) : remoteDocHeader : '') )) || '' ); - case StyleProp.Color: - if (SettingsManager.Instance.LastPressedBtn === doc) return SettingsManager.userBackgroundColor; - if (Doc.IsSystem(doc!)) return SettingsManager.userColor; - if (doc?.type === DocumentType.FONTICON) return SettingsManager.userColor; + case StyleProp.Color: { + if (SnappingManager.LastPressedBtn === doc?.[Id]) return SnappingManager.userBackgroundColor; + if (Doc.IsSystem(doc!)) return SnappingManager.userColor; + if (doc?.type === DocumentType.FONTICON) return SnappingManager.userColor; const docColor: Opt<string> = StrCast(doc?.[fieldKey + 'color'], StrCast(doc?._color)); if (docColor) return docColor; const backColor = backgroundCol(); return backColor ? lightOrDark(backColor) : undefined; - case StyleProp.BorderRounding: + } + case StyleProp.BorderRounding: { const rounding = StrCast(doc?.[fieldKey + 'borderRounding'], StrCast(doc?.layout_borderRounding, doc?._type_collection === CollectionViewType.Pile ? '50%' : '')); return (doc?.[StrCast(doc?.layout_fieldKey)] instanceof Doc || doc?.isTemplateDoc) ? StrCast(doc._layout_borderRounding,rounding) : rounding; - case StyleProp.BorderPath: + } + case StyleProp.BorderPath: { const borderPath = Doc.IsComicStyle(doc) && - props?.renderDepth && - !doc?.layout_isSvg && { path: wavyBorderPath(props?.PanelWidth?.() || 0, props?.PanelHeight?.() || 0), fill: wavyBorderPath(props?.PanelWidth?.() || 0, props?.PanelHeight?.() || 0, 0.08), width: 3 }; - return !borderPath - ? null - : { - clipPath: `path('${borderPath.path}')`, - jsx: ( - <div key="border2" className="documentView-customBorder" style={{ pointerEvents: 'none' }}> - <svg style={{ overflow: 'visible', height: '100%' }} viewBox={`0 0 ${props.PanelWidth()} ${props.PanelHeight()}`}> - <path d={borderPath.path} style={{ stroke: 'black', fill: 'transparent', strokeWidth: borderPath.width }} /> - </svg> - </div> - ), - }; + renderDepth && + !doc?.layout_isSvg && { path: wavyBorderPath(PanelWidth?.() || 0, PanelHeight?.() || 0), fill: wavyBorderPath(PanelWidth?.() || 0, PanelHeight?.() || 0, 0.08), width: 3 }; + return !borderPath + ? null + : { + clipPath: `path('${borderPath.path}')`, + jsx: ( + <div key="border2" className="documentView-customBorder" style={{ pointerEvents: 'none' }}> + <svg style={{ overflow: 'visible', height: '100%' }} viewBox={`0 0 ${PanelWidth?.()} ${PanelHeight?.()}`}> + <path d={borderPath.path} style={{ stroke: 'black', fill: 'transparent', strokeWidth: borderPath.width }} /> + </svg> + </div> + ), + }; + } case StyleProp.HeaderMargin: return ([CollectionViewType.Stacking, CollectionViewType.NoteTaking, CollectionViewType.Masonry, CollectionViewType.Tree].includes(doc?._type_collection as any) || - (doc?.type === DocumentType.RTF && !layout_showTitle()?.includes('noMargin')) || + (doc?.type === DocumentType.RTF && !layoutShowTitle()?.includes('noMargin')) || doc?.type === DocumentType.LABEL) && - layout_showTitle() && + layoutShowTitle() && !StrCast(doc?.layout_showTitle).includes(':hover') ? titleHeight() : 0; case StyleProp.BackgroundColor: { - if (SettingsManager.Instance.LastPressedBtn === doc) return SettingsManager.userColor; // hack to indicate active menu panel item + if (SnappingManager.LastPressedBtn === doc?.[Id]) return SnappingManager.userColor; // hack to indicate active menu panel item const dataKey = doc ? Doc.LayoutFieldKey(doc) : ""; const usePath = StrCast(doc?.[dataKey + "_usePath"]); const alternate = usePath.includes(":hover") ? ( doc?.isHovering ? '_' + usePath.replace(":hover","") : "") : usePath ? "_" +usePath:usePath; @@ -224,47 +240,48 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<FieldViewProps & case DocumentType.VID: docColor = docColor || (Colors.LIGHT_GRAY); break; case DocumentType.COL: docColor = docColor || (doc && Doc.IsSystem(doc) - ? SettingsManager.userBackgroundColor + ? SnappingManager.userBackgroundColor : doc?.annotationOn ? '#00000010' // faint interior for collections on PDFs, images, etc : doc?.isGroup ? undefined : doc?._type_collection === CollectionViewType.Stacking ? (Colors.DARK_GRAY) - : Cast((props?.renderDepth || 0) > 0 ? Doc.UserDoc().activeCollectionNestedBackground : Doc.UserDoc().activeCollectionBackground, 'string') ?? (Colors.MEDIUM_GRAY)); + : Cast((renderDepth || 0) > 0 ? Doc.UserDoc().activeCollectionNestedBackground : Doc.UserDoc().activeCollectionBackground, 'string') ?? (Colors.MEDIUM_GRAY)); break; - //if (doc._type_collection !== CollectionViewType.Freeform && doc._type_collection !== CollectionViewType.Time) return "rgb(62,62,62)"; + // if (doc._type_collection !== CollectionViewType.Freeform && doc._type_collection !== CollectionViewType.Time) return "rgb(62,62,62)"; default: docColor = docColor || (Colors.WHITE); } - if (isNonTransparent && isNonTransparentLevel < 9 && (!docColor || docColor === 'transparent') && doc?.embedContainer && props?.styleProvider) { - return props.styleProvider(DocCast(doc.embedContainer), props, StyleProp.BackgroundColor+":nonTransparent"+(isNonTransparentLevel+1)); + if (isNonTransparent && isNonTransparentLevel < 9 && (!docColor || docColor === 'transparent') && doc?.embedContainer && styleProvider) { + return styleProvider(DocCast(doc.embedContainer), props, StyleProp.BackgroundColor+":nonTransparent"+(isNonTransparentLevel+1)); } return (docColor && !doc) ? DashColor(docColor).fade(0.5).toString() : docColor; } case StyleProp.BoxShadow: { if (!doc || opacity() === 0 || doc.noShadow) return undefined; // if it's not visible, then no shadow) if (doc.layout_boxShadow === 'standard') return Shadows.STANDARD_SHADOW; - if (IsFollowLinkScript(doc?.onClick) && LinkManager.Links(doc).length && !layoutDoc?.layout_isSvg) return StrCast(doc?._linkButtonShadow, 'lightblue 0em 0em 1em'); + if (IsFollowLinkScript(doc?.onClick) && Doc.Links(doc).length && !layoutDoc?.layout_isSvg) return StrCast(doc?._linkButtonShadow, 'lightblue 0em 0em 1em'); switch (doc?.type) { case DocumentType.COL: return StrCast( doc?.layout_boxShadow, doc?._type_collection === CollectionViewType.Pile ? '4px 4px 10px 2px' - : lockedPosition() || doc?.isGroup || props?.LayoutTemplateString + : lockedPosition() || doc?.isGroup || LayoutTemplateString ? undefined // groups have no drop shadow -- they're supposed to be "invisible". LayoutString's imply collection is being rendered as something else (e.g., title of a Slide) : `${Colors.DARK_GRAY} ${StrCast(doc.layout_boxShadow, '0.2vw 0.2vw 0.8vw')}` ); case DocumentType.LABEL: if (doc?.annotationOn !== undefined) return 'black 2px 2px 1px'; + // eslint-disable-next-line no-fallthrough default: return doc.z ? `#9c9396 ${StrCast(doc?.layout_boxShadow, '10px 10px 0.9vw')}` // if it's a floating doc, give it a big shadow - : props?.containerViewPath?.().lastElement()?.Document._freeform_useClusters - ? `${backgroundCol()} ${StrCast(doc.layout_boxShadow, `0vw 0vw ${(lockedPosition() ? 100 : 50) / (props?.NativeDimScaling?.() || 1)}px`)}` // if it's just in a cluster, make the shadown roughly match the cluster border extent + : containerViewPath?.().lastElement()?.Document._freeform_useClusters + ? `${backgroundCol()} ${StrCast(doc.layout_boxShadow, `0vw 0vw ${(lockedPosition() ? 100 : 50) / (NativeDimScaling?.() || 1)}px`)}` // if it's just in a cluster, make the shadown roughly match the cluster border extent : NumCast(doc.group, -1) !== -1 - ? `gray ${StrCast(doc.layout_boxShadow, `0vw 0vw ${(lockedPosition() ? 100 : 50) / (props?.NativeDimScaling?.() || 1)}px`)}` // if it's just in a cluster, make the shadown roughly match the cluster border extent + ? `gray ${StrCast(doc.layout_boxShadow, `0vw 0vw ${(lockedPosition() ? 100 : 50) / (NativeDimScaling?.() || 1)}px`)}` // if it's just in a cluster, make the shadown roughly match the cluster border extent : lockedPosition() ? undefined // if it's a background & has a cluster color, make the shadow spread really big : fieldKey.includes('_inline') // if doc is an inline document in a text box @@ -275,33 +292,33 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<FieldViewProps & } } case StyleProp.PointerEvents: - if (StrCast(doc?.pointerEvents) && !props?.LayoutTemplateString?.includes(KeyValueBox.name)) return StrCast(doc!.pointerEvents); // honor pointerEvents field (set by lock button usually) if it's not a keyValue view of the Doc - if (props?.LayoutTemplateString?.includes(KeyValueBox.name)) return 'all'; + if (componentView?.dontRegisterView?.()) return 'all'; + if (StrCast(doc?.pointerEvents)) return StrCast(doc!.pointerEvents); // honor pointerEvents field (set by lock button usually) if it's not a keyValue view of the Doc if (SnappingManager.ExploreMode || doc?.layout_unrendered) return isInk() ? 'visiblePainted' : 'all'; - if (props?.pointerEvents?.() === 'none') return 'none'; + if (pointerEvents?.() === 'none') return 'none'; if (opacity() === 0) return 'none'; - if (props?.isGroupActive?.() ) return isInk() ? 'visiblePainted': (doc?. + if (isGroupActive?.() ) return isInk() ? 'visiblePainted': (doc?. isGroup )? undefined: 'all' - if (props?.isDocumentActive?.()) return isInk() ? 'visiblePainted' : 'all'; + if (isDocumentActive?.()) return isInk() ? 'visiblePainted' : 'all'; return undefined; // fixes problem with tree view elements getting pointer events when the tree view is not active - case StyleProp.Decorations: + case StyleProp.Decorations: { const lock = () => doc?.pointerEvents !== 'none' ? null : ( <div className="styleProvider-lock" onClick={() => toggleLockedPosition(doc)}> <FontAwesomeIcon icon='lock' size="lg" /> </div> ); const paint = () => !doc?.onPaint ? null : ( - <div className={`styleProvider-paint${props?.DocumentView?.().IsSelected ? "-selected":""}`} onClick={e => togglePaintView(e, doc, props)}> + <div className={`styleProvider-paint${isSelected?.() ? "-selected":""}`} onClick={e => togglePaintView(e, doc, props)}> <FontAwesomeIcon icon='pen' size="lg" /> </div> ); const filter = () => { - const dashView = untracked(() => DocumentManager.Instance.getDocumentView(Doc.ActiveDashboard)); + const dashView = untracked(() => DocumentView.getDocumentView(Doc.ActiveDashboard)); const showFilterIcon = StrListCast(doc?._childFilters).length || StrListCast(doc?._childFiltersByRanges).length ? 'green' // #18c718bd' //'hasFilter' - : props?.childFilters?.().filter(f => Utils.IsRecursiveFilter(f) && f !== Utils.noDragDocsFilter).length || props?.childFiltersByRanges().length - ? 'orange' //'inheritsFilter' + : childFilters?.().filter(f => ClientUtils.IsRecursiveFilter(f) && f !== ClientUtils.noDragDocsFilter).length || childFiltersByRanges?.().length + ? 'orange' // 'inheritsFilter' : undefined; return !showFilterIcon ? null : ( <div className="styleProvider-filter"> @@ -309,19 +326,14 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<FieldViewProps & type={Type.TERT} dropdownType={DropdownType.CLICK} fillWidth - iconProvider={(active:boolean) => <div className='styleProvider-filterShift'><FaFilter/></div>} - closeOnSelect={true} - setSelectedVal={ - action((dv) => { - (dv as any).select(false); - (SettingsManager.Instance.propertiesWidth = 250); - setTimeout(action(() => { - if (PropertiesView.Instance) { - PropertiesView.Instance.CloseAll(); - PropertiesView.Instance.openFilters = true; - } - })); - }) + // eslint-disable-next-line react/no-unstable-nested-components + iconProvider={() => <div className='styleProvider-filterShift'><FaFilter/></div>} + closeOnSelect + setSelectedVal={((dv: DocumentView) => { + dv.select(false); + SnappingManager.SetPropertiesWidth(250); + _filterOpener?.(); + }) as any // Dropdown assumes values are strings or numbers.. } size={Size.XSMALL} width={15} @@ -329,27 +341,27 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<FieldViewProps & title={showFilterIcon === 'green' ? "This view is filtered. Click to view/change filters": "this view inherits filters from one of its parents"} - color={SettingsManager.userColor} + color={SnappingManager.userColor} background={showFilterIcon} - items={[ ...(dashView ? [dashView]: []), ...(props?.docViewPath?.()??[])] + items={[ ...(dashView ? [dashView]: []), ...(docViewPath?.()??[])] .filter(dv => StrListCast(dv?.Document.childFilters).length || StrListCast(dv?.Document.childRangeFilters).length) .map(dv => ({ text: StrCast(dv?.Document.title), val: dv as any, - style: {color:SettingsManager.userColor, background:SettingsManager.userBackgroundColor}, + style: {color:SnappingManager.userColor, background:SnappingManager.userBackgroundColor}, } as IListItemProps)) } /> </div> ); }; const audio = () => { - const audioAnnoState = (doc: Doc) => StrCast(doc.audioAnnoState, AudioAnnoState.stopped); - const audioAnnosCount = (doc: Doc) => StrListCast(doc[fieldKey + 'audioAnnotations']).length; - if (!doc || props?.renderDepth === -1 || !audioAnnosCount(doc)) return null; + const audioAnnoState = (audioDoc: Doc) => StrCast(audioDoc.audioAnnoState, AudioAnnoState.stopped); + const audioAnnosCount = (audioDoc: Doc) => StrListCast(audioDoc[fieldKey + 'audioAnnotations']).length; + if (!doc || renderDepth === -1 || !audioAnnosCount(doc)) return null; const audioIconColors: { [key: string]: string } = { playing: 'green', stopped: 'blue' }; return ( <Tooltip title={<div>{StrListCast(doc[fieldKey + 'audioAnnotations_text']).lastElement()}</div>}> - <div className="styleProvider-audio" onPointerDown={() => DocumentManager.Instance.getFirstDocumentView(doc)?.playAnnotation()}> + <div className="styleProvider-audio" onPointerDown={() => DocumentView.getFirstDocumentView(doc)?.playAnnotation()}> <FontAwesomeIcon className="documentView-audioFont" style={{ color: audioIconColors[audioAnnoState(doc)] }} icon='file-audio' size="sm" /> </div> </Tooltip> @@ -363,11 +375,13 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<FieldViewProps & {audio()} </> ); + } + default: } } export function DashboardToggleButton(doc: Doc, field: string, onIcon: IconProp, offIcon: IconProp, clickFunc?: () => void) { - const color = SettingsManager.userColor; + const color = SnappingManager.userColor; return ( <IconButton size={Size.XSMALL} @@ -389,7 +403,11 @@ export function DashboardStyleProvider(doc: Opt<Doc>, props: Opt<FieldViewProps> if (doc && property.split(':')[0] === StyleProp.Decorations) { return doc._type_collection === CollectionViewType.Docking || Doc.IsSystem(doc) ? null - : DashboardToggleButton(doc, 'hidden', 'eye-slash', 'eye', () => DocFocusOrOpen(doc, { toggleTarget: true, willZoomCentered: true, zoomScale: 0 }, DocCast(doc?.embedContainer ?? doc?.annotationOn))); + : DashboardToggleButton(doc, 'hidden', 'eye-slash', 'eye', () => DocumentView.FocusOrOpen(doc, { toggleTarget: true, willZoomCentered: true, zoomScale: 0 }, DocCast(doc?.embedContainer ?? doc?.annotationOn))); } return DefaultStyleProvider(doc, props, property); } + +export function returnEmptyDocViewList() { + return emptyPath; +} |