From a23e4c26d23224b56ec51d73b38adeb2b54fed6d Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Thu, 6 Feb 2025 14:37:19 -0500
Subject: overhaul of presbox properties ui + fixing bugs with progressivize
 highlight expanding

---
 src/client/views/nodes/trails/PresBox.tsx | 591 ++++++++++++++----------------
 1 file changed, 284 insertions(+), 307 deletions(-)

(limited to 'src/client/views/nodes/trails/PresBox.tsx')

diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx
index 5dbf502d2..28afe1df4 100644
--- a/src/client/views/nodes/trails/PresBox.tsx
+++ b/src/client/views/nodes/trails/PresBox.tsx
@@ -1,4 +1,4 @@
-import { Button, Dropdown, DropdownType, IconButton, Size, Toggle, ToggleType, Type } from '@dash/components';
+import { Button, Dropdown, DropdownType, IconButton, Size, Type } from '@dash/components';
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { Tooltip } from '@mui/material';
 import Slider from '@mui/material/Slider';
@@ -101,8 +101,6 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
     @observable _forceKeyEvents: boolean = false;
 
     @observable _showAIGallery = false;
-    @observable _showBezierEditor = false;
-    @observable _showSpringEditor = false;
     @observable _showPreview = true;
     @observable _easeDropdownVal = 'ease';
 
@@ -150,8 +148,6 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
     setAnimationChat =          action((input: string) => { this._animationChat = input; }); // prettier-ignore
     setIsLoading =              action((input?: boolean) => { this._isLoading = !!input; }); // prettier-ignore
     setIsRecording =            action((input: boolean) => { this._isRecording = input; }); // prettier-ignore
