Skip to content

Commit 9c87b6a

Browse files
committed
adding support for drag and drop in all editons and main input area
1 parent 6b35ca9 commit 9c87b6a

File tree

3 files changed

+41
-18
lines changed

3 files changed

+41
-18
lines changed

packages/jupyter-chat/src/input-model.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,9 +117,14 @@ export interface IInputModel extends IDisposable {
117117
clearAttachments(): void;
118118

119119
/**
120-
* If the user is editing a message, this points to the active edition input model.
120+
* The input node.
121121
*/
122-
currentEdition?: IInputModel;
122+
node?: HTMLElement;
123+
124+
/**
125+
* If the user is editing messages, this tracks all active edition input models.
126+
*/
127+
activeEditions: IInputModel[];
123128

124129
/**
125130
* A signal emitting when the attachment list has changed.
@@ -201,6 +206,11 @@ export class InputModel implements IInputModel {
201206
*/
202207
cancel: (() => void) | undefined;
203208

209+
/**
210+
* If the user is editing messages, this tracks all active edition input models.
211+
*/
212+
activeEditions: IInputModel[] = [];
213+
204214
/**
205215
* The entire input value.
206216
*/

packages/jupyter-chat/src/widgets/chat-widget.tsx

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -122,12 +122,19 @@ export class ChatWidget extends ReactWidget {
122122
* Handle drag over events
123123
*/
124124
private _handleDrag(event: Drag.Event): void {
125-
const inputContainer = this.node.querySelector(`.${INPUT_CONTAINER_CLASS}`);
125+
const inputContainers = this.node.querySelectorAll<HTMLElement>(
126+
`.${INPUT_CONTAINER_CLASS}`
127+
);
126128
const target = event.target as HTMLElement;
127-
const isOverInput =
128-
inputContainer?.contains(target) || inputContainer === target;
129+
let overInput: HTMLElement | null = null;
130+
for (const container of inputContainers) {
131+
if (container.contains(target)) {
132+
overInput = container;
133+
break;
134+
}
135+
}
129136

130-
if (!isOverInput) {
137+
if (!overInput) {
131138
this._removeDragHoverClass();
132139
return;
133140
}
@@ -140,12 +147,9 @@ export class ChatWidget extends ReactWidget {
140147
event.stopPropagation();
141148
event.dropAction = 'move';
142149

143-
if (
144-
inputContainer &&
145-
!inputContainer.classList.contains(DRAG_HOVER_CLASS)
146-
) {
147-
inputContainer.classList.add(DRAG_HOVER_CLASS);
148-
this._dragTarget = inputContainer as HTMLElement;
150+
if (!overInput.classList.contains(DRAG_HOVER_CLASS)) {
151+
overInput.classList.add(DRAG_HOVER_CLASS);
152+
this._dragTarget = overInput;
149153
}
150154
}
151155

@@ -184,8 +188,15 @@ export class ChatWidget extends ReactWidget {
184188
}
185189
}
186190

187-
private _getActiveInput(): IInputModel {
188-
return this.model.input.currentEdition ?? this.model.input;
191+
private _getTargetInput(event: Drag.Event): IInputModel {
192+
const target = event.target as HTMLElement;
193+
194+
for (const edition of this.model.input.activeEditions ?? []) {
195+
if (edition.node && edition.node.contains(target)) {
196+
return edition;
197+
}
198+
}
199+
return this.model.input;
189200
}
190201

191202
/**
@@ -206,7 +217,7 @@ export class ChatWidget extends ReactWidget {
206217
value: data.model.path,
207218
mimetype: data.model.mimetype
208219
};
209-
const activeInput = this._getActiveInput();
220+
const activeInput = this._getTargetInput(event);
210221
activeInput.addAttachment?.(attachment);
211222
}
212223

@@ -269,7 +280,7 @@ export class ChatWidget extends ReactWidget {
269280
value: notebookPath,
270281
cells: validCells
271282
};
272-
const activeInput = this._getActiveInput();
283+
const activeInput = this._getTargetInput(event);
273284
activeInput.addAttachment?.(attachment);
274285
}
275286
} catch (error) {

packages/jupyterlab-chat/src/model.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -336,10 +336,12 @@ export class LabChatModel
336336

337337
edition.model.valueChanged.connect(_onInputChanged);
338338

339-
this.input.currentEdition = edition.model;
339+
this.input.activeEditions.push(edition.model);
340340

341341
edition.model.onDisposed.connect(() => {
342-
this.input.currentEdition = undefined;
342+
this.input.activeEditions = this.input.activeEditions.filter(
343+
(e: IInputModel) => e !== edition.model
344+
);
343345
});
344346
}
345347
};

0 commit comments

Comments
 (0)