aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorbobzel <zzzman@gmail.com>2025-02-05 17:10:20 -0500
committerbobzel <zzzman@gmail.com>2025-02-05 17:10:20 -0500
commit382e09f606d94921dab460cc8c8564199bb0b70d (patch)
treed4c0414ad5c72fd1cec1db66dc32d5b8c5eee170 /src
parent68bf2f9e4141d8a99407ff4c6c02d44795c638de (diff)
cleanup of presbox properties.
Diffstat (limited to 'src')
-rw-r--r--src/client/views/nodes/trails/CubicBezierEditor.tsx154
-rw-r--r--src/client/views/nodes/trails/PresBox.scss83
-rw-r--r--src/client/views/nodes/trails/PresBox.tsx475
3 files changed, 402 insertions, 310 deletions
diff --git a/src/client/views/nodes/trails/CubicBezierEditor.tsx b/src/client/views/nodes/trails/CubicBezierEditor.tsx
index e1ad1e6e5..627b77184 100644
--- a/src/client/views/nodes/trails/CubicBezierEditor.tsx
+++ b/src/client/views/nodes/trails/CubicBezierEditor.tsx
@@ -118,84 +118,82 @@ function CubicBezierEditor({ setFunc, currPoints }: Props) {
}, [c2Down, currPoints]);
return (
- <div
- onPointerMove={e => {
- e.stopPropagation;
- }}>
- <svg className="presBox-bezier-editor" width={`${CONTAINER_WIDTH}`} height={`${CONTAINER_WIDTH}`} xmlns="http://www.w3.org/2000/svg">
- {/* Outlines */}
- <line x1={`${0 + OFFSET}`} y1={`${EDITOR_WIDTH + OFFSET}`} x2={`${EDITOR_WIDTH + OFFSET}`} y2={`${0 + OFFSET}`} stroke="#c1c1c1" strokeWidth="1" />
- {/* Box Outline */}
- <rect x={`${0 + OFFSET}`} y={`${0 + OFFSET}`} width={EDITOR_WIDTH} height={EDITOR_WIDTH} stroke="#c5c5c5" fill="transparent" strokeWidth="1" />
- {/* Editor */}
- <path
- d={`M ${0 + OFFSET} ${EDITOR_WIDTH + OFFSET} C ${currPoints.p1[0] * EDITOR_WIDTH + OFFSET} ${EDITOR_WIDTH - currPoints.p1[1] * EDITOR_WIDTH + OFFSET}, ${
- currPoints.p2[0] * EDITOR_WIDTH + OFFSET
- } ${EDITOR_WIDTH - currPoints.p2[1] * EDITOR_WIDTH + OFFSET}, ${EDITOR_WIDTH + OFFSET} ${0 + OFFSET}`}
- stroke="#ffffff"
- fill="transparent"
- />
- {/* Bottom left */}
- <line
- onPointerDown={() => {
- setC1Down(true);
- }}
- onPointerUp={() => {
- setC1Down(false);
- }}
- x1={`${0 + OFFSET}`}
- y1={`${EDITOR_WIDTH + OFFSET}`}
- x2={`${currPoints.p1[0] * EDITOR_WIDTH + OFFSET}`}
- y2={`${EDITOR_WIDTH - currPoints.p1[1] * EDITOR_WIDTH + OFFSET}`}
- stroke="#00000000"
- strokeWidth="5"
- />
- <line x1={`${0 + OFFSET}`} y1={`${EDITOR_WIDTH + OFFSET}`} x2={`${currPoints.p1[0] * EDITOR_WIDTH + OFFSET}`} y2={`${EDITOR_WIDTH - currPoints.p1[1] * EDITOR_WIDTH + OFFSET}`} stroke="#ffffff" strokeWidth="1" />
- <circle
- cx={`${currPoints.p1[0] * EDITOR_WIDTH + OFFSET}`}
- cy={`${EDITOR_WIDTH - currPoints.p1[1] * EDITOR_WIDTH + OFFSET}`}
- r="5"
- fill={`${c1Down ? '#3fa9ff' : '#ffffff'}`}
- onPointerDown={e => {
- e.stopPropagation();
- setC1Down(true);
- }}
- onPointerUp={() => {
- setC1Down(false);
- }}
- />
- {/* Top right */}
- <line
- onPointerDown={e => {
- e.stopPropagation();
- setC2Down(true);
- }}
- onPointerUp={() => {
- setC2Down(false);
- }}
- x1={`${EDITOR_WIDTH + OFFSET}`}
- y1={`${0 + OFFSET}`}
- x2={`${currPoints.p2[0] * EDITOR_WIDTH + OFFSET}`}
- y2={`${EDITOR_WIDTH - currPoints.p2[1] * EDITOR_WIDTH + OFFSET}`}
- stroke="#00000000"
- strokeWidth="5"
- />
- <line x1={`${EDITOR_WIDTH + OFFSET}`} y1={`${0 + OFFSET}`} x2={`${currPoints.p2[0] * EDITOR_WIDTH + OFFSET}`} y2={`${EDITOR_WIDTH - currPoints.p2[1] * EDITOR_WIDTH + OFFSET}`} stroke="#ffffff" strokeWidth="1" />
- <circle
- cx={`${currPoints.p2[0] * EDITOR_WIDTH + OFFSET}`}
- cy={`${EDITOR_WIDTH - currPoints.p2[1] * EDITOR_WIDTH + OFFSET}`}
- r="5"
- fill={`${c2Down ? '#3fa9ff' : '#ffffff'}`}
- onPointerDown={e => {
- e.stopPropagation();
- setC2Down(true);
- }}
- onPointerUp={() => {
- setC2Down(false);
- }}
- />
- </svg>
- </div>
+ <svg className="presBox-bezier-editor" width={`${CONTAINER_WIDTH}`} height={`${CONTAINER_WIDTH}`} xmlns="http://www.w3.org/2000/svg">
+ {/* Outlines */}
+ <line x1={`${0 + OFFSET}`} y1={`${EDITOR_WIDTH + OFFSET}`} x2={`${EDITOR_WIDTH + OFFSET}`} y2={`${0 + OFFSET}`} stroke="#c1c1c1" strokeWidth="1" />
+ {/* Box Outline */}
+ <rect x={`${0 + OFFSET}`} y={`${0 + OFFSET}`} width={EDITOR_WIDTH} height={EDITOR_WIDTH} stroke="#c5c5c5" fill="transparent" strokeWidth="1" />
+ {/* Editor */}
+ <path
+ d={`M ${0 + OFFSET} ${EDITOR_WIDTH + OFFSET} C ${currPoints.p1[0] * EDITOR_WIDTH + OFFSET} ${EDITOR_WIDTH - currPoints.p1[1] * EDITOR_WIDTH + OFFSET}, ${
+ currPoints.p2[0] * EDITOR_WIDTH + OFFSET
+ } ${EDITOR_WIDTH - currPoints.p2[1] * EDITOR_WIDTH + OFFSET}, ${EDITOR_WIDTH + OFFSET} ${0 + OFFSET}`}
+ stroke="#ffffff"
+ fill="transparent"
+ />
+ {/* Bottom left */}
+ <line
+ onPointerDown={() => {
+ setC1Down(true);
+ }}
+ onPointerMove={e => {
+ e.stopPropagation;
+ }}
+ onPointerUp={() => {
+ setC1Down(false);
+ }}
+ x1={`${0 + OFFSET}`}
+ y1={`${EDITOR_WIDTH + OFFSET}`}
+ x2={`${currPoints.p1[0] * EDITOR_WIDTH + OFFSET}`}
+ y2={`${EDITOR_WIDTH - currPoints.p1[1] * EDITOR_WIDTH + OFFSET}`}
+ stroke="#00000000"
+ strokeWidth="5"
+ />
+ <line x1={`${0 + OFFSET}`} y1={`${EDITOR_WIDTH + OFFSET}`} x2={`${currPoints.p1[0] * EDITOR_WIDTH + OFFSET}`} y2={`${EDITOR_WIDTH - currPoints.p1[1] * EDITOR_WIDTH + OFFSET}`} stroke="#ffffff" strokeWidth="1" />
+ <circle
+ cx={`${currPoints.p1[0] * EDITOR_WIDTH + OFFSET}`}
+ cy={`${EDITOR_WIDTH - currPoints.p1[1] * EDITOR_WIDTH + OFFSET}`}
+ r="5"
+ fill={`${c1Down ? '#3fa9ff' : '#ffffff'}`}
+ onPointerDown={e => {
+ e.stopPropagation();
+ setC1Down(true);
+ }}
+ onPointerUp={() => {
+ setC1Down(false);
+ }}
+ />
+ {/* Top right */}
+ <line
+ onPointerDown={e => {
+ e.stopPropagation();
+ setC2Down(true);
+ }}
+ onPointerUp={() => {
+ setC2Down(false);
+ }}
+ x1={`${EDITOR_WIDTH + OFFSET}`}
+ y1={`${0 + OFFSET}`}
+ x2={`${currPoints.p2[0] * EDITOR_WIDTH + OFFSET}`}
+ y2={`${EDITOR_WIDTH - currPoints.p2[1] * EDITOR_WIDTH + OFFSET}`}
+ stroke="#00000000"
+ strokeWidth="5"
+ />
+ <line x1={`${EDITOR_WIDTH + OFFSET}`} y1={`${0 + OFFSET}`} x2={`${currPoints.p2[0] * EDITOR_WIDTH + OFFSET}`} y2={`${EDITOR_WIDTH - currPoints.p2[1] * EDITOR_WIDTH + OFFSET}`} stroke="#ffffff" strokeWidth="1" />
+ <circle
+ cx={`${currPoints.p2[0] * EDITOR_WIDTH + OFFSET}`}
+ cy={`${EDITOR_WIDTH - currPoints.p2[1] * EDITOR_WIDTH + OFFSET}`}
+ r="5"
+ fill={`${c2Down ? '#3fa9ff' : '#ffffff'}`}
+ onPointerDown={e => {
+ e.stopPropagation();
+ setC2Down(true);
+ }}
+ onPointerUp={() => {
+ setC2Down(false);
+ }}
+ />
+ </svg>
);
}
diff --git a/src/client/views/nodes/trails/PresBox.scss b/src/client/views/nodes/trails/PresBox.scss
index 60d4e580d..a181687f8 100644
--- a/src/client/views/nodes/trails/PresBox.scss
+++ b/src/client/views/nodes/trails/PresBox.scss
@@ -5,11 +5,24 @@
display: flex;
flex-direction: column;
gap: 1rem;
+ .presBox-gpt-chat-span {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ }
+ textarea {
+ width: 100%;
+ }
+}
+.presBox-subheading-slider {
+ max-width: calc(100% - 25px);
+ width: 100%;
+ padding: 15px;
}
.pres-chat {
display: flex;
- flex-direction: column;
+ flex-direction: row;
gap: 8px;
}
@@ -18,30 +31,38 @@
gap: 8px;
}
-.pres-chatbox-container {
- padding: 16px;
+.pres-chatbox-container,
+.pres-chatbox-container-ai {
+ width: 100%;
+ padding-left: 16px;
+ padding-right: 16px;
outline: 1px solid #999999;
- border-radius: 16px;
+ border-radius: 5px;
display: flex;
align-items: center;
justify-content: space-between;
+ overflow: auto;
+ max-height: 200px;
+ .pres-chatbox {
+ outline: none;
+ border: none;
+ resize: none;
+ font-family: Verdana, Geneva, sans-serif;
+ background-color: transparent;
+ overflow-y: hidden;
+ }
}
-.pres-chatbox {
- outline: none;
- border: none;
- resize: none;
- font-family: Verdana, Geneva, sans-serif;
- background-color: transparent;
- overflow-y: hidden;
+.pres-chatbox-container-ai {
+ padding-left: 8px;
+ padding-right: 8px;
+ margin-left: 8px;
}
-
// Effect Animations
.presBox-effects {
- display: grid;
- grid-template-columns: auto auto;
- gap: 8px;
+ display: flow;
+ margin: auto;
}
.presBox-effect-row {
@@ -55,7 +76,7 @@
overflow: hidden;
width: 80px;
height: 80px;
- display: flex;
+ display: inline-flex;
justify-content: center;
align-items: center;
border: 1px solid rgb(118, 118, 118);
@@ -74,7 +95,6 @@
.presBox-show-hide-dropdown {
cursor: pointer;
- padding: 8px 0;
display: flex;
align-items: center;
gap: 4px;
@@ -96,6 +116,18 @@
align-items: center;
}
+.presBox-previewContainer {
+ display: flex;
+ align-items: center;
+ width: fit-content;
+ margin: auto;
+ grid-template-columns: auto auto;
+ grid-gap: 10px;
+ .presBox-option-block {
+ padding: 0px;
+ }
+}
+
.presBox-cont {
cursor: auto;
position: absolute;
@@ -280,6 +312,9 @@
font-family: Roboto;
z-index: 100;
transition: 0.7s;
+ .form-wrapper.left .formLabel {
+ width: 100px;
+ }
.ribbon-doubleButton {
display: flex;
@@ -352,6 +387,18 @@
font-size: 11;
font-weight: 400;
margin-top: 10px;
+ max-width: min(100px, 25%);
+ width: 100%;
+ }
+ .presBox-springSlider {
+ display: grid;
+ column-count: 2;
+ grid-template-columns: min(60px, 25%) calc(100% - min(60px, 25%) - min(5px, 10%));
+ grid-gap: min(5px, 10%);
+ > span {
+ overflow: hidden;
+ text-overflow: ellipsis;
+ }
}
@media screen and (-webkit-min-device-pixel-ratio: 0) {
@@ -459,7 +506,7 @@
justify-content: space-between;
width: 100%;
height: max-content;
- grid-template-columns: auto auto auto;
+ grid-template-columns: auto auto;
grid-template-rows: max-content;
font-weight: 100;
margin-top: 3px;
diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx
index 3919ac3a8..5dbf502d2 100644
--- a/src/client/views/nodes/trails/PresBox.tsx
+++ b/src/client/views/nodes/trails/PresBox.tsx
@@ -100,8 +100,9 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
@observable _presKeyEvents: boolean = false;
@observable _forceKeyEvents: boolean = false;
+ @observable _showAIGallery = false;
@observable _showBezierEditor = false;
- @observable _showSpringEditor = true;
+ @observable _showSpringEditor = false;
@observable _showPreview = true;
@observable _easeDropdownVal = 'ease';
@@ -151,6 +152,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
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]})`);
});
@@ -1735,19 +1737,14 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
const { activeItem } = this;
// Retrieving spring timing properties
const timing = StrCast(activeItem?.presentation_effectTiming);
- let timingConfig: SpringSettings | undefined;
- if (timing) {
- timingConfig = JSON.parse(timing);
- }
-
- if (!timingConfig) {
- timingConfig = {
- type: SpringType.GENTLE,
- stiffness: 100,
- damping: 15,
- mass: 1,
- };
- }
+ const timingConfig: SpringSettings = timing
+ ? JSON.parse(timing)
+ : {
+ type: SpringType.GENTLE,
+ stiffness: 100,
+ damping: 15,
+ mass: 1,
+ };
if (activeItem && this.targetDoc) {
const transitionSpeed = activeItem.presentation_transition ? NumCast(activeItem.presentation_transition) / 1000 : 0.5;
@@ -1758,20 +1755,32 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
return (
<>
{/* This chatbox is for customizing the properties of trails, like transition time, movement type (zoom, pan) using GPT */}
- <div className="presBox-gpt-chat">
- <span style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>
+ <div className="presBox-gpt-chat" style={{ display: SnappingManager.PropertiesWidth < 1 ? 'none' : undefined }}>
+ <span className="presBox-gpt-chat-span">
Customize Slide Properties{' '}
<div className="propertiesView-info" onClick={() => window.open('https://brown-dash.github.io/Dash-Documentation/features/trails/#slide-customization')}>
<IconButton icon={<FontAwesomeIcon icon="info-circle" />} color={SnappingManager.userColor} />
</div>
</span>
<div className="pres-chat">
- <div className="pres-chatbox-container">
+ <div className="pres-chatbox-container-ai">
<ReactTextareaAutosize
- placeholder="Describe how you would like to modify the slide properties."
+ placeholder="Describe how to modify the slide properties."
className="pres-chatbox"
+ ref={r => {
+ setTimeout(() => {
+ if (r && !r.textContent) {
+ r.style.height = '';
+ r.style.height = r.scrollHeight + 'px';
+ }
+ });
+ }}
value={this._chatInput}
- onChange={e => this.setChatInput(e.target.value)}
+ onChange={e => {
+ e.currentTarget.style.height = '';
+ e.currentTarget.style.height = e.currentTarget.scrollHeight + 'px';
+ this.setChatInput(e.target.value);
+ }}
onKeyDown={e => {
this.stopDictation();
e.stopPropagation();
@@ -1805,6 +1814,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
/>
</div>
</div>
+
{/* Movement */}
<div
className={`presBox-ribbon ${this._transitionTools && this.layoutDoc.presentation_status === PresStatus.Edit ? 'active' : ''}`}
@@ -1816,46 +1826,47 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
this._openEffectDropdown = false;
this._openBulletEffectDropdown = false;
})}>
- <div
- className="presBox-option-block"
- // style={{ padding: '16px' }}
- >
- Movement
+ <div className="presBox-option-block">
<Dropdown
color={SnappingManager.userColor}
- formLabel="Movement"
+ formLabel="Navigation"
+ formLabelPlacement="left"
closeOnSelect
items={movementItems}
selectedVal={this.movementName(activeItem)}
- setSelectedVal={val => {
- this.updateMovement(val as PresMovement);
- }}
+ 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 ${SnappingManager.userColor}` }}>
- <input className="presBox-input" readOnly type="number" value={zoom} onChange={e => this.updateZoom(e.target.value)} />%
+ <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>
- {PresBox.inputter('0', '1', '100', zoom, activeItem.presentation_movement === PresMovement.Zoom, this.updateZoom)}
- <div className="ribbon-doubleButton" style={{ display: 'inline-flex' }}>
- <div className="presBox-subheading">Transition Time</div>
- <div className="ribbon-property" style={{ border: `solid 1px ${SnappingManager.userColor}` }}>
- <input className="presBox-input" type="number" readOnly value={transitionSpeed} onKeyDown={e => e.stopPropagation()} onChange={action(e => this.updateTransitionTime(e.target.value))} /> s
+ <div className="ribbon-doubleButton">
+ <div className="presBox-subheading">ZOOM/EFFECT TIME</div>
+ <div className="presBox-subheading-slider">
+ {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">Slow</div>
+ </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))} />
+ <span>s</span>
</div>
- </div>
- {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 */}
<Dropdown
color={SnappingManager.userColor}
- formLabel="Easing Function"
+ formLabel="Timing Function"
+ formLabelPlacement="left"
closeOnSelect
items={easeItems}
selectedVal={this.activeItem.presentation_easeFunc ? (StrCast(this.activeItem.presentation_easeFunc).startsWith('cubic') ? 'custom' : StrCast(this.activeItem.presentation_easeFunc)) : 'ease'}
@@ -1880,32 +1891,75 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
e.stopPropagation();
this.setBezierEditorVisibility(!this._showBezierEditor);
}}>
- {`${this._showBezierEditor ? 'Hide' : 'Show'} Timing Editor`}
- <FontAwesomeIcon icon={this._showBezierEditor ? 'chevron-up' : 'chevron-down'} />
+ TIMING EDITOR
+ <FontAwesomeIcon icon={this._showBezierEditor ? 'chevron-down' : 'chevron-up'} />
</div>
</div>
</div>
{/* Cubic bezier editor */}
{this._showBezierEditor && (
- <div className="presBox-option-block" style={{ paddingTop: 0 }}>
- <p className="presBox-submenu-label" style={{ alignSelf: 'flex-start' }}>
- Custom Timing Function
- </p>
+ <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">
- Effects
- <div className="pres-chat">
- <div className="pres-chatbox-container">
+ <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="Customize prompt for effect suggestions. Leave blank for random results."
+ 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 => {
@@ -1924,6 +1978,31 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
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
@@ -1937,171 +2016,139 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
this._openBulletEffectDropdown = false;
})}>
<div className="presBox-option-block">
- Click on a box to apply the effect.
- <div className="presBox-option-block presBox-option-center">
- {/* 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>
{/* Effect dropdown */}
- <Dropdown
- color={SnappingManager.userColor}
- formLabel="Slide Effect"
- closeOnSelect
- items={effectItems}
- selectedVal={effect?.toString()}
- setSelectedVal={val => {
- this.updateEffect(val as PresEffect, false);
- // set default spring options for that effect
- this.updateEffectTiming(activeItem, presEffectDefaultTimings[val as keyof typeof presEffectDefaultTimings]);
- }}
- dropdownType={DropdownType.SELECT}
- type={Type.TERT}
- />
- {/* Effect direction */}
- {/* Only applies to certain effects */}
- {(effect === PresEffect.Flip || effect === PresEffect.Bounce || effect === PresEffect.Roll) && (
- <>
- <div className="ribbon-doubleButton" style={{ display: 'inline-flex' }}>
- <div className="presBox-subheading">Effect direction</div>
- <div className="ribbon-property" style={{ border: `solid 1px ${SnappingManager.userColor}` }}>
- {StrCast(this.activeItem.presentation_effectDirection)}
+ <div>
+ <Dropdown
+ color={SnappingManager.userColor}
+ formLabel="Slide Effect"
+ formLabelPlacement="left"
+ closeOnSelect
+ items={effectItems}
+ selectedVal={effect?.toString()}
+ setSelectedVal={val => {
+ this.updateEffect(val as PresEffect, false);
+ // set default spring options for that effect
+ this.updateEffectTiming(activeItem, presEffectDefaultTimings[val as keyof typeof presEffectDefaultTimings]);
+ }}
+ dropdownType={DropdownType.SELECT}
+ type={Type.TERT}
+ />
+ </div>
+ <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>
</div>
- </div>
- <div className="presBox-icon-list">
- <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
+ </>
+ )}
+ {effect !== PresEffect.Lightspeed && (
+ <>
+ <Dropdown
+ color={SnappingManager.userColor}
+ formLabel="Effect Timing"
+ formLabelPlacement="left"
+ closeOnSelect
+ items={effectTimings}
+ selectedVal={timingConfig.type}
+ setSelectedVal={val => this.updateEffectTiming(activeItem, { type: val as SpringType, ...springMappings[val] })}
+ dropdownType={DropdownType.SELECT}
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>
- </>
- )}
- {/* Spring settings */}
- {/* No spring settings for jackinthebox (lightspeed) */}
- {effect !== PresEffect.Lightspeed && (
- <>
- <Dropdown
- color={SnappingManager.userColor}
- formLabel="Effect Timing"
- closeOnSelect
- items={effectTimings}
- selectedVal={timingConfig.type}
- setSelectedVal={val => this.updateEffectTiming(activeItem, { type: val as SpringType, ...springMappings[val] })}
- dropdownType={DropdownType.SELECT}
- type={Type.TERT}
- />
- <div
- className="presBox-show-hide-dropdown"
- onClick={e => {
- e.stopPropagation();
- this.setSpringEditorVisibility(!this._showSpringEditor);
- }}>
- {`${this._showSpringEditor ? 'Hide' : 'Show'} Spring Settings`}
- <FontAwesomeIcon icon={this._showSpringEditor ? 'chevron-up' : 'chevron-down'} />
- </div>
- {this._showSpringEditor && (
- <>
- <div>Tension</div>
- <div onPointerDown={e => e.stopPropagation()}>
- {/* prettier-ignore */}
- <Slider min={1} max={1000} step={5} size="small"
- value={timingConfig.stiffness}
- onChange={(e, val) => timingConfig && this.updateEffectTiming(activeItem, { ...timingConfig, type: SpringType.CUSTOM, stiffness: val as number })}
- valueLabelDisplay="auto"
- />
- </div>
- <div>Damping</div>
- <div onPointerDown={e => e.stopPropagation()}>
- {/* prettier-ignore */}
- <Slider min={1} max={100} step={1} size="small"
- value={timingConfig.damping}
- onChange={(e, val) => timingConfig && this.updateEffectTiming(activeItem, { ...timingConfig, type: SpringType.CUSTOM, damping: val as number })}
- valueLabelDisplay="auto"
- />
- </div>
- <div>Mass</div>
- <div onPointerDown={e => e.stopPropagation()}>
- {/* prettier-ignore */}
- <Slider min={1} max={10} step={1} size="small"
- value={timingConfig.mass}
- onChange={(e, val) => timingConfig && this.updateEffectTiming(activeItem, { ...timingConfig, type: SpringType.CUSTOM, mass: val as number })}
- valueLabelDisplay="auto"
- />
+
+ <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>
- <div style={{ display: 'flex', alignItems: 'center'}}>
- <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 of: ' + effect + ', ' + direction}
- />
- <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>
- )}
+ {/* Spring settings */}
+ {/* No spring settings for jackinthebox (lightspeed) */}
+ {this._showSpringEditor && effect !== PresEffect.None && (
+ <>
+ <div className="presBox-springSlider">
+ <span>Tension</span>
+ <div onPointerDown={e => e.stopPropagation()}>
+ {/* prettier-ignore */}
+ <Slider min={1} max={1000} step={5} size="small"
+ value={timingConfig.stiffness}
+ onChange={(e, val) => timingConfig && this.updateEffectTiming(activeItem, { ...timingConfig, type: SpringType.CUSTOM, stiffness: val as number })}
+ valueLabelDisplay="auto"
+ />
+ </div>
</div>
- </div>
- </div>
- </>
- )}
- </>
- )}
+ <div className="presBox-springSlider">
+ <span>Damping</span>
+ <div onPointerDown={e => e.stopPropagation()}>
+ {/* prettier-ignore */}
+ <Slider min={1} max={100} step={1} size="small"
+ value={timingConfig.damping}
+ onChange={(e, val) => timingConfig && this.updateEffectTiming(activeItem, { ...timingConfig, type: SpringType.CUSTOM, damping: val as number })}
+ valueLabelDisplay="auto"
+ />
+ </div>
+ </div>
+ <div className="presBox-springSlider">
+ <span>Mass</span>
+ <div onPointerDown={e => e.stopPropagation()}>
+ {/* prettier-ignore */}
+ <Slider min={1} max={10} step={1} size="small"
+ value={timingConfig.mass}
+ onChange={(e, val) => timingConfig && this.updateEffectTiming(activeItem, { ...timingConfig, type: SpringType.CUSTOM, mass: val as number })}
+ valueLabelDisplay="auto"
+ />
+ </div>
+ </div>
+ </>
+ )}
+ </div>
+ </>
+ )}
+ </div>
</div>
{/* Toggles */}