aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/StyleProvider.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views/StyleProvider.tsx')
-rw-r--r--src/client/views/StyleProvider.tsx112
1 files changed, 51 insertions, 61 deletions
diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx
index c6d3efd0c..5a0167338 100644
--- a/src/client/views/StyleProvider.tsx
+++ b/src/client/views/StyleProvider.tsx
@@ -1,29 +1,30 @@
import { IconProp } from '@fortawesome/fontawesome-svg-core';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { Tooltip } from '@material-ui/core';
+import { Tooltip } from '@mui/material';
import { Dropdown, DropdownType, IconButton, IListItemProps, Shadows, Size, Type } from 'browndash-components';
-import { action, runInAction, untracked } from 'mobx';
+import { action, untracked } from 'mobx';
import { extname } from 'path';
+import * as React from 'react';
import { BsArrowDown, BsArrowDownUp, BsArrowUp } from 'react-icons/bs';
import { FaFilter } from 'react-icons/fa';
import { Doc, Opt, StrListCast } from '../../fields/Doc';
+import { DocViews } from '../../fields/DocSymbols';
import { BoolCast, Cast, DocCast, ImageCast, NumCast, StrCast } from '../../fields/Types';
import { DashColor, lightOrDark, Utils } from '../../Utils';
import { CollectionViewType, DocumentType } from '../documents/DocumentTypes';
import { DocFocusOrOpen, DocumentManager } from '../util/DocumentManager';
import { IsFollowLinkScript } from '../util/LinkFollower';
import { LinkManager } from '../util/LinkManager';
-import { SelectionManager } from '../util/SelectionManager';
import { SettingsManager } from '../util/SettingsManager';
+import { SnappingManager } from '../util/SnappingManager';
import { undoBatch, UndoManager } from '../util/UndoManager';
import { TreeSort } from './collections/TreeSort';
import { Colors } from './global/globalEnums';
-import { DocumentView, DocumentViewProps } from './nodes/DocumentView';
+import { DocumentViewProps } from './nodes/DocumentView';
import { FieldViewProps } from './nodes/FieldView';
import { KeyValueBox } from './nodes/KeyValueBox';
import { PropertiesView } from './PropertiesView';
import './StyleProvider.scss';
-import React = require('react');
export enum StyleProp {
TreeViewIcon = 'treeView_Icon',
@@ -36,7 +37,6 @@ export enum StyleProp {
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
- HideLinkBtn = 'hideLinkButton', // hides the blue-dot link button. used when a document acts like a button
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
@@ -51,18 +51,7 @@ export enum StyleProp {
}
function toggleLockedPosition(doc: Doc) {
- UndoManager.RunInBatch(
- () =>
- runInAction(() => {
- doc._lockedPosition = !doc._lockedPosition;
- doc._pointerEvents = doc._lockedPosition ? 'none' : undefined;
- }),
- 'toggleBackground'
- );
-}
-
-export function testDocProps(toBeDetermined: any): toBeDetermined is DocumentViewProps {
- return toBeDetermined?.isContentActive ? toBeDetermined : undefined;
+ UndoManager.RunInBatch(() => Doc.toggleLockedPosition(doc), 'toggleBackground');
}
export function wavyBorderPath(pw: number, ph: number, inset: number = 0.05) {
@@ -77,13 +66,12 @@ export function wavyBorderPath(pw: number, ph: number, inset: number = 0.05) {
// 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<DocumentViewProps>, property: string): any {
+export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<FieldViewProps & DocumentViewProps>, property: string): any {
const remoteDocHeader = 'author;author_date;noMargin';
- const docProps = testDocProps(props) ? props : undefined;
- const selected = property.includes(':selected');
const isCaption = property.includes(':caption');
const isAnchor = property.includes(':anchor');
- const isContent = property.includes(':content');
+ const isNonTransparent = property.includes(':nonTransparent');
+ const isNonTransparentLevel = isNonTransparent ? Number(property.replace(/.*:nonTransparent([0-9]+).*/, '$1')) : 0; // property.includes(':nonTransparent');
const isAnnotated = property.includes(':annotated');
const isInk = () => doc?._layout_isSvg && !props?.LayoutTemplateString;
const isOpen = property.includes(':open');
@@ -92,7 +80,7 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps
const fieldKey = props?.fieldKey ? props.fieldKey + '_' : isCaption ? 'caption_' : '';
const lockedPosition = () => doc && BoolCast(doc._lockedPosition);
const titleHeight = () => props?.styleProvider?.(doc, props, StyleProp.TitleHeight);
- const backgroundCol = () => props?.styleProvider?.(doc, props, StyleProp.BackgroundColor);
+ 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);
@@ -105,7 +93,7 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps
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, isEmpty ? undefined : isOpen);
+ return Doc.toIcon(doc, isOpen);
case StyleProp.TreeViewSortings:
const allSorts: { [key: string]: { color: string; icon: JSX.Element | string } | undefined } = {};
allSorts[TreeSort.AlphaDown] = { color: Colors.MEDIUM_BLUE, icon: <BsArrowDown/> };
@@ -116,13 +104,13 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps
case StyleProp.Highlighting:
if (doc && (Doc.IsSystem(doc) || doc.type === DocumentType.FONTICON)) return undefined;
if (doc && !doc.layout_disableBrushing && !props?.disableBrushing) {
- const selected = SelectionManager.Views().some(dv => dv.rootDoc === doc);
- const highlightIndex = Doc.isBrushedHighlightedDegree(doc) || (selected ? Doc.DocBrushStatus.selfBrushed : 0);
+ const selected = Array.from(doc?.[DocViews]??[]).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];
if (highlightIndex) {
return {
- highlightStyle: doc._isGroup ? "dotted": highlightStyle,
+ highlightStyle: doc.isGroup ? "dotted": highlightStyle,
highlightColor,
highlightIndex,
highlightStroke: doc.layout_isSvg,
@@ -133,13 +121,12 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps
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.HideLinkBtn:return props?.hideLinkButton || (!selected && doc?.layout_hideLinkButton);
case StyleProp.FontSize: return StrCast(doc?.[fieldKey + 'fontSize'], StrCast(doc?._text_fontSize, StrCast(Doc.UserDoc().fontSize)));
case StyleProp.FontFamily: return StrCast(doc?.[fieldKey + 'fontFamily'], StrCast(doc?._text_fontFamily, StrCast(Doc.UserDoc().fontFamily)));
case StyleProp.FontWeight: return StrCast(doc?.[fieldKey + 'fontWeight'], StrCast(doc?._text_fontWeight, StrCast(Doc.UserDoc().fontWeight)));
case StyleProp.FillColor: return StrCast(doc?._fillColor, StrCast(doc?.fillColor, 'transparent'));
- case StyleProp.ShowCaption:return doc?._type_collection === CollectionViewType.Carousel || props?.hideCaptions ? undefined : StrCast(doc?._layout_showCaption);
- case StyleProp.TitleHeight:return (props?.ScreenToLocalTransform().Scale ?? 1)*(props?.NativeDimScaling?.()??1) * NumCast(Doc.UserDoc().headerHeight,30)
+ case StyleProp.ShowCaption:return props?.hideCaptions || doc?._type_collection === CollectionViewType.Carousel ? undefined: StrCast(doc?._layout_showCaption);
+ case StyleProp.TitleHeight:return (props?.ScreenToLocalTransform().Scale ?? 1) * NumCast(Doc.UserDoc().headerHeight,30);
case StyleProp.ShowTitle:
return (
(doc &&
@@ -159,13 +146,12 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps
''
);
case StyleProp.Color:
- if (DocumentView.LastPressedSidebarBtn === doc) return SettingsManager.userBackgroundColor;
+ if (SettingsManager.Instance.LastPressedBtn === doc) return SettingsManager.userBackgroundColor;
if (Doc.IsSystem(doc!)) return SettingsManager.userColor;
if (doc?.type === DocumentType.FONTICON) return SettingsManager.userColor;
const docColor: Opt<string> = StrCast(doc?.[fieldKey + 'color'], StrCast(doc?._color));
if (docColor) return docColor;
- const docView = props?.DocumentView?.();
- const backColor = backgroundCol() || docView?.props.styleProvider?.(docView.props.treeViewDoc, docView.props, StyleProp.BackgroundColor);
+ const backColor = backgroundCol();
return backColor ? lightOrDark(backColor) : undefined;
case StyleProp.BorderRounding:
return StrCast(doc?.[fieldKey + 'borderRounding'], StrCast(doc?.layout_borderRounding, doc?._type_collection === CollectionViewType.Pile ? '50%' : ''));
@@ -194,19 +180,19 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps
? titleHeight()
: 0;
case StyleProp.BackgroundColor: {
- if (DocumentView.LastPressedSidebarBtn === doc) return SettingsManager.userColor; // hack to indicate active menu panel item
- let docColor: Opt<string> = StrCast(doc?.[fieldKey + '_backgroundColor'], StrCast(doc?._backgroundColor, isCaption ? 'rgba(0,0,0,0.4)' : ''));
+ if (SettingsManager.Instance.LastPressedBtn === doc) return SettingsManager.userColor; // hack to indicate active menu panel item
+ let docColor: Opt<string> = StrCast(doc?.[fieldKey + 'backgroundColor'], StrCast(doc?._backgroundColor, isCaption ? 'rgba(0,0,0,0.4)' : ''));
// prettier-ignore
switch (doc?.type) {
case DocumentType.PRESELEMENT: docColor = docColor || ""; break;
case DocumentType.PRES: docColor = docColor || 'transparent'; break;
case DocumentType.FONTICON: docColor = boxBackground ? undefined : docColor || Colors.DARK_GRAY; break;
- case DocumentType.RTF: docColor = docColor || Colors.LIGHT_GRAY; break;
+ case DocumentType.RTF: docColor = docColor || Colors.LIGHT_GRAY; break;
case DocumentType.LINK: docColor = (isAnchor ? docColor : undefined); break;
case DocumentType.INK: docColor = doc?.stroke_isInkMask ? 'rgba(0,0,0,0.7)' : undefined; break;
case DocumentType.EQUATION: docColor = docColor || 'transparent'; break;
case DocumentType.LABEL: docColor = docColor || Colors.LIGHT_GRAY; break;
- case DocumentType.BUTTON: docColor = docColor || Colors.LIGHT_GRAY; break;
+ case DocumentType.BUTTON: docColor = docColor || Colors.LIGHT_GRAY; break;
case DocumentType.IMG:
case DocumentType.WEB:
case DocumentType.PDF:
@@ -218,7 +204,7 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps
? SettingsManager.userBackgroundColor
: doc.annotationOn
? '#00000010' // faint interior for collections on PDFs, images, etc
- : doc?._isGroup
+ : doc?.isGroup
? undefined
: doc._type_collection === CollectionViewType.Stacking ?
(Colors.DARK_GRAY)
@@ -227,6 +213,9 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps
//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));
+ }
return (docColor && !doc) ? DashColor(docColor).fade(0.5).toString() : docColor;
}
case StyleProp.BoxShadow: {
@@ -239,7 +228,7 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps
doc?.layout_boxShadow,
doc?._type_collection === CollectionViewType.Pile
? '4px 4px 10px 2px'
- : lockedPosition() || doc?._isGroup || docProps?.LayoutTemplateString
+ : lockedPosition() || doc?.isGroup || props?.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')}`
);
@@ -249,40 +238,41 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps
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?.docViewPath().lastElement()?.rootDoc._freeform_useClusters
- ? `${backgroundCol()} ${StrCast(doc.layout_boxShadow, `0vw 0vw ${(lockedPosition() ? 100 : 50) / (docProps?.NativeDimScaling?.() || 1)}px`)}` // if it's just in a cluster, make the shadown roughly match the cluster border extent
+ : 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
: NumCast(doc.group, -1) !== -1
- ? `gray ${StrCast(doc.layout_boxShadow, `0vw 0vw ${(lockedPosition() ? 100 : 50) / (docProps?.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) / (props?.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
+ ? `${Colors.DARK_GRAY} ${StrCast(doc.layout_boxShadow, '0vw 0vw 0.1vw')}`
+ : DocCast(doc.embedContainer)?.type=== DocumentType.RTF // if doc is embedded in a text document (but not an inline)
+ ? `${Colors.DARK_GRAY} ${StrCast(doc.layout_boxShadow, '0.2vw 0.2vw 0.8vw')}`
: StrCast(doc.layout_boxShadow, '');
}
}
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 (docProps?.DocumentView?.().ComponentView?.overridePointerEvents?.() !== undefined) return docProps?.DocumentView?.().ComponentView?.overridePointerEvents?.();
- if (DocumentView.ExploreMode || doc?.layout_unrendered) return isInk() ? 'visiblePainted' : 'all';
+ if (props?.LayoutTemplateString?.includes(KeyValueBox.name)) return 'all';
+ if (SnappingManager.ExploreMode || doc?.layout_unrendered) return isInk() ? 'visiblePainted' : 'all';
if (props?.pointerEvents?.() === 'none') return 'none';
if (opacity() === 0) return 'none';
- if (props?.isGroupActive?.() ) return isInk() ? 'visiblePainted': (doc?._isGroup )? undefined: 'all'
- if (props?.isDocumentActive?.() && !props.treeViewDoc) return isInk() ? 'visiblePainted' : 'all';
+ if (props?.isGroupActive?.() ) return isInk() ? 'visiblePainted': (doc?.
+ isGroup )? undefined: 'all'
+ if (props?.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:
- const lock = () => {
- if (props?.docViewPath().lastElement()?.rootDoc?._type_collection === CollectionViewType.Freeform) {
- return doc?.pointerEvents !== 'none' ? null : (
+ const lock = () => doc?.pointerEvents !== 'none' ? null : (
<div className="styleProvider-lock" onClick={() => toggleLockedPosition(doc)}>
<FontAwesomeIcon icon='lock' size="lg" />
</div>
);
- }
- };
const filter = () => {
const dashView = untracked(() => DocumentManager.Instance.getDocumentView(Doc.ActiveDashboard));
const showFilterIcon =
StrListCast(doc?._childFilters).length || StrListCast(doc?._childFiltersByRanges).length
? 'green' // #18c718bd' //'hasFilter'
- : docProps?.childFilters?.().filter(f => Utils.IsRecursiveFilter(f) && f !== Utils.noDragsDocFilter).length || docProps?.childFiltersByRanges().length
+ : props?.childFilters?.().filter(f => Utils.IsRecursiveFilter(f) && f !== Utils.noDragDocsFilter).length || props?.childFiltersByRanges().length
? 'orange' //'inheritsFilter'
: undefined;
return !showFilterIcon ? null : (
@@ -296,7 +286,7 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps
setSelectedVal={
action((dv) => {
(dv as any).select(false);
- (SettingsManager.propertiesWidth = 250);
+ (SettingsManager.Instance.propertiesWidth = 250);
setTimeout(action(() => {
if (PropertiesView.Instance) {
PropertiesView.Instance.CloseAll();
@@ -313,10 +303,10 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps
"this view inherits filters from one of its parents"}
color={SettingsManager.userColor}
background={showFilterIcon}
- items={[ ...(dashView ? [dashView]: []), ...(props?.docViewPath?.()??[]), ...(props?.DocumentView?[props?.DocumentView?.()]:[])]
- .filter(dv => StrListCast(dv.rootDoc.childFilters).length || StrListCast(dv.rootDoc.childRangeFilters).length)
+ items={[ ...(dashView ? [dashView]: []), ...(props?.docViewPath?.()??[])]
+ .filter(dv => StrListCast(dv?.Document.childFilters).length || StrListCast(dv?.Document.childRangeFilters).length)
.map(dv => ({
- text: StrCast(dv.rootDoc.title),
+ text: StrCast(dv?.Document.title),
val: dv as any,
style: {color:SettingsManager.userColor, background:SettingsManager.userBackgroundColor},
} as IListItemProps)) }
@@ -326,12 +316,12 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps
};
const audio = () => {
const audioAnnoState = (doc: Doc) => StrCast(doc.audioAnnoState, 'stopped');
- const audioAnnosCount = (doc: Doc) => StrListCast(doc[Doc.LayoutFieldKey(doc) + '_audioAnnotations']).length;
+ const audioAnnosCount = (doc: Doc) => StrListCast(doc[fieldKey + 'audioAnnotations']).length;
if (!doc || props?.renderDepth === -1 || !audioAnnosCount(doc)) return null;
const audioIconColors: { [key: string]: string } = { recording: 'red', playing: 'green', stopped: 'blue' };
return (
- <Tooltip title={<div>{StrListCast(doc[Doc.LayoutFieldKey(doc) + '_audioAnnotations_text']).lastElement()}</div>}>
- <div className="styleProvider-audio" onPointerDown={() => DocumentManager.Instance.getFirstDocumentView(doc)?.docView?.playAnnotation()}>
+ <Tooltip title={<div>{StrListCast(doc[fieldKey + 'audioAnnotations_text']).lastElement()}</div>}>
+ <div className="styleProvider-audio" onPointerDown={() => DocumentManager.Instance.getFirstDocumentView(doc)?.playAnnotation()}>
<FontAwesomeIcon className="documentView-audioFont" style={{ color: audioIconColors[audioAnnoState(doc)] }} icon={'file-audio'} size="sm" />
</div>
</Tooltip>
@@ -364,9 +354,9 @@ export function DashboardToggleButton(doc: Doc, field: string, onIcon: IconProp,
);
}
/**
- * add lock and hide button decorations for the "Dashboards" flyout TreeView
+ * add hide button decorations for the "Dashboards" flyout TreeView
*/
-export function DashboardStyleProvider(doc: Opt<Doc>, props: Opt<FieldViewProps | DocumentViewProps>, property: string) {
+export function DashboardStyleProvider(doc: Opt<Doc>, props: Opt<FieldViewProps>, property: string) {
if (doc && property.split(':')[0] === StyleProp.Decorations) {
return doc._type_collection === CollectionViewType.Docking || Doc.IsSystem(doc)
? null