diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx | 3 | ||||
-rw-r--r-- | src/client/views/nodes/DocumentView.tsx | 23 | ||||
-rw-r--r-- | src/client/views/nodes/trails/CubicBezierEditor.tsx | 69 | ||||
-rw-r--r-- | src/client/views/nodes/trails/PresBox.scss | 52 | ||||
-rw-r--r-- | src/client/views/nodes/trails/PresBox.tsx | 216 | ||||
-rw-r--r-- | src/client/views/nodes/trails/SlideEffect.tsx | 131 |
6 files changed, 410 insertions, 84 deletions
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index a62ea2eb9..5cc921d85 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -10,7 +10,6 @@ import { DocData, Height, Width } from '../../../../fields/DocSymbols'; import { Id } from '../../../../fields/FieldSymbols'; import { InkData, InkField, InkTool, PointData, Segment } from '../../../../fields/InkField'; import { List } from '../../../../fields/List'; -import { RichTextField } from '../../../../fields/RichTextField'; import { listSpec } from '../../../../fields/Schema'; import { ScriptField } from '../../../../fields/ScriptField'; import { BoolCast, Cast, DocCast, NumCast, ScriptCast, StrCast } from '../../../../fields/Types'; @@ -57,8 +56,8 @@ import { MarqueeView } from './MarqueeView'; import { PropertiesView } from '../../PropertiesView'; import { ExtractColors } from '../../ExtractColors'; import { smartLayout, smartLayout2, StyleInputDocument } from '../../../apis/gpt/customization'; -import { RichTextField } from '../../../../fields/RichTextField'; import { extname } from 'path'; +import { RichTextField } from '../../../../fields/RichTextField'; export interface collectionFreeformViewProps { NativeWidth?: () => number; diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index d131f72d5..3c1896474 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -48,6 +48,7 @@ import { KeyValueBox } from './KeyValueBox'; import { LinkAnchorBox } from './LinkAnchorBox'; import { FormattedTextBox } from './formattedText/FormattedTextBox'; import { PresEffect, PresEffectDirection } from './trails'; +import SlideEffect, { EffectType } from './trails/SlideEffect'; interface Window { MediaRecorder: MediaRecorder; } @@ -1004,18 +1005,34 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document delay: 0, duration: Cast(presEffectDoc?.presentation_transition, 'number', Cast(presEffectDoc?.followLinkTransitionTime, 'number', null)), }; + console.log('dir', dir); + console.log('effect', StrCast(presEffectDoc?.presentation_effect, StrCast(presEffectDoc?.followLinkAnimEffect))); //prettier-ignore + switch (StrCast(presEffectDoc?.presentation_effect, StrCast(presEffectDoc?.followLinkAnimEffect))) { - default: + default: + // package used: react-awesome-reveal case PresEffect.None: return renderDoc; - case PresEffect.Zoom: return <Zoom {...effectProps}>{renderDoc}</Zoom>; + case PresEffect.Zoom: return <SlideEffect effectType={EffectType.ZOOM} tension={300} friction={12} mass={2}>{renderDoc}</SlideEffect> case PresEffect.Fade: return <Fade {...effectProps}>{renderDoc}</Fade>; case PresEffect.Flip: return <Flip {...effectProps}>{renderDoc}</Flip>; case PresEffect.Rotate: return <Rotate {...effectProps}>{renderDoc}</Rotate>; - case PresEffect.Bounce: return <Bounce {...effectProps}>{renderDoc}</Bounce>; + case PresEffect.Bounce: return <SlideEffect effectType={EffectType.BOUNCE} tension={300} friction={12} mass={2}>{renderDoc}</SlideEffect> case PresEffect.Roll: return <Roll {...effectProps}>{renderDoc}</Roll>; case PresEffect.Lightspeed: return <JackInTheBox {...effectProps}>{renderDoc}</JackInTheBox>; } + // switch (StrCast(presEffectDoc?.presentation_effect, StrCast(presEffectDoc?.followLinkAnimEffect))) { + // default: + // // package used: react-awesome-reveal + // case PresEffect.None: return renderDoc; + // case PresEffect.Zoom: return <Zoom {...effectProps}>{renderDoc}</Zoom>; + // case PresEffect.Fade: return <Fade {...effectProps}>{renderDoc}</Fade>; + // case PresEffect.Flip: return <Flip {...effectProps}>{renderDoc}</Flip>; + // case PresEffect.Rotate: return <Rotate {...effectProps}>{renderDoc}</Rotate>; + // case PresEffect.Bounce: return <Bounce {...effectProps}>{renderDoc}</Bounce>; + // case PresEffect.Roll: return <Roll {...effectProps}>{renderDoc}</Roll>; + // case PresEffect.Lightspeed: return <JackInTheBox {...effectProps}>{renderDoc}</JackInTheBox>; + // } } public static recordAudioAnnotation(dataDoc: Doc, field: string, onRecording?: (stop: () => void) => void, onEnd?: () => void) { let gumStream: any; diff --git a/src/client/views/nodes/trails/CubicBezierEditor.tsx b/src/client/views/nodes/trails/CubicBezierEditor.tsx index 06a246675..d6ce9db1f 100644 --- a/src/client/views/nodes/trails/CubicBezierEditor.tsx +++ b/src/client/views/nodes/trails/CubicBezierEditor.tsx @@ -1,8 +1,10 @@ import React, { useEffect, useState } from 'react'; +import { StrCast } from '../../../../fields/Types'; type Props = { setFunc: (newPoints: { p1: number[]; p2: number[] }) => void; currPoints: { p1: number[]; p2: number[] }; + easeFunc: string; }; const ANIMATION_DURATION = 750; @@ -20,7 +22,7 @@ export const TIMING_DEFAULT_MAPPINGS = { 'ease-in-out': 'cubic-bezier(0.42, 0, 0.58, 1.0)', }; -const CubicBezierEditor = ({ setFunc, currPoints }: Props) => { +const CubicBezierEditor = ({ setFunc, currPoints, easeFunc }: Props) => { const [animating, setAnimating] = useState(false); // Should let parent control state const [cPoints, setCPoints] = useState( @@ -38,6 +40,49 @@ const CubicBezierEditor = ({ setFunc, currPoints }: Props) => { return Math.round(num * 100) / 100; }; + const convertToPoints = (func: string) => { + console.log('getting curr c points'); + let strPoints = func ? func : 'ease'; + if (!strPoints.startsWith('cubic')) { + switch (func) { + case 'linear': + strPoints = 'cubic-bezier(0.0, 0.0, 1.0, 1.0)'; + break; + case 'ease': + strPoints = 'cubic-bezier(0.25, 0.1, 0.25, 1.0)'; + break; + case 'ease-in': + strPoints = 'cubic-bezier(0.42, 0, 1.0, 1.0)'; + break; + case 'ease-out': + strPoints = 'cubic-bezier(0, 0, 0.58, 1.0)'; + break; + case 'ease-in-out': + strPoints = 'cubic-bezier(0.42, 0, 0.58, 1.0)'; + break; + default: + strPoints = 'cubic-bezier(0.25, 0.1, 0.25, 1.0)'; + } + } + console.log('str points', strPoints); + const components = strPoints + .split('(')[1] + .split(')')[0] + .split(',') + .map(elem => parseFloat(elem)); + console.log('bezier components', components); + return { + p1: [components[0], components[1]], + p2: [components[2], components[3]], + }; + }; + + useEffect(() => { + if (!easeFunc.startsWith('cubic')) { + setCPoints(convertToPoints(easeFunc)); + } + }, [easeFunc]); + useEffect(() => { if (animating) { setTimeout(() => { @@ -124,6 +169,20 @@ const CubicBezierEditor = ({ setFunc, currPoints }: Props) => { fill="transparent" /> {/* Bottom left */} + <line + onPointerDown={() => { + setC1Down(true); + }} + onPointerUp={() => { + setC1Down(false); + }} + x1={`${0 + OFFSET}`} + y1={`${EDITOR_WIDTH + OFFSET}`} + x2={`${cPoints.p1[0] * EDITOR_WIDTH + OFFSET}`} + y2={`${EDITOR_WIDTH - cPoints.p1[1] * EDITOR_WIDTH + OFFSET}`} + stroke="#00000000" + strokeWidth="5" + /> <line x1={`${0 + OFFSET}`} y1={`${EDITOR_WIDTH + OFFSET}`} x2={`${cPoints.p1[0] * EDITOR_WIDTH + OFFSET}`} y2={`${EDITOR_WIDTH - cPoints.p1[1] * EDITOR_WIDTH + OFFSET}`} stroke="#ffffff" strokeWidth="1" /> <circle cx={`${cPoints.p1[0] * EDITOR_WIDTH + OFFSET}`} @@ -139,6 +198,14 @@ const CubicBezierEditor = ({ setFunc, currPoints }: Props) => { }} /> {/* Top right */} + <line onPointerDown={e => { + e.stopPropagation(); + setC2Down(true); + }} + onPointerUp={e => { + setC2Down(false); + }} x1={`${EDITOR_WIDTH + OFFSET}`} y1={`${0 + OFFSET}`} x2={`${cPoints.p2[0] * EDITOR_WIDTH + OFFSET}`} y2={`${EDITOR_WIDTH - cPoints.p2[1] * EDITOR_WIDTH + OFFSET}`} stroke="#00000000" + strokeWidth="5" /> <line x1={`${EDITOR_WIDTH + OFFSET}`} y1={`${0 + OFFSET}`} x2={`${cPoints.p2[0] * EDITOR_WIDTH + OFFSET}`} y2={`${EDITOR_WIDTH - cPoints.p2[1] * EDITOR_WIDTH + OFFSET}`} stroke="#ffffff" strokeWidth="1" /> <circle cx={`${cPoints.p2[0] * EDITOR_WIDTH + OFFSET}`} diff --git a/src/client/views/nodes/trails/PresBox.scss b/src/client/views/nodes/trails/PresBox.scss index 7f687c2dc..23c170cf7 100644 --- a/src/client/views/nodes/trails/PresBox.scss +++ b/src/client/views/nodes/trails/PresBox.scss @@ -17,6 +17,10 @@ // gap: 16px; } +.presBox-icon-list { + display: flex; + gap: 8px; +} .pres-chatbox-container { padding: 16px; outline: 1px solid #999999; @@ -42,12 +46,15 @@ border-radius: 4px; } -.presBox-easing-function-options { +.presBox-option-block { display: flex; flex-direction: column; - align-items: center; gap: 1rem; - padding: 8px; + // padding: 8px; +} + +.presBox-option-center { + align-items: center; } .presBox-cont { @@ -231,7 +238,9 @@ transition: 0.7s; .ribbon-doubleButton { - display: inline-flex; + display: flex; + justify-content: space-between; + align-items: center; } .presBox-reactiveGrid { @@ -259,16 +268,18 @@ .ribbon-property { font-size: 11; font-weight: 200; - height: 20; - display: flex; - margin-left: 5px; - margin-top: 5px; - margin-bottom: 5px; - width: max-content; - justify-content: center; - align-items: center; - padding-right: 10px; - padding-left: 10px; + padding: 8px; + border-radius: 4px; + // height: 20; + // display: flex; + // margin-left: 5px; + // margin-top: 5px; + // margin-bottom: 5px; + // width: max-content; + // justify-content: center; + // align-items: center; + // padding-right: 10px; + // padding-left: 10px; } .ribbon-propertyUpDown { @@ -465,11 +476,16 @@ } .presBox-input { - width: 30; - height: 100%; - background: none; border: none; - text-align: right; + background-color: transparent; + width: 40; + // padding: 8px; + // border-radius: 4px; + // width: 30; + // height: 100%; + // background: none; + // border: none; + // text-align: right; } .presBox-input:focus { diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx index ed676dff5..d330c8157 100644 --- a/src/client/views/nodes/trails/PresBox.tsx +++ b/src/client/views/nodes/trails/PresBox.tsx @@ -38,12 +38,15 @@ import './PresBox.scss'; import ReactLoading from 'react-loading'; import { PresEffect, PresEffectDirection, PresMovement, PresStatus } from './PresEnums'; import ReactTextareaAutosize from 'react-textarea-autosize'; -import { Button, Dropdown, DropdownType, IconButton, Type } from 'browndash-components'; +import { Button, Dropdown, DropdownType, IconButton, Toggle, ToggleType, Type } from 'browndash-components'; import { BiMicrophone, BiX } from 'react-icons/bi'; import { AiOutlineSend } from 'react-icons/ai'; import { gptSlideProperties, gptTrailSlideCustomization } from '../../../apis/gpt/customization'; import { DictationManager } from '../../../util/DictationManager'; import CubicBezierEditor, { TIMING_DEFAULT_MAPPINGS } from './CubicBezierEditor'; +import Slider from '@mui/material/Slider'; +import { FaArrowDown, FaArrowLeft, FaArrowRight, FaArrowUp, FaCompressArrowsAlt } from 'react-icons/fa'; + export interface pinDataTypes { scrollable?: boolean; dataviz?: number[]; @@ -98,6 +101,21 @@ const easeItems = [ }, ]; +const movementItems = [ + { text: 'None', val: PresMovement.None }, + { text: 'Center', val: PresMovement.Center }, + { text: 'Zoom', val: PresMovement.Zoom }, + { text: 'Pan', val: PresMovement.Pan }, + { text: 'Jump', val: PresMovement.Jump }, +]; + +const effectItems = Object.values(PresEffect) + .filter(v => isNaN(Number(v))) + .map(effect => ({ + text: effect, + val: effect, + })); + @observer export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() { public static LayoutString(fieldKey: string) { @@ -962,6 +980,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() { (DocumentManager.Instance.getFirstDocumentView(targetDoc)?.ComponentView as ScriptingBox)?.onRun?.(); return; } + console.log('pres_effect_dir', StrCast(activeItem.presentation_effectDirection)); const effect = activeItem.presentation_effect && activeItem.presentation_effect !== PresEffect.None ? activeItem.presentation_effect : undefined; // default with effect: 750ms else 500ms const presTime = NumCast(activeItem.presentation_transition, effect ? 750 : 500); @@ -1665,7 +1684,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() { }; @undoBatch - updateEffectDirection = (effect: PresEffectDirection, all?: boolean) => (all ? this.childDocs : this.selectedArray).forEach(doc => (doc.presentation_effectDirection = effect)); + updateEffectDirection = (effectDir: PresEffectDirection, all?: boolean) => (all ? this.childDocs : this.selectedArray).forEach(doc => (doc.presentation_effectDirection = effectDir)); @undoBatch updateEffect = (effect: PresEffect, bullet: boolean, all?: boolean) => (all ? this.childDocs : this.selectedArray).forEach(doc => (bullet ? (doc.presBulletEffect = effect) : (doc.presentation_effect = effect))); @@ -1677,25 +1696,46 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() { }; public static inputter = (min: string, step: string, max: string, value: number, active: boolean, change: (val: string) => void, hmargin?: number) => { return ( - <input - type="range" - step={step} - min={min} - max={max} - value={value} - readOnly={true} - style={{ marginLeft: hmargin, marginRight: hmargin, width: `calc(100% - ${2 * (hmargin ?? 0)}px)`, background: SettingsManager.userColor, color: SettingsManager.userVariantColor }} - className={`toolbar-slider ${active ? '' : 'none'}`} + <div onPointerDown={e => { PresBox._sliderBatch = UndoManager.StartBatch('pres slider'); document.addEventListener('pointerup', PresBox.endBatch, true); e.stopPropagation(); - }} - onChange={e => { - e.stopPropagation(); - change(e.target.value); - }} - /> + }}> + <Slider + onChange={(e, val) => { + e.stopPropagation(); + change(val.toString()); + }} + step={parseFloat(step)} + min={parseFloat(min)} + max={parseFloat(max)} + value={value} + size="small" + defaultValue={value} + aria-label="Small" + valueLabelDisplay="auto" + /> + </div> + // <input + // type="range" + // step={step} + // min={min} + // max={max} + // value={value} + // readOnly={true} + // style={{ marginLeft: hmargin, marginRight: hmargin, width: `calc(100% - ${2 * (hmargin ?? 0)}px)`, background: SettingsManager.userColor, color: SettingsManager.userVariantColor }} + // className={`toolbar-slider ${active ? '' : 'none'}`} + // onPointerDown={e => { + // PresBox._sliderBatch = UndoManager.StartBatch('pres slider'); + // document.addEventListener('pointerup', PresBox.endBatch, true); + // e.stopPropagation(); + // }} + // onChange={e => { + // e.stopPropagation(); + // change(e.target.value); + // }} + // /> ); }; @@ -1920,10 +1960,12 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() { </Tooltip> ); }; + 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 = activeItem.presentation_effect ? activeItem.presentation_effect : PresMovement.None; + return ( <> {/* GPT Component */} @@ -1971,16 +2013,6 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() { this.customizeWithGPT(this.chatInput); }} /> - - {/* <IconButton - type={Type.TERT} - color={!this.isLoading ? StrCast(Doc.UserDoc().userVariantColor) : '#7c7c7c'} - tooltip="Send" - icon={<AiOutlineSend size={'16px'} />} - onClick={() => { - this.customizeWithGPT(this.chatInput); - }} - /> */} </div> </div> <div @@ -1993,22 +2025,9 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() { this._openEffectDropdown = false; this._openBulletEffectDropdown = false; })}> - <div className="ribbon-box"> + <div className="presBox-option-block" style={{ padding: '16px' }}> Movement - {/* <Dropdown - color={StrCast(Doc.UserDoc().userColor)} - formLabel={'Type'} - closeOnSelect={true} - items={bugDropdownItems} - selectedVal={this.formData.type} - setSelectedVal={val => { - if (typeof val === 'string') this.setFormData({ ...this.formData, type: val as BugType }); - }} - dropdownType={DropdownType.SELECT} - type={Type.TERT} - fillWidth - /> */} - <div + {/* <div className="presBox-dropdown" onClick={action(e => { e.stopPropagation(); @@ -2037,20 +2056,32 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() { {presMovement(PresMovement.Pan)} {presMovement(PresMovement.Jump)} </div> - </div> + </div> */} + <Dropdown + color={StrCast(Doc.UserDoc().userColor)} + formLabel={'Movement'} + closeOnSelect={true} + items={movementItems} + selectedVal={this.movementName(activeItem)} + setSelectedVal={val => { + this.updateMovement(val as PresMovement); + }} + dropdownType={DropdownType.SELECT} + type={Type.TERT} + /> <div className="ribbon-doubleButton" style={{ display: activeItem.presentation_movement === PresMovement.Zoom ? 'inline-flex' : 'none' }}> <div className="presBox-subheading">Zoom (% screen filled)</div> <div className="ribbon-property" style={{ border: `solid 1px ${SettingsManager.userColor}` }}> <input className="presBox-input" type="number" readOnly={true} value={zoom} onChange={e => this.updateZoom(e.target.value)} />% </div> - <div className="ribbon-propertyUpDown" style={{ color: SettingsManager.userBackgroundColor, background: SettingsManager.userColor }}> + {/* <div className="ribbon-propertyUpDown" style={{ color: SettingsManager.userBackgroundColor, background: SettingsManager.userColor }}> <div className="ribbon-propertyUpDownItem" onClick={() => this.updateZoom(String(zoom), 0.1)}> <FontAwesomeIcon icon={'caret-up'} /> </div> <div className="ribbon-propertyUpDownItem" onClick={() => this.updateZoom(String(zoom), -0.1)}> <FontAwesomeIcon icon={'caret-down'} /> </div> - </div> + </div> */} </div> {PresBox.inputter('0', '1', '100', zoom, activeItem.presentation_movement === PresMovement.Zoom, this.updateZoom)} <div className="ribbon-doubleButton" style={{ display: 'inline-flex' }}> @@ -2058,23 +2089,23 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() { <div className="ribbon-property" style={{ border: `solid 1px ${SettingsManager.userColor}` }}> <input className="presBox-input" type="number" readOnly={true} value={transitionSpeed} onKeyDown={e => e.stopPropagation()} onChange={action(e => this.updateTransitionTime(e.target.value))} /> s </div> - <div className="ribbon-propertyUpDown" style={{ color: SettingsManager.userBackgroundColor, background: SettingsManager.userColor }}> + {/* <div className="ribbon-propertyUpDown" style={{ color: SettingsManager.userBackgroundColor, background: SettingsManager.userColor }}> <div className="ribbon-propertyUpDownItem" onClick={() => this.updateTransitionTime(String(transitionSpeed), 1000)}> <FontAwesomeIcon icon={'caret-up'} /> </div> <div className="ribbon-propertyUpDownItem" onClick={() => this.updateTransitionTime(String(transitionSpeed), -1000)}> <FontAwesomeIcon icon={'caret-down'} /> </div> - </div> + </div> */} </div> - {PresBox.inputter('0.1', '0.1', '100', transitionSpeed, true, this.updateTransitionTime)} + {PresBox.inputter('0.1', '0.1', '10', transitionSpeed, true, this.updateTransitionTime)} <div className={'slider-headers'}> <div className="slider-text">Fast</div> <div className="slider-text">Medium</div> <div className="slider-text">Slow</div> </div> {/* Easing function */} - <div className="presBox-easing-function-options"> + <div className="presBox-option-block presBox-option-cente"> <Dropdown color={StrCast(Doc.UserDoc().userColor)} formLabel={'Easing Function'} @@ -2092,16 +2123,22 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() { }} dropdownType={DropdownType.SELECT} type={Type.TERT} - // fillWidth /> {/* Custom */} <p className="presBox-submenu-label">Custom Timing Function</p> - <CubicBezierEditor setFunc={this.setBezierControlPoints} currPoints={this.currCPoints} /> + <CubicBezierEditor setFunc={this.setBezierControlPoints} currPoints={this.currCPoints} easeFunc={StrCast(this.activeItem.presEaseFunc)} /> </div> </div> - <div className="ribbon-box"> + <div className="presBox-option-block"> Effects - <div className="ribbon-doubleButton" style={{ display: 'inline-flex' }}> + <Toggle + formLabel={'Play Audio Annotation'} + toggleType={ToggleType.SWITCH} + toggleStatus={BoolCast(activeItem.presPlayAudio)} + onClick={() => (activeItem.presPlayAudio = !BoolCast(activeItem.presPlayAudio))} + color={SettingsManager.userColor} + /> + {/* <div className="ribbon-doubleButton" style={{ display: 'inline-flex' }}> <div className="presBox-subheading">Play Audio Annotation</div> <input className="presBox-checkbox" @@ -2110,8 +2147,15 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() { onChange={() => (activeItem.presPlayAudio = !BoolCast(activeItem.presPlayAudio))} checked={BoolCast(activeItem.presPlayAudio)} /> - </div> - <div className="ribbon-doubleButton" style={{ display: 'inline-flex' }}> + </div> */} + <Toggle + formLabel={'Zoom Text Selections'} + toggleType={ToggleType.SWITCH} + toggleStatus={BoolCast(activeItem.presentation_zoomText)} + onClick={() => (activeItem.presentation_zoomText = !BoolCast(activeItem.presentation_zoomText))} + color={SettingsManager.userColor} + /> + {/* <div className="ribbon-doubleButton" style={{ display: 'inline-flex' }}> <div className="presBox-subheading">Zoom Text Selections</div> <input className="presBox-checkbox" @@ -2120,8 +2164,21 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() { onChange={() => (activeItem.presentation_zoomText = !BoolCast(activeItem.presentation_zoomText))} checked={BoolCast(activeItem.presentation_zoomText)} /> - </div> - <div + </div> */} + {/* Effect dropdown */} + <Dropdown + color={StrCast(Doc.UserDoc().userColor)} + formLabel={'Slide Effect'} + closeOnSelect={true} + items={effectItems} + selectedVal={effect?.toString()} + setSelectedVal={val => { + this.updateEffect(val as PresEffect, false); + }} + dropdownType={DropdownType.SELECT} + type={Type.TERT} + /> + {/* <div className="presBox-dropdown" onClick={action(e => { e.stopPropagation(); @@ -2148,20 +2205,59 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() { .filter(v => isNaN(Number(v))) .map(effect => preseEffect(effect))} </div> - </div> + </div> */} + {/* Effect direction */} <div className="ribbon-doubleButton" style={{ display: effect === PresEffectDirection.None ? 'none' : 'inline-flex' }}> <div className="presBox-subheading">Effect direction</div> <div className="ribbon-property" style={{ border: `solid 1px ${SettingsManager.userColor}` }}> {StrCast(this.activeItem.presentation_effectDirection)} </div> </div> - <div className="effectDirection" style={{ display: effect === PresEffectDirection.None ? 'none' : 'grid', width: 40 }}> + <div className="presBox-icon-list"> + <IconButton + type={Type.TERT} + color={activeItem.presentation_effectDirection === PresEffectDirection.Center ? SettingsManager.userVariantColor : SettingsManager.userBackgroundColor} + tooltip="Center" + icon={<FaCompressArrowsAlt size={'16px'} />} + onClick={() => this.updateEffectDirection(PresEffectDirection.Center)} + /> + <IconButton + type={Type.TERT} + color={activeItem.presentation_effectDirection === PresEffectDirection.Left ? SettingsManager.userVariantColor : SettingsManager.userBackgroundColor} + tooltip="Left" + icon={<FaArrowLeft size={'16px'} />} + onClick={() => this.updateEffectDirection(PresEffectDirection.Left)} + /> + <IconButton + type={Type.TERT} + color={activeItem.presentation_effectDirection === PresEffectDirection.Right ? SettingsManager.userVariantColor : SettingsManager.userBackgroundColor} + tooltip="Right" + icon={<FaArrowRight size={'16px'} />} + onClick={() => this.updateEffectDirection(PresEffectDirection.Right)} + /> + <IconButton + type={Type.TERT} + color={activeItem.presentation_effectDirection === PresEffectDirection.Top ? SettingsManager.userVariantColor : SettingsManager.userBackgroundColor} + tooltip="Top" + icon={<FaArrowUp size={'16px'} />} + onClick={() => this.updateEffectDirection(PresEffectDirection.Top)} + /> + <IconButton + type={Type.TERT} + color={activeItem.presentation_effectDirection === PresEffectDirection.Bottom ? SettingsManager.userVariantColor : SettingsManager.userBackgroundColor} + tooltip="Bottom" + icon={<FaArrowDown size={'16px'} />} + onClick={() => this.updateEffectDirection(PresEffectDirection.Bottom)} + /> + </div> + {/* <div className="effectDirection" style={{ display: effect === PresEffectDirection.None ? 'none' : 'grid', width: 40 }}> {presDirection(PresEffectDirection.Left, 'angle-right', 1, 2, {})} {presDirection(PresEffectDirection.Right, 'angle-left', 3, 2, {})} {presDirection(PresEffectDirection.Top, 'angle-down', 2, 1, {})} {presDirection(PresEffectDirection.Bottom, 'angle-up', 2, 3, {})} {presDirection(PresEffectDirection.Center, '', 2, 2, { width: 10, height: 10, alignSelf: 'center' })} - </div> + </div> */} + {/* Effect spring settings */} </div> <div className="ribbon-final-box"> <div className="ribbon-final-button-hidden" onClick={() => this.applyTo(this.childDocs)}> diff --git a/src/client/views/nodes/trails/SlideEffect.tsx b/src/client/views/nodes/trails/SlideEffect.tsx new file mode 100644 index 000000000..918ea93bd --- /dev/null +++ b/src/client/views/nodes/trails/SlideEffect.tsx @@ -0,0 +1,131 @@ +import { Button } from '@mui/material'; +import { useSpring, animated, easings } from '@react-spring/web'; +import React, { useEffect, useState } from 'react'; + +export enum EffectType { + ZOOM = 'zoom', + FADE = 'fade', + BOUNCE = 'bounce', +} + +interface Props { + effectType: EffectType; + friction: number; + tension: number; + mass: number; + children: React.ReactNode; +} + +export default function SpringAnimation({ friction, tension, mass, effectType, children }: Props) { + const [springs, api] = useSpring( + () => ({ + from: { + x: 0, + y: 0, + opacity: 0, + scale: 1, + }, + config: { + tension: tension, + friction: friction, + mass: mass, + }, + onStart: () => { + console.log('started'); + }, + onRest: () => { + console.log('resting'); + }, + }), + [tension, friction, mass] + ); + + // Whether the animation is currently playing + const [animating, setAnimating] = useState(false); + + const zoomConfig = { + from: { + x: 0, + y: 0, + opacity: 0, + scale: 0, + }, + to: { + x: 0, + y: 0, + opacity: 1, + scale: 1, + config: { + tension: tension, + friction: friction, + mass: mass, + }, + }, + }; + + const bounceConfig = { + from: { + opacity: 0, + x: -200, + y: 0, + }, + to: [ + { + opacity: 1, + x: 0, + y: 0, + config: { + tension: tension, + friction: friction, + mass: mass, + }, + }, + ], + }; + + const handleClick = () => { + if (effectType === EffectType.BOUNCE) { + api.start(bounceConfig); + } else if (effectType === EffectType.ZOOM) { + api.start(zoomConfig); + } + }; + + useEffect(() => { + setTimeout(() => { + handleClick(); + }, 200); + }, []); + + return ( + <div + // className="demo" + // onPointerEnter={() => { + // handleClick(); + // }} + > + {/* style={{ + width: "50px", + height: "50px", + backgroundColor: "#ff6d6d", + borderRadius: "4px", + ...springs, + }} */} + <animated.div + style={{ + // display: 'inline-block', + // transform: 'translate(50px, 50px)', + ...springs, + }}> + {children} + </animated.div> + {/* <Button + onClick={handleClick} + sx={{ marginTop: "100px" }} + variant="contained" + > + Animate + </Button> */} + </div> + ); +} |