aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/nodes
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views/nodes')
-rw-r--r--src/client/views/nodes/DiagramBox.tsx12
-rw-r--r--src/client/views/nodes/ImageBox.scss9
-rw-r--r--src/client/views/nodes/ImageBox.tsx156
-rw-r--r--src/client/views/nodes/calendarBox/CalendarBox.tsx7
-rw-r--r--src/client/views/nodes/formattedText/FormattedTextBox.tsx6
5 files changed, 133 insertions, 57 deletions
diff --git a/src/client/views/nodes/DiagramBox.tsx b/src/client/views/nodes/DiagramBox.tsx
index 3b666bad5..7cfccf0dc 100644
--- a/src/client/views/nodes/DiagramBox.tsx
+++ b/src/client/views/nodes/DiagramBox.tsx
@@ -185,11 +185,6 @@ export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
return '( )';
};
- /**
- * This stops scroll wheel events when they are used to scroll the face collection.
- */
- onPassiveWheel = (e: WheelEvent) => e.stopPropagation();
-
render() {
return (
<div
@@ -197,12 +192,7 @@ export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
style={{
pointerEvents: this._props.isContentActive() ? undefined : 'none',
}}
- ref={action((ele: HTMLDivElement | null) => {
- this._boxRef?.removeEventListener('wheel', this.onPassiveWheel);
- this._boxRef = ele;
- // prevent wheel events from passively propagating up through containers and prevents containers from preventDefault which would block scrolling
- ele?.addEventListener('wheel', this.onPassiveWheel, { passive: false });
- })}>
+ ref={r => this.fixWheelEvents(r, this._props.isContentActive)}>
<div className="DIYNodeBox-searchbar">
<input type="text" value={this._inputValue} onKeyDown={action(e => e.key === 'Enter' && this.generateMermaidCode())} onChange={action(e => (this._inputValue = e.target.value))} />
<button type="button" onClick={this.generateMermaidCode}>
diff --git a/src/client/views/nodes/ImageBox.scss b/src/client/views/nodes/ImageBox.scss
index ac1a6ece9..9f7a5d03f 100644
--- a/src/client/views/nodes/ImageBox.scss
+++ b/src/client/views/nodes/ImageBox.scss
@@ -106,7 +106,7 @@
height: 100%;
img {
object-fit: contain;
- height: fit-content;
+ height: 100%;
}
.imageBox-fadeBlocker,
@@ -242,12 +242,9 @@
}
}
.imageBox-regenerate-dialog {
- position: fixed;
- top: 50%;
- left: 50%;
- transform: translate(-50%, -50%);
+ position: absolute;
background: white;
- padding: 20px;
+ padding: 10px;
border-radius: 8px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
z-index: 10000;
diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx
index 31a135fa7..d16baada6 100644
--- a/src/client/views/nodes/ImageBox.tsx
+++ b/src/client/views/nodes/ImageBox.tsx
@@ -1,4 +1,4 @@
-import { Button, Colors, EditableText, Size, Type } from '@dash/components';
+import { Button, Colors, EditableText, IconButton, Size, Toggle, ToggleType, Type } from '@dash/components';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { Slider, Tooltip } from '@mui/material';
import axios from 'axios';
@@ -353,6 +353,8 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
@action
openOutpaintPrompt = () => {
+ this._outpaintVAlign = '';
+ this._outpaintAlign = '';
this._showOutpaintPrompt = true;
};
@@ -362,6 +364,16 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
};
@action
+ cancelOutpaintPrompt = () => {
+ const origWidth = NumCast(this.Document[this.fieldKey + '_outpaintOriginalWidth']);
+ const origHeight = NumCast(this.Document[this.fieldKey + '_outpaintOriginalHeight']);
+ this.Document._width = origWidth;
+ this.Document._height = origHeight;
+ this._outpaintingInProgress = false;
+ this.closeOutpaintPrompt();
+ };
+
+ @action
handlePromptChange = (val: string | number) => {
this._outpaintPromptInput = '' + val;
};
@@ -377,17 +389,12 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
const field = Cast(this.dataDoc[this.fieldKey], ImageField);
if (!field) return;
- const origWidth = NumCast(this.Document[this.fieldKey + '_outpaintOriginalWidth']);
- const origHeight = NumCast(this.Document[this.fieldKey + '_outpaintOriginalHeight']);
-
// Set flag that outpainting is in progress
this._outpaintingInProgress = true;
// Revert dimensions if prompt is blank (acts like Cancel)
if (!customPrompt) {
- this.Document._width = origWidth;
- this.Document._height = origHeight;
- this._outpaintingInProgress = false;
+ this.cancelOutpaintPrompt();
return;
}
@@ -410,11 +417,15 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
loadingOverlay.innerHTML = '<div style="color: white; font-size: 16px;">Generating outpainted image...</div>';
this._mainCont?.appendChild(loadingOverlay);
+ const origWidth = NumCast(this.Document[this.fieldKey + '_outpaintOriginalWidth']);
+ const origHeight = NumCast(this.Document[this.fieldKey + '_outpaintOriginalHeight']);
const response = await Networking.PostToServer('/outpaintImage', {
imageUrl: currentPath,
prompt: customPrompt,
originalDimensions: { width: Math.min(newWidth, origWidth), height: Math.min(newHeight, origHeight) },
newDimensions: { width: newWidth, height: newHeight },
+ halignment: this._outpaintAlign,
+ valignment: this._outpaintVAlign,
});
const error = ('error' in response && (response.error as string)) || '';
@@ -447,8 +458,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
this.Document[this.fieldKey + '_outpaintOriginalWidth'] = undefined;
this.Document[this.fieldKey + '_outpaintOriginalHeight'] = undefined;
} else {
- this.Document._width = origWidth;
- this.Document._height = origHeight;
+ this.cancelOutpaintPrompt();
alert('Failed to receive a valid image URL from server.');
}
batch.end();
@@ -456,30 +466,106 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
this._mainCont?.removeChild(loadingOverlay);
} catch (error) {
- console.error('Error during outpainting:', error);
- this.Document._width = origWidth;
- this.Document._height = origHeight;
- alert('An error occurred while outpainting. Please try again.');
+ this.cancelOutpaintPrompt();
+ alert('An error occurred while outpainting.' + error);
} finally {
runInAction(() => (this._outpaintingInProgress = false));
}
};
- componentUI = () =>
+ @observable _outpaintAlign = '';
+ @observable _outpaintVAlign = '';
+ @computed get outpaintVertical() {
+ return this._props.PanelWidth() / this._props.PanelHeight() < this.nativeSize.nativeWidth / this.nativeSize.nativeHeight;
+ }
+
+ componentUI = (/* boundsLeft: number, boundsTop: number*/) =>
!this._showOutpaintPrompt ? null : (
- <div key="imageBox-componentui" className="imageBox-regenerate-dialog" style={{ backgroundColor: SettingsManager.userBackgroundColor, color: SettingsManager.userColor }}>
- <h3>Outpaint Image</h3>
- <EditableText
- placeholder="Enter a prompt for extending the image:"
- setVal={val => this.handlePromptChange(val)}
- val={this._outpaintPromptInput}
- type={Type.TERT}
- color={SettingsManager.userColor}
- background={SettingsManager.userBackgroundColor}
- />
- <div className="buttons">
- <Button text="Cancel" type={Type.TERT} onClick={this.closeOutpaintPrompt} color={SnappingManager.userColor} background={SnappingManager.userVariantColor} />
- <Button text="Generate" type={Type.TERT} onClick={this.submitOutpaintPrompt} color={SnappingManager.userColor} background={SnappingManager.userVariantColor} />
+ <div
+ key="imageBox-componentui"
+ className="imageBox-regenerate-dialog"
+ style={{
+ top: -70 + (this._props.DocumentView?.().getBounds?.top ?? 0),
+ left: this._props.DocumentView?.().getBounds?.left ?? 0,
+ backgroundColor: SettingsManager.userBackgroundColor,
+ color: SettingsManager.userColor,
+ }}>
+ <div style={{ position: 'absolute', top: 5, right: 5 }}>
+ <IconButton type={Type.TERT} onClick={this.cancelOutpaintPrompt} icon={<FontAwesomeIcon icon="times" color={'red'} />} color={SnappingManager.userColor} background={SnappingManager.userVariantColor} />
+ </div>
+ <div>Outpaint Image</div>
+ <div style={{ display: 'flex', flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between' }}>
+ <EditableText
+ placeholder="Enter a prompt for extending the image:"
+ setVal={val => this.handlePromptChange(val)}
+ val={this._outpaintPromptInput}
+ type={Type.TERT}
+ color={SettingsManager.userColor}
+ background={SettingsManager.userBackgroundColor}
+ />
+ <div className="buttons" style={{ display: 'flex', flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between' }}>
+ <IconButton type={Type.TERT} onClick={this.submitOutpaintPrompt} icon={<AiOutlineSend />} color={SnappingManager.userColor} background={SnappingManager.userVariantColor} />
+ <div style={{ display: 'flex', flexDirection: 'row', alignItems: 'center' }}>
+ {this.outpaintVertical ? null : (
+ <Toggle
+ type={Type.TERT}
+ toggleType={ToggleType.BUTTON}
+ toggleStatus={this._outpaintAlign === 'left' && this._outpaintVAlign === ''}
+ onClick={action(() => (this._outpaintAlign = 'left'))}
+ icon={<FontAwesomeIcon icon="chevron-left" color={SnappingManager.userColor} />}
+ color={SnappingManager.userColor}
+ background={SnappingManager.userVariantColor}
+ />
+ )}
+ <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center' }}>
+ {!this.outpaintVertical ? null : (
+ <Toggle
+ type={Type.TERT}
+ toggleType={ToggleType.BUTTON}
+ toggleStatus={this._outpaintAlign === '' && this._outpaintVAlign === 'top'}
+ onClick={action(() => (this._outpaintVAlign = 'top'))}
+ icon={<FontAwesomeIcon icon="chevron-up" color={SnappingManager.userColor} />}
+ color={SnappingManager.userColor}
+ background={SnappingManager.userColor}
+ />
+ )}
+ <Toggle
+ type={Type.TERT}
+ toggleType={ToggleType.BUTTON}
+ toggleStatus={this._outpaintAlign === '' && this._outpaintVAlign === ''}
+ onClick={action(() => {
+ this._outpaintAlign = '';
+ this._outpaintVAlign = '';
+ })}
+ icon={<FontAwesomeIcon icon="bullseye" color={SnappingManager.userColor} />}
+ color={SnappingManager.userColor}
+ background={SnappingManager.userColor}
+ />
+ {!this.outpaintVertical ? null : (
+ <Toggle
+ type={Type.TERT}
+ toggleType={ToggleType.BUTTON}
+ toggleStatus={this._outpaintAlign === '' && this._outpaintVAlign === 'bottom'}
+ onClick={action(() => (this._outpaintVAlign = 'bottom'))}
+ icon={<FontAwesomeIcon icon="chevron-down" color={SnappingManager.userColor} />}
+ color={SnappingManager.userColor}
+ background={SnappingManager.userColor}
+ />
+ )}
+ </div>
+ {this.outpaintVertical ? null : (
+ <Toggle
+ type={Type.TERT}
+ toggleType={ToggleType.BUTTON}
+ toggleStatus={this._outpaintAlign === 'right' && this._outpaintVAlign === ''}
+ onClick={action(() => (this._outpaintAlign = 'right'))}
+ icon={<FontAwesomeIcon icon="chevron-right" color={SnappingManager.userColor} />}
+ color={SnappingManager.userColor}
+ background={SnappingManager.userColor}
+ />
+ )}
+ </div>
+ </div>
</div>
</div>
);
@@ -718,13 +804,25 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
})}
key={this.layoutDoc[Id]}
onPointerDown={this.marqueeDown}>
- <div className="imageBox-fader" style={{ opacity: backAlpha }}>
+ <div
+ className="imageBox-fader"
+ style={{
+ opacity: backAlpha,
+ flexDirection: this._outpaintVAlign ? 'row' : 'column',
+ alignItems: this._outpaintAlign === 'left' || this._outpaintVAlign === 'top' ? 'flex-start' : this._outpaintAlign === 'right' || this._outpaintVAlign === 'bottom' ? 'flex-end' : undefined,
+ }}>
<img
alt=""
ref={action((r: HTMLImageElement | null) => (this.imageRef = r))}
key="paths"
src={srcpath}
- style={{ transform, transformOrigin, height: this.Document[this.fieldKey + '_outpaintOriginalWidth'] !== undefined ? '100%' : undefined }}
+ style={{
+ position: 'relative',
+ transform,
+ transformOrigin,
+ width: this._outpaintAlign ? 'max-content' : this._outpaintAlign ? '100%' : undefined,
+ height: this._outpaintVAlign ? 'max-content' : this.Document[this.fieldKey + '_outpaintOriginalWidth'] !== undefined ? '100%' : undefined,
+ }}
onError={action(e => (this._error = e.toString()))}
draggable={false}
width={nativeWidth}
diff --git a/src/client/views/nodes/calendarBox/CalendarBox.tsx b/src/client/views/nodes/calendarBox/CalendarBox.tsx
index fa863e123..2b20a666d 100644
--- a/src/client/views/nodes/calendarBox/CalendarBox.tsx
+++ b/src/client/views/nodes/calendarBox/CalendarBox.tsx
@@ -24,7 +24,6 @@ type CalendarView = 'multiMonth' | 'dayGridMonth' | 'timeGridWeek' | 'timeGridDa
export class CalendarBox extends CollectionSubView() {
_calendarRef: HTMLDivElement | null = null;
_calendar: Calendar | undefined;
- _oldWheel: HTMLElement | null = null;
_observer: ResizeObserver | undefined;
_eventsDisposer: IReactionDisposer | undefined;
_selectDisposer: IReactionDisposer | undefined;
@@ -194,7 +193,6 @@ export class CalendarBox extends CollectionSubView() {
setTimeout(() => cal?.view.calendar.select(this.dateSelect.start, this.dateSelect.end));
};
- onPassiveWheel = (e: WheelEvent) => e.stopPropagation();
render() {
return (
<div
@@ -218,10 +216,7 @@ export class CalendarBox extends CollectionSubView() {
}}
ref={r => {
this.createDashEventsTarget(r);
- this._oldWheel?.removeEventListener('wheel', this.onPassiveWheel);
- this._oldWheel = r;
- // prevent wheel events from passively propagating up through containers and prevents containers from preventDefault which would block scrolling
- r?.addEventListener('wheel', this.onPassiveWheel, { passive: false });
+ this.fixWheelEvents(r, this._props.isContentActive);
if (r) {
this._observer?.disconnect();
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index d6fa3172d..c51f6c38b 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -2120,11 +2120,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
) : styleFromLayout?.height === '0px' ? null : (
<div
className="formattedTextBox"
- ref={r => {
- this._oldWheel?.removeEventListener('wheel', this.onPassiveWheel);
- this._oldWheel = r;
- r?.addEventListener('wheel', this.onPassiveWheel, { passive: false });
- }}
+ ref={r => this.fixWheelEvents(r, this._props.isContentActive, this.onPassiveWheel)}
style={{
...(this._props.dontScale
? {}