aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbobzel <zzzman@gmail.com>2024-10-04 20:18:21 -0400
committerbobzel <zzzman@gmail.com>2024-10-04 20:18:21 -0400
commitaa37c6c00ca5caae059edb9244ee90b586892183 (patch)
treeb7cfe96f8b09c43418d578bb43585b3659527531
parentb21d8cc9d1b25ccd2e0103f47ad132dd6f04612d (diff)
parentf63aa4c65f6336c7708c50ced83867702a310240 (diff)
Merge branch 'master' into nathan-starter
-rw-r--r--src/client/views/Main.tsx2
-rw-r--r--src/client/views/collections/CollectionCalendarView.tsx99
-rw-r--r--src/client/views/collections/CollectionCardDeckView.tsx199
-rw-r--r--src/client/views/collections/CollectionCarouselView.tsx3
-rw-r--r--src/client/views/collections/CollectionSubView.tsx2
-rw-r--r--src/client/views/collections/CollectionView.tsx2
-rw-r--r--src/client/views/nodes/DocumentView.tsx1
-rw-r--r--src/client/views/nodes/FieldView.tsx3
-rw-r--r--src/client/views/nodes/calendarBox/CalendarBox.tsx2
-rw-r--r--src/client/views/nodes/formattedText/FormattedTextBox.tsx15
10 files changed, 100 insertions, 228 deletions
diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx
index 73d2872d1..17eea585a 100644
--- a/src/client/views/Main.tsx
+++ b/src/client/views/Main.tsx
@@ -18,7 +18,6 @@ import { TrackMovements } from '../util/TrackMovements';
import { KeyManager } from './GlobalKeyHandler';
import { InkingStroke } from './InkingStroke';
import { MainView } from './MainView';
-import { CollectionCalendarView } from './collections/CollectionCalendarView';
import { CollectionDockingView } from './collections/CollectionDockingView';
import { CollectionView } from './collections/CollectionView';
import { TabDocView } from './collections/TabDocView';
@@ -128,7 +127,6 @@ FieldLoader.ServerLoadStatus = { requested: 0, retrieved: 0, message: 'cache' };
CollectionFreeFormView,
CollectionDockingView,
CollectionSchemaView,
- CollectionCalendarView,
CollectionView,
WebBox,
KeyValueBox,
diff --git a/src/client/views/collections/CollectionCalendarView.tsx b/src/client/views/collections/CollectionCalendarView.tsx
deleted file mode 100644
index 0ea9f8ebc..000000000
--- a/src/client/views/collections/CollectionCalendarView.tsx
+++ /dev/null
@@ -1,99 +0,0 @@
-import { computed, makeObservable } from 'mobx';
-import { observer } from 'mobx-react';
-import * as React from 'react';
-import { emptyFunction } from '../../../Utils';
-import { dateRangeStrToDates, returnTrue } from '../../../ClientUtils';
-import { Doc, DocListCast } from '../../../fields/Doc';
-import { StrCast } from '../../../fields/Types';
-import { CollectionStackingView } from './CollectionStackingView';
-import { CollectionSubView, SubCollectionViewProps } from './CollectionSubView';
-
-@observer
-export class CollectionCalendarView extends CollectionSubView() {
- constructor(props: SubCollectionViewProps) {
- super(props);
- makeObservable(this);
- }
-
- componentDidMount(): void {}
-
- componentWillUnmount(): void {}
-
- @computed get allCalendars() {
- return this.childDocs; // returns a list of docs (i.e. calendars)
- }
-
- removeCalendar = () => {};
-
- addCalendar = (/* doc: Doc | Doc[], annotationKey?: string | undefined */): boolean =>
- // bring up calendar modal with option to create a calendar
- true;
-
- _stackRef = React.createRef<CollectionStackingView>();
-
- panelHeight = () => this._props.PanelHeight() - 40; // this should be the height of the stacking view. For now, it's the hieight of the calendar view minus 40 to allow for a title
-
- // most recent calendar should come first
- sortByMostRecentDate = (calendarA: Doc, calendarB: Doc) => {
- const aDateRangeStr = StrCast(DocListCast(calendarA.data).lastElement()?.date_range);
- const bDateRangeStr = StrCast(DocListCast(calendarB.data).lastElement()?.date_range);
-
- const { start: aFromDate, end: aToDate } = dateRangeStrToDates(aDateRangeStr);
- const { start: bFromDate, end: bToDate } = dateRangeStrToDates(bDateRangeStr);
-
- if (aFromDate > bFromDate) {
- return -1; // a comes first
- }
- if (aFromDate < bFromDate) {
- return 1; // b comes first
- }
- // start dates are the same
- if (aToDate > bToDate) {
- return -1; // a comes first
- }
- if (aToDate < bToDate) {
- return 1; // b comes first
- }
- return 0; // same start and end dates
- };
-
- screenToLocalTransform = () =>
- this._props
- .ScreenToLocalTransform()
- .translate(Doc.NativeWidth(this.Document), 0)
- .scale(this._props.NativeDimScaling?.() || 1);
-
- get calendarsKey() {
- return this._props.fieldKey;
- }
-
- render() {
- return (
- <div className="collectionCalendarView">
- <CollectionStackingView
- // eslint-disable-next-line react/jsx-props-no-spreading
- {...this._props}
- setContentViewBox={emptyFunction}
- ref={this._stackRef}
- PanelHeight={this.panelHeight}
- PanelWidth={this._props.PanelWidth}
- sortFunc={this.sortByMostRecentDate}
- setHeight={undefined}
- isAnnotationOverlay={false}
- // select={emptyFunction} What does this mean?
- isAnyChildContentActive={returnTrue} // ??
- dontCenter="y"
- // childDocumentsActive={}
- // whenChildContentsActiveChanged={}
- childHideDecorationTitle={false}
- removeDocument={this.removeDocument} // will calendar automatically be removed from myCalendars
- moveDocument={this.moveDocument}
- addDocument={this.addCalendar}
- ScreenToLocalTransform={this.screenToLocalTransform}
- renderDepth={this._props.renderDepth + 1}
- fieldKey={this.calendarsKey}
- />
- </div>
- );
- }
-}
diff --git a/src/client/views/collections/CollectionCardDeckView.tsx b/src/client/views/collections/CollectionCardDeckView.tsx
index 101cc8082..a9ab9de26 100644
--- a/src/client/views/collections/CollectionCardDeckView.tsx
+++ b/src/client/views/collections/CollectionCardDeckView.tsx
@@ -2,7 +2,6 @@ import { IReactionDisposer, ObservableMap, action, computed, makeObservable, obs
import { observer } from 'mobx-react';
import * as React from 'react';
import { ClientUtils, DashColor, returnFalse, returnZero } from '../../../ClientUtils';
-import { emptyFunction } from '../../../Utils';
import { Doc } from '../../../fields/Doc';
import { DocData } from '../../../fields/DocSymbols';
import { Id } from '../../../fields/FieldSymbols';
@@ -13,7 +12,6 @@ import { gptImageLabel } from '../../apis/gpt/GPT';
import { DocumentType } from '../../documents/DocumentTypes';
import { DragManager } from '../../util/DragManager';
import { dropActionType } from '../../util/DropActionTypes';
-import { SelectionManager } from '../../util/SelectionManager';
import { SnappingManager } from '../../util/SnappingManager';
import { Transform } from '../../util/Transform';
import { undoable } from '../../util/UndoManager';
@@ -23,12 +21,12 @@ import { DocumentView } from '../nodes/DocumentView';
import { GPTPopup, GPTPopupMode } from '../pdf/GPTPopup/GPTPopup';
import './CollectionCardDeckView.scss';
import { CollectionSubView, SubCollectionViewProps } from './CollectionSubView';
+import { computedFn } from 'mobx-utils';
enum cardSortings {
Time = 'time',
Type = 'type',
Color = 'color',
- Custom = 'custom',
Chat = 'chat',
Tag = 'tag',
None = '',
@@ -46,14 +44,13 @@ export class CollectionCardView extends CollectionSubView() {
private _dropDisposer?: DragManager.DragDropDisposer;
private _disposers: { [key: string]: IReactionDisposer } = {};
private _textToDoc = new Map<string, Doc>();
- private _dropped = false; // indicate when a card doc has just moved;
+ private _dropped = false; // set when a card doc has just moved and the drop method has been called - prevents the pointerUp method from hiding doc decorations (which needs to be done when clicking on a card to animate it to front/center)
@observable _forceChildXf = 0;
@observable _hoveredNodeIndex = -1;
@observable _docRefs = new ObservableMap<Doc, DocumentView>();
@observable _maxRowCount = 10;
@observable _docDraggedIndex: number = -1;
- @observable overIndex: number = -1;
static imageUrlToBase64 = async (imageUrl: string): Promise<string> => {
try {
@@ -101,7 +98,6 @@ export class CollectionCardView extends CollectionSubView() {
componentDidMount() {
this._props.setContentViewBox?.(this);
- // Reaction to cardSort changes
this._disposers.sort = reaction(
() => GPTPopup.Instance.visible,
isVis => {
@@ -135,8 +131,7 @@ export class CollectionCardView extends CollectionSubView() {
}
/**
- * The child documents to be rendered-- either all of them except the Links or the docs in the currently active
- * custom group
+ * The child documents to be rendered-- everything other than ink/link docs (which are marks as being svg's)
*/
@computed get childDocsWithoutLinks() {
return this.childDocs.filter(l => !l.layout_isSvg);
@@ -155,8 +150,7 @@ export class CollectionCardView extends CollectionSubView() {
*/
quizMode = () => {
const randomIndex = Math.floor(Math.random() * this.childDocs.length);
- SelectionManager.DeselectAll();
- DocumentView.SelectView(DocumentView.getDocumentView(this.childDocs[randomIndex]), false);
+ DocumentView.getDocumentView(this.childDocs[randomIndex])?.select(false);
};
/**
@@ -168,29 +162,15 @@ export class CollectionCardView extends CollectionSubView() {
@action
setHoveredNodeIndex = (index: number) => {
- if (!DocumentView.SelectedDocs().includes(this.childDocs[index])) {
- this._hoveredNodeIndex = index;
- }
+ if (!SnappingManager.IsDragging) this._hoveredNodeIndex = index;
};
- /**
- * Translates the hovered node to the center of the screen
- * @param index
- * @returns
- */
- translateHover = (index: number) => (this._hoveredNodeIndex === index && !DocumentView.SelectedDocs().includes(this.childDocs[index]) ? -50 : 0);
-
- isSelected = (index: number) => DocumentView.SelectedDocs().includes(this.childDocs[index]);
-
- /**
- * Returns all the documents except the one that's currently selected
- */
- inactiveDocs = () => this.childDocsWithoutLinks.filter(d => !DocumentView.SelectedDocs().includes(d));
+ isSelected = (doc: Doc) => this._docRefs.get(doc)?.IsSelected;
childPanelWidth = () => NumCast(this.layoutDoc.childPanelWidth, this._props.PanelWidth() / 2);
childPanelHeight = () => this._props.PanelHeight() * this.fitContentScale;
onChildDoubleClick = () => ScriptCast(this.layoutDoc.onChildDoubleClick);
- isContentActive = () => this._props.isSelected() || this._props.isContentActive() || this._props.isAnyChildContentActive();
- isChildContentActive = () => !!this.isContentActive();
+ isContentActive = () => this._props.isSelected() || this._props.isContentActive() || this.isAnyChildContentActive();
+ isAnyChildContentActive = this._props.isAnyChildContentActive;
/**
* Returns the degree to rotate a card dependind on the amount of cards in their row and their index in said row
@@ -202,13 +182,14 @@ export class CollectionCardView extends CollectionSubView() {
if (amCards == 1) return 0;
const possRotate = -30 + index * (30 / ((amCards - (amCards % 2)) / 2));
- const stepMag = Math.abs(-30 + (amCards / 2 - 1) * (30 / ((amCards - (amCards % 2)) / 2)));
-
- if (amCards % 2 === 0 && possRotate === 0) {
- return possRotate + Math.abs(-30 + (index - 1) * (30 / (amCards / 2)));
- }
- if (amCards % 2 === 0 && index > (amCards + 1) / 2) {
- return possRotate + stepMag;
+ if (amCards % 2 === 0) {
+ if (possRotate === 0) {
+ return possRotate + Math.abs(-30 + (index - 1) * (30 / (amCards / 2)));
+ }
+ if (index > (amCards + 1) / 2) {
+ const stepMag = Math.abs(-30 + (amCards / 2 - 1) * (30 / ((amCards - (amCards % 2)) / 2)));
+ return possRotate + stepMag;
+ }
}
return possRotate;
@@ -274,22 +255,13 @@ export class CollectionCardView extends CollectionSubView() {
/**
* Checks to see if a card is being dragged and calls the appropriate methods if so
- * @param e the current pointer event
*/
-
@action
onPointerMove = (x: number, y: number) => {
this._docDraggedIndex = DragManager.docsBeingDragged.length ? this.findCardDropIndex(x, y) : -1;
};
/**
- * Handles external drop of images/PDFs etc from outside Dash.
- */
- onExternalDrop = async (e: React.DragEvent): Promise<void> => {
- super.onExternalDrop(e, {});
- };
-
- /**
* Resets all the doc dragging vairables once a card is dropped
* @param e
* @param de drop event
@@ -326,7 +298,7 @@ export class CollectionCardView extends CollectionSubView() {
}
/**
- * Used to determine how to sort cards based on tags. The lestmost tags are given lower values while cards to the right are
+ * Used to determine how to sort cards based on tags. The leftmost tags are given lower values while cards to the right are
* given higher values. Decimals are used to determine placement for cards with multiple tags
* @param doc the doc whose value is being determined
* @returns its value based on its tags
@@ -352,24 +324,14 @@ export class CollectionCardView extends CollectionSubView() {
docs.sort((docA, docB) => {
const [typeA, typeB] = (() => {
switch (sortType) {
- case cardSortings.Time:
- return [DateCast(docA.author_date)?.date ?? Date.now(), DateCast(docB.author_date)?.date ?? Date.now()];
- case cardSortings.Color: {
- const d1 = DashColor(StrCast(docA.backgroundColor));
- const d2 = DashColor(StrCast(docB.backgroundColor));
- return [d1.hsv().hue(), d2.hsv().hue()];
- }
- case cardSortings.Tag:
- return [this.tagValue(docA) ?? 9999, this.tagValue(docB) ?? 9999];
- case cardSortings.Chat:
- return [NumCast(docA.chatIndex) ?? 9999, NumCast(docB.chatIndex) ?? 9999];
- default:
- return [StrCast(docA.type), StrCast(docB.type)];
+ default:
+ case cardSortings.Type: return [StrCast(docA.type), StrCast(docB.type)];
+ case cardSortings.Chat: return [NumCast(docA.chatIndex, 9999), NumCast(docB.chatIndex,9999)];
+ case cardSortings.Time: return [DateCast(docA.author_date)?.date ?? Date.now(), DateCast(docB.author_date)?.date ?? Date.now()];
+ case cardSortings.Color:return [DashColor(StrCast(docA.backgroundColor)).hsv().hue(), DashColor(StrCast(docB.backgroundColor)).hsv().hue()];
}
- })();
-
- const out = typeA < typeB ? -1 : typeA > typeB ? 1 : 0;
- return isDesc ? out : -out;
+ })(); //prettier-ignore
+ return (typeA < typeB ? -1 : typeA > typeB ? 1 : 0) * (isDesc ? 1 : -1);
});
if (dragIndex !== -1) {
const draggedDoc = DragManager.docsBeingDragged[0];
@@ -382,6 +344,15 @@ export class CollectionCardView extends CollectionSubView() {
return docs;
};
+ isChildContentActive = () =>
+ this._props.isContentActive?.() === false
+ ? false
+ : this._props.isDocumentActive?.() && (this._props.childDocumentsActive?.() || BoolCast(this.Document.childDocumentsActive))
+ ? true
+ : this._props.childDocumentsActive?.() === false || this.Document.childDocumentsActive === false
+ ? false
+ : undefined;
+
displayDoc = (doc: Doc, screenToLocalTransform: () => Transform) => (
<DocumentView
{...this._props}
@@ -396,13 +367,14 @@ export class CollectionCardView extends CollectionSubView() {
LayoutTemplateString={this._props.childLayoutString}
containerViewPath={this.childContainerViewPath}
ScreenToLocalTransform={screenToLocalTransform} // makes sure the box wrapper thing is in the right spot
- isContentActive={emptyFunction}
isDocumentActive={this._props.childDocumentsActive?.() || this.Document._childDocumentsActive ? this._props.isDocumentActive : this.isContentActive}
PanelWidth={this.childPanelWidth}
PanelHeight={this.childPanelHeight}
dontCenter="y" // Don't center it vertically, because the grid it's in is already doing that and we don't want to do it twice.
dragAction={(this.Document.childDragAction ?? this._props.childDragAction) as dropActionType}
showTags={BoolCast(this.layoutDoc.showChildTags)}
+ whenChildContentsActiveChanged={this._props.whenChildContentsActiveChanged}
+ isContentActive={this.isChildContentActive}
dontHideOnDrag
/>
);
@@ -416,13 +388,11 @@ export class CollectionCardView extends CollectionSubView() {
if (this.sortedDocs.length < this._maxRowCount) {
return this.sortedDocs.length;
}
- // 13 - 3 = 10
const totalCards = this.sortedDocs.length;
// if 9 or less
if (index < totalCards - (totalCards % this._maxRowCount)) {
return this._maxRowCount;
}
- // (3)
return totalCards % this._maxRowCount;
};
/**
@@ -443,17 +413,17 @@ export class CollectionCardView extends CollectionSubView() {
/**
* Determines how far to translate a card in the y direction depending on its index, whether or not its being hovered, or if it's selected
* @param isHovered
- * @param isSelected
+ * @param isActive
* @param realIndex
* @param amCards
* @param calcRowIndex
* @returns
*/
- calculateTranslateY = (isHovered: boolean, isSelected: boolean, realIndex: number, amCards: number, calcRowIndex: number) => {
+ calculateTranslateY = (isHovered: boolean, isActive: boolean, realIndex: number, amCards: number, calcRowIndex: number) => {
const rowHeight = (this._props.PanelHeight() * this.fitContentScale) / this.numRows;
const rowIndex = Math.trunc(realIndex / this._maxRowCount);
const rowToCenterShift = this.numRows / 2 - rowIndex;
- if (isSelected) return rowToCenterShift * rowHeight - rowHeight / 2;
+ if (isActive) return rowToCenterShift * rowHeight - rowHeight / 2;
if (amCards == 1) return 50 * this.fitContentScale;
return this.translateY(amCards, calcRowIndex, realIndex);
};
@@ -576,15 +546,43 @@ export class CollectionCardView extends CollectionSubView() {
await this.childPairStringListAndUpdateSortDesc();
};
+ childScreenToLocal = computedFn((doc: Doc, index: number, calcRowIndex: number, isSelected: boolean, amCards: number) => () => {
+ // need to explicitly trigger an invalidation since we're reading everything from the Dom
+ this._forceChildXf;
+ this._props.ScreenToLocalTransform();
+
+ const dref = this._docRefs.get(doc);
+ const { translateX, translateY, scale } = ClientUtils.GetScreenTransform(dref?.ContentDiv);
+ if (!scale) return new Transform(0, 0, 0);
+
+ return new Transform(-translateX + (dref?.centeringX || 0) * scale,
+ -translateY + (dref?.centeringY || 0) * scale, 1)
+ .scale(1 / scale).rotate(!isSelected ? -this.rotate(amCards, calcRowIndex) : 0); // prettier-ignore
+ });
+
+ cardPointerUp = action((doc: Doc) => {
+ // if a card doc has just moved, or a card is selected and in front, then ignore this event
+ if (this.isSelected(doc) || this._dropped) {
+ this._dropped = false;
+ } else {
+ // otherwise, turn off documentDecorations becase we're in a selection transition and want to avoid artifacts.
+ // Turn them back on when the animation has completed and the render and backend structures are in synch
+ SnappingManager.SetIsResizing(doc[Id]);
+ setTimeout(
+ action(() => {
+ SnappingManager.SetIsResizing(undefined);
+ this._forceChildXf++;
+ }),
+ 1000
+ );
+ }
+ });
+
/**
* Actually renders all the cards
*/
@computed get renderCards() {
- const sortedDocs = this.sortedDocs;
- const anySelected = this.childDocs.some(doc => DocumentView.SelectedDocs().includes(doc));
- const isEmpty = this.childDocsWithoutLinks.length === 0;
-
- if (isEmpty) {
+ if (!this.childDocsWithoutLinks.length) {
return (
<span className="no-card-span" style={{ width: ` ${this._props.PanelWidth()}px`, height: ` ${this._props.PanelHeight()}px` }}>
Sorry ! There are no cards in this group
@@ -593,31 +591,18 @@ export class CollectionCardView extends CollectionSubView() {
}
// Map sorted documents to their rendered components
- return sortedDocs.map((doc, index) => {
- const realIndex = sortedDocs.indexOf(doc);
+ return this.sortedDocs.map((doc, index) => {
+ const realIndex = this.sortedDocs.indexOf(doc);
const calcRowIndex = this.overflowIndexCalc(realIndex);
const amCards = this.overflowAmCardsCalc(realIndex);
const view = DocumentView.getDocumentView(doc, this.DocumentView?.());
- const isSelected = view?.ComponentView?.isAnyChildContentActive?.() || view?.IsSelected ? true : false;
- const childScreenToLocal = () => {
- // need to explicitly trigger an invalidation since we're reading everything from the Dom
- this._forceChildXf;
- this._props.ScreenToLocalTransform();
-
- const dref = this._docRefs.get(doc);
- const { translateX, translateY, scale } = ClientUtils.GetScreenTransform(dref?.ContentDiv);
- if (!scale) return new Transform(0, 0, 0);
-
- return new Transform(-translateX + (dref?.centeringX || 0) * scale,
- -translateY + (dref?.centeringY || 0) * scale, 1)
- .scale(1 / scale).rotate(!isSelected ? -this.rotate(amCards, calcRowIndex) : 0); // prettier-ignore
- };
+ const childScreenToLocal = this.childScreenToLocal(doc, index, calcRowIndex, !!view?.IsContentActive, amCards);
const translateIfSelected = () => {
const indexInRow = index % this._maxRowCount;
const rowIndex = Math.trunc(index / this._maxRowCount);
- const rowCenterIndex = Math.min(this._maxRowCount, sortedDocs.length - rowIndex * this._maxRowCount) / 2;
+ const rowCenterIndex = Math.min(this._maxRowCount, this.sortedDocs.length - rowIndex * this._maxRowCount) / 2;
return (rowCenterIndex - indexInRow) * 100 - 50;
};
const aspect = NumCast(doc.height) / NumCast(doc.width, 1);
@@ -627,33 +612,18 @@ export class CollectionCardView extends CollectionSubView() {
return (
<div
key={doc[Id]}
- className={`card-item${isSelected ? '-active' : anySelected ? '-inactive' : ''}`}
- onPointerUp={action(() => {
- // if a card doc has just moved, or a card is selected and in front, then ignore this event
- if (DocumentView.SelectedDocs().includes(doc) || this._dropped) {
- this._dropped = false;
- } else {
- // otherwise, turn off documentDecorations becase we're in a selection transition and want to avoid artifacts.
- // Turn them back on when the animation has completed and the render and backend structures are in synch
- SnappingManager.SetIsResizing(doc[Id]);
- setTimeout(
- action(() => {
- SnappingManager.SetIsResizing(undefined);
- this._forceChildXf++;
- }),
- 1000
- );
- }
- })}
+ className={`card-item${view?.IsContentActive ? '-active' : this.isAnyChildContentActive() ? '-inactive' : ''}`}
+ onPointerUp={() => this.cardPointerUp(doc)}
style={{
width: this.childPanelWidth(),
height: 'max-content',
- transform: `translateY(${this.calculateTranslateY(this._hoveredNodeIndex === index, isSelected, realIndex, amCards, calcRowIndex)}px)
- translateX(calc(${isSelected ? translateIfSelected() : 0}% + ${this.translateOverflowX(realIndex, amCards)}px))
- rotate(${!isSelected ? this.rotate(amCards, calcRowIndex) : 0}deg)
- scale(${isSelected ? `${Math.min(hscale, vscale) * 100}%` : this._hoveredNodeIndex === index ? 1.05 : 1})`,
+ transform: `translateY(${this.calculateTranslateY(this._hoveredNodeIndex === index, !!view?.IsContentActive, realIndex, amCards, calcRowIndex)}px)
+ translateX(calc(${view?.IsContentActive ? translateIfSelected() : 0}% + ${this.translateOverflowX(realIndex, amCards)}px))
+ rotate(${!view?.IsContentActive ? this.rotate(amCards, calcRowIndex) : 0}deg)
+ scale(${view?.IsContentActive ? `${Math.min(hscale, vscale) * 100}%` : this._hoveredNodeIndex === index ? 1.1 : 1})`,
}} // prettier-ignore
- onPointerEnter={() => !SnappingManager.IsDragging && this.setHoveredNodeIndex(index)}>
+ onPointerEnter={() => this.setHoveredNodeIndex(index)}
+ onPointerLeave={() => this.setHoveredNodeIndex(-1)}>
{this.displayDoc(doc, childScreenToLocal)}
</div>
);
@@ -680,8 +650,7 @@ export class CollectionCardView extends CollectionSubView() {
...(!isEmpty && { transform: `scale(${1 / this.fitContentScale})` }),
...(!isEmpty && { height: `${100 * this.fitContentScale}%` }),
gridAutoRows: `${100 / this.numRows}%`,
- }}
- onMouseLeave={() => this.setHoveredNodeIndex(-1)}>
+ }}>
{this.renderCards}
</div>
</div>
diff --git a/src/client/views/collections/CollectionCarouselView.tsx b/src/client/views/collections/CollectionCarouselView.tsx
index 74cf580c9..8b3a699ed 100644
--- a/src/client/views/collections/CollectionCarouselView.tsx
+++ b/src/client/views/collections/CollectionCarouselView.tsx
@@ -165,7 +165,7 @@ export class CollectionCarouselView extends CollectionSubView() {
NativeWidth={returnZero}
NativeHeight={returnZero}
fitWidth={this._props.childLayoutFitWidth}
- showTags={true}
+ showTags={BoolCast(this.layoutDoc.showChildTags)}
containerViewPath={this.childContainerViewPath}
setContentViewBox={undefined}
ScreenToLocalTransform={this.childScreenToLocalXf}
@@ -178,6 +178,7 @@ export class CollectionCarouselView extends CollectionSubView() {
LayoutTemplate={this._props.childLayoutTemplate}
LayoutTemplateString={this._props.childLayoutString}
TemplateDataDocument={DocCast(Doc.Layout(doc).resolvedDataDoc)}
+ xPadding={35}
PanelHeight={this.panelHeight}
/>
);
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index 5d32482c3..581201a20 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -296,7 +296,7 @@ export function CollectionSubView<X>() {
return false;
}
- protected async onExternalDrop(e: React.DragEvent, options: DocumentOptions, completed?: (docs: Doc[]) => void) {
+ protected async onExternalDrop(e: React.DragEvent, options: DocumentOptions = {}, completed?: (docs: Doc[]) => void) {
if (e.ctrlKey) {
e.stopPropagation(); // bcz: this is a hack to stop propagation when dropping an image on a text document with shift+ctrl
return;
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index c9e934448..7418d4360 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -1,4 +1,3 @@
-/* eslint-disable react/jsx-props-no-spreading */
import { IReactionDisposer, makeObservable, observable, reaction } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
@@ -16,7 +15,6 @@ import { ContextMenuProps } from '../ContextMenuItem';
import { ViewBoxAnnotatableComponent } from '../DocComponent';
import { FieldView } from '../nodes/FieldView';
import { OpenWhere } from '../nodes/OpenWhere';
-import { CollectionCalendarView } from './CollectionCalendarView';
import { CollectionCardView } from './CollectionCardDeckView';
import { CollectionCarousel3DView } from './CollectionCarousel3DView';
import { CollectionCarouselView } from './CollectionCarouselView';
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 4a249838b..f84bf6db0 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -1207,6 +1207,7 @@ export class DocumentView extends DocComponent<DocumentViewProps>() {
public set IsSelected(val) { runInAction(() => { this._selected = val; }); } // prettier-ignore
public get IsSelected() { return this._selected; } // prettier-ignore
+ public get IsContentActive(){ return this._docViewInternal?.isContentActive(); } // prettier-ignore
public get topMost() { return this._props.renderDepth === 0; } // prettier-ignore
public get ContentDiv() { return this._docViewInternal?._contentDiv; } // prettier-ignore
public get ComponentView() { return this._docViewInternal?._componentView; } // prettier-ignore
diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx
index a0d69d29d..ba85bfb68 100644
--- a/src/client/views/nodes/FieldView.tsx
+++ b/src/client/views/nodes/FieldView.tsx
@@ -6,7 +6,6 @@ import { DateField } from '../../../fields/DateField';
import { Doc, Field, FieldType, Opt } from '../../../fields/Doc';
import { List } from '../../../fields/List';
import { ScriptField } from '../../../fields/ScriptField';
-import { WebField } from '../../../fields/URLField';
import { dropActionType } from '../../util/DropActionTypes';
import { Transform } from '../../util/Transform';
import { PinProps } from '../PinFuncs';
@@ -14,9 +13,9 @@ import { ViewBoxInterface } from '../ViewBoxInterface';
import { DocumentView } from './DocumentView';
import { FocusViewOptions } from './FocusViewOptions';
import { OpenWhere } from './OpenWhere';
+import { WebField } from '../../../fields/URLField';
export type FocusFuncType = (doc: Doc, options: FocusViewOptions) => Opt<number>;
-// eslint-disable-next-line no-use-before-define
export type StyleProviderFuncType = (
doc: Opt<Doc>,
// eslint-disable-next-line no-use-before-define
diff --git a/src/client/views/nodes/calendarBox/CalendarBox.tsx b/src/client/views/nodes/calendarBox/CalendarBox.tsx
index 678b7dd0b..d38cb5423 100644
--- a/src/client/views/nodes/calendarBox/CalendarBox.tsx
+++ b/src/client/views/nodes/calendarBox/CalendarBox.tsx
@@ -1,4 +1,4 @@
-import { Calendar, DateInput, EventClickArg, EventSourceInput } from '@fullcalendar/core';
+import { Calendar, EventClickArg, EventSourceInput } from '@fullcalendar/core';
import dayGridPlugin from '@fullcalendar/daygrid';
import multiMonthPlugin from '@fullcalendar/multimonth';
import timeGrid from '@fullcalendar/timegrid';
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index 730c57794..c1367aa0b 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -1195,6 +1195,10 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
if (nh) this.layoutDoc._nativeHeight = scrollHeight;
};
+ @computed get tagsHeight() {
+ return this.DocumentView?.().showTags ? Math.max(0, 20 - Math.max(this._props.yPadding ?? 0, NumCast(this.layoutDoc._yMargin))) * this.ScreenToLocalBoxXf().Scale : 0;
+ }
+
@computed get contentScaling() {
return Doc.NativeAspect(this.Document, this.dataDoc, false) ? this._props.NativeDimScaling?.() || 1 : 1;
}
@@ -1222,9 +1226,9 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
);
this._disposers.componentHeights = reaction(
// set the document height when one of the component heights changes and layout_autoHeight is on
- () => ({ sidebarHeight: this.sidebarHeight, textHeight: this.textHeight, layoutAutoHeight: this.layout_autoHeight, marginsHeight: this.layout_autoHeightMargins }),
- ({ sidebarHeight, textHeight, layoutAutoHeight, marginsHeight }) => {
- const newHeight = this.contentScaling * (marginsHeight + Math.max(sidebarHeight, textHeight));
+ () => ({ sidebarHeight: this.sidebarHeight, textHeight: this.textHeight, layoutAutoHeight: this.layout_autoHeight, marginsHeight: this.layout_autoHeightMargins, tagsHeight: this.tagsHeight }),
+ ({ sidebarHeight, textHeight, layoutAutoHeight, marginsHeight, tagsHeight }) => {
+ const newHeight = this.contentScaling * (tagsHeight + marginsHeight + Math.max(sidebarHeight, textHeight));
if (
(!Array.from(FormattedTextBox._globalHighlights).includes('Bold Text') || this._props.isSelected()) && //
layoutAutoHeight &&
@@ -2005,8 +2009,8 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
const scale = this._props.NativeDimScaling?.() || 1;
const rounded = StrCast(this.layoutDoc.layout_borderRounding) === '100%' ? '-rounded' : '';
setTimeout(() => !this._props.isContentActive() && FormattedTextBoxComment.textBox === this && FormattedTextBoxComment.Hide);
- const paddingX = NumCast(this.layoutDoc._xMargin, this._props.xPadding || 0);
- const paddingY = NumCast(this.layoutDoc._yMargin, this._props.yPadding || 0);
+ const paddingX = Math.max(this._props.xPadding ?? 0, NumCast(this.layoutDoc._xMargin));
+ const paddingY = Math.max(this._props.yPadding ?? 0, NumCast(this.layoutDoc._yMargin));
const styleFromLayout = styleFromLayoutString(this.Document, this._props, scale); // this converts any expressions in the format string to style props. e.g., <FormattedTextBox height='{this._header_height}px' >
return styleFromLayout?.height === '0px' ? null : (
<div
@@ -2025,6 +2029,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
height: `${100 / scale}%`,
}),
transition: 'inherit',
+ paddingBottom: this.tagsHeight,
// overflowY: this.layoutDoc._layout_autoHeight ? "hidden" : undefined,
color: this.fontColor,
fontSize: this.fontSize,