aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/client/apis/gpt/customization.ts18
-rw-r--r--src/client/documents/Documents.ts1
-rw-r--r--src/client/util/DocumentManager.ts6
-rw-r--r--src/client/views/PinFuncs.ts2
-rw-r--r--src/client/views/PropertiesView.tsx2
-rw-r--r--src/client/views/animationtimeline/Timeline.tsx2
-rw-r--r--src/client/views/nodes/DocumentView.tsx18
-rw-r--r--src/client/views/nodes/trails/PresBox.tsx50
-rw-r--r--src/client/views/nodes/trails/PresEnums.ts2
-rw-r--r--src/client/views/nodes/trails/SlideEffect.scss2
-rw-r--r--src/client/views/nodes/trails/SlideEffect.tsx402
-rw-r--r--src/client/views/nodes/trails/SpringUtils.ts2
12 files changed, 134 insertions, 373 deletions
diff --git a/src/client/apis/gpt/customization.ts b/src/client/apis/gpt/customization.ts
index 61b666bd3..2262886a2 100644
--- a/src/client/apis/gpt/customization.ts
+++ b/src/client/apis/gpt/customization.ts
@@ -25,13 +25,13 @@ export const addCustomizationProperty = (type: CustomizationType, name: string,
// includes most fields but is not yet fully comprehensive
export const gptSlideProperties = [
'title',
+ 'config_zoom',
'presentation_transition',
- 'presEaseFunc',
+ 'presentation_easeFunc',
'presentation_effect',
'presentation_effectDirection',
- 'presEffectTiming',
- 'config_zoom',
- 'presPlayAudio',
+ 'presentation_effectTiming',
+ 'presentation_playAudio',
'presentation_zoomText',
'presentation_hideBefore',
'presentation_hide',
@@ -43,20 +43,20 @@ export const gptSlideProperties = [
const setupPresSlideCustomization = () => {
addCustomizationProperty(CustomizationType.PRES_TRAIL_SLIDE, 'title', 'is the title/name of the slide.');
addCustomizationProperty(CustomizationType.PRES_TRAIL_SLIDE, 'presentation_transition', 'is a number in milliseconds for how long it should take to transition/move to a slide.');
- addCustomizationProperty(CustomizationType.PRES_TRAIL_SLIDE, 'presEaseFunc', 'is the easing function for the movement to the slide.', ['Ease', 'Ease In', 'Ease Out', 'Ease Out', 'Ease In Out', 'Linear']);
+ addCustomizationProperty(CustomizationType.PRES_TRAIL_SLIDE, 'presentation_easeFunc', 'is the easing function for the movement to the slide.', ['Ease', 'Ease In', 'Ease Out', 'Ease Out', 'Ease In Out', 'Linear']);
- addCustomizationProperty(CustomizationType.PRES_TRAIL_SLIDE, 'presentation_effect', 'is an effect applied to the slide when we transition to it.', ['None', 'Zoom', 'Fade in', 'Bounce', 'Flip', 'Rotate', 'Roll']);
+ addCustomizationProperty(CustomizationType.PRES_TRAIL_SLIDE, 'presentation_effect', 'is an effect applied to the slide when we transition to it.', ['None', 'Expand', 'Fade in', 'Bounce', 'Flip', 'Rotate', 'Roll']);
addCustomizationProperty(CustomizationType.PRES_TRAIL_SLIDE, 'presentation_effectDirection', 'is what direction the effect is applied.', ['Enter from left', 'Enter from right', 'Enter from bottom', 'Enter from Top', 'Enter from center']);
addCustomizationProperty(
CustomizationType.PRES_TRAIL_SLIDE,
- 'presEffectTiming',
+ 'presentation_effectTiming',
"is a json object of the format: {type: string, stiffness: number, damping: number, mass: number}. Type is always “custom”. Controls the spring-based timing of the presentation effect animation. Stiffness, damping, and mass control the physics-based properties of spring animations. This is used to create a more natural looking timing, bouncy effects, etc. Use spring physics to adjust these parameters to match the user's description of how they want to animate the effect."
);
addCustomizationProperty(CustomizationType.PRES_TRAIL_SLIDE, 'config_zoom', 'is a number from 0 to 1.0 indicating the percentage we should zoom into the slide.');
// boolean values
- addCustomizationProperty(CustomizationType.PRES_TRAIL_SLIDE, 'presPlayAudio', 'is a boolean value indicating if we should play audio when we go to the slide.');
+ addCustomizationProperty(CustomizationType.PRES_TRAIL_SLIDE, 'presentation_playAudio', 'is a boolean value indicating if we should play audio when we go to the slide.');
addCustomizationProperty(CustomizationType.PRES_TRAIL_SLIDE, 'presentation_zoomText', 'is a boolean value indicating if we should zoom into text selections when we go to the slide.');
addCustomizationProperty(CustomizationType.PRES_TRAIL_SLIDE, 'presentation_hideBefore', 'is a boolean value indicating if we should hide the slide before going to it.');
addCustomizationProperty(CustomizationType.PRES_TRAIL_SLIDE, 'presentation_hide', 'is a boolean value indicating if we should hide the slide during the presentation.');
@@ -82,7 +82,7 @@ export const getSlideTransitionSuggestions = async (inputText: string) => {
*/
const prompt =
- "I want to generate four distinct types of slide effect animations. Return a json of the form {effect: string, direction: string, stiffness: number, damping: number, mass: number}[] with four elements. Effect is the type of animation; its only possible values are ['Zoom', 'Fade in', 'Bounce', 'Flip', 'Rotate', 'Roll']. Direction is the direction that the animation starts from; its only possible values are ['Enter from left', 'Enter from right', 'Enter from bottom', 'Enter from Top', 'Enter from center']. Stiffness, damping, and mass control the physics-based properties of spring animations. This is used to create a more natural-looking timing, bouncy effects, etc. Use spring physics to adjust these parameters to animate the effect.";
+ "I want to generate four distinct types of slide effect animations. Return a json of the form {effect: string, direction: string, stiffness: number, damping: number, mass: number}[] with four elements. Effect is the type of animation; its only possible values are ['Expand', 'Fade in', 'Bounce', 'Flip', 'Rotate', 'Roll']. Direction is the direction that the animation starts from; its only possible values are ['Enter from left', 'Enter from right', 'Enter from bottom', 'Enter from Top', 'Enter from center']. Stiffness, damping, and mass control the physics-based properties of spring animations. This is used to create a more natural-looking timing, bouncy effects, etc. Use spring physics to adjust these parameters to animate the effect.";
const customInput = inputText ?? 'Make them as contrasting as possible with different effects and timings ranging from gentle to energetic.';
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 1c18c0d84..24dd5cf37 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -343,6 +343,7 @@ export class DocumentOptions {
config_map?: STRt = new StrInfo('text location of map', false);
config_panX?: NUMt = new NumInfo('panX saved as a view spec', false);
config_panY?: NUMt = new NumInfo('panY saved as a view spec', false);
+ config_zoom?: NUMt = new NumInfo('zoom saved as a view spec', false);
config_viewScale?: NUMt = new NumInfo('viewScale saved as a view Spec', false);
presentation_transition?: NUMt = new NumInfo('the time taken for the transition TO a document', false);
presentation_duration?: NUMt = new NumInfo('the duration of the slide in presentation view', false);
diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts
index 09a8194ca..8ad6ddf47 100644
--- a/src/client/util/DocumentManager.ts
+++ b/src/client/util/DocumentManager.ts
@@ -338,11 +338,13 @@ export class DocumentManager {
// viewSpec !== docView.Document &&
docView.ComponentView?.focus?.(viewSpec, options);
PresBox.restoreTargetDocView(docView, viewSpec, options.zoomTime ?? 500);
- Doc.linkFollowHighlight(viewSpec ? [docView.Document, viewSpec] : docView.Document, undefined, options.effect);
+ // if there's an options.effect, it will be handled from linkFollowHighlight. We delay the start of
+ // the highlight so that the target document can be somewhat centered so that the effect/highlight will be seen
+ // bcz: should this delay be an options parameter?
+ setTimeout(() => Doc.linkFollowHighlight(viewSpec ? [docView.Document, viewSpec] : docView.Document, undefined, options.effect), (options.zoomTime ?? 0) * 0.5);
if (options.playMedia) docView.ComponentView?.playFrom?.(NumCast(docView.Document._layout_currentTimecode));
if (options.playAudio) DocumentManager.playAudioAnno(docView.Document);
if (options.toggleTarget && (!options.didMove || docView.Document.hidden)) docView.Document.hidden = !docView.Document.hidden;
- if (options.effect) docView.Document[Animation] = options.effect;
if (options.zoomTextSelections && Doc.IsUnhighlightTimerSet() && contextView && targetDoc.text_html) {
// if the docView is a text anchor, the contextView is the PDF/Web/Text doc
diff --git a/src/client/views/PinFuncs.ts b/src/client/views/PinFuncs.ts
index 3d998ecaf..430455644 100644
--- a/src/client/views/PinFuncs.ts
+++ b/src/client/views/PinFuncs.ts
@@ -54,7 +54,7 @@ export function PinDocView(pinDocIn: Doc, pinProps: PinProps, targetDoc: Doc) {
pinDoc.config_width = NumCast(targetDoc.width);
pinDoc.config_height = NumCast(targetDoc.height);
}
- if (pinProps.pinAudioPlay) pinDoc.presPlayAudio = true;
+ if (pinProps.pinAudioPlay) pinDoc.presentation_playAudio = true;
if (pinProps.pinData) {
pinDoc.config_pinData =
pinProps.pinData.scrollable ||
diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx
index df4ed98ac..024db82a4 100644
--- a/src/client/views/PropertiesView.tsx
+++ b/src/client/views/PropertiesView.tsx
@@ -1487,7 +1487,7 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
onChange={e => this.changeAnimationBehavior(e.currentTarget.value)}
value={StrCast(this.sourceAnchor?.followLinkAnimEffect, 'default')}>
<option value="default">Default</option>
- {[PresEffect.None, PresEffect.Zoom, PresEffect.Lightspeed, PresEffect.Fade, PresEffect.Flip, PresEffect.Rotate, PresEffect.Bounce, PresEffect.Roll].map(effect => (
+ {[PresEffect.None, PresEffect.Expand, PresEffect.Lightspeed, PresEffect.Fade, PresEffect.Flip, PresEffect.Rotate, PresEffect.Bounce, PresEffect.Roll].map(effect => (
<option key={effect.toString()} value={effect.toString()}>
{effect.toString()}
</option>
diff --git a/src/client/views/animationtimeline/Timeline.tsx b/src/client/views/animationtimeline/Timeline.tsx
index c4d35330b..d9ff21035 100644
--- a/src/client/views/animationtimeline/Timeline.tsx
+++ b/src/client/views/animationtimeline/Timeline.tsx
@@ -547,7 +547,7 @@ export class Timeline extends ObservableReactComponent<FieldViewProps> {
<div key="timeline_info" className="info-container" onPointerDown={this.onPanDown} ref={this._infoContainer} onWheel={this.onWheelZoom}>
{this.drawTicks()}
<div key="timeline_scrubber" className="scrubber" style={{ transform: `translate(${this._currentBarX}px)` }}>
- <div key="timeline_scrubberhead" className="scrubberhead" onPointerDown={this.onScrubberDown}></div>
+ <div key="timeline_scrubberhead" className="scrubberhead" onPointerDown={this.onScrubberDown} />
</div>
<div key="timeline_trackbox" className="trackbox" ref={this._trackbox} style={{ width: `${this._totalLength}px` }}>
{[...this.children, this._props.Document].map(doc => (
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 6f9e14c1b..c59cd0ee4 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -934,7 +934,7 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
borderRadius: this.borderRounding,
pointerEvents: this._pointerEvents === 'visiblePainted' ? 'none' : this._pointerEvents, // visible painted means that the underlying doc contents are irregular and will process their own pointer events (otherwise, the contents are expected to fill the entire doc view box so we can handle pointer events here)
}}>
- {this._componentView?.isUnstyledView?.() ? renderDoc : DocumentViewInternal.AnimationEffect(renderDoc, this.Document[Animation], this.Document)}
+ {this._componentView?.isUnstyledView?.() || this.Document.type === DocumentType.CONFIG ? renderDoc : DocumentViewInternal.AnimationEffect(renderDoc, this.Document[Animation], this.Document)}
{borderPath?.jsx}
</div>
);
@@ -958,7 +958,7 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
duration: Cast(presEffectDoc?.presentation_transition, 'number', Cast(presEffectDoc?.followLinkTransitionTime, 'number', null)),
};
- const timing = StrCast(presEffectDoc?.presEffectTiming);
+ const timing = StrCast(presEffectDoc?.presentation_effectTiming);
let timingConfig: SpringSettings | undefined;
if (timing) {
timingConfig = JSON.parse(timing);
@@ -976,13 +976,13 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
}
switch (StrCast(presEffectDoc?.presentation_effect, StrCast(presEffectDoc?.followLinkAnimEffect))) {
- case PresEffect.Zoom: return <SpringAnimation doc={root} dir={dir} presEffect={PresEffect.Zoom} tension={timingConfig.stiffness} friction={timingConfig.damping} mass={timingConfig.mass}>{renderDoc}</SpringAnimation>
- // case PresEffect.Fade: return <SlideEffect doc={root} dir={dir} presEffect={PresEffect.Fade} tension={timingConfig.stiffness} friction={timingConfig.damping} mass={timingConfig.mass}>{renderDoc}</SlideEffect>
+ case PresEffect.Expand: return <SpringAnimation doc={root} startOpacity={0} dir={dir} presEffect={PresEffect.Expand} springSettings={timingConfig}>{renderDoc}</SpringAnimation>
+ case PresEffect.Flip: return <SpringAnimation doc={root} startOpacity={0} dir={dir} presEffect={PresEffect.Flip} springSettings={timingConfig}>{renderDoc}</SpringAnimation>
+ case PresEffect.Rotate: return <SpringAnimation doc={root} startOpacity={0} dir={dir} presEffect={PresEffect.Rotate} springSettings={timingConfig}>{renderDoc}</SpringAnimation>
+ case PresEffect.Bounce: return <SpringAnimation doc={root} startOpacity={0} dir={dir} presEffect={PresEffect.Bounce} springSettings={timingConfig}>{renderDoc}</SpringAnimation>
+ case PresEffect.Roll: return <SpringAnimation doc={root} startOpacity={0} dir={dir} presEffect={PresEffect.Roll} springSettings={timingConfig}>{renderDoc}</SpringAnimation>
+ // case PresEffect.Fade: return <SlideEffect doc={root} dir={dir} presEffect={PresEffect.Fade} tension={timingConfig.stiffness} friction={timingConfig.damping} mass={timingConfig.mass}>{renderDoc}</SlideEffect>
case PresEffect.Fade: return <Fade {...effectProps}>{renderDoc}</Fade>
- case PresEffect.Flip: return <SpringAnimation doc={root} dir={dir} presEffect={PresEffect.Flip} tension={timingConfig.stiffness} friction={timingConfig.damping} mass={timingConfig.mass}>{renderDoc}</SpringAnimation>
- case PresEffect.Rotate: return <SpringAnimation doc={root} dir={dir} presEffect={PresEffect.Rotate} tension={timingConfig.stiffness} friction={timingConfig.damping} mass={timingConfig.mass}>{renderDoc}</SpringAnimation>
- case PresEffect.Bounce: return <SpringAnimation doc={root} dir={dir} presEffect={PresEffect.Bounce} tension={timingConfig.stiffness} friction={timingConfig.damping} mass={timingConfig.mass}>{renderDoc}</SpringAnimation>
- case PresEffect.Roll: return <SpringAnimation doc={root} dir={dir} presEffect={PresEffect.Roll} tension={timingConfig.stiffness} friction={timingConfig.damping} mass={timingConfig.mass}>{renderDoc}</SpringAnimation>
// keep as preset, doesn't really make sense with spring config
case PresEffect.Lightspeed: return <JackInTheBox {...effectProps}>{renderDoc}</JackInTheBox>;
case PresEffect.None:
@@ -1416,7 +1416,7 @@ export class DocumentView extends DocComponent<DocumentViewProps>() {
<div className="webBox-textHighlight">
<ObserverJsxParser autoCloseVoidElements key={42} onError={(e: any) => console.log('PARSE error', e)} renderInWrapper={false} jsx={StrCast(this._htmlOverlayText)} />
</div>,
- { ...(this._htmlOverlayEffect ?? {}), presentation_effect: effect ?? PresEffect.Zoom } as any as Doc,
+ { ...(this._htmlOverlayEffect ?? {}), presentation_effect: effect ?? PresEffect.Expand } as any as Doc,
this.Document
)}
</div>
diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx
index 69d03ac2e..101f28ae7 100644
--- a/src/client/views/nodes/trails/PresBox.tsx
+++ b/src/client/views/nodes/trails/PresBox.tsx
@@ -185,7 +185,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
@computed
get currCPoints() {
- const strPoints = this.activeItem.presEaseFunc ? StrCast(this.activeItem.presEaseFunc) : 'ease';
+ const strPoints = this.activeItem.presentation_easeFunc ? StrCast(this.activeItem.presentation_easeFunc) : 'ease';
return EaseFuncToPoints(strPoints);
}
@@ -858,9 +858,9 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
effect: activeItem,
noSelect: true,
openLocation: targetDoc.type === DocumentType.PRES ? ((OpenWhere.replace + ':' + PresBox.PanelName) as OpenWhere) : OpenWhere.addLeft,
- easeFunc: StrCast(activeItem.presEaseFunc, 'ease') as any,
+ easeFunc: StrCast(activeItem.presentation_easeFunc, 'ease') as any,
zoomTextSelections: BoolCast(activeItem.presentation_zoomText),
- playAudio: BoolCast(activeItem.presPlayAudio),
+ playAudio: BoolCast(activeItem.presentation_playAudio),
playMedia: activeItem.presentation_mediaStart === 'auto',
};
if (activeItem.presentation_openInLightbox) {
@@ -1575,16 +1575,16 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
@undoBatch
updateEaseFunc = (activeItem: Doc) => {
- activeItem.presEaseFunc = activeItem.presEaseFunc === 'linear' ? 'ease' : 'linear';
+ activeItem.presentation_easeFunc = activeItem.presentation_easeFunc === 'linear' ? 'ease' : 'linear';
this.selectedArray.forEach(doc => {
- doc.presEaseFunc = activeItem.presEaseFunc;
+ doc.presentation_easeFunc = activeItem.presentation_easeFunc;
});
};
setEaseFunc = (activeItem: Doc, easeFunc: string) => {
- activeItem.presEaseFunc = easeFunc;
+ activeItem.presentation_easeFunc = easeFunc;
this.selectedArray.forEach(doc => {
- doc.presEaseFunc = activeItem.presEaseFunc;
+ doc.presentation_easeFunc = activeItem.presentation_easeFunc;
});
};
@@ -1602,9 +1602,9 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
@undoBatch
updateEffectTiming = (activeItem: Doc, timing: SpringSettings) => {
- activeItem.presEffectTiming = JSON.stringify(timing);
+ activeItem.presentation_effectTiming = JSON.stringify(timing);
this.selectedArray.forEach(doc => {
- doc.presEffectTiming = activeItem.presEffectTiming;
+ doc.presentation_effectTiming = activeItem.presentation_effectTiming;
});
};
@@ -1829,7 +1829,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
@computed get transitionDropdown() {
const { activeItem } = this;
// Retrieving spring timing properties
- const timing = StrCast(activeItem.presEffectTiming);
+ const timing = StrCast(activeItem.presentation_effectTiming);
let timingConfig: SpringSettings | undefined;
if (timing) {
timingConfig = JSON.parse(timing);
@@ -1847,8 +1847,8 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
if (activeItem && this.targetDoc) {
const transitionSpeed = activeItem.presentation_transition ? NumCast(activeItem.presentation_transition) / 1000 : 0.5;
const zoom = NumCast(activeItem.config_zoom, 1) * 100;
- const effect = StrCast(activeItem.presentation_effect) ? StrCast(activeItem.presentation_effect) : PresEffect.None;
- const direction = StrCast(activeItem.presentation_effectDirection);
+ const effect = StrCast(activeItem.presentation_effect) ? (StrCast(activeItem.presentation_effect) as any as PresEffect) : PresEffect.None;
+ const direction = StrCast(activeItem.presentation_effectDirection) as PresEffectDirection;
return (
<>
@@ -1876,7 +1876,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
/>
<IconButton
type={Type.TERT}
- color={this.isRecording ? '#2bcaff' : StrCast(Doc.UserDoc().userVariantColor)}
+ color={this.isRecording ? '#2bcaff' : SnappingManager.userVariantColor}
tooltip="Record"
icon={<BiMicrophone size="16px" />}
onClick={() => {
@@ -1894,7 +1894,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
type={Type.TERT}
icon={this.isLoading ? <ReactLoading type="spin" color="#ffffff" width={20} height={20} /> : <AiOutlineSend />}
iconPlacement="right"
- color={StrCast(Doc.UserDoc().userVariantColor)}
+ color={SnappingManager.userVariantColor}
onClick={() => {
this.stopDictation();
this.customizeWithGPT(this.chatInput);
@@ -1919,7 +1919,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
>
Movement
<Dropdown
- color={StrCast(Doc.UserDoc().userColor)}
+ color={SnappingManager.userColor}
formLabel="Movement"
closeOnSelect
items={movementItems}
@@ -1951,11 +1951,11 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
</div>
{/* Easing function */}
<Dropdown
- color={StrCast(Doc.UserDoc().userColor)}
+ color={SnappingManager.userColor}
formLabel="Easing Function"
closeOnSelect
items={easeItems}
- selectedVal={this.activeItem.presEaseFunc ? (StrCast(this.activeItem.presEaseFunc).startsWith('cubic') ? 'custom' : StrCast(this.activeItem.presEaseFunc)) : 'ease'}
+ selectedVal={this.activeItem.presentation_easeFunc ? (StrCast(this.activeItem.presentation_easeFunc).startsWith('cubic') ? 'custom' : StrCast(this.activeItem.presentation_easeFunc)) : 'ease'}
setSelectedVal={val => {
if (typeof val === 'string') {
if (val !== 'custom') {
@@ -2017,7 +2017,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
type={Type.TERT}
icon={this.isLoading ? <ReactLoading type="spin" color="#ffffff" width={20} height={20} /> : <AiOutlineSend />}
iconPlacement="right"
- color={StrCast(Doc.UserDoc().userVariantColor)}
+ color={SnappingManager.userVariantColor}
onClick={this.customizeAnimations}
/>
</div>
@@ -2053,7 +2053,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
mass: elem.mass,
});
}}>
- <SlideEffect dir={elem.direction as PresEffectDirection} presEffect={elem.effect as PresEffect} tension={elem.stiffness} friction={elem.damping} mass={elem.mass} infinite>
+ <SlideEffect dir={elem.direction} presEffect={elem.effect} springSettings={elem} infinite>
<div className="presBox-effect-demo-box" style={{ backgroundColor: springPreviewColors[i] }} />
</SlideEffect>
</div>
@@ -2062,7 +2062,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
</div>
{/* Effect dropdown */}
<Dropdown
- color={StrCast(Doc.UserDoc().userColor)}
+ color={SnappingManager.userColor}
formLabel="Slide Effect"
closeOnSelect
items={effectItems}
@@ -2126,7 +2126,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
{effect !== PresEffect.Lightspeed && (
<>
<Dropdown
- color={StrCast(Doc.UserDoc().userColor)}
+ color={SnappingManager.userColor}
formLabel="Effect Timing"
closeOnSelect
items={effectTimings}
@@ -2208,7 +2208,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
Preview Effect
<div className="presBox-option-block presBox-option-center">
<div className="presBox-effect-container">
- <SlideEffect dir={direction as PresEffectDirection} presEffect={effect as PresEffect} tension={timingConfig.stiffness} friction={timingConfig.damping} mass={timingConfig.mass} infinite>
+ <SlideEffect dir={direction} presEffect={effect} springSettings={timingConfig} infinite>
<div className="presBox-effect-demo-box" style={{ backgroundColor: springPreviewColors[0] }} />
</SlideEffect>
</div>
@@ -2224,9 +2224,9 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
<Toggle
formLabel="Play Audio Annotation"
toggleType={ToggleType.SWITCH}
- toggleStatus={BoolCast(activeItem.presPlayAudio)}
+ toggleStatus={BoolCast(activeItem.presentation_playAudio)}
onClick={() => {
- activeItem.presPlayAudio = !BoolCast(activeItem.presPlayAudio);
+ activeItem.presentation_playAudio = !BoolCast(activeItem.presentation_playAudio);
}}
color={SnappingManager.userColor}
/>
@@ -2239,7 +2239,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
}}
color={SnappingManager.userColor}
/>
- <Button text="Apply to all" type={Type.TERT} color={StrCast(Doc.UserDoc().userVariantColor)} onClick={() => this.applyTo(this.childDocs)} />
+ <Button text="Apply to all" type={Type.TERT} color={SnappingManager.userVariantColor} onClick={() => this.applyTo(this.childDocs)} />
</div>
</div>
</>
diff --git a/src/client/views/nodes/trails/PresEnums.ts b/src/client/views/nodes/trails/PresEnums.ts
index 564829d54..67cad9c5d 100644
--- a/src/client/views/nodes/trails/PresEnums.ts
+++ b/src/client/views/nodes/trails/PresEnums.ts
@@ -7,7 +7,7 @@ export enum PresMovement {
}
export enum PresEffect {
- Zoom = 'Zoom',
+ Expand = 'Expand',
Lightspeed = 'Lightspeed',
Fade = 'Fade in',
Flip = 'Flip',
diff --git a/src/client/views/nodes/trails/SlideEffect.scss b/src/client/views/nodes/trails/SlideEffect.scss
index cc851354e..aa2e5bbd9 100644
--- a/src/client/views/nodes/trails/SlideEffect.scss
+++ b/src/client/views/nodes/trails/SlideEffect.scss
@@ -8,7 +8,7 @@
.flip-side {
position: absolute;
will-change: transform, opacity;
- backface-visibility: hidden;
+ // backface-visibility: hidden;
}
.flip-front {
diff --git a/src/client/views/nodes/trails/SlideEffect.tsx b/src/client/views/nodes/trails/SlideEffect.tsx
index 03cd88f45..00039e3cb 100644
--- a/src/client/views/nodes/trails/SlideEffect.tsx
+++ b/src/client/views/nodes/trails/SlideEffect.tsx
@@ -5,358 +5,116 @@ import { Doc } from '../../../../fields/Doc';
import { NumCast } from '../../../../fields/Types';
import { PresEffect, PresEffectDirection } from './PresEnums';
import './SlideEffect.scss';
+import { emptyFunction } from '../../../../Utils';
interface SlideEffectProps {
- // pass in doc to extract width, height, bg
- doc?: Doc;
+ doc?: Doc; // pass in doc to extract width, height, bg
dir: PresEffectDirection;
presEffect: PresEffect;
- // stiffness (figma) = tension (react-spring)
- tension: number;
- // damping (figma) = friction (react-spring)
- friction: number;
- mass: number;
+ springSettings: {
+ stiffness: number;
+ damping: number;
+ mass: number;
+ };
children: React.ReactNode;
infinite?: boolean;
+ startOpacity?: number; // set to zero to linearly fade in while animating
}
const DEFAULT_WIDTH = 40;
const PREVIEW_OFFSET = 60;
const ACTUAL_OFFSET = 200;
-const infiniteOptions = {
- loop: true,
- delay: 500,
-};
/**
* This component wraps around the doc to create an effect animation, and also wraps the preview animations
* for the effects as well.
*/
-export default function SpringAnimation({ doc, dir, friction, tension, mass, presEffect, children, infinite }: SlideEffectProps) {
- const [springs, api] = useSpring(
- () => ({
- from: {
- x: 0,
- y: 0,
- opacity: 0,
- scale: 1,
- },
- config: {
- tension,
- friction,
- mass,
- },
- onStart: () => {},
- onRest: () => {},
- }),
- [tension, friction, mass]
- );
- const [ref, inView] = useInView({
- once: true,
- });
-
- const zoomConfig = {
- from: {
- scale: 0,
- x: 0,
- y: 0,
- opacity: 1,
- },
- to: {
- scale: 1,
- x: 0,
- y: 0,
- opacity: 1,
- config: {
- tension: tension,
- friction: friction,
- mass: mass,
- },
- },
+export default function SpringAnimation({ doc, dir, springSettings, presEffect, children, infinite, startOpacity }: SlideEffectProps) {
+ const expandConfig = {
+ to: { scale: 1, x: 0, y: 0 },
+ from: { scale: 0, x: 0, y: 0 },
};
-
const fadeConfig = {
- from: {
- opacity: 0,
- scale: 1,
- x: 0,
- y: 0,
- },
- to: {
- opacity: 1,
- scale: 1,
- x: 0,
- y: 0,
- config: {
- tension: tension,
- friction: friction,
- mass: mass,
- },
- },
+ to: { x: 0, y: 0 },
+ from: { x: 0, y: 0 },
};
-
const rotateConfig = {
- from: {
- x: 0,
- },
- to: {
- x: 360,
- config: {
- tension: tension,
- friction: friction,
- mass: mass,
- },
- },
+ to: { x: 360, y: 0 },
+ from: { x: 0, y: 0 },
};
-
- const getBounceConfigFrom = () => {
- switch (dir) {
- case PresEffectDirection.Left:
- return {
- from: {
- opacity: 0,
- x: infinite ? -PREVIEW_OFFSET : -ACTUAL_OFFSET,
- y: 0,
- },
- };
- case PresEffectDirection.Right:
- return {
- from: {
- opacity: 0,
- x: infinite ? PREVIEW_OFFSET : ACTUAL_OFFSET,
- y: 0,
- },
- };
- case PresEffectDirection.Top:
- return {
- from: {
- opacity: 0,
- x: 0,
- y: infinite ? -PREVIEW_OFFSET : -ACTUAL_OFFSET,
- },
- };
- case PresEffectDirection.Bottom:
- return {
- from: {
- opacity: 0,
- x: 0,
- y: infinite ? PREVIEW_OFFSET : ACTUAL_OFFSET,
- },
- };
- default:
- // no movement for center
- return {
- from: {
- opacity: 0,
- x: 0,
- y: 0,
- },
- };
- }
- };
-
- const bounceConfig = {
- ...getBounceConfigFrom(),
- to: [
- {
- opacity: 1,
- x: 0,
- y: 0,
- config: {
- tension: tension,
- friction: friction,
- mass: mass,
- },
- },
- ],
- };
-
const flipConfig = {
- from: {
- x: 0,
- },
- to: {
- x: 180,
- config: {
- tension: tension,
- friction: friction,
- mass: mass,
- },
- },
+ to: { x: 180, y: 0 },
+ from: { x: 0, y: 0 },
};
-
- // only left and right for now
- const getRollConfigFrom = () => {
- switch (dir) {
- case PresEffectDirection.Left:
- return {
- from: {
- opacity: 0,
- x: -100,
- y: -120,
- },
- };
- case PresEffectDirection.Right:
- return {
- from: {
- opacity: 0,
- x: 100,
- y: 120,
- },
- };
- case PresEffectDirection.Top:
- return {
- from: {
- opacity: 0,
- x: -100,
- y: -120,
- },
- };
- case PresEffectDirection.Bottom:
- return {
- from: {
- opacity: 0,
- x: -100,
- y: -120,
- },
- };
- default:
- // no movement for center
- return {
- from: {
- opacity: 0,
- x: 0,
- y: 0,
- },
- };
- }
+ const bounceConfig = {
+ to: { x: 0, y: 0 },
+ from: (() => {
+ const offset = infinite ? PREVIEW_OFFSET : ACTUAL_OFFSET;
+ switch (dir) {
+ case PresEffectDirection.Left: return { x: -offset, y: 0, };
+ case PresEffectDirection.Right: return { x: offset, y: 0, };
+ case PresEffectDirection.Top: return { x: 0, y: -offset, };
+ case PresEffectDirection.Bottom:return { x: 0, y: offset, };
+ default: return { x: 0, y: 0, }; // no movement for center
+ }})(), // prettier-ignore
};
-
const rollConfig = {
- ...getRollConfigFrom(),
- to: {
- opacity: 1,
- x: 0,
- y: 0,
- config: {
- tension: tension,
- friction: friction,
- mass: mass,
- },
- },
+ to: { x: 0, y: 0 },
+ from: (() => {
+ switch (dir) {
+ case PresEffectDirection.Left: return { x: -100, y: -120, };
+ case PresEffectDirection.Right: return { x: 100, y: 120, };
+ case PresEffectDirection.Top: return { x: -100, y: -120, };
+ case PresEffectDirection.Bottom: return { x: -100, y: -120, };
+ default: return { x: 0, y: 0, }; // no movement for center
+ }})(), // prettier-ignore
};
- // Switch animation depending on slide effect
- const startAnimation = () => {
- api.stop();
- let config: any = zoomConfig;
+ // prettier-ignore
+ const effectConfig = (() => {
switch (presEffect) {
- case PresEffect.Bounce:
- config = bounceConfig;
- break;
- case PresEffect.Zoom:
- config = zoomConfig;
- break;
- case PresEffect.Rotate:
- config = rotateConfig;
- break;
- case PresEffect.Fade:
- config = fadeConfig;
- break;
- case PresEffect.Flip:
- config = flipConfig;
- break;
- case PresEffect.Roll:
- config = rollConfig;
- break;
- case PresEffect.Lightspeed:
- break;
- default:
- break;
- }
-
- if (infinite) {
- config = { ...config, ...infiniteOptions };
- }
+ case PresEffect.Fade: return fadeConfig;
+ case PresEffect.Bounce: return bounceConfig;
+ case PresEffect.Rotate: return rotateConfig;
+ case PresEffect.Flip: return flipConfig;
+ case PresEffect.Roll: return rollConfig;
+ case PresEffect.Lightspeed: return { from: {}, to: {} };
+ case PresEffect.Expand:
+ default: return expandConfig;
+ } // prettier-ignore
+ })();
- api.start(config);
- };
-
- const getRenderDoc = () => {
- switch (presEffect) {
- case PresEffect.Rotate:
- return (
- <animated.div ref={ref} style={{ transform: to(springs.x, val => `rotate(${val}deg)`) }}>
- {children}
- </animated.div>
- );
- case PresEffect.Flip:
- return (
- // Pass in doc dimensions
- <div className="flip-container" ref={ref}>
- {dir === PresEffectDirection.Bottom || dir === PresEffectDirection.Top ? (
- <>
- <animated.div
- className="flip-side flip-back"
- style={{
- transform: to(springs.x, val => `perspective(600px) rotateX(${val}deg)`),
- width: doc ? NumCast(doc.width) : DEFAULT_WIDTH,
- height: doc ? NumCast(doc.height) : DEFAULT_WIDTH,
- backgroundColor: infinite ? '#a825ff' : 'rgb(223, 223, 223);',
- }}
- />
- <animated.div
- className="flip-side flip-front"
- style={{ transform: to(springs.x, val => `perspective(600px) rotateX(${val}deg)`), rotateX: '180deg', width: doc ? NumCast(doc.width) : DEFAULT_WIDTH, height: doc ? NumCast(doc.height) : DEFAULT_WIDTH }}>
- {children}
- </animated.div>
- </>
- ) : (
- <>
- <animated.div
- className="flip-side flip-back"
- style={{ transform: to(springs.x, val => `perspective(600px) rotateY(${val}deg)`), width: doc ? NumCast(doc.width) : DEFAULT_WIDTH, height: doc ? NumCast(doc.height) : DEFAULT_WIDTH }}
- />
- <animated.div
- className="flip-side flip-front"
- style={{ transform: to(springs.x, val => `perspective(600px) rotateY(${val}deg)`), rotateY: '180deg', width: doc ? NumCast(doc.width) : DEFAULT_WIDTH, height: doc ? NumCast(doc.height) : DEFAULT_WIDTH }}>
- {children}
- </animated.div>
- </>
- )}
- </div>
- );
- case PresEffect.Roll:
- return (
- <animated.div ref={ref} style={{ opacity: springs.opacity, transform: to([springs.x, springs.y], (val, val2) => `translate3d(${val}%, 0, 0) rotate3d(0, 0, 1, ${val2}deg)`) }}>
- {children}
- </animated.div>
- );
- default:
- return (
- <animated.div
- ref={ref}
- style={{
- ...springs,
- }}>
- {children}
- </animated.div>
- );
- }
- };
-
- useEffect(() => {
- if (infinite || !inView) return;
- setTimeout(() => {
- startAnimation();
- }, 100);
- }, [inView]);
+ const [springs, api] = useSpring(
+ () => ({
+ to: { ...effectConfig.to, opacity: 1 },
+ from: { ...effectConfig.from, opacity: startOpacity ?? 1 },
+ config: { tension: springSettings.stiffness, friction: springSettings.damping, mass: springSettings.mass },
+ onStart: emptyFunction,
+ onRest: emptyFunction,
+ }),
+ [springSettings]
+ );
+ const [ref, inView] = useInView({
+ once: true,
+ });
useEffect(() => {
- if (infinite) {
- startAnimation();
+ if (inView) {
+ api.start({ loop: infinite, delay: infinite ? 500 : 0 });
}
- }, [presEffect, tension, friction, mass]);
-
- return <div>{getRenderDoc()}</div>;
+ }, [inView]);
+ const animatedDiv = (style: any) => (
+ <animated.div ref={ref} style={{ ...style, opacity: to(springs.opacity, val => `${val}`) }}>
+ {children}
+ </animated.div>
+ );
+ const [width, height] = [NumCast(doc?.width, DEFAULT_WIDTH), NumCast(doc?.height, DEFAULT_WIDTH)];
+ const flipAxis = dir === PresEffectDirection.Bottom || dir === PresEffectDirection.Top ? 'X' : 'Y';
+ const [rotateX, rotateY] = flipAxis === 'X' ? ['180deg', undefined] : [undefined, '180deg'];
+ switch (presEffect) {
+ case PresEffect.Flip: return animatedDiv({ transform: to(springs.x, val => `perspective(600px) rotate${flipAxis}(${val}deg)`), width, height, rotateX, rotateY })
+ case PresEffect.Rotate:return animatedDiv({ transform: to(springs.x, val => `rotate(${val}deg)`) });
+ case PresEffect.Roll: return animatedDiv({ transform: to([springs.x, springs.y], (val, val2) => `translate3d(${val}%, 0, 0) rotate3d(0, 0, 1, ${val2}deg)`) });
+ default: return animatedDiv(springs);
+ } // prettier-ignore
}
diff --git a/src/client/views/nodes/trails/SpringUtils.ts b/src/client/views/nodes/trails/SpringUtils.ts
index bfb22c46a..73e1e14f1 100644
--- a/src/client/views/nodes/trails/SpringUtils.ts
+++ b/src/client/views/nodes/trails/SpringUtils.ts
@@ -80,7 +80,7 @@ export const effectItems = Object.values(PresEffect)
export const presEffectDefaultTimings: {
[key: string]: SpringSettings;
} = {
- Zoom: { type: SpringType.GENTLE, stiffness: 100, damping: 15, mass: 1 },
+ Expand: { type: SpringType.GENTLE, stiffness: 100, damping: 15, mass: 1 },
Bounce: {
type: SpringType.BOUNCY,
stiffness: 600,