@design.estate/dees-catalog 3.101.0 → 3.103.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist_bundle/bundle.js +1558 -979
- package/dist_ts_web/00_commitinfo_data.js +1 -1
- package/dist_ts_web/elements/00group-harness/dees-harness-session-list/dees-harness-session-list.d.ts +30 -1
- package/dist_ts_web/elements/00group-harness/dees-harness-session-list/dees-harness-session-list.js +330 -9
- package/dist_ts_web/elements/00group-harness/dees-terminal-view/dees-terminal-view.d.ts +50 -0
- package/dist_ts_web/elements/00group-harness/dees-terminal-view/dees-terminal-view.demo.d.ts +1 -0
- package/dist_ts_web/elements/00group-harness/dees-terminal-view/dees-terminal-view.demo.js +26 -0
- package/dist_ts_web/elements/00group-harness/dees-terminal-view/dees-terminal-view.js +347 -0
- package/dist_ts_web/elements/00group-harness/dees-terminal-view/index.d.ts +1 -0
- package/dist_ts_web/elements/00group-harness/dees-terminal-view/index.js +2 -0
- package/dist_ts_web/elements/00group-harness/index.d.ts +1 -0
- package/dist_ts_web/elements/00group-harness/index.js +2 -1
- package/dist_ts_web/elements/00group-harness/interfaces.d.ts +23 -0
- package/package.json +1 -1
- package/ts_web/00_commitinfo_data.ts +1 -1
- package/ts_web/elements/00group-harness/dees-harness-session-list/dees-harness-session-list.ts +336 -7
- package/ts_web/elements/00group-harness/dees-terminal-view/dees-terminal-view.demo.ts +26 -0
- package/ts_web/elements/00group-harness/dees-terminal-view/dees-terminal-view.ts +317 -0
- package/ts_web/elements/00group-harness/dees-terminal-view/index.ts +1 -0
- package/ts_web/elements/00group-harness/index.ts +1 -0
- package/ts_web/elements/00group-harness/interfaces.ts +26 -0
package/ts_web/elements/00group-harness/dees-harness-session-list/dees-harness-session-list.ts
CHANGED
|
@@ -10,7 +10,13 @@ import {
|
|
|
10
10
|
cssManager,
|
|
11
11
|
} from '@design.estate/dees-element';
|
|
12
12
|
import { themeDefaultStyles } from '../../00theme.js';
|
|
13
|
-
import type {
|
|
13
|
+
import type {
|
|
14
|
+
IHarnessGroupContextDetail,
|
|
15
|
+
IHarnessSessionContextDetail,
|
|
16
|
+
IHarnessSessionGroup,
|
|
17
|
+
IHarnessSessionMeta,
|
|
18
|
+
IHarnessSessionMoveDetail,
|
|
19
|
+
} from '../interfaces.js';
|
|
14
20
|
import { harnessFormatRelativeTime } from '../harness.helpers.js';
|
|
15
21
|
import '../../00group-utility/dees-icon/dees-icon.js';
|
|
16
22
|
|
|
@@ -20,11 +26,24 @@ declare global {
|
|
|
20
26
|
}
|
|
21
27
|
}
|
|
22
28
|
|
|
29
|
+
interface IDropSlot {
|
|
30
|
+
groupId: string | null;
|
|
31
|
+
index: number;
|
|
32
|
+
}
|
|
33
|
+
|
|
23
34
|
/**
|
|
24
35
|
* Searchable conversation list, embeddable in a sidebar or a DeesModal.
|
|
25
36
|
* Emits `harness-session-select` on click, `harness-session-open` on
|
|
26
37
|
* double-click or Enter, and `harness-session-context` with viewport
|
|
27
38
|
* pointer coordinates on right-click (the browser menu is suppressed).
|
|
39
|
+
*
|
|
40
|
+
* With `enableGrouping`, sessions render under user-defined `groups` and can
|
|
41
|
+
* be dragged between groups and reordered. The component never mutates its
|
|
42
|
+
* inputs: drops emit `harness-session-move`, the "new group" button emits
|
|
43
|
+
* `harness-group-create-request`, and right-clicking a group header emits
|
|
44
|
+
* `harness-group-context` — the host persists changes and passes fresh
|
|
45
|
+
* `groups` back in. Sessions in no group render in the trailing ungrouped
|
|
46
|
+
* section, recency-sorted. While a search query is active the list is flat.
|
|
28
47
|
*/
|
|
29
48
|
@customElement('dees-harness-session-list')
|
|
30
49
|
export class DeesHarnessSessionList extends DeesElement {
|
|
@@ -43,9 +62,24 @@ export class DeesHarnessSessionList extends DeesElement {
|
|
|
43
62
|
@property()
|
|
44
63
|
accessor emptyText: string = 'No conversations yet.';
|
|
45
64
|
|
|
65
|
+
@property({ attribute: false })
|
|
66
|
+
accessor groups: IHarnessSessionGroup[] = [];
|
|
67
|
+
|
|
68
|
+
@property({ type: Boolean })
|
|
69
|
+
accessor enableGrouping: boolean = false;
|
|
70
|
+
|
|
46
71
|
@state()
|
|
47
72
|
accessor search: string = '';
|
|
48
73
|
|
|
74
|
+
@state()
|
|
75
|
+
accessor draggingSessionId: string = '';
|
|
76
|
+
|
|
77
|
+
@state()
|
|
78
|
+
accessor dropSlot: IDropSlot | undefined = undefined;
|
|
79
|
+
|
|
80
|
+
@state()
|
|
81
|
+
accessor collapsedGroupIds: ReadonlySet<string> = new Set<string>();
|
|
82
|
+
|
|
49
83
|
public static styles = [
|
|
50
84
|
themeDefaultStyles,
|
|
51
85
|
cssManager.defaultStyles,
|
|
@@ -118,6 +152,10 @@ export class DeesHarnessSessionList extends DeesElement {
|
|
|
118
152
|
box-shadow: inset 2px 0 0 var(--dees-color-accent-primary);
|
|
119
153
|
}
|
|
120
154
|
|
|
155
|
+
.item.dragging {
|
|
156
|
+
opacity: 0.4;
|
|
157
|
+
}
|
|
158
|
+
|
|
121
159
|
.itemTitle {
|
|
122
160
|
display: flex;
|
|
123
161
|
align-items: baseline;
|
|
@@ -133,6 +171,12 @@ export class DeesHarnessSessionList extends DeesElement {
|
|
|
133
171
|
white-space: nowrap;
|
|
134
172
|
}
|
|
135
173
|
|
|
174
|
+
.itemTitle .itemIcon {
|
|
175
|
+
flex: 0 0 auto;
|
|
176
|
+
align-self: center;
|
|
177
|
+
color: var(--dees-color-text-secondary);
|
|
178
|
+
}
|
|
179
|
+
|
|
136
180
|
.itemTime {
|
|
137
181
|
margin-left: auto;
|
|
138
182
|
flex: 0 0 auto;
|
|
@@ -155,9 +199,109 @@ export class DeesHarnessSessionList extends DeesElement {
|
|
|
155
199
|
font-size: var(--dees-font-control-size-sm, 12px);
|
|
156
200
|
text-align: center;
|
|
157
201
|
}
|
|
202
|
+
|
|
203
|
+
.groupHeader {
|
|
204
|
+
display: flex;
|
|
205
|
+
align-items: center;
|
|
206
|
+
gap: var(--dees-spacing-xs);
|
|
207
|
+
width: 100%;
|
|
208
|
+
margin-top: var(--dees-spacing-xs);
|
|
209
|
+
padding: 2px var(--dees-spacing-sm);
|
|
210
|
+
border: 0;
|
|
211
|
+
border-radius: var(--dees-radius-md);
|
|
212
|
+
background: transparent;
|
|
213
|
+
color: var(--dees-color-text-secondary);
|
|
214
|
+
cursor: pointer;
|
|
215
|
+
font-family: inherit;
|
|
216
|
+
font-size: var(--dees-font-caption1-size, 11px);
|
|
217
|
+
font-weight: 650;
|
|
218
|
+
text-transform: uppercase;
|
|
219
|
+
letter-spacing: 0.05em;
|
|
220
|
+
text-align: left;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
.groupHeader:hover {
|
|
224
|
+
background: var(--dees-color-hover);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
.groupHeader .chevron {
|
|
228
|
+
transition: transform var(--dees-transition-fast) var(--dees-ease-standard);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
.groupHeader.collapsed .chevron {
|
|
232
|
+
transform: rotate(-90deg);
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
.groupHeader .groupCount {
|
|
236
|
+
margin-left: auto;
|
|
237
|
+
font-weight: 500;
|
|
238
|
+
text-transform: none;
|
|
239
|
+
letter-spacing: normal;
|
|
240
|
+
color: var(--dees-color-text-muted);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
.groupHeader.dropTarget {
|
|
244
|
+
outline: 1px dashed var(--dees-color-accent-primary);
|
|
245
|
+
outline-offset: -1px;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
.dropLine {
|
|
249
|
+
height: 2px;
|
|
250
|
+
margin: 0 var(--dees-spacing-sm);
|
|
251
|
+
border-radius: 1px;
|
|
252
|
+
background: var(--dees-color-accent-primary);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
.newGroupRow {
|
|
256
|
+
flex: 0 0 auto;
|
|
257
|
+
padding: var(--dees-spacing-xs) var(--dees-spacing-sm) var(--dees-spacing-sm);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
.newGroupButton {
|
|
261
|
+
display: flex;
|
|
262
|
+
align-items: center;
|
|
263
|
+
gap: var(--dees-spacing-xs);
|
|
264
|
+
width: 100%;
|
|
265
|
+
padding: var(--dees-spacing-xs) var(--dees-spacing-sm);
|
|
266
|
+
border: 1px dashed var(--dees-color-border-default);
|
|
267
|
+
border-radius: var(--dees-radius-md);
|
|
268
|
+
background: transparent;
|
|
269
|
+
color: var(--dees-color-text-secondary);
|
|
270
|
+
cursor: pointer;
|
|
271
|
+
font-family: inherit;
|
|
272
|
+
font-size: var(--dees-font-control-size-sm, 12px);
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
.newGroupButton:hover {
|
|
276
|
+
border-color: var(--dees-color-accent-primary);
|
|
277
|
+
color: var(--dees-color-text-primary);
|
|
278
|
+
}
|
|
158
279
|
`,
|
|
159
280
|
];
|
|
160
281
|
|
|
282
|
+
private get sessionsById(): Map<string, IHarnessSessionMeta> {
|
|
283
|
+
return new Map(this.sessions.map((session) => [session.id, session]));
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
private get groupedSessionIds(): Set<string> {
|
|
287
|
+
const ids = new Set<string>();
|
|
288
|
+
for (const group of this.groups) {
|
|
289
|
+
for (const id of group.sessionIds) ids.add(id);
|
|
290
|
+
}
|
|
291
|
+
return ids;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
/** Ungrouped sessions, most recent first. */
|
|
295
|
+
private get ungroupedSessions(): IHarnessSessionMeta[] {
|
|
296
|
+
const grouped = this.groupedSessionIds;
|
|
297
|
+
return [...this.sessions]
|
|
298
|
+
.filter((session) => !grouped.has(session.id))
|
|
299
|
+
.sort(
|
|
300
|
+
(left, right) =>
|
|
301
|
+
(right.updatedAt ?? right.createdAt ?? 0) - (left.updatedAt ?? left.createdAt ?? 0),
|
|
302
|
+
);
|
|
303
|
+
}
|
|
304
|
+
|
|
161
305
|
private get filteredSessions(): IHarnessSessionMeta[] {
|
|
162
306
|
const query = this.search.trim().toLowerCase();
|
|
163
307
|
const sorted = [...this.sessions].sort(
|
|
@@ -174,7 +318,7 @@ export class DeesHarnessSessionList extends DeesElement {
|
|
|
174
318
|
}
|
|
175
319
|
|
|
176
320
|
public render(): TemplateResult {
|
|
177
|
-
const
|
|
321
|
+
const groupingActive = this.enableGrouping && !this.search.trim();
|
|
178
322
|
return html`
|
|
179
323
|
<div class="searchRow">
|
|
180
324
|
<input
|
|
@@ -188,18 +332,138 @@ export class DeesHarnessSessionList extends DeesElement {
|
|
|
188
332
|
<div class="list">
|
|
189
333
|
${this.loading
|
|
190
334
|
? html`<div class="emptyNote">Loading conversations…</div>`
|
|
191
|
-
:
|
|
192
|
-
?
|
|
193
|
-
:
|
|
335
|
+
: groupingActive
|
|
336
|
+
? this.renderGroupedList()
|
|
337
|
+
: this.renderFlatList()}
|
|
194
338
|
</div>
|
|
339
|
+
${groupingActive
|
|
340
|
+
? html`
|
|
341
|
+
<div class="newGroupRow">
|
|
342
|
+
<button
|
|
343
|
+
class="newGroupButton"
|
|
344
|
+
type="button"
|
|
345
|
+
@click=${() => {
|
|
346
|
+
this.dispatchEvent(
|
|
347
|
+
new CustomEvent('harness-group-create-request', {
|
|
348
|
+
bubbles: true,
|
|
349
|
+
composed: true,
|
|
350
|
+
}),
|
|
351
|
+
);
|
|
352
|
+
}}
|
|
353
|
+
>
|
|
354
|
+
<dees-icon icon="lucide:FolderPlus" iconSize="13"></dees-icon>
|
|
355
|
+
New group
|
|
356
|
+
</button>
|
|
357
|
+
</div>
|
|
358
|
+
`
|
|
359
|
+
: ''}
|
|
360
|
+
`;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
private renderFlatList(): TemplateResult {
|
|
364
|
+
const sessions = this.filteredSessions;
|
|
365
|
+
if (!sessions.length) {
|
|
366
|
+
return html`<div class="emptyNote">
|
|
367
|
+
${this.sessions.length ? 'No conversations match this search.' : this.emptyText}
|
|
368
|
+
</div>`;
|
|
369
|
+
}
|
|
370
|
+
return html`${sessions.map((session) => this.renderItem(session, null, -1))}`;
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
private renderGroupedList(): TemplateResult {
|
|
374
|
+
const byId = this.sessionsById;
|
|
375
|
+
const ungrouped = this.ungroupedSessions;
|
|
376
|
+
if (!this.sessions.length && !this.groups.length) {
|
|
377
|
+
return html`<div class="emptyNote">${this.emptyText}</div>`;
|
|
378
|
+
}
|
|
379
|
+
return html`
|
|
380
|
+
${this.groups.map((group) => {
|
|
381
|
+
const members = group.sessionIds
|
|
382
|
+
.map((id) => byId.get(id))
|
|
383
|
+
.filter((session): session is IHarnessSessionMeta => session !== undefined);
|
|
384
|
+
const collapsed = this.collapsedGroupIds.has(group.id);
|
|
385
|
+
const isHeaderDrop =
|
|
386
|
+
this.dropSlot?.groupId === group.id && this.dropSlot.index === members.length && collapsed;
|
|
387
|
+
return html`
|
|
388
|
+
<button
|
|
389
|
+
class="groupHeader ${collapsed ? 'collapsed' : ''} ${isHeaderDrop ? 'dropTarget' : ''}"
|
|
390
|
+
type="button"
|
|
391
|
+
@click=${() => this.toggleGroupCollapsed(group.id)}
|
|
392
|
+
@contextmenu=${(event: MouseEvent) => {
|
|
393
|
+
event.preventDefault();
|
|
394
|
+
const detail: IHarnessGroupContextDetail = {
|
|
395
|
+
group,
|
|
396
|
+
clientX: event.clientX,
|
|
397
|
+
clientY: event.clientY,
|
|
398
|
+
originalEvent: event,
|
|
399
|
+
};
|
|
400
|
+
this.dispatchEvent(
|
|
401
|
+
new CustomEvent('harness-group-context', { detail, bubbles: true, composed: true }),
|
|
402
|
+
);
|
|
403
|
+
}}
|
|
404
|
+
@dragover=${(event: DragEvent) => this.handleDragOverSlot(event, group.id, members.length)}
|
|
405
|
+
@drop=${(event: DragEvent) => this.handleDrop(event, group.id, members.length)}
|
|
406
|
+
>
|
|
407
|
+
<dees-icon class="chevron" icon="lucide:ChevronDown" iconSize="12"></dees-icon>
|
|
408
|
+
<span>${group.name}</span>
|
|
409
|
+
<span class="groupCount">${members.length}</span>
|
|
410
|
+
</button>
|
|
411
|
+
${collapsed
|
|
412
|
+
? ''
|
|
413
|
+
: this.renderSection(members, group.id)}
|
|
414
|
+
`;
|
|
415
|
+
})}
|
|
416
|
+
${this.groups.length && ungrouped.length
|
|
417
|
+
? html`
|
|
418
|
+
<button
|
|
419
|
+
class="groupHeader"
|
|
420
|
+
type="button"
|
|
421
|
+
tabindex="-1"
|
|
422
|
+
@dragover=${(event: DragEvent) => this.handleDragOverSlot(event, null, 0)}
|
|
423
|
+
@drop=${(event: DragEvent) => this.handleDrop(event, null, 0)}
|
|
424
|
+
>
|
|
425
|
+
<span>Ungrouped</span>
|
|
426
|
+
<span class="groupCount">${ungrouped.length}</span>
|
|
427
|
+
</button>
|
|
428
|
+
`
|
|
429
|
+
: ''}
|
|
430
|
+
${this.renderSection(ungrouped, null)}
|
|
195
431
|
`;
|
|
196
432
|
}
|
|
197
433
|
|
|
198
|
-
private
|
|
434
|
+
private renderSection(
|
|
435
|
+
sessions: IHarnessSessionMeta[],
|
|
436
|
+
groupId: string | null,
|
|
437
|
+
): TemplateResult {
|
|
438
|
+
const slot = this.dropSlot;
|
|
439
|
+
return html`
|
|
440
|
+
${sessions.map(
|
|
441
|
+
(session, index) => html`
|
|
442
|
+
${slot && slot.groupId === groupId && slot.index === index
|
|
443
|
+
? html`<div class="dropLine"></div>`
|
|
444
|
+
: ''}
|
|
445
|
+
${this.renderItem(session, groupId, index)}
|
|
446
|
+
`,
|
|
447
|
+
)}
|
|
448
|
+
${slot && slot.groupId === groupId && slot.index === sessions.length
|
|
449
|
+
? html`<div class="dropLine"></div>`
|
|
450
|
+
: ''}
|
|
451
|
+
`;
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
private renderItem(
|
|
455
|
+
session: IHarnessSessionMeta,
|
|
456
|
+
groupId: string | null,
|
|
457
|
+
index: number,
|
|
458
|
+
): TemplateResult {
|
|
459
|
+
const draggable = this.enableGrouping && index >= 0;
|
|
199
460
|
return html`
|
|
200
461
|
<button
|
|
201
|
-
class="item ${session.id === this.selectedSessionId ? 'selected' : ''}
|
|
462
|
+
class="item ${session.id === this.selectedSessionId ? 'selected' : ''} ${
|
|
463
|
+
this.draggingSessionId === session.id ? 'dragging' : ''
|
|
464
|
+
}"
|
|
202
465
|
type="button"
|
|
466
|
+
draggable=${draggable ? 'true' : 'false'}
|
|
203
467
|
@click=${() => this.emit('harness-session-select', session)}
|
|
204
468
|
@dblclick=${() => this.emit('harness-session-open', session)}
|
|
205
469
|
@keydown=${(event: KeyboardEvent) => {
|
|
@@ -217,8 +481,34 @@ export class DeesHarnessSessionList extends DeesElement {
|
|
|
217
481
|
new CustomEvent('harness-session-context', { detail, bubbles: true, composed: true }),
|
|
218
482
|
);
|
|
219
483
|
}}
|
|
484
|
+
@dragstart=${(event: DragEvent) => {
|
|
485
|
+
if (!draggable) return;
|
|
486
|
+
this.draggingSessionId = session.id;
|
|
487
|
+
event.dataTransfer?.setData('text/plain', session.id);
|
|
488
|
+
if (event.dataTransfer) event.dataTransfer.effectAllowed = 'move';
|
|
489
|
+
}}
|
|
490
|
+
@dragend=${() => {
|
|
491
|
+
this.draggingSessionId = '';
|
|
492
|
+
this.dropSlot = undefined;
|
|
493
|
+
}}
|
|
494
|
+
@dragover=${(event: DragEvent) => {
|
|
495
|
+
if (!this.draggingSessionId || index < 0) return;
|
|
496
|
+
event.preventDefault();
|
|
497
|
+
const rect = (event.currentTarget as HTMLElement).getBoundingClientRect();
|
|
498
|
+
const before = event.clientY < rect.top + rect.height / 2;
|
|
499
|
+
this.setDropSlot(groupId, before ? index : index + 1);
|
|
500
|
+
}}
|
|
501
|
+
@drop=${(event: DragEvent) => {
|
|
502
|
+
if (index < 0) return;
|
|
503
|
+
const rect = (event.currentTarget as HTMLElement).getBoundingClientRect();
|
|
504
|
+
const before = event.clientY < rect.top + rect.height / 2;
|
|
505
|
+
this.handleDrop(event, groupId, before ? index : index + 1);
|
|
506
|
+
}}
|
|
220
507
|
>
|
|
221
508
|
<span class="itemTitle">
|
|
509
|
+
${session.icon
|
|
510
|
+
? html`<dees-icon class="itemIcon" icon=${session.icon} iconSize="12"></dees-icon>`
|
|
511
|
+
: ''}
|
|
222
512
|
<span class="titleText">${session.title || session.id}</span>
|
|
223
513
|
<span class="itemTime">${harnessFormatRelativeTime(session.updatedAt ?? session.createdAt)}</span>
|
|
224
514
|
</span>
|
|
@@ -229,6 +519,45 @@ export class DeesHarnessSessionList extends DeesElement {
|
|
|
229
519
|
`;
|
|
230
520
|
}
|
|
231
521
|
|
|
522
|
+
private toggleGroupCollapsed(groupIdArg: string): void {
|
|
523
|
+
const next = new Set(this.collapsedGroupIds);
|
|
524
|
+
if (next.has(groupIdArg)) {
|
|
525
|
+
next.delete(groupIdArg);
|
|
526
|
+
} else {
|
|
527
|
+
next.add(groupIdArg);
|
|
528
|
+
}
|
|
529
|
+
this.collapsedGroupIds = next;
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
private setDropSlot(groupIdArg: string | null, indexArg: number): void {
|
|
533
|
+
const current = this.dropSlot;
|
|
534
|
+
if (current && current.groupId === groupIdArg && current.index === indexArg) return;
|
|
535
|
+
this.dropSlot = { groupId: groupIdArg, index: indexArg };
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
private handleDragOverSlot(event: DragEvent, groupIdArg: string | null, indexArg: number): void {
|
|
539
|
+
if (!this.draggingSessionId) return;
|
|
540
|
+
event.preventDefault();
|
|
541
|
+
this.setDropSlot(groupIdArg, indexArg);
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
private handleDrop(event: DragEvent, groupIdArg: string | null, indexArg: number): void {
|
|
545
|
+
event.preventDefault();
|
|
546
|
+
event.stopPropagation();
|
|
547
|
+
const sessionId = this.draggingSessionId || event.dataTransfer?.getData('text/plain') || '';
|
|
548
|
+
this.draggingSessionId = '';
|
|
549
|
+
this.dropSlot = undefined;
|
|
550
|
+
if (!sessionId) return;
|
|
551
|
+
const detail: IHarnessSessionMoveDetail = {
|
|
552
|
+
sessionId,
|
|
553
|
+
groupId: groupIdArg,
|
|
554
|
+
index: Math.max(0, indexArg),
|
|
555
|
+
};
|
|
556
|
+
this.dispatchEvent(
|
|
557
|
+
new CustomEvent('harness-session-move', { detail, bubbles: true, composed: true }),
|
|
558
|
+
);
|
|
559
|
+
}
|
|
560
|
+
|
|
232
561
|
private emit(name: string, session: IHarnessSessionMeta): void {
|
|
233
562
|
this.dispatchEvent(new CustomEvent(name, { detail: { session }, bubbles: true, composed: true }));
|
|
234
563
|
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { html } from '@design.estate/dees-element';
|
|
2
|
+
|
|
3
|
+
// A loopback demo: keystrokes echo straight back into the terminal so the
|
|
4
|
+
// component is explorable without a live PTY behind it.
|
|
5
|
+
export const demoFunc = () => html`
|
|
6
|
+
<style>
|
|
7
|
+
.terminalDemo {
|
|
8
|
+
height: 380px;
|
|
9
|
+
border: 1px solid var(--dees-color-border-default);
|
|
10
|
+
border-radius: 8px;
|
|
11
|
+
overflow: hidden;
|
|
12
|
+
}
|
|
13
|
+
</style>
|
|
14
|
+
<div class="terminalDemo">
|
|
15
|
+
<dees-terminal-view
|
|
16
|
+
@terminal-input=${(event: CustomEvent<{ data: string }>) => {
|
|
17
|
+
const view = event.currentTarget as HTMLElementTagNameMap['dees-terminal-view'];
|
|
18
|
+
const data = event.detail.data;
|
|
19
|
+
view.write(data === '\r' ? '\r\n' : data);
|
|
20
|
+
}}
|
|
21
|
+
@terminal-resize=${(event: CustomEvent<{ rows: number; cols: number }>) => {
|
|
22
|
+
console.log('terminal size', event.detail);
|
|
23
|
+
}}
|
|
24
|
+
></dees-terminal-view>
|
|
25
|
+
</div>
|
|
26
|
+
`;
|