-    setBezierEditorVisibility = action((visible: boolean) => { this._showBezierEditor = visible; }); // prettier-ignore
-    setSpringEditorVisibility = action((visible: boolean) => { this._showSpringEditor = visible; }); // prettier-ignore
     setShowAIGalleryVisibilty = action((visible: boolean) => { this._showAIGallery = visible; }); // prettier-ignore
     setBezierControlPoints = action((newPoints: { p1: number[]; p2: number[] }) => {
         this.setEaseFunc(this.activeItem, `cubic-bezier(${newPoints.p1[0]}, ${newPoints.p1[1]}, ${newPoints.p2[0]}, ${newPoints.p2[1]})`);
@@ -390,7 +386,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                     if (!first) {
                         const presBulletTiming = 500; // bcz: hardwired for now
                         Doc.linkFollowUnhighlight();
-                        Doc.HighlightDoc(listItemDoc);
+                        Doc.linkFollowHighlight(listItemDoc);
                         listItemDoc.presentation_effect = this.activeItem.presBulletEffect;
                         listItemDoc.presentation_transition = presBulletTiming;
                         listItemDoc.opacity = undefined;
@@ -1612,20 +1608,22 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                             </Tooltip>
                         </div>
                         {[DocumentType.AUDIO, DocumentType.VID].includes(targetType as DocumentType) ? null : (
-                            <>
-                                <div className="ribbon-doubleButton">
-                                    <div className="presBox-subheading">Slide Duration</div>
-                                    <div className="ribbon-property" style={{ border: `solid 1px ${SnappingManager.userColor}` }}>
-                                        <input className="presBox-input" type="number" readOnly value={duration} onKeyDown={e => e.stopPropagation()} onChange={e => this.updateDurationTime(e.target.value)} /> s
+                            <div className="ribbon-doubleButton">
+                                <Tooltip title={<div>How long to view the slide before transitioning to the next slide</div>}>
+                                    <div className="presBox-subheading">DURATION</div>
+                                </Tooltip>
+                                <div className="presBox-subheading-slider">
+                                    {PresBox.inputter('0.1', '0.1', '10', duration, targetType !== DocumentType.AUDIO, this.updateDurationTime)}
+                                    <div className="slider-headers">
+                                        <div className="slider-text">Short</div>
+                                        <div className="slider-text">Long</div>
                                     </div>
                                 </div>
-                                {PresBox.inputter('0.1', '0.1', '20', duration, targetType !== DocumentType.AUDIO, this.updateDurationTime)}
-                                <div className="slider-headers" style={{ display: targetType === DocumentType.AUDIO ? 'none' : 'grid' }}>
-                                    <div className="slider-text">Short</div>
-                                    <div className="slider-text">Medium</div>
-                                    <div className="slider-text">Long</div>
+                                <div className="ribbon-property" style={{ border: `solid 1px ${SnappingManager.userColor}`, display: 'flex', maxWidth: 60, width: '100%' }}>
+                                    <input className="presBox-inputNumber" type="number" readOnly value={duration} onKeyDown={e => e.stopPropagation()} onChange={action(e => this.updateDurationTime(e.target.value))} />
+                                    <span>s</span>
                                 </div>
-                            </>
+                            </div>
                         )}
                     </div>
                 </div>
@@ -1633,28 +1631,62 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
         }
         return undefined;
     }
-    @computed get progressivizeDropdown() {
+
+    @computed get mediaDropdown() {
         const { activeItem } = this;
         if (activeItem && this.targetDoc) {
-            const effect = activeItem.presBulletEffect ? activeItem.presBulletEffect : PresMovement.None;
-            const bulletEffect = (presEffect: PresEffect) => (
-                <div
-                    className={`presBox-dropdownOption ${activeItem.presentation_effect === presEffect || (presEffect === PresEffect.None && !activeItem.presentation_effect) ? 'active' : ''}`}
-                    onPointerDown={StopEvent}
-                    onClick={() => this.updateEffect(presEffect, true)}>
-                    {presEffect}
+            return (
+                <div className="presBox-option-block">
+                    <div className="presBox-ribbon presbox-toggles">
+                        <Tooltip title={<div className="dash-tooltip">Should first bullet be progressively disclosed or does it appear with slide.</div>}>
+                            <div
+                                className={`ribbon-toggle ${BoolCast(activeItem.presentation_playAudio) ? 'active' : ''}`}
+                                style={{
+                                    border: `solid 1px ${SnappingManager.userColor}`,
+                                    color: SnappingManager.userColor,
+                                    background: BoolCast(activeItem.presentation_playAudio) ? SnappingManager.userVariantColor : SnappingManager.userBackgroundColor,
+                                }}
+                                onClick={() => {
+                                    activeItem.presentation_playAudio = !BoolCast(activeItem.presentation_playAudio);
+                                }}>
+                                Play Audio Annotation
+                            </div>
+                        </Tooltip>
+                        <Tooltip title={<div className="dash-tooltip">Should first bullet be progressively disclosed or does it appear with slide.</div>}>
+                            <div
+                                className={`ribbon-toggle ${BoolCast(activeItem.presentation_zoomText) ? 'active' : ''}`}
+                                style={{
+                                    border: `solid 1px ${SnappingManager.userColor}`,
+                                    color: SnappingManager.userColor,
+                                    background: BoolCast(activeItem.presentation_zoomText) ? SnappingManager.userVariantColor : SnappingManager.userBackgroundColor,
+                                }}
+                                onClick={() => {
+                                    activeItem.presentation_zoomText = !BoolCast(activeItem.presentation_zoomText);
+                                }}>
+                                Zoom Text Selections
+                            </div>
+                        </Tooltip>
+                    </div>
                 </div>
             );
+        }
+        return null;
+    }
+    @computed get progressivizeDropdown() {
+        const { activeItem } = this;
+        if (activeItem && this.targetDoc) {
             return (
                 <div className="presBox-option-block">
-                    <div className="presBox-ribbon">
-                        <div className="ribbon-doubleButton" style={{ display: 'inline-flex' }}>
-                            <div className="presBox-subheading">Progressivize Collection</div>
-                            <input
-                                className="presBox-checkbox"
-                                style={{ margin: 10, border: `solid 1px ${SnappingManager.userColor}` }}
-                                type="checkbox"
-                                onChange={() => {
+                    <div className="presBox-toggles presBox-ribbon">
+                        <Tooltip title={<div className="dash-tooltip">whether progressivization is active for this slide</div>}>
+                            <div
+                                className={`ribbon-toggle ${Cast(activeItem.presentation_indexed, 'number', null) !== undefined ? 'active' : ''}`}
+                                style={{
+                                    border: `solid 1px ${SnappingManager.userColor}`,
+                                    color: SnappingManager.userColor,
+                                    background: Cast(activeItem.presentation_indexed, 'number', null) !== undefined ? SnappingManager.userVariantColor : SnappingManager.userBackgroundColor,
+                                }}
+                                onClick={() => {
                                     activeItem.presentation_indexed = activeItem.presentation_indexed === undefined ? 0 : undefined;
                                     activeItem.presentation_hideBefore = activeItem.presentation_indexed !== undefined;
                                     const tagDoc = PresBox.targetRenderedDoc(this.activeItem);
@@ -1667,62 +1699,51 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
 
                                     if (DocCast(activeItem.presentation_targetDoc).annotationOn) activeItem.data = ComputedField.MakeFunction(`this.presentation_targetDoc.annotationOn?.["${dataField}"]`);
                                     else activeItem.data = ComputedField.MakeFunction(`this.presentation_targetDoc?.["${dataField}"]`);
+                                }}>
+                                Enable
+                            </div>
+                        </Tooltip>
+                        <Tooltip title={<div className="dash-tooltip">Should first bullet be progressively disclosed or does it appear with slide.</div>}>
+                            <div
+                                className={`ribbon-toggle ${!NumCast(activeItem.presentation_indexedStart) ? 'active' : ''}`}
+                                style={{
+                                    border: `solid 1px ${SnappingManager.userColor}`,
+                                    color: SnappingManager.userColor,
+                                    background: !NumCast(activeItem.presentation_indexedStart) ? SnappingManager.userVariantColor : SnappingManager.userBackgroundColor,
                                 }}
-                                checked={Cast(activeItem.presentation_indexed, 'number', null) !== undefined}
-                            />
-                        </div>
-                        <div className="ribbon-doubleButton" style={{ display: 'inline-flex' }}>
-                            <div className="presBox-subheading">Progressivize First Bullet</div>
-                            <input
-                                className="presBox-checkbox"
-                                style={{ margin: 10, border: `solid 1px ${SnappingManager.userColor}` }}
-                                type="checkbox"
-                                onChange={() => {
+                                onClick={() => {
                                     activeItem.presentation_indexedStart = activeItem.presentation_indexedStart ? 0 : 1;
-                                }}
-                                checked={!NumCast(activeItem.presentation_indexedStart)}
-                            />
-                        </div>
-                        <div className="ribbon-doubleButton" style={{ display: 'inline-flex' }}>
-                            <div className="presBox-subheading">Expand Current Bullet</div>
-                            <input
-                                className="presBox-checkbox"
-                                style={{ margin: 10, border: `solid 1px ${SnappingManager.userColor}` }}
-                                type="checkbox"
-                                onChange={() => {
-                                    activeItem.presBulletExpand = !activeItem.presBulletExpand;
-                                }}
-                                checked={BoolCast(activeItem.presBulletExpand)}
-                            />
-                        </div>
-
-                        <div className="ribbon-box">
-                            Bullet Effect
+                                }}>
+                                All Bullets
+                            </div>
+                        </Tooltip>
+                        <Tooltip title={<div className="dash-tooltip">Whether the active bullet expands when active.</div>}>
                             <div
-                                className="presBox-dropdown"
-                                onClick={action(e => {
-                                    e.stopPropagation();
-                                    this._openBulletEffectDropdown = !this._openBulletEffectDropdown;
-                                })}
+                                className={`ribbon-toggle ${BoolCast(activeItem.presBulletExpand) ? 'active' : ''}`}
                                 style={{
+                                    border: `solid 1px ${SnappingManager.userColor}`,
                                     color: SnappingManager.userColor,
-                                    background: SnappingManager.userVariantColor,
-                                    borderBottomLeftRadius: this._openBulletEffectDropdown ? 0 : 5,
-                                    border: this._openBulletEffectDropdown ? `solid 2px ${SnappingManager.userVariantColor}` : `solid 1px ${SnappingManager.userColor}`,
+                                    background: BoolCast(activeItem.presBulletExpand) ? SnappingManager.userVariantColor : SnappingManager.userBackgroundColor,
+                                }}
+                                onClick={() => {
+                                    activeItem.presBulletExpand = !activeItem.presBulletExpand;
                                 }}>
-                                {effect?.toString()}
-                                <FontAwesomeIcon className="presBox-dropdownIcon" style={{ gridColumn: 2, color: this._openBulletEffectDropdown ? Colors.MEDIUM_BLUE : 'black' }} icon="angle-down" />
-                                <div
-                                    className="presBox-dropdownOptions"
-                                    style={{ display: this._openBulletEffectDropdown ? 'grid' : 'none', color: SnappingManager.userColor, background: SnappingManager.userBackgroundColor }}
-                                    onPointerDown={e => e.stopPropagation()}>
-                                    {Object.values(PresEffect)
-                                        .filter(v => isNaN(Number(v)))
-                                        .map(pEffect => bulletEffect(pEffect))}
-                                </div>
+                                Expand Active
                             </div>
-                        </div>
+                        </Tooltip>
                     </div>
+                    <Dropdown
+                        color={SnappingManager.userColor}
+                        formLabel="Effect"
+                        toolTip="Animation effect to use when bullet activates"
+                        formLabelPlacement="left"
+                        closeOnSelect
+                        items={Object.values(PresEffect).map(v => ({ text: v.toString(), val: v }))}
+                        selectedVal={StrCast(activeItem.presBulletEffect, PresMovement.None)}
+                        setSelectedVal={val => this.updateEffect(val as PresEffect, true)}
+                        dropdownType={DropdownType.SELECT}
+                        type={Type.TERT}
+                    />
                 </div>
             );
         }
@@ -1733,6 +1754,77 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
         return <div />;
     }
 
+    /**
+     * This chatbox is for getting slide effect transition suggestions from gpt and visualizing them
+     */
+    @computed get aiEffects() {
+        return (
+            <div className="presBox-gpt-chat" style={{ display: SnappingManager.PropertiesWidth < 1 || !this._showAIGallery ? 'none' : undefined }}>
+                {/* Custom */}
+                <div className="pres-chat">
+                    <div className="pres-chatbox-container-ai">
+                        <ReactTextareaAutosize
+                            placeholder="Use AI to suggest effects. Leave blank for random results."
+                            className="pres-chatbox"
+                            ref={r => {
+                                setTimeout(() => {
+                                    if (r && !r.textContent) {
+                                        r.style.height = '';
+                                        r.style.height = r.scrollHeight + 'px';
+                                    }
+                                });
+                            }}
+                            value={this._animationChat}
+                            onChange={e => {
+                                e.currentTarget.style.height = '';
+                                e.currentTarget.style.height = e.currentTarget.scrollHeight + 'px';
+                                this.setAnimationChat(e.target.value);
+                            }}
+                            onKeyDown={e => {
+                                this.stopDictation();
+                                e.stopPropagation();
+                            }}
+                        />
+                    </div>
+                    <Button
+                        style={{ alignSelf: 'flex-end' }}
+                        text="Send"
+                        type={Type.TERT}
+                        icon={this._isLoading ? <ReactLoading type="spin" color="#ffffff" width={20} height={20} /> : <AiOutlineSend />}
+                        iconPlacement="right"
+                        color={SnappingManager.userVariantColor}
+                        onClick={this.customizeAnimations}
+                    />
+                </div>
+                <div style={{ alignItems: 'center' }}>
+                    Click a box to use the effect.
+                    {/* Preview Animations  */}
+                    <div className="presBox-effects">
+                        {this.generatedAnimations.map((elem, i) => (
+                            <div
+                                key={i}
+                                className="presBox-effect-container"
+                                onClick={() => {
+                                    this.updateEffect(elem.effect, false);
+                                    this.updateEffectDirection(elem.direction);
+                                    this.updateEffectTiming(this.activeItem, {
+                                        type: SpringType.CUSTOM,
+                                        stiffness: elem.stiffness,
+                                        damping: elem.damping,
+                                        mass: elem.mass,
+                                    });
+                                }}>
+                                <SlideEffect dir={elem.direction} presEffect={elem.effect} springSettings={elem} infinite>
+                                    <div className="presBox-effect-demo-box" style={{ backgroundColor: springPreviewColors[i] }} />
+                                </SlideEffect>
+                            </div>
+                        ))}
+                    </div>
+                </div>
+            </div>
+        );
+    }
+
     @computed get transitionDropdown() {
         const { activeItem } = this;
         // Retrieving spring timing properties
@@ -1827,29 +1919,10 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                             this._openBulletEffectDropdown = false;
                         })}>
                         <div className="presBox-option-block">
-                            <Dropdown
-                                color={SnappingManager.userColor}
-                                formLabel="Navigation"
-                                formLabelPlacement="left"
-                                closeOnSelect
-                                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 ? undefined : 'none' }}>
-                                <Tooltip title={<div>How much (%) of screen target should occupy</div>}>
-                                    <div className="presBox-subheading">ZOOM %</div>
-                                </Tooltip>
-                                <div className="presBox-subheading-slider">{PresBox.inputter('0', '1', '100', zoom, activeItem.presentation_movement === PresMovement.Zoom, this.updateZoom)}</div>
-                                <div className="ribbon-property" style={{ border: `solid 1px ${SnappingManager.userColor}`, display: 'flex', maxWidth: 60, width: '100%' }}>
-                                    <input style={{ maxWidth: 25 }} className="presBox-input" readOnly type="number" value={zoom} onChange={e => this.updateZoom(e.target.value)} />
-                                    <span>%</span>
-                                </div>
-                            </div>
                             <div className="ribbon-doubleButton">
-                                <div className="presBox-subheading">ZOOM/EFFECT TIME</div>
+                                <Tooltip title={<div>How long the transition (view navigation and slide animation effect) lasts</div>}>
+                                    <div className="presBox-subheading">SPEED</div>
+                                </Tooltip>
                                 <div className="presBox-subheading-slider">
                                     {PresBox.inputter('0.1', '0.1', '10', transitionSpeed, true, this.updateTransitionTime)}
                                     <div className="slider-headers">
@@ -1858,153 +1931,55 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                                     </div>
                                 </div>
                                 <div className="ribbon-property" style={{ border: `solid 1px ${SnappingManager.userColor}`, display: 'flex', maxWidth: 60, width: '100%' }}>
-                                    <input style={{ maxWidth: 25 }} className="presBox-input" type="number" readOnly value={transitionSpeed} onKeyDown={e => e.stopPropagation()} onChange={action(e => this.updateTransitionTime(e.target.value))} />
+                                    <input className="presBox-inputNumber" type="number" readOnly value={transitionSpeed} onKeyDown={e => e.stopPropagation()} onChange={action(e => this.updateTransitionTime(e.target.value))} />
                                     <span>s</span>
                                 </div>
                             </div>
-                            {/* Easing function */}
                             <Dropdown
                                 color={SnappingManager.userColor}
-                                formLabel="Timing Function"
+                                formLabel="View"
                                 formLabelPlacement="left"
                                 closeOnSelect
-                                items={easeItems}
-                                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') {
-                                            this.setEaseFunc(this.activeItem, val);
-                                        } else {
-                                            this.setBezierEditorVisibility(true);
-                                            this.setEaseFunc(this.activeItem, TIMING_DEFAULT_MAPPINGS.ease);
-                                        }
-                                    }
-                                }}
+                                items={movementItems}
+                                selectedVal={this.movementName(activeItem)}
+                                setSelectedVal={val => this.updateMovement(val as PresMovement)}
                                 dropdownType={DropdownType.SELECT}
                                 type={Type.TERT}
                             />
-                            {/* Custom */}
-                            <div
-                                className="presBox-show-hide-dropdown"
-                                style={{ alignSelf: 'flex-start' }}
-                                onClick={e => {
-                                    e.stopPropagation();
-                                    this.setBezierEditorVisibility(!this._showBezierEditor);
-                                }}>
-                                TIMING EDITOR
-                                <FontAwesomeIcon icon={this._showBezierEditor ? 'chevron-down' : 'chevron-up'} />
+                            <div className="ribbon-doubleButton" style={{ display: activeItem.presentation_movement === PresMovement.Zoom ? undefined : 'none' }}>
+                                <Tooltip title={<div>How much (%) of screen target should occupy</div>}>
+                                    <div className="presBox-subheading">ZOOM %</div>
+                                </Tooltip>
+                                <div className="presBox-subheading-slider">{PresBox.inputter('0', '1', '100', zoom, activeItem.presentation_movement === PresMovement.Zoom, this.updateZoom)}</div>
+                                <div className="ribbon-property" style={{ border: `solid 1px ${SnappingManager.userColor}`, display: 'flex', maxWidth: 60, width: '100%' }}>
+                                    <input className="presBox-inputNumber" readOnly type="number" value={zoom} onChange={e => this.updateZoom(e.target.value)} />
+                                    <span>%</span>
+                                </div>
                             </div>
+                            {/* Easing function */}
+                            {[PresMovement.None, PresMovement.Jump, ''].includes(StrCast(activeItem.presentation_movement) as PresMovement) ? null : (
+                                <Dropdown
+                                    color={SnappingManager.userColor}
+                                    formLabel="Timing"
+                                    formLabelPlacement="left"
+                                    closeOnSelect
+                                    items={easeItems}
+                                    selectedVal={this.activeItem.presentation_easeFunc ? (StrCast(this.activeItem.presentation_easeFunc).startsWith('cubic') ? 'custom' : StrCast(this.activeItem.presentation_easeFunc)) : 'ease'}
+                                    setSelectedVal={val => typeof val === 'string' && this.setEaseFunc(this.activeItem, val !== 'custom' ? val : TIMING_DEFAULT_MAPPINGS.ease)}
+                                    dropdownType={DropdownType.SELECT}
+                                    type={Type.TERT}
+                                />
+                            )}
                         </div>
                     </div>
 
                     {/* Cubic bezier editor */}
-                    {this._showBezierEditor && (
+                    {StrCast(activeItem.presentation_easeFunc).includes('cubic-bezier') && (
                         <div className="presBox-option-block" style={{ paddingTop: 0, alignItems: 'center' }}>
                             <CubicBezierEditor setFunc={this.setBezierControlPoints} currPoints={this.currCPoints} />
                         </div>
                     )}
 
-                    {effect === PresEffect.None ? null : (
-                        <div className="presBox-previewContainer">
-                            <Button
-                                type={Type.TERT}
-                                tooltip="show preview of slide animation effect"
-                                size={Size.SMALL}
-                                color={SnappingManager.userColor}
-                                background={'transparent'}
-                                onClick={action(() => {
-                                    this._showPreview = false;
-                                    setTimeout(action(() => { this._showPreview = true; }) ); // prettier-ignore
-                                })}
-                                text="Preview Effect"
-                            />
-                            <div className="presBox-option-block presBox-option-center">
-                                <div className="presBox-effect-container">
-                                    {!this._showPreview ? null : (
-                                        <SlideEffect dir={direction} presEffect={effect} springSettings={timingConfig}>
-                                            <div className="presBox-effect-demo-box" style={{ backgroundColor: springPreviewColors[0] }} />
-                                        </SlideEffect>
-                                    )}
-                                </div>
-                            </div>
-                        </div>
-                    )}
-
-                    {/* This chatbox is for getting slide effect transition suggestions from gpt and visualizing them */}
-                    <div className="presBox-gpt-chat" style={{ display: SnappingManager.PropertiesWidth < 1 ? 'none' : undefined }}>
-                        {/* Custom */}
-                        <div
-                            className="presBox-show-hide-dropdown"
-                            style={{ alignSelf: 'flex-start' }}
-                            onClick={e => {
-                                e.stopPropagation();
-                                this.setShowAIGalleryVisibilty(!this._showAIGallery);
-                            }}>
-                            AI EFFECTS
-                            <FontAwesomeIcon icon={this._showAIGallery ? 'chevron-down' : 'chevron-up'} />
-                        </div>
-                        <div className="pres-chat" style={{ display: this._showAIGallery ? undefined : 'none' }}>
-                            <div className="pres-chatbox-container-ai">
-                                <ReactTextareaAutosize
-                                    placeholder="Use AI to suggest effects. Leave blank for random results."
-                                    className="pres-chatbox"
-                                    ref={r => {
-                                        setTimeout(() => {
-                                            if (r && !r.textContent) {
-                                                r.style.height = '';
-                                                r.style.height = r.scrollHeight + 'px';
-                                            }
-                                        });
-                                    }}
-                                    value={this._animationChat}
-                                    onChange={e => {
-                                        e.currentTarget.style.height = '';
-                                        e.currentTarget.style.height = e.currentTarget.scrollHeight + 'px';
-                                        this.setAnimationChat(e.target.value);
-                                    }}
-                                    onKeyDown={e => {
-                                        this.stopDictation();
-                                        e.stopPropagation();
-                                    }}
-                                />
-                            </div>
-                            <Button
-                                style={{ alignSelf: 'flex-end' }}
-                                text="Send"
-                                type={Type.TERT}
-                                icon={this._isLoading ? <ReactLoading type="spin" color="#ffffff" width={20} height={20} /> : <AiOutlineSend />}
-                                iconPlacement="right"
-                                color={SnappingManager.userVariantColor}
-                                onClick={this.customizeAnimations}
-                            />
-                        </div>
-                        <div style={{ display: this._showAIGallery ? 'flex' : 'none', alignItems: 'center' }}>
-                            Click a box to use the effect.
-                            {/* Preview Animations  */}
-                            <div className="presBox-effects">
-                                {this.generatedAnimations.map((elem, i) => (
-                                    <div
-                                        key={i}
-                                        className="presBox-effect-container"
-                                        onClick={() => {
-                                            this.updateEffect(elem.effect, false);
-                                            this.updateEffectDirection(elem.direction);
-                                            this.updateEffectTiming(this.activeItem, {
-                                                type: SpringType.CUSTOM,
-                                                stiffness: elem.stiffness,
-                                                damping: elem.damping,
-                                                mass: elem.mass,
-                                            });
-                                        }}>
-                                        <SlideEffect dir={elem.direction} presEffect={elem.effect} springSettings={elem} infinite>
-                                            <div className="presBox-effect-demo-box" style={{ backgroundColor: springPreviewColors[i] }} />
-                                        </SlideEffect>
-                                    </div>
-                                ))}
-                            </div>
-                        </div>
-                    </div>
-
                     <div
                         className={`presBox-ribbon ${this._transitionTools && this.layoutDoc.presentation_status === PresStatus.Edit ? 'active' : ''}`}
                         onPointerDown={StopEvent}
@@ -2017,10 +1992,11 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                         })}>
                         <div className="presBox-option-block">
                             {/* Effect dropdown */}
-                            <div>
+                            <div style={{ display: 'flex' }}>
                                 <Dropdown
                                     color={SnappingManager.userColor}
-                                    formLabel="Slide Effect"
+                                    formLabel="Effect"
+                                    toolTip="Animation effect to apply when transitiong to slide"
                                     formLabelPlacement="left"
                                     closeOnSelect
                                     items={effectItems}
@@ -2033,58 +2009,68 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                                     dropdownType={DropdownType.SELECT}
                                     type={Type.TERT}
                                 />
+
+                                <div
+                                    className={`ribbon-toggle ${this._showAIGallery ? 'active' : ''}`}
+                                    style={{
+                                        border: `solid 1px ${SnappingManager.userColor}`,
+                                        color: SnappingManager.userColor,
+                                        background: this._showAIGallery ? SnappingManager.userVariantColor : SnappingManager.userBackgroundColor,
+                                    }}
+                                    onClick={() => this.setShowAIGalleryVisibilty(!this._showAIGallery)}>
+                                    MORE
+                                </div>
                             </div>
+                            {this.aiEffects}
                             <div className="presBox-gpt-chat">
                                 {/* Effect direction */}
                                 {/* Only applies to certain effects */}
                                 {(effect === PresEffect.Flip || effect === PresEffect.Bounce || effect === PresEffect.Roll) && (
-                                    <>
-                                        <div className="ribbon-doubleButton">
-                                            <div className="presBox-subheading">EFFECT DIRECTION</div>
-                                            <div style={{ width: '100%' }}>
-                                                <div className="presBox-icon-list" style={{ width: 'fit-content', margin: 'auto' }}>
-                                                    <IconButton
-                                                        type={Type.TERT}
-                                                        color={activeItem.presentation_effectDirection === PresEffectDirection.Left ? SnappingManager.userVariantColor : SnappingManager.userBackgroundColor}
-                                                        tooltip="Left"
-                                                        icon={<FaArrowRight size="16px" />}
-                                                        onClick={() => this.updateEffectDirection(PresEffectDirection.Left)}
-                                                    />
-                                                    <IconButton
-                                                        type={Type.TERT}
-                                                        color={activeItem.presentation_effectDirection === PresEffectDirection.Right ? SnappingManager.userVariantColor : SnappingManager.userBackgroundColor}
-                                                        tooltip="Right"
-                                                        icon={<FaArrowLeft size="16px" />}
-                                                        onClick={() => this.updateEffectDirection(PresEffectDirection.Right)}
-                                                    />
-                                                    {effect !== PresEffect.Roll && (
-                                                        <>
-                                                            <IconButton
-                                                                type={Type.TERT}
-                                                                color={activeItem.presentation_effectDirection === PresEffectDirection.Top ? SnappingManager.userVariantColor : SnappingManager.userBackgroundColor}
-                                                                tooltip="Top"
-                                                                icon={<FaArrowDown size="16px" />}
-                                                                onClick={() => this.updateEffectDirection(PresEffectDirection.Top)}
-                                                            />
-                                                            <IconButton
-                                                                type={Type.TERT}
-                                                                color={activeItem.presentation_effectDirection === PresEffectDirection.Bottom ? SnappingManager.userVariantColor : SnappingManager.userBackgroundColor}
-                                                                tooltip="Bottom"
-                                                                icon={<FaArrowUp size="16px" />}
-                                                                onClick={() => this.updateEffectDirection(PresEffectDirection.Bottom)}
-                                                            />
-                                                        </>
-                                                    )}
-                                                </div>
+                                    <div className="ribbon-doubleButton">
+                                        <div className="presBox-subheading">DIRECTION</div>
+                                        <div style={{ width: '100%' }}>
+                                            <div className="presBox-icon-list" style={{ width: 'fit-content', margin: 'auto' }}>
+                                                <IconButton
+                                                    type={Type.TERT}
+                                                    color={activeItem.presentation_effectDirection === PresEffectDirection.Left ? SnappingManager.userVariantColor : SnappingManager.userBackgroundColor}
+                                                    tooltip="Left"
+                                                    icon={<FaArrowRight size="16px" />}
+                                                    onClick={() => this.updateEffectDirection(PresEffectDirection.Left)}
+                                                />
+                                                <IconButton
+                                                    type={Type.TERT}
+                                                    color={activeItem.presentation_effectDirection === PresEffectDirection.Right ? SnappingManager.userVariantColor : SnappingManager.userBackgroundColor}
+                                                    tooltip="Right"
+                                                    icon={<FaArrowLeft size="16px" />}
+                                                    onClick={() => this.updateEffectDirection(PresEffectDirection.Right)}
+                                                />
+                                                {effect !== PresEffect.Roll && (
+                                                    <>
+                                                        <IconButton
+                                                            type={Type.TERT}
+                                                            color={activeItem.presentation_effectDirection === PresEffectDirection.Top ? SnappingManager.userVariantColor : SnappingManager.userBackgroundColor}
+                                                            tooltip="Top"
+                                                            icon={<FaArrowDown size="16px" />}
+                                                            onClick={() => this.updateEffectDirection(PresEffectDirection.Top)}
+                                                        />
+                                                        <IconButton
+                                                            type={Type.TERT}
+                                                            color={activeItem.presentation_effectDirection === PresEffectDirection.Bottom ? SnappingManager.userVariantColor : SnappingManager.userBackgroundColor}
+                                                            tooltip="Bottom"
+                                                            icon={<FaArrowUp size="16px" />}
+                                                            onClick={() => this.updateEffectDirection(PresEffectDirection.Bottom)}
+                                                        />
+                                                    </>
+                                                )}
                                             </div>
                                         </div>
-                                    </>
+                                    </div>
                                 )}
                                 {effect !== PresEffect.Lightspeed && (
                                     <>
                                         <Dropdown
                                             color={SnappingManager.userColor}
-                                            formLabel="Effect Timing"
+                                            formLabel="Springiness"
                                             formLabelPlacement="left"
                                             closeOnSelect
                                             items={effectTimings}
@@ -2095,20 +2081,8 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                                         />
 
                                         <div style={{ display: SnappingManager.PropertiesWidth < 1 ? 'none' : undefined }}>
-                                            {/* Custom */}
-                                            <div
-                                                className="presBox-show-hide-dropdown"
-                                                style={{ display: effect !== PresEffect.None ? undefined : 'none' }}
-                                                onClick={e => {
-                                                    e.stopPropagation();
-                                                    this.setSpringEditorVisibility(!this._showSpringEditor);
-                                                }}>
-                                                SPRING SETTINGS
-                                                <FontAwesomeIcon icon={this._showSpringEditor ? 'chevron-down' : 'chevron-up'} />
-                                            </div>
-                                            {/* Spring settings */}
                                             {/* No spring settings for jackinthebox (lightspeed) */}
-                                            {this._showSpringEditor && effect !== PresEffect.None && (
+                                            {StrCast(activeItem.presentation_effectTiming).includes('custom') && effect !== PresEffect.None && (
                                                 <>
                                                     <div className="presBox-springSlider">
                                                         <span>Tension</span>
@@ -2150,30 +2124,35 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                                 )}
                             </div>
                         </div>
+                    </div>
 
-                        {/* Toggles */}
-                        <div className="presBox-option-block">
-                            <Toggle
-                                formLabel="Play Audio Annotation"
-                                toggleType={ToggleType.SWITCH}
-                                toggleStatus={BoolCast(activeItem.presentation_playAudio)}
-                                onClick={() => {
-                                    activeItem.presentation_playAudio = !BoolCast(activeItem.presentation_playAudio);
-                                }}
-                                color={SnappingManager.userColor}
-                            />
-                            <Toggle
-                                formLabel="Zoom Text Selections"
-                                toggleType={ToggleType.SWITCH}
-                                toggleStatus={BoolCast(activeItem.presentation_zoomText)}
-                                onClick={() => {
-                                    activeItem.presentation_zoomText = !BoolCast(activeItem.presentation_zoomText);
-                                }}
+                    {effect === PresEffect.None ? null : (
+                        <div className="presBox-previewContainer">
+                            <Button
+                                type={Type.TERT}
+                                tooltip="show preview of slide animation effect"
+                                size={Size.SMALL}
                                 color={SnappingManager.userColor}
+                                background={'transparent'}
+                                onClick={action(() => {
+                                    this._showPreview = false;
+                                    setTimeout(action(() => { this._showPreview = true; }) ); // prettier-ignore
+                                })}
+                                text="Preview Effect"
                             />
-                            <Button text="Apply to all" type={Type.TERT} color={SnappingManager.userVariantColor} onClick={() => this.applyTo(this.childDocs)} />
+                            <div className="presBox-option-block presBox-option-center">
+                                <div className="presBox-effect-container">
+                                    {!this._showPreview ? null : (
+                                        <SlideEffect dir={direction} presEffect={effect} springSettings={timingConfig}>
+                                            <div className="presBox-effect-demo-box" style={{ backgroundColor: springPreviewColors[0] }} />
+                                        </SlideEffect>
+                                    )}
+                                </div>
+                            </div>
                         </div>
-                    </div>
+                    )}
+
+                    <Button text="Apply to all slides" type={Type.TERT} color={SnappingManager.userVariantColor} onClick={() => this.applyTo(this.childDocs)} />
                 </>
             );
         }
@@ -2199,7 +2178,6 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                                     <div id="startTime" className="slider-number" style={{ color: SnappingManager.userColor, backgroundColor: SnappingManager.userBackgroundColor }}>
                                         <input
                                             className="presBox-input"
-                                            style={{ textAlign: 'center', width: '100%', height: 15, fontSize: 10 }}
                                             type="number"
                                             readOnly
                                             value={NumCast(activeItem.config_clipStart).toFixed(2)}
@@ -2226,7 +2204,6 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                                         <input
                                             className="presBox-input"
                                             onKeyDown={e => e.stopPropagation()}
-                                            style={{ textAlign: 'center', width: '100%', height: 15, fontSize: 10 }}
                                             type="number"
                                             readOnly
                                             value={configClipEnd.toFixed(2)}
-- 
cgit v1.2.3-70-g09d2

