@design.estate/dees-catalog 10.0.0 → 11.0.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.
@@ -122196,6 +122196,20 @@ body > div[style*="top: -50000px"][style*="width: 50000px"] {
122196
122196
  }
122197
122197
  return _DeesServiceLibLoader.instance;
122198
122198
  }
122199
+ /**
122200
+ * Shares one in-flight load between concurrent callers — but only for as long
122201
+ * as that load can still succeed. A rejected load clears its own cache entry,
122202
+ * so the next call makes a fresh attempt instead of replaying a stale failure
122203
+ * for the lifetime of the page. Every load below goes through this.
122204
+ */
122205
+ shareLoad(loadArg, readArg, writeArg) {
122206
+ const pending = loadArg();
122207
+ writeArg(pending);
122208
+ pending.catch(() => {
122209
+ if (readArg() === pending) writeArg(null);
122210
+ });
122211
+ return pending;
122212
+ }
122199
122213
  /**
122200
122214
  * Load xterm terminal emulator from CDN
122201
122215
  * @returns Promise resolving to xterm module with Terminal class
@@ -122207,19 +122221,24 @@ body > div[style*="top: -50000px"][style*="width: 50000px"] {
122207
122221
  if (this.xtermLoadingPromise) {
122208
122222
  return this.xtermLoadingPromise;
122209
122223
  }
122210
- this.xtermLoadingPromise = (async () => {
122211
- const url = `${CDN_BASE}/xterm@${CDN_VERSIONS.xterm}/+esm`;
122212
- const module = await import(
122213
- /* @vite-ignore */
122214
- url
122215
- );
122216
- await this.injectXtermStyles();
122217
- this.xtermLib = {
122218
- Terminal: module.Terminal
122219
- };
122220
- return this.xtermLib;
122221
- })();
122222
- return this.xtermLoadingPromise;
122224
+ return this.shareLoad(
122225
+ async () => {
122226
+ const url = `${CDN_BASE}/xterm@${CDN_VERSIONS.xterm}/+esm`;
122227
+ const module = await import(
122228
+ /* @vite-ignore */
122229
+ url
122230
+ );
122231
+ await this.injectXtermStyles();
122232
+ this.xtermLib = {
122233
+ Terminal: module.Terminal
122234
+ };
122235
+ return this.xtermLib;
122236
+ },
122237
+ () => this.xtermLoadingPromise,
122238
+ (promiseArg) => {
122239
+ this.xtermLoadingPromise = promiseArg;
122240
+ }
122241
+ );
122223
122242
  }
122224
122243
  /**
122225
122244
  * Provides xterm modules from the host application instead of the CDN.
@@ -122257,18 +122276,23 @@ body > div[style*="top: -50000px"][style*="width: 50000px"] {
122257
122276
  if (this.xtermFitAddonLoadingPromise) {
122258
122277
  return this.xtermFitAddonLoadingPromise;
122259
122278
  }
122260
- this.xtermFitAddonLoadingPromise = (async () => {
122261
- const url = `${CDN_BASE}/xterm-addon-fit@${CDN_VERSIONS.xtermAddonFit}/+esm`;
122262
- const module = await import(
122263
- /* @vite-ignore */
122264
- url
122265
- );
122266
- this.xtermFitAddonLib = {
122267
- FitAddon: module.FitAddon
122268
- };
122269
- return this.xtermFitAddonLib;
122270
- })();
122271
- return this.xtermFitAddonLoadingPromise;
122279
+ return this.shareLoad(
122280
+ async () => {
122281
+ const url = `${CDN_BASE}/xterm-addon-fit@${CDN_VERSIONS.xtermAddonFit}/+esm`;
122282
+ const module = await import(
122283
+ /* @vite-ignore */
122284
+ url
122285
+ );
122286
+ this.xtermFitAddonLib = {
122287
+ FitAddon: module.FitAddon
122288
+ };
122289
+ return this.xtermFitAddonLib;
122290
+ },
122291
+ () => this.xtermFitAddonLoadingPromise,
122292
+ (promiseArg) => {
122293
+ this.xtermFitAddonLoadingPromise = promiseArg;
122294
+ }
122295
+ );
122272
122296
  }
122273
122297
  /**
122274
122298
  * Load xterm-addon-search from CDN
@@ -122281,18 +122305,23 @@ body > div[style*="top: -50000px"][style*="width: 50000px"] {
122281
122305
  if (this.xtermSearchAddonLoadingPromise) {
122282
122306
  return this.xtermSearchAddonLoadingPromise;
122283
122307
  }
122284
- this.xtermSearchAddonLoadingPromise = (async () => {
122285
- const url = `${CDN_BASE}/xterm-addon-search@${CDN_VERSIONS.xtermAddonSearch}/+esm`;
122286
- const module = await import(
122287
- /* @vite-ignore */
122288
- url
122289
- );
122290
- this.xtermSearchAddonLib = {
122291
- SearchAddon: module.SearchAddon
122292
- };
122293
- return this.xtermSearchAddonLib;
122294
- })();
122295
- return this.xtermSearchAddonLoadingPromise;
122308
+ return this.shareLoad(
122309
+ async () => {
122310
+ const url = `${CDN_BASE}/xterm-addon-search@${CDN_VERSIONS.xtermAddonSearch}/+esm`;
122311
+ const module = await import(
122312
+ /* @vite-ignore */
122313
+ url
122314
+ );
122315
+ this.xtermSearchAddonLib = {
122316
+ SearchAddon: module.SearchAddon
122317
+ };
122318
+ return this.xtermSearchAddonLib;
122319
+ },
122320
+ () => this.xtermSearchAddonLoadingPromise,
122321
+ (promiseArg) => {
122322
+ this.xtermSearchAddonLoadingPromise = promiseArg;
122323
+ }
122324
+ );
122296
122325
  }
122297
122326
  /**
122298
122327
  * Inject xterm CSS styles into the document head
@@ -122331,16 +122360,21 @@ body > div[style*="top: -50000px"][style*="width: 50000px"] {
122331
122360
  if (this.highlightJsLoadingPromise) {
122332
122361
  return this.highlightJsLoadingPromise;
122333
122362
  }
122334
- this.highlightJsLoadingPromise = (async () => {
122335
- const url = `${CDN_BASE}/highlight.js@${CDN_VERSIONS.highlightJs}/+esm`;
122336
- const module = await import(
122337
- /* @vite-ignore */
122338
- url
122339
- );
122340
- this.highlightJsLib = module.default;
122341
- return this.highlightJsLib;
122342
- })();
122343
- return this.highlightJsLoadingPromise;
122363
+ return this.shareLoad(
122364
+ async () => {
122365
+ const url = `${CDN_BASE}/highlight.js@${CDN_VERSIONS.highlightJs}/+esm`;
122366
+ const module = await import(
122367
+ /* @vite-ignore */
122368
+ url
122369
+ );
122370
+ this.highlightJsLib = module.default;
122371
+ return this.highlightJsLib;
122372
+ },
122373
+ () => this.highlightJsLoadingPromise,
122374
+ (promiseArg) => {
122375
+ this.highlightJsLoadingPromise = promiseArg;
122376
+ }
122377
+ );
122344
122378
  }
122345
122379
  /**
122346
122380
  * Load TradingView Lightweight Charts from CDN
@@ -122353,23 +122387,28 @@ body > div[style*="top: -50000px"][style*="width: 50000px"] {
122353
122387
  if (this.lightweightChartsLoadingPromise) {
122354
122388
  return this.lightweightChartsLoadingPromise;
122355
122389
  }
122356
- this.lightweightChartsLoadingPromise = (async () => {
122357
- const url = `${CDN_BASE}/lightweight-charts@${CDN_VERSIONS.lightweightCharts}/+esm`;
122358
- const module = await import(
122359
- /* @vite-ignore */
122360
- url
122361
- );
122362
- this.lightweightChartsLib = {
122363
- createChart: module.createChart,
122364
- AreaSeries: module.AreaSeries,
122365
- LineSeries: module.LineSeries,
122366
- ColorType: module.ColorType,
122367
- LineType: module.LineType,
122368
- CrosshairMode: module.CrosshairMode
122369
- };
122370
- return this.lightweightChartsLib;
122371
- })();
122372
- return this.lightweightChartsLoadingPromise;
122390
+ return this.shareLoad(
122391
+ async () => {
122392
+ const url = `${CDN_BASE}/lightweight-charts@${CDN_VERSIONS.lightweightCharts}/+esm`;
122393
+ const module = await import(
122394
+ /* @vite-ignore */
122395
+ url
122396
+ );
122397
+ this.lightweightChartsLib = {
122398
+ createChart: module.createChart,
122399
+ AreaSeries: module.AreaSeries,
122400
+ LineSeries: module.LineSeries,
122401
+ ColorType: module.ColorType,
122402
+ LineType: module.LineType,
122403
+ CrosshairMode: module.CrosshairMode
122404
+ };
122405
+ return this.lightweightChartsLib;
122406
+ },
122407
+ () => this.lightweightChartsLoadingPromise,
122408
+ (promiseArg) => {
122409
+ this.lightweightChartsLoadingPromise = promiseArg;
122410
+ }
122411
+ );
122373
122412
  }
122374
122413
  /**
122375
122414
  * Load Apache ECharts from CDN
@@ -122382,20 +122421,25 @@ body > div[style*="top: -50000px"][style*="width: 50000px"] {
122382
122421
  if (this.echartsLoadingPromise) {
122383
122422
  return this.echartsLoadingPromise;
122384
122423
  }
122385
- this.echartsLoadingPromise = (async () => {
122386
- const url = `${CDN_BASE}/echarts@${CDN_VERSIONS.echarts}/dist/echarts.esm.min.js`;
122387
- const module = await import(
122388
- /* @vite-ignore */
122389
- url
122390
- );
122391
- this.echartsLib = {
122392
- init: module.init,
122393
- dispose: module.dispose,
122394
- getInstanceByDom: module.getInstanceByDom
122395
- };
122396
- return this.echartsLib;
122397
- })();
122398
- return this.echartsLoadingPromise;
122424
+ return this.shareLoad(
122425
+ async () => {
122426
+ const url = `${CDN_BASE}/echarts@${CDN_VERSIONS.echarts}/dist/echarts.esm.min.js`;
122427
+ const module = await import(
122428
+ /* @vite-ignore */
122429
+ url
122430
+ );
122431
+ this.echartsLib = {
122432
+ init: module.init,
122433
+ dispose: module.dispose,
122434
+ getInstanceByDom: module.getInstanceByDom
122435
+ };
122436
+ return this.echartsLib;
122437
+ },
122438
+ () => this.echartsLoadingPromise,
122439
+ (promiseArg) => {
122440
+ this.echartsLoadingPromise = promiseArg;
122441
+ }
122442
+ );
122399
122443
  }
122400
122444
  /**
122401
122445
  * Load Tiptap rich text editor and extensions from CDN
@@ -122408,26 +122452,31 @@ body > div[style*="top: -50000px"][style*="width: 50000px"] {
122408
122452
  if (this.tiptapLoadingPromise) {
122409
122453
  return this.tiptapLoadingPromise;
122410
122454
  }
122411
- this.tiptapLoadingPromise = (async () => {
122412
- const [coreModule, starterKitModule, underlineModule, textAlignModule, linkModule, typographyModule] = await Promise.all([
122413
- Promise.resolve().then(() => (init_dist17(), dist_exports2)),
122414
- Promise.resolve().then(() => (init_dist43(), dist_exports3)),
122415
- Promise.resolve().then(() => (init_dist44(), dist_exports4)),
122416
- Promise.resolve().then(() => (init_dist45(), dist_exports5)),
122417
- Promise.resolve().then(() => (init_dist46(), dist_exports6)),
122418
- Promise.resolve().then(() => (init_dist47(), dist_exports7))
122419
- ]);
122420
- this.tiptapLib = {
122421
- Editor: coreModule.Editor,
122422
- StarterKit: starterKitModule.default || starterKitModule.StarterKit,
122423
- Underline: underlineModule.default || underlineModule.Underline,
122424
- TextAlign: textAlignModule.default || textAlignModule.TextAlign,
122425
- Link: linkModule.default || linkModule.Link,
122426
- Typography: typographyModule.default || typographyModule.Typography
122427
- };
122428
- return this.tiptapLib;
122429
- })();
122430
- return this.tiptapLoadingPromise;
122455
+ return this.shareLoad(
122456
+ async () => {
122457
+ const [coreModule, starterKitModule, underlineModule, textAlignModule, linkModule, typographyModule] = await Promise.all([
122458
+ Promise.resolve().then(() => (init_dist17(), dist_exports2)),
122459
+ Promise.resolve().then(() => (init_dist43(), dist_exports3)),
122460
+ Promise.resolve().then(() => (init_dist44(), dist_exports4)),
122461
+ Promise.resolve().then(() => (init_dist45(), dist_exports5)),
122462
+ Promise.resolve().then(() => (init_dist46(), dist_exports6)),
122463
+ Promise.resolve().then(() => (init_dist47(), dist_exports7))
122464
+ ]);
122465
+ this.tiptapLib = {
122466
+ Editor: coreModule.Editor,
122467
+ StarterKit: starterKitModule.default || starterKitModule.StarterKit,
122468
+ Underline: underlineModule.default || underlineModule.Underline,
122469
+ TextAlign: textAlignModule.default || textAlignModule.TextAlign,
122470
+ Link: linkModule.default || linkModule.Link,
122471
+ Typography: typographyModule.default || typographyModule.Typography
122472
+ };
122473
+ return this.tiptapLib;
122474
+ },
122475
+ () => this.tiptapLoadingPromise,
122476
+ (promiseArg) => {
122477
+ this.tiptapLoadingPromise = promiseArg;
122478
+ }
122479
+ );
122431
122480
  }
122432
122481
  /**
122433
122482
  * Preload multiple libraries in parallel
@@ -165037,9 +165086,9 @@ var _DeesAppui = class _DeesAppui extends (_a75 = DeesElement, _appbarMenuItems_
165037
165086
  /**
165038
165087
  * Set the selected secondary menu item by key (for tab items only)
165039
165088
  */
165040
- setSecondaryMenuSelection(itemKey) {
165089
+ setSecondaryMenuSelection(itemKey2) {
165041
165090
  for (const group of this.secondarymenuGroups) {
165042
- const item = group.items.find((i11) => "key" in i11 && i11.key === itemKey);
165091
+ const item = group.items.find((i11) => "key" in i11 && i11.key === itemKey2);
165043
165092
  if (item && (!("type" in item) || item.type === "tab" || item.type === void 0)) {
165044
165093
  this.secondarymenuSelectedItem = item;
165045
165094
  return;
@@ -179337,7 +179386,7 @@ init_dist_ts26();
179337
179386
  init_templates();
179338
179387
  init_theme();
179339
179388
  init_dees_contextmenu();
179340
- var _showDetails_dec, _notice_dec, _associations_dec, _ungroupedSessionIds_dec, _groups_dec2, _selectedSessionId_dec, _sessions_dec, _a99, _DeesDemoSessionWorkspace_decorators, _init101, _sessions, _selectedSessionId, _groups2, _ungroupedSessionIds, _associations, _notice, _showDetails;
179389
+ var _showDetails_dec, _notice_dec, _associations_dec, _ungroupedItemIds_dec, _groups_dec2, _selectedSessionId_dec, _sessions_dec, _a99, _DeesDemoSessionWorkspace_decorators, _init101, _sessions, _selectedSessionId, _groups2, _ungroupedItemIds, _associations, _notice, _showDetails;
179341
179390
  var stages = {
179342
179391
  idle: { state: "normal", label: "Ready to start", description: "The brief is ready. Start the session to prepare the workspace." },
179343
179392
  starting: { state: "working", label: "Starting", description: "Opening the workspace and reading the project instructions." },
@@ -179366,9 +179415,29 @@ var demoSessions = /* @__PURE__ */ __name(() => [
179366
179415
  preview: stages[session.stage].description
179367
179416
  })), "demoSessions");
179368
179417
  var demoGroups = [
179369
- { id: "active", name: "Workspace", sessionIds: ["session-0", "session-1", "session-2", "session-6"] },
179370
- { id: "review", name: "Recent", sessionIds: ["session-3", "session-5", "session-4"] }
179418
+ {
179419
+ id: "active",
179420
+ name: "Workspace",
179421
+ itemIds: [
179422
+ { kind: "session", id: "session-0" },
179423
+ { kind: "resource", id: "terminal:build" },
179424
+ { kind: "session", id: "session-1" },
179425
+ { kind: "session", id: "session-2" },
179426
+ { kind: "session", id: "session-6" }
179427
+ ]
179428
+ },
179429
+ {
179430
+ id: "review",
179431
+ name: "Recent",
179432
+ itemIds: [
179433
+ { kind: "session", id: "session-3" },
179434
+ { kind: "session", id: "session-5" },
179435
+ { kind: "session", id: "session-4" }
179436
+ ]
179437
+ }
179371
179438
  ];
179439
+ var cloneGroups = /* @__PURE__ */ __name((groupsArg) => groupsArg.map((group) => ({ ...group, itemIds: group.itemIds.map((ref) => ({ ...ref })) })), "cloneGroups");
179440
+ var sameRef = /* @__PURE__ */ __name((leftArg, rightArg) => leftArg.kind === rightArg.kind && leftArg.id === rightArg.id, "sameRef");
179372
179441
  var demoResources = [
179373
179442
  {
179374
179443
  id: "terminal:build",
@@ -179397,34 +179466,43 @@ var demoResources = [
179397
179466
  }
179398
179467
  ];
179399
179468
  var demoResourceAssociations = [
179400
- { resourceId: "terminal:build", sessionId: "session-4" },
179401
- { resourceId: "file:release-notes", sessionId: "session-4" }
179469
+ { resourceId: "terminal:build", target: { kind: "session", id: "session-4" } },
179470
+ { resourceId: "file:release-notes", target: { kind: "resource", id: "terminal:build" } }
179471
+ ];
179472
+ var demoEligibleSessionTargets = [
179473
+ { kind: "session", id: "session-0" },
179474
+ { kind: "session", id: "session-1" },
179475
+ { kind: "session", id: "session-2" },
179476
+ { kind: "session", id: "session-4" }
179402
179477
  ];
179403
- var demoResourceEligibleSessionIds = Object.fromEntries(
179404
- demoResources.map((resource) => [resource.id, ["session-0", "session-1", "session-2", "session-4"]])
179478
+ var demoResourceEligibleTargets = Object.fromEntries(
179479
+ demoResources.map((resource) => [
179480
+ resource.id,
179481
+ resource.kind === "terminal" ? demoEligibleSessionTargets : [...demoEligibleSessionTargets, { kind: "resource", id: "terminal:build" }]
179482
+ ])
179405
179483
  );
179406
179484
  var handleSessionSelect = /* @__PURE__ */ __name((event) => {
179407
179485
  const list5 = event.currentTarget;
179408
179486
  list5.selectedSessionId = event.detail.session.id;
179409
179487
  }, "handleSessionSelect");
179410
- var handleSessionMove = /* @__PURE__ */ __name((event) => {
179488
+ var handleItemMove = /* @__PURE__ */ __name((event) => {
179411
179489
  const list5 = event.currentTarget;
179412
- applySessionMove(list5, event.detail);
179413
- }, "handleSessionMove");
179414
- var applySessionMove = /* @__PURE__ */ __name((list5, detail) => {
179415
- const { sessionId, groupId, beforeSessionId } = detail;
179490
+ applyItemMove(list5, event.detail);
179491
+ }, "handleItemMove");
179492
+ var applyItemMove = /* @__PURE__ */ __name((list5, moveArg) => {
179493
+ const { item, toGroupId, beforeItem } = moveArg;
179416
179494
  const groups = list5.groups.map((group) => ({
179417
179495
  ...group,
179418
- sessionIds: group.sessionIds.filter((id) => id !== sessionId)
179496
+ itemIds: group.itemIds.filter((ref) => !sameRef(ref, item))
179419
179497
  }));
179420
- const ungroupedSessionIds = list5.ungroupedSessionIds.filter((id) => id !== sessionId);
179421
- const targetIds = groupId === null ? ungroupedSessionIds : groups.find((group) => group.id === groupId)?.sessionIds;
179498
+ const ungroupedItemIds = list5.ungroupedItemIds.filter((ref) => !sameRef(ref, item));
179499
+ const targetIds = toGroupId === null ? ungroupedItemIds : groups.find((group) => group.id === toGroupId)?.itemIds;
179422
179500
  if (!targetIds) return;
179423
- const anchorIndex = beforeSessionId ? targetIds.indexOf(beforeSessionId) : -1;
179424
- targetIds.splice(anchorIndex >= 0 ? anchorIndex : targetIds.length, 0, sessionId);
179501
+ const anchorIndex = beforeItem ? targetIds.findIndex((ref) => sameRef(ref, beforeItem)) : -1;
179502
+ targetIds.splice(anchorIndex >= 0 ? anchorIndex : targetIds.length, 0, { ...item });
179425
179503
  list5.groups = groups;
179426
- list5.ungroupedSessionIds = ungroupedSessionIds;
179427
- }, "applySessionMove");
179504
+ list5.ungroupedItemIds = ungroupedItemIds;
179505
+ }, "applyItemMove");
179428
179506
  var handleSessionOpen = /* @__PURE__ */ __name((event) => {
179429
179507
  const list5 = event.currentTarget;
179430
179508
  list5.selectedSessionId = event.detail.session.id;
@@ -179437,7 +179515,10 @@ var handleSessionContext = /* @__PURE__ */ __name(async (event, onChange = () =>
179437
179515
  const invokingControl = originalEvent.composedPath().find(
179438
179516
  (target) => target instanceof HTMLButtonElement
179439
179517
  );
179440
- const currentGroup = list5.groups.find((group) => group.sessionIds.includes(session.id));
179518
+ const sessionRef = { kind: "session", id: session.id };
179519
+ const currentGroup = list5.groups.find(
179520
+ (group) => group.itemIds.some((ref) => sameRef(ref, sessionRef))
179521
+ );
179441
179522
  const menu = await DeesContextmenu.openContextMenuWithOptions(originalEvent, [
179442
179523
  {
179443
179524
  name: "Open conversation",
@@ -179457,7 +179538,7 @@ var handleSessionContext = /* @__PURE__ */ __name(async (event, onChange = () =>
179457
179538
  name: `Move to ${group.name}`,
179458
179539
  iconName: "lucide:FolderInput",
179459
179540
  action: /* @__PURE__ */ __name(async () => {
179460
- applySessionMove(list5, { sessionId: session.id, groupId: group.id, index: group.sessionIds.length });
179541
+ applyItemMove(list5, { item: sessionRef, toGroupId: group.id, beforeItem: null });
179461
179542
  onChange();
179462
179543
  showDemoResult(list5, `Moved \u201C${session.title}\u201D to ${group.name}.`);
179463
179544
  }, "action")
@@ -179466,7 +179547,7 @@ var handleSessionContext = /* @__PURE__ */ __name(async (event, onChange = () =>
179466
179547
  name: "Move to Ungrouped",
179467
179548
  iconName: "lucide:FolderInput",
179468
179549
  action: /* @__PURE__ */ __name(async () => {
179469
- applySessionMove(list5, { sessionId: session.id, groupId: null, index: list5.ungroupedSessionIds.length });
179550
+ applyItemMove(list5, { item: sessionRef, toGroupId: null, beforeItem: null });
179470
179551
  onChange();
179471
179552
  showDemoResult(list5, `Moved \u201C${session.title}\u201D to Ungrouped.`);
179472
179553
  }, "action")
@@ -179486,33 +179567,34 @@ var handleResourceAssociation = /* @__PURE__ */ __name((event) => {
179486
179567
  const next2 = list5.resourceAssociations.filter(
179487
179568
  (association2) => association2.resourceId !== event.detail.resource.id
179488
179569
  );
179489
- if (event.detail.toSessionId) {
179570
+ if (event.detail.toTarget) {
179490
179571
  next2.push({
179491
179572
  resourceId: event.detail.resource.id,
179492
- sessionId: event.detail.toSessionId
179573
+ target: { ...event.detail.toTarget }
179493
179574
  });
179494
179575
  }
179495
179576
  list5.resourceAssociations = next2;
179496
179577
  }, "handleResourceAssociation");
179497
179578
  var handleResourceContext = /* @__PURE__ */ __name(async (event) => {
179498
179579
  const list5 = event.currentTarget;
179499
- const currentSessionId = event.detail.sessionId;
179500
- const eligibleSessionIds = list5.eligibleSessionIdsByResourceId[event.detail.resource.id] ?? [];
179580
+ const currentTarget = event.detail.target;
179581
+ const eligibleTargets = list5.eligibleTargetsByResourceId[event.detail.resource.id] ?? [];
179582
+ const titleFor = /* @__PURE__ */ __name((refArg) => (refArg.kind === "session" ? list5.sessions.find((session) => session.id === refArg.id)?.title : list5.resources.find((resource) => resource.id === refArg.id)?.title) ?? refArg.id, "titleFor");
179501
179583
  const menu = await DeesContextmenu.openContextMenuWithOptions(
179502
179584
  new MouseEvent("contextmenu", {
179503
179585
  clientX: event.detail.clientX,
179504
179586
  clientY: event.detail.clientY
179505
179587
  }),
179506
179588
  [
179507
- ...eligibleSessionIds.filter((sessionId) => sessionId !== currentSessionId).map((sessionId) => ({
179508
- name: `${currentSessionId ? "Reassign" : "Attach"} to ${list5.sessions.find((session) => session.id === sessionId)?.title}`,
179589
+ ...eligibleTargets.filter((target) => !currentTarget || !sameRef(target, currentTarget)).map((target) => ({
179590
+ name: `${currentTarget ? "Reassign" : "Attach"} to ${titleFor(target)}`,
179509
179591
  iconName: "lucide:Link",
179510
179592
  action: /* @__PURE__ */ __name(async () => {
179511
- event.detail.requestAssociation(sessionId);
179593
+ event.detail.requestAssociation(target);
179512
179594
  event.detail.close();
179513
179595
  }, "action")
179514
179596
  })),
179515
- ...currentSessionId ? [{
179597
+ ...currentTarget ? [{
179516
179598
  name: "Detach",
179517
179599
  iconName: "lucide:Unlink",
179518
179600
  action: /* @__PURE__ */ __name(async () => {
@@ -179534,7 +179616,7 @@ var openModal = /* @__PURE__ */ __name(async (sessions, groups) => {
179534
179616
  const content3 = document.createElement("dees-harness-session-list");
179535
179617
  content3.sessions = sessions;
179536
179618
  content3.groups = groups;
179537
- content3.ungroupedSessionIds = [];
179619
+ content3.ungroupedItemIds = [];
179538
179620
  content3.enableGrouping = true;
179539
179621
  content3.style.height = "420px";
179540
179622
  content3.addEventListener("harness-session-select", handleSessionSelect);
@@ -179542,7 +179624,7 @@ var openModal = /* @__PURE__ */ __name(async (sessions, groups) => {
179542
179624
  content3.addEventListener("harness-session-context", (event) => {
179543
179625
  void handleSessionContext(event);
179544
179626
  });
179545
- content3.addEventListener("harness-session-move", handleSessionMove);
179627
+ content3.addEventListener("harness-item-move", handleItemMove);
179546
179628
  DeesModal2.createAndShow({
179547
179629
  heading: "Conversations",
179548
179630
  content: b2`<style>${demoStyles}</style><div class="dees-demo-stack">${content3}${demoOutput("Choose a conversation action.")}</div>`,
@@ -179550,13 +179632,13 @@ var openModal = /* @__PURE__ */ __name(async (sessions, groups) => {
179550
179632
  });
179551
179633
  }, "openModal");
179552
179634
  _DeesDemoSessionWorkspace_decorators = [customElement("dees-demo-session-workspace")];
179553
- var _DeesDemoSessionWorkspace = class _DeesDemoSessionWorkspace extends (_a99 = DeesElement, _sessions_dec = [r5()], _selectedSessionId_dec = [r5()], _groups_dec2 = [r5()], _ungroupedSessionIds_dec = [r5()], _associations_dec = [r5()], _notice_dec = [r5()], _showDetails_dec = [r5()], _a99) {
179635
+ var _DeesDemoSessionWorkspace = class _DeesDemoSessionWorkspace extends (_a99 = DeesElement, _sessions_dec = [r5()], _selectedSessionId_dec = [r5()], _groups_dec2 = [r5()], _ungroupedItemIds_dec = [r5()], _associations_dec = [r5()], _notice_dec = [r5()], _showDetails_dec = [r5()], _a99) {
179554
179636
  constructor() {
179555
179637
  super(...arguments);
179556
179638
  __privateAdd(this, _sessions, __runInitializers(_init101, 8, this, demoSessions())), __runInitializers(_init101, 11, this);
179557
179639
  __privateAdd(this, _selectedSessionId, __runInitializers(_init101, 12, this, "session-0")), __runInitializers(_init101, 15, this);
179558
- __privateAdd(this, _groups2, __runInitializers(_init101, 16, this, demoGroups.map((group) => ({ ...group, sessionIds: [...group.sessionIds] })))), __runInitializers(_init101, 19, this);
179559
- __privateAdd(this, _ungroupedSessionIds, __runInitializers(_init101, 20, this, [])), __runInitializers(_init101, 23, this);
179640
+ __privateAdd(this, _groups2, __runInitializers(_init101, 16, this, cloneGroups(demoGroups))), __runInitializers(_init101, 19, this);
179641
+ __privateAdd(this, _ungroupedItemIds, __runInitializers(_init101, 20, this, [])), __runInitializers(_init101, 23, this);
179560
179642
  __privateAdd(this, _associations, __runInitializers(_init101, 24, this, [...demoResourceAssociations])), __runInitializers(_init101, 27, this);
179561
179643
  __privateAdd(this, _notice, __runInitializers(_init101, 28, this, "Interactive demo \xB7 Changes stay in this example.")), __runInitializers(_init101, 31, this);
179562
179644
  __privateAdd(this, _showDetails, __runInitializers(_init101, 32, this, false)), __runInitializers(_init101, 35, this);
@@ -179569,7 +179651,7 @@ var _DeesDemoSessionWorkspace = class _DeesDemoSessionWorkspace extends (_a99 =
179569
179651
  if (!list5) return;
179570
179652
  this.selectedSessionId = list5.selectedSessionId;
179571
179653
  this.groups = list5.groups;
179572
- this.ungroupedSessionIds = list5.ungroupedSessionIds;
179654
+ this.ungroupedItemIds = list5.ungroupedItemIds;
179573
179655
  this.associations = list5.resourceAssociations;
179574
179656
  }
179575
179657
  async select(event) {
@@ -179602,8 +179684,8 @@ var _DeesDemoSessionWorkspace = class _DeesDemoSessionWorkspace extends (_a99 =
179602
179684
  reset() {
179603
179685
  this.sessions = demoSessions();
179604
179686
  this.selectedSessionId = "session-0";
179605
- this.groups = demoGroups.map((group) => ({ ...group, sessionIds: [...group.sessionIds] }));
179606
- this.ungroupedSessionIds = [];
179687
+ this.groups = cloneGroups(demoGroups);
179688
+ this.ungroupedItemIds = [];
179607
179689
  this.associations = [...demoResourceAssociations];
179608
179690
  this.notice = "Demo reset. Choose a session or respond to the approval request.";
179609
179691
  if (this.list) {
@@ -179632,23 +179714,23 @@ var _DeesDemoSessionWorkspace = class _DeesDemoSessionWorkspace extends (_a99 =
179632
179714
  <span class="attentionSummary"><dees-icon icon="lucide:CircleAlert" iconSize="12"></dees-icon>${attentionCount} need attention</span>
179633
179715
  </div>
179634
179716
  <dees-harness-session-list
179635
- .sessions=${this.sessions} .groups=${this.groups} .ungroupedSessionIds=${this.ungroupedSessionIds}
179717
+ .sessions=${this.sessions} .groups=${this.groups} .ungroupedItemIds=${this.ungroupedItemIds}
179636
179718
  .resources=${demoResources} .resourceAssociations=${this.associations}
179637
- .eligibleSessionIdsByResourceId=${demoResourceEligibleSessionIds} .enableGrouping=${true}
179719
+ .eligibleTargetsByResourceId=${demoResourceEligibleTargets} .enableGrouping=${true}
179638
179720
  .selectedSessionId=${this.selectedSessionId}
179639
179721
  @harness-session-select=${this.select} @harness-session-open=${this.select}
179640
179722
  @harness-session-context=${(event) => handleSessionContext(event, (opened) => {
179641
179723
  this.syncList();
179642
179724
  if (opened) void this.revealSession();
179643
179725
  })}
179644
- @harness-session-move=${(event) => {
179645
- handleSessionMove(event);
179726
+ @harness-item-move=${(event) => {
179727
+ handleItemMove(event);
179646
179728
  this.syncList();
179647
179729
  }}
179648
179730
  @harness-group-create-request=${() => {
179649
- this.groups = [...this.groups, { id: `group-${this.groups.length}`, name: `Group ${this.groups.length + 1}`, sessionIds: [] }];
179731
+ this.groups = [...this.groups, { id: `group-${this.groups.length}`, name: `Group ${this.groups.length + 1}`, itemIds: [] }];
179650
179732
  if (this.list) this.list.search = "";
179651
- this.notice = "Group created. Drag a session here or use its Actions menu.";
179733
+ this.notice = "Group created. Drag a conversation or resource here, or use its Actions menu.";
179652
179734
  }}
179653
179735
  @harness-resource-select=${(event) => {
179654
179736
  event.currentTarget.selectedResourceId = event.detail.resource.id;
@@ -179738,14 +179820,14 @@ _init101 = __decoratorStart(_a99);
179738
179820
  _sessions = new WeakMap();
179739
179821
  _selectedSessionId = new WeakMap();
179740
179822
  _groups2 = new WeakMap();
179741
- _ungroupedSessionIds = new WeakMap();
179823
+ _ungroupedItemIds = new WeakMap();
179742
179824
  _associations = new WeakMap();
179743
179825
  _notice = new WeakMap();
179744
179826
  _showDetails = new WeakMap();
179745
179827
  __decorateElement(_init101, 4, "sessions", _sessions_dec, _DeesDemoSessionWorkspace, _sessions);
179746
179828
  __decorateElement(_init101, 4, "selectedSessionId", _selectedSessionId_dec, _DeesDemoSessionWorkspace, _selectedSessionId);
179747
179829
  __decorateElement(_init101, 4, "groups", _groups_dec2, _DeesDemoSessionWorkspace, _groups2);
179748
- __decorateElement(_init101, 4, "ungroupedSessionIds", _ungroupedSessionIds_dec, _DeesDemoSessionWorkspace, _ungroupedSessionIds);
179830
+ __decorateElement(_init101, 4, "ungroupedItemIds", _ungroupedItemIds_dec, _DeesDemoSessionWorkspace, _ungroupedItemIds);
179749
179831
  __decorateElement(_init101, 4, "associations", _associations_dec, _DeesDemoSessionWorkspace, _associations);
179750
179832
  __decorateElement(_init101, 4, "notice", _notice_dec, _DeesDemoSessionWorkspace, _notice);
179751
179833
  __decorateElement(_init101, 4, "showDetails", _showDetails_dec, _DeesDemoSessionWorkspace, _showDetails);
@@ -179801,12 +179883,18 @@ var demoFunc67 = /* @__PURE__ */ __name(() => demoApp(b2`<dees-demo-session-work
179801
179883
  init_dist_ts26();
179802
179884
  init_theme();
179803
179885
  init_dees_icon();
179804
- var _resourceContextResourceId_dec, _moveAnnouncement_dec, _bottomScrollShadowVisible_dec, _topScrollShadowVisible_dec, _collapsedGroupIds_dec, _expandedSessionIds_dec, _draggedItemHeight_dec, _dropSlot_dec, _resourceDropTargetSessionId_dec, _draggingResourceId_dec, _draggingSessionId_dec, _search_dec, _eligibleSessionIdsByResourceId_dec, _selectedResourceId_dec, _resourceAssociations_dec, _resources_dec, _ungroupedSessionIds_dec2, _enableGrouping_dec, _groups_dec3, _emptyText_dec2, _loading_dec5, _selectedSessionId_dec2, _sessions_dec2, _a100, _DeesHarnessSessionList_decorators, _init102, _sessions2, _selectedSessionId2, _loading5, _emptyText2, _groups3, _enableGrouping, _ungroupedSessionIds2, _resources, _resourceAssociations, _selectedResourceId, _eligibleSessionIdsByResourceId, _search, _draggingSessionId, _draggingResourceId, _resourceDropTargetSessionId, _dropSlot, _draggedItemHeight, _expandedSessionIds, _collapsedGroupIds, _topScrollShadowVisible, _bottomScrollShadowVisible, _moveAnnouncement, _resourceContextResourceId;
179886
+ var _resourceContextResourceId_dec, _moveAnnouncement_dec, _bottomScrollShadowVisible_dec, _topScrollShadowVisible_dec, _collapsedGroupIds_dec, _expandedSessionIds_dec, _draggedItemHeight_dec, _dropSlot_dec, _draggingItem_dec, _search_dec, _eligibleTargetsByResourceId_dec, _selectedResourceId_dec, _resourceAssociations_dec, _resources_dec, _ungroupedItemIds_dec2, _enableGrouping_dec, _groups_dec3, _emptyText_dec2, _loading_dec5, _selectedSessionId_dec2, _sessions_dec2, _a100, _DeesHarnessSessionList_decorators, _init102, _sessions2, _selectedSessionId2, _loading5, _emptyText2, _groups3, _enableGrouping, _ungroupedItemIds2, _resources, _resourceAssociations, _selectedResourceId, _eligibleTargetsByResourceId, _search, _draggingItem, _dropSlot, _draggedItemHeight, _expandedSessionIds, _collapsedGroupIds, _topScrollShadowVisible, _bottomScrollShadowVisible, _moveAnnouncement, _resourceContextResourceId;
179805
179887
  var { repeat: repeat6 } = directives_exports;
179806
179888
  var dragAutoScrollMaxPixelsPerSecond = 900;
179807
179889
  var dragThresholdPixels = 4;
179890
+ var itemKey = /* @__PURE__ */ __name((refArg) => `${refArg.kind}:${refArg.id}`, "itemKey");
179891
+ var itemRef = /* @__PURE__ */ __name((itemArg) => ({
179892
+ kind: itemArg.kind,
179893
+ id: itemArg.id
179894
+ }), "itemRef");
179895
+ var sameItem = /* @__PURE__ */ __name((leftArg, rightArg) => !!leftArg && !!rightArg && leftArg.kind === rightArg.kind && leftArg.id === rightArg.id, "sameItem");
179808
179896
  _DeesHarnessSessionList_decorators = [customElement("dees-harness-session-list")];
179809
- var _DeesHarnessSessionList = class _DeesHarnessSessionList extends (_a100 = DeesElement, _sessions_dec2 = [n5({ attribute: false })], _selectedSessionId_dec2 = [n5()], _loading_dec5 = [n5({ type: Boolean })], _emptyText_dec2 = [n5()], _groups_dec3 = [n5({ attribute: false })], _enableGrouping_dec = [n5({ type: Boolean })], _ungroupedSessionIds_dec2 = [n5({ attribute: false })], _resources_dec = [n5({ attribute: false })], _resourceAssociations_dec = [n5({ attribute: false })], _selectedResourceId_dec = [n5()], _eligibleSessionIdsByResourceId_dec = [n5({ attribute: false })], _search_dec = [r5()], _draggingSessionId_dec = [r5()], _draggingResourceId_dec = [r5()], _resourceDropTargetSessionId_dec = [r5()], _dropSlot_dec = [r5()], _draggedItemHeight_dec = [r5()], _expandedSessionIds_dec = [r5()], _collapsedGroupIds_dec = [r5()], _topScrollShadowVisible_dec = [r5()], _bottomScrollShadowVisible_dec = [r5()], _moveAnnouncement_dec = [r5()], _resourceContextResourceId_dec = [r5()], _a100) {
179897
+ var _DeesHarnessSessionList = class _DeesHarnessSessionList extends (_a100 = DeesElement, _sessions_dec2 = [n5({ attribute: false })], _selectedSessionId_dec2 = [n5()], _loading_dec5 = [n5({ type: Boolean })], _emptyText_dec2 = [n5()], _groups_dec3 = [n5({ attribute: false })], _enableGrouping_dec = [n5({ type: Boolean })], _ungroupedItemIds_dec2 = [n5({ attribute: false })], _resources_dec = [n5({ attribute: false })], _resourceAssociations_dec = [n5({ attribute: false })], _selectedResourceId_dec = [n5()], _eligibleTargetsByResourceId_dec = [n5({ attribute: false })], _search_dec = [r5()], _draggingItem_dec = [r5()], _dropSlot_dec = [r5()], _draggedItemHeight_dec = [r5()], _expandedSessionIds_dec = [r5()], _collapsedGroupIds_dec = [r5()], _topScrollShadowVisible_dec = [r5()], _bottomScrollShadowVisible_dec = [r5()], _moveAnnouncement_dec = [r5()], _resourceContextResourceId_dec = [r5()], _a100) {
179810
179898
  constructor() {
179811
179899
  super(...arguments);
179812
179900
  __privateAdd(this, _sessions2, __runInitializers(_init102, 8, this, [])), __runInitializers(_init102, 11, this);
@@ -179815,23 +179903,21 @@ var _DeesHarnessSessionList = class _DeesHarnessSessionList extends (_a100 = Dee
179815
179903
  __privateAdd(this, _emptyText2, __runInitializers(_init102, 20, this, "No conversations yet.")), __runInitializers(_init102, 23, this);
179816
179904
  __privateAdd(this, _groups3, __runInitializers(_init102, 24, this, [])), __runInitializers(_init102, 27, this);
179817
179905
  __privateAdd(this, _enableGrouping, __runInitializers(_init102, 28, this, false)), __runInitializers(_init102, 31, this);
179818
- __privateAdd(this, _ungroupedSessionIds2, __runInitializers(_init102, 32, this, [])), __runInitializers(_init102, 35, this);
179906
+ __privateAdd(this, _ungroupedItemIds2, __runInitializers(_init102, 32, this, [])), __runInitializers(_init102, 35, this);
179819
179907
  __privateAdd(this, _resources, __runInitializers(_init102, 36, this, [])), __runInitializers(_init102, 39, this);
179820
179908
  __privateAdd(this, _resourceAssociations, __runInitializers(_init102, 40, this, [])), __runInitializers(_init102, 43, this);
179821
179909
  __privateAdd(this, _selectedResourceId, __runInitializers(_init102, 44, this, "")), __runInitializers(_init102, 47, this);
179822
- __privateAdd(this, _eligibleSessionIdsByResourceId, __runInitializers(_init102, 48, this, {})), __runInitializers(_init102, 51, this);
179910
+ __privateAdd(this, _eligibleTargetsByResourceId, __runInitializers(_init102, 48, this, {})), __runInitializers(_init102, 51, this);
179823
179911
  __privateAdd(this, _search, __runInitializers(_init102, 52, this, "")), __runInitializers(_init102, 55, this);
179824
- __privateAdd(this, _draggingSessionId, __runInitializers(_init102, 56, this, "")), __runInitializers(_init102, 59, this);
179825
- __privateAdd(this, _draggingResourceId, __runInitializers(_init102, 60, this, "")), __runInitializers(_init102, 63, this);
179826
- __privateAdd(this, _resourceDropTargetSessionId, __runInitializers(_init102, 64, this, "")), __runInitializers(_init102, 67, this);
179827
- __privateAdd(this, _dropSlot, __runInitializers(_init102, 68, this)), __runInitializers(_init102, 71, this);
179828
- __privateAdd(this, _draggedItemHeight, __runInitializers(_init102, 72, this, 0)), __runInitializers(_init102, 75, this);
179829
- __privateAdd(this, _expandedSessionIds, __runInitializers(_init102, 76, this, /* @__PURE__ */ new Set())), __runInitializers(_init102, 79, this);
179830
- __privateAdd(this, _collapsedGroupIds, __runInitializers(_init102, 80, this, /* @__PURE__ */ new Set())), __runInitializers(_init102, 83, this);
179831
- __privateAdd(this, _topScrollShadowVisible, __runInitializers(_init102, 84, this, false)), __runInitializers(_init102, 87, this);
179832
- __privateAdd(this, _bottomScrollShadowVisible, __runInitializers(_init102, 88, this, false)), __runInitializers(_init102, 91, this);
179833
- __privateAdd(this, _moveAnnouncement, __runInitializers(_init102, 92, this, "")), __runInitializers(_init102, 95, this);
179834
- __privateAdd(this, _resourceContextResourceId, __runInitializers(_init102, 96, this, "")), __runInitializers(_init102, 99, this);
179912
+ __privateAdd(this, _draggingItem, __runInitializers(_init102, 56, this)), __runInitializers(_init102, 59, this);
179913
+ __privateAdd(this, _dropSlot, __runInitializers(_init102, 60, this)), __runInitializers(_init102, 63, this);
179914
+ __privateAdd(this, _draggedItemHeight, __runInitializers(_init102, 64, this, 0)), __runInitializers(_init102, 67, this);
179915
+ __privateAdd(this, _expandedSessionIds, __runInitializers(_init102, 68, this, /* @__PURE__ */ new Set())), __runInitializers(_init102, 71, this);
179916
+ __privateAdd(this, _collapsedGroupIds, __runInitializers(_init102, 72, this, /* @__PURE__ */ new Set())), __runInitializers(_init102, 75, this);
179917
+ __privateAdd(this, _topScrollShadowVisible, __runInitializers(_init102, 76, this, false)), __runInitializers(_init102, 79, this);
179918
+ __privateAdd(this, _bottomScrollShadowVisible, __runInitializers(_init102, 80, this, false)), __runInitializers(_init102, 83, this);
179919
+ __privateAdd(this, _moveAnnouncement, __runInitializers(_init102, 84, this, "")), __runInitializers(_init102, 87, this);
179920
+ __privateAdd(this, _resourceContextResourceId, __runInitializers(_init102, 88, this, "")), __runInitializers(_init102, 91, this);
179835
179921
  __publicField(this, "reflowGeneration", 0);
179836
179922
  __publicField(this, "reflowAnimations", /* @__PURE__ */ new Set());
179837
179923
  __publicField(this, "pointerDragGesture");
@@ -179859,16 +179945,8 @@ var _DeesHarnessSessionList = class _DeesHarnessSessionList extends (_a100 = Dee
179859
179945
  eventArg.clientX - gesture.startClientX,
179860
179946
  eventArg.clientY - gesture.startClientY
179861
179947
  ) < dragThresholdPixels) return;
179862
- if (gesture.phase === "pending" && !(gesture.type === "session" ? this.startPointerDrag(eventArg, gesture) : this.startResourcePointerDrag(eventArg, gesture))) return;
179948
+ if (gesture.phase === "pending" && !this.startPointerDrag(eventArg, gesture)) return;
179863
179949
  eventArg.preventDefault();
179864
- if (gesture.type === "resource") {
179865
- this.moveResourceDragPreview(eventArg.clientX, eventArg.clientY, gesture);
179866
- this.dragAutoScrollClientX = eventArg.clientX;
179867
- this.dragAutoScrollClientY = eventArg.clientY;
179868
- this.updateDragAutoScrollVelocity();
179869
- this.updateResourceDropTargetFromPointer(eventArg.clientX, eventArg.clientY);
179870
- return;
179871
- }
179872
179950
  this.moveDragPreview(eventArg.clientX, eventArg.clientY, gesture);
179873
179951
  this.dragAutoScrollClientX = eventArg.clientX;
179874
179952
  this.dragAutoScrollClientY = eventArg.clientY;
@@ -179879,14 +179957,6 @@ var _DeesHarnessSessionList = class _DeesHarnessSessionList extends (_a100 = Dee
179879
179957
  const gesture = this.pointerDragGesture;
179880
179958
  if (!gesture || eventArg.pointerId !== gesture.pointerId) return;
179881
179959
  if (gesture.phase === "active") {
179882
- if (gesture.type === "resource") {
179883
- this.dragAutoScrollClientX = eventArg.clientX;
179884
- this.dragAutoScrollClientY = eventArg.clientY;
179885
- this.moveResourceDragPreview(eventArg.clientX, eventArg.clientY, gesture);
179886
- this.updateResourceDropTargetFromPointer(eventArg.clientX, eventArg.clientY);
179887
- this.finishPointerDrag(true);
179888
- return;
179889
- }
179890
179960
  this.dragAutoScrollClientX = eventArg.clientX;
179891
179961
  this.dragAutoScrollClientY = eventArg.clientY;
179892
179962
  this.moveDragPreview(eventArg.clientX, eventArg.clientY, gesture);
@@ -179926,14 +179996,7 @@ var _DeesHarnessSessionList = class _DeesHarnessSessionList extends (_a100 = Dee
179926
179996
  this.stopDragAutoScroll();
179927
179997
  return;
179928
179998
  }
179929
- if (gesture.type === "resource") {
179930
- this.updateResourceDropTargetFromPointer(
179931
- this.dragAutoScrollClientX,
179932
- this.dragAutoScrollClientY
179933
- );
179934
- } else {
179935
- this.updateDropSlotFromPointer();
179936
- }
179999
+ this.updateDropSlotFromPointer();
179937
180000
  this.dragAutoScrollFrame = requestAnimationFrame(this.runDragAutoScroll);
179938
180001
  }, "runDragAutoScroll"));
179939
180002
  __publicField(this, "syncScrollShadowState", /* @__PURE__ */ __name(() => {
@@ -179945,9 +180008,6 @@ var _DeesHarnessSessionList = class _DeesHarnessSessionList extends (_a100 = Dee
179945
180008
  if (this.bottomScrollShadowVisible !== bottomVisible) this.bottomScrollShadowVisible = bottomVisible;
179946
180009
  }, "syncScrollShadowState"));
179947
180010
  }
179948
- get sessionsById() {
179949
- return new Map(this.sessions.map((session) => [session.id, session]));
179950
- }
179951
180011
  get resourcesById() {
179952
180012
  const result = /* @__PURE__ */ new Map();
179953
180013
  for (const resource of this.resources) {
@@ -179956,20 +180016,103 @@ var _DeesHarnessSessionList = class _DeesHarnessSessionList extends (_a100 = Dee
179956
180016
  }
179957
180017
  return result;
179958
180018
  }
179959
- /** First valid record wins; unknown and duplicate records remain untouched but are not projected. */
180019
+ /**
180020
+ * First valid record wins; unknown records, self-references and duplicates
180021
+ * remain untouched but are not projected. Keyed by resource id.
180022
+ */
179960
180023
  get acceptedResourceAssociations() {
179961
180024
  const resourcesById = this.resourcesById;
179962
- const sessionsById = this.sessionsById;
180025
+ const itemsByKey = this.itemsByKey;
179963
180026
  const result = /* @__PURE__ */ new Map();
179964
180027
  for (const association2 of this.resourceAssociations) {
179965
- if (!resourcesById.has(association2.resourceId) || !sessionsById.has(association2.sessionId) || result.has(association2.resourceId)) continue;
179966
- result.set(association2.resourceId, association2.sessionId);
180028
+ if (!association2.target || !resourcesById.has(association2.resourceId) || !itemsByKey.has(itemKey(association2.target)) || sameItem(association2.target, { kind: "resource", id: association2.resourceId }) || result.has(association2.resourceId)) continue;
180029
+ result.set(association2.resourceId, itemRef(association2.target));
179967
180030
  }
179968
180031
  return result;
179969
180032
  }
179970
180033
  get acceptedResources() {
179971
180034
  return [...this.resourcesById.values()];
179972
180035
  }
180036
+ /** Sessions and resources as one pool of orderable items, before grouping and search. */
180037
+ get acceptedItems() {
180038
+ const result = [];
180039
+ const seenSessionIds = /* @__PURE__ */ new Set();
180040
+ for (const session of this.sessions) {
180041
+ if (!session.id || seenSessionIds.has(session.id)) continue;
180042
+ seenSessionIds.add(session.id);
180043
+ result.push({
180044
+ kind: "session",
180045
+ key: `session:${session.id}`,
180046
+ id: session.id,
180047
+ title: session.title || session.id,
180048
+ sortable: session.draggable !== false,
180049
+ timestamp: session.updatedAt ?? session.createdAt ?? 0,
180050
+ session
180051
+ });
180052
+ }
180053
+ for (const resource of this.resourcesById.values()) {
180054
+ result.push({
180055
+ kind: "resource",
180056
+ key: `resource:${resource.id}`,
180057
+ id: resource.id,
180058
+ title: resource.title || resource.id,
180059
+ sortable: resource.draggable !== false,
180060
+ timestamp: resource.updatedAt ?? resource.createdAt ?? 0,
180061
+ resource
180062
+ });
180063
+ }
180064
+ return result;
180065
+ }
180066
+ get itemsByKey() {
180067
+ return new Map(this.acceptedItems.map((item) => [item.key, item]));
180068
+ }
180069
+ /** Groups only organize the list while grouping is enabled. */
180070
+ get effectiveGroups() {
180071
+ return this.enableGrouping ? this.groups : [];
180072
+ }
180073
+ get groupedItemKeys() {
180074
+ const keys3 = /* @__PURE__ */ new Set();
180075
+ for (const group of this.effectiveGroups) {
180076
+ for (const ref of group.itemIds) keys3.add(itemKey(ref));
180077
+ }
180078
+ return keys3;
180079
+ }
180080
+ itemsForGroup(groupIdArg) {
180081
+ if (groupIdArg === null) return this.ungroupedItems;
180082
+ const group = this.effectiveGroups.find((candidate) => candidate.id === groupIdArg);
180083
+ if (!group) return [];
180084
+ const byKey = this.itemsByKey;
180085
+ const seen = /* @__PURE__ */ new Set();
180086
+ const result = [];
180087
+ for (const ref of group.itemIds) {
180088
+ const key2 = itemKey(ref);
180089
+ const item = byKey.get(key2);
180090
+ if (!item || seen.has(key2)) continue;
180091
+ seen.add(key2);
180092
+ result.push(item);
180093
+ }
180094
+ return result;
180095
+ }
180096
+ /** Pinned entries first, then explicitly ordered items, then unknown items by recency. */
180097
+ get ungroupedItems() {
180098
+ const grouped = this.groupedItemKeys;
180099
+ const available = this.acceptedItems.filter((item) => !grouped.has(item.key));
180100
+ const pinned = available.filter((item) => !item.sortable);
180101
+ const sortableByKey = new Map(
180102
+ available.filter((item) => item.sortable).map((item) => [item.key, item])
180103
+ );
180104
+ const ordered = [];
180105
+ for (const ref of this.ungroupedItemIds) {
180106
+ const item = sortableByKey.get(itemKey(ref));
180107
+ if (!item) continue;
180108
+ ordered.push(item);
180109
+ sortableByKey.delete(item.key);
180110
+ }
180111
+ const unknown3 = [...sortableByKey.values()].sort(
180112
+ (left, right) => right.timestamp - left.timestamp
180113
+ );
180114
+ return [...pinned, ...ordered, ...unknown3];
180115
+ }
179973
180116
  resourceMatchesSearch(resourceArg, queryArg) {
179974
180117
  return [resourceArg.id, resourceArg.kind, resourceArg.title, resourceArg.preview].filter(Boolean).join(" ").toLowerCase().includes(queryArg);
179975
180118
  }
@@ -179984,95 +180127,69 @@ var _DeesHarnessSessionList = class _DeesHarnessSessionList extends (_a100 = Dee
179984
180127
  this.sessionStateLabel(sessionArg.state ?? "normal")
179985
180128
  ].filter(Boolean).join(" ").toLowerCase().includes(queryArg);
179986
180129
  }
179987
- resourcesForSession(sessionArg) {
179988
- const associations = this.acceptedResourceAssociations;
179989
- const associated = this.acceptedResources.filter(
179990
- (resource) => associations.get(resource.id) === sessionArg.id
179991
- );
179992
- const query3 = this.search.trim().toLowerCase();
179993
- if (!query3 || this.sessionMatchesSearch(sessionArg, query3)) return associated;
179994
- return associated.filter((resource) => this.resourceMatchesSearch(resource, query3));
179995
- }
179996
- get unattachedResources() {
179997
- const associations = this.acceptedResourceAssociations;
179998
- const query3 = this.search.trim().toLowerCase();
179999
- return this.acceptedResources.filter((resource) => !associations.has(resource.id) && (!query3 || this.resourceMatchesSearch(resource, query3)));
180000
- }
180001
- get groupedSessionIds() {
180002
- const ids = /* @__PURE__ */ new Set();
180003
- for (const group of this.groups) {
180004
- for (const id of group.sessionIds) ids.add(id);
180005
- }
180006
- return ids;
180007
- }
180008
- /** Pinned entries first, followed by explicitly ordered sortable sessions. */
180009
- get ungroupedSessions() {
180010
- const grouped = this.groupedSessionIds;
180011
- const available = this.sessions.filter((session) => !grouped.has(session.id));
180012
- const pinned = available.filter((session) => session.draggable === false);
180013
- const sortableById = new Map(
180014
- available.filter((session) => session.draggable !== false).map((session) => [session.id, session])
180015
- );
180016
- const ordered = [];
180017
- for (const sessionId of this.ungroupedSessionIds) {
180018
- const session = sortableById.get(sessionId);
180019
- if (!session) continue;
180020
- ordered.push(session);
180021
- sortableById.delete(sessionId);
180022
- }
180023
- const newSessions = [...sortableById.values()].sort(
180024
- (left, right) => (right.updatedAt ?? right.createdAt ?? 0) - (left.updatedAt ?? left.createdAt ?? 0)
180025
- );
180026
- return [...pinned, ...ordered, ...newSessions];
180130
+ itemMatchesSearch(itemArg, queryArg) {
180131
+ return itemArg.kind === "session" ? this.sessionMatchesSearch(itemArg.session, queryArg) : this.resourceMatchesSearch(itemArg.resource, queryArg);
180027
180132
  }
180028
- get filteredSessions() {
180133
+ /** Search flattens the list: sessions and resources match as peers, newest first. */
180134
+ get searchItems() {
180029
180135
  const query3 = this.search.trim().toLowerCase();
180030
- const associations = this.acceptedResourceAssociations;
180031
- const matchingAttachedSessionIds = new Set(
180032
- this.acceptedResources.filter((resource) => query3 && this.resourceMatchesSearch(resource, query3)).map((resource) => associations.get(resource.id)).filter((sessionId) => sessionId !== void 0)
180033
- );
180034
- const sorted = [...this.sessions].sort(
180035
- (left, right) => (right.updatedAt ?? right.createdAt ?? 0) - (left.updatedAt ?? left.createdAt ?? 0)
180136
+ const sorted = [...this.acceptedItems].sort(
180137
+ (left, right) => right.timestamp - left.timestamp
180036
180138
  );
180037
180139
  if (!query3) return sorted;
180038
- return sorted.filter(
180039
- (session) => this.sessionMatchesSearch(session, query3) || matchingAttachedSessionIds.has(session.id)
180040
- );
180140
+ return sorted.filter((item) => this.itemMatchesSearch(item, query3));
180141
+ }
180142
+ get searchActive() {
180143
+ return this.search.trim().length > 0;
180144
+ }
180145
+ sortableItems(itemsArg, excludeDraggingArg = true) {
180146
+ return itemsArg.filter((item) => item.sortable && (!excludeDraggingArg || !sameItem(this.draggingItem, item)));
180147
+ }
180148
+ groupIdForItem(refArg) {
180149
+ return this.effectiveGroups.find(
180150
+ (group) => group.itemIds.some((candidate) => sameItem(candidate, refArg))
180151
+ )?.id ?? null;
180152
+ }
180153
+ rowElementFor(refArg) {
180154
+ return Array.from(
180155
+ this.shadowRoot?.querySelectorAll("[data-item-kind][data-item-id]") ?? []
180156
+ ).find((candidate) => candidate.dataset.itemKind === refArg.kind && candidate.dataset.itemId === refArg.id);
180041
180157
  }
180042
180158
  focusSearch() {
180043
180159
  this.shadowRoot?.querySelector(".searchRow input")?.focus();
180044
180160
  }
180045
- requestResourceAssociation(resourceIdArg, toSessionIdArg, sourceArg = "action") {
180161
+ requestResourceAssociation(resourceIdArg, toTargetArg, sourceArg = "action") {
180046
180162
  const resource = this.resourcesById.get(resourceIdArg);
180047
180163
  if (!resource) return false;
180048
- const fromSessionId = this.acceptedResourceAssociations.get(resourceIdArg) ?? null;
180049
- if (fromSessionId === toSessionIdArg) return false;
180050
- if (toSessionIdArg !== null && (!this.sessionsById.has(toSessionIdArg) || !this.isResourceTargetEligible(resourceIdArg, toSessionIdArg))) return false;
180051
- if (toSessionIdArg === null && fromSessionId === null) return false;
180052
- const detail = fromSessionId === null ? {
180164
+ const fromTarget = this.acceptedResourceAssociations.get(resourceIdArg) ?? null;
180165
+ if (sameItem(fromTarget, toTargetArg)) return false;
180166
+ if (toTargetArg !== null && (!this.itemsByKey.has(itemKey(toTargetArg)) || sameItem(toTargetArg, { kind: "resource", id: resourceIdArg }) || !this.isResourceTargetEligible(resourceIdArg, toTargetArg))) return false;
180167
+ if (toTargetArg === null && fromTarget === null) return false;
180168
+ const toTarget = toTargetArg === null ? null : itemRef(toTargetArg);
180169
+ const detail = fromTarget === null ? {
180053
180170
  intent: "attach",
180054
180171
  resource,
180055
- fromSessionId: null,
180056
- toSessionId: toSessionIdArg,
180172
+ fromTarget: null,
180173
+ toTarget,
180057
180174
  source: sourceArg
180058
- } : toSessionIdArg === null ? {
180175
+ } : toTarget === null ? {
180059
180176
  intent: "detach",
180060
180177
  resource,
180061
- fromSessionId,
180062
- toSessionId: null,
180178
+ fromTarget,
180179
+ toTarget: null,
180063
180180
  source: sourceArg
180064
180181
  } : {
180065
180182
  intent: "reassign",
180066
180183
  resource,
180067
- fromSessionId,
180068
- toSessionId: toSessionIdArg,
180184
+ fromTarget,
180185
+ toTarget,
180069
180186
  source: sourceArg
180070
180187
  };
180071
180188
  this.pendingResourceAssociationRequest = {
180072
180189
  resourceId: resource.id,
180073
180190
  resourceTitle: resource.title || resource.id,
180074
- fromSessionId,
180075
- toSessionId: toSessionIdArg,
180191
+ fromTarget,
180192
+ toTarget,
180076
180193
  intent: detail.intent
180077
180194
  };
180078
180195
  this.moveAnnouncement = this.resourceAssociationAnnouncement(detail, false);
@@ -180095,9 +180212,6 @@ var _DeesHarnessSessionList = class _DeesHarnessSessionList extends (_a100 = Dee
180095
180212
  }
180096
180213
  if (changedProperties.has("sessions")) {
180097
180214
  const knownIds = new Set(this.sessions.map((session) => session.id));
180098
- if (this.pointerDragGesture?.type === "session" && !knownIds.has(this.pointerDragGesture.sessionId)) {
180099
- this.finishPointerDrag(false);
180100
- }
180101
180215
  const nextExpanded = new Set(
180102
180216
  [...this.expandedSessionIds].filter((sessionId) => knownIds.has(sessionId))
180103
180217
  );
@@ -180106,22 +180220,14 @@ var _DeesHarnessSessionList = class _DeesHarnessSessionList extends (_a100 = Dee
180106
180220
  }
180107
180221
  }
180108
180222
  if (changedProperties.has("resources") || changedProperties.has("resourceAssociations")) {
180109
- const gesture = this.pointerDragGesture;
180110
- if (gesture?.type === "resource") {
180111
- const currentSessionId = this.acceptedResourceAssociations.get(gesture.resourceId) ?? null;
180112
- if (!this.resourcesById.has(gesture.resourceId) || currentSessionId !== gesture.fromSessionId) {
180113
- this.finishPointerDrag(false);
180114
- }
180115
- }
180116
180223
  if (this.resourceContextResourceId && !this.resourcesById.has(this.resourceContextResourceId)) this.closeResourceContext(this.resourceContextGeneration);
180117
180224
  this.reconcilePendingResourceAssociation();
180118
180225
  }
180119
- if (changedProperties.has("sessions") || changedProperties.has("eligibleSessionIdsByResourceId")) {
180226
+ if (changedProperties.has("sessions") || changedProperties.has("resources") || changedProperties.has("search")) {
180120
180227
  const gesture = this.pointerDragGesture;
180121
- if (gesture?.type === "resource" && !this.sameSessionIds(
180122
- gesture.eligibleSessionIds,
180123
- new Set(this.eligibleSessionIds(gesture.resourceId))
180124
- )) this.finishPointerDrag(false);
180228
+ if (gesture && (this.searchActive || !this.itemsByKey.has(itemKey(gesture.item)))) {
180229
+ this.finishPointerDrag(false);
180230
+ }
180125
180231
  }
180126
180232
  }
180127
180233
  async connectedCallback() {
@@ -180141,7 +180247,6 @@ var _DeesHarnessSessionList = class _DeesHarnessSessionList extends (_a100 = Dee
180141
180247
  await super.disconnectedCallback();
180142
180248
  }
180143
180249
  render() {
180144
- const groupingActive = this.enableGrouping && !this.search.trim();
180145
180250
  return b2`
180146
180251
  <div class="searchRow">
180147
180252
  <div class="searchField">
@@ -180175,11 +180280,11 @@ var _DeesHarnessSessionList = class _DeesHarnessSessionList extends (_a100 = Dee
180175
180280
  <div class="listFrame">
180176
180281
  <div class="scrollShadow top ${this.topScrollShadowVisible ? "visible" : ""}"></div>
180177
180282
  <div
180178
- class="list ${this.draggingSessionId || this.draggingResourceId ? "dragActive" : ""}"
180283
+ class="list ${this.draggingItem ? "dragActive" : ""}"
180179
180284
  @scroll=${this.syncScrollShadowState}
180180
180285
  >
180181
180286
  <div class="listContent">
180182
- ${this.loading ? b2`<div class="emptyNote">Loading conversations…</div>` : groupingActive ? this.renderGroupedList() : this.renderFlatList()}
180287
+ ${this.loading ? b2`<div class="emptyNote">Loading conversations…</div>` : this.searchActive ? this.renderSearchList() : this.renderOrderedList()}
180183
180288
  </div>
180184
180289
  </div>
180185
180290
  <div class="scrollShadow bottom ${this.bottomScrollShadowVisible ? "visible" : ""}"></div>
@@ -180187,70 +180292,25 @@ var _DeesHarnessSessionList = class _DeesHarnessSessionList extends (_a100 = Dee
180187
180292
  <div class="visuallyHidden" aria-live="polite">${this.moveAnnouncement}</div>
180188
180293
  `;
180189
180294
  }
180190
- renderFlatList() {
180191
- const sessions = this.filteredSessions;
180192
- const unattachedResources = this.unattachedResources;
180193
- if (!sessions.length && !unattachedResources.length) {
180194
- return b2`<div class="emptyNote">
180195
- ${this.acceptedResources.length ? this.sessions.length ? "No conversations or resources match this search." : "No resources match this search." : this.sessions.length ? "No conversations match this search." : this.emptyText}
180196
- </div>`;
180197
- }
180198
- return b2`
180199
- <div class="section">
180200
- ${repeat6(
180201
- sessions,
180202
- (session) => session.id,
180203
- (session) => this.renderItem(session, null, -1)
180204
- )}
180205
- </div>
180206
- ${this.renderUnattachedResources(unattachedResources)}
180207
- `;
180295
+ renderEmptyNote() {
180296
+ return b2`<div class="emptyNote">
180297
+ ${this.acceptedResources.length ? this.sessions.length ? "No conversations or resources match this search." : "No resources match this search." : this.sessions.length ? "No conversations match this search." : this.emptyText}
180298
+ </div>`;
180208
180299
  }
180209
- renderGroupedList() {
180210
- const byId = this.sessionsById;
180211
- const ungrouped = this.ungroupedSessions;
180212
- const unattachedResources = this.unattachedResources;
180213
- if (!this.sessions.length && !this.groups.length && !unattachedResources.length) {
180300
+ renderSearchList() {
180301
+ const items = this.searchItems;
180302
+ if (!items.length) return this.renderEmptyNote();
180303
+ return this.renderSection(items, null, false);
180304
+ }
180305
+ renderOrderedList() {
180306
+ const groups = this.effectiveGroups;
180307
+ const ungrouped = this.ungroupedItems;
180308
+ if (!this.acceptedItems.length && !groups.length) {
180214
180309
  return b2`<div class="emptyNote">${this.emptyText}</div>`;
180215
180310
  }
180216
180311
  return b2`
180217
- ${this.groups.map((group) => {
180218
- const members = group.sessionIds.map((id) => byId.get(id)).filter((session) => session !== void 0);
180219
- const collapsed = this.collapsedGroupIds.has(group.id);
180220
- const attentionCount = members.filter((session) => session.state === "attention" || session.state === "error").length;
180221
- const isHeaderDrop = this.dropSlot?.groupId === group.id && this.dropSlot.index === this.sortableSessions(members).length && collapsed;
180222
- return b2`
180223
- <button
180224
- class="groupHeader ${collapsed ? "collapsed" : ""} ${isHeaderDrop ? "dropTarget" : ""}"
180225
- data-drop-group-id=${group.id}
180226
- data-drop-index=${this.sortableSessions(members).length}
180227
- data-drop-kind="slot"
180228
- type="button"
180229
- @click=${() => this.toggleGroupCollapsed(group.id)}
180230
- @contextmenu=${(event) => {
180231
- event.preventDefault();
180232
- const detail = {
180233
- group,
180234
- clientX: event.clientX,
180235
- clientY: event.clientY,
180236
- originalEvent: event
180237
- };
180238
- this.dispatchEvent(
180239
- new CustomEvent("harness-group-context", { detail, bubbles: true, composed: true })
180240
- );
180241
- }}
180242
- >
180243
- <dees-icon class="chevron" icon="lucide:ChevronDown" iconSize="12"></dees-icon>
180244
- <span>${group.name}</span>
180245
- ${attentionCount ? b2`<span class="groupAttention" aria-label=${`${attentionCount} need attention`}>
180246
- <dees-icon aria-hidden="true" icon="lucide:CircleAlert" iconSize="11"></dees-icon>${attentionCount}
180247
- </span>` : ""}
180248
- <span class="groupCount">${members.length}</span>
180249
- </button>
180250
- ${collapsed ? "" : this.renderSection(members, group.id)}
180251
- `;
180252
- })}
180253
- ${this.groups.length && (ungrouped.length || this.draggingSessionId) ? b2`
180312
+ ${groups.map((group) => this.renderGroup(group))}
180313
+ ${groups.length && (ungrouped.length || this.draggingItem) ? b2`
180254
180314
  <button
180255
180315
  class="groupHeader"
180256
180316
  data-drop-group-id=""
@@ -180263,43 +180323,85 @@ var _DeesHarnessSessionList = class _DeesHarnessSessionList extends (_a100 = Dee
180263
180323
  <span class="groupCount">${ungrouped.length}</span>
180264
180324
  </button>
180265
180325
  ` : ""}
180266
- ${this.renderSection(ungrouped, null)}
180267
- ${this.renderUnattachedResources(unattachedResources)}
180326
+ ${this.renderSection(ungrouped, null, true)}
180327
+ `;
180328
+ }
180329
+ renderGroup(groupArg) {
180330
+ const members = this.itemsForGroup(groupArg.id);
180331
+ const collapsed = this.collapsedGroupIds.has(groupArg.id);
180332
+ const attentionCount = members.filter((item) => item.kind === "session" && (item.session.state === "attention" || item.session.state === "error")).length;
180333
+ const appendIndex = this.sortableItems(members).length;
180334
+ const isHeaderDrop = this.dropSlot?.groupId === groupArg.id && this.dropSlot.index === appendIndex && collapsed;
180335
+ return b2`
180336
+ <button
180337
+ class="groupHeader ${collapsed ? "collapsed" : ""} ${isHeaderDrop ? "dropTarget" : ""}"
180338
+ data-drop-group-id=${groupArg.id}
180339
+ data-drop-index=${appendIndex}
180340
+ data-drop-kind="slot"
180341
+ type="button"
180342
+ @click=${() => this.toggleGroupCollapsed(groupArg.id)}
180343
+ @contextmenu=${(event) => {
180344
+ event.preventDefault();
180345
+ const detail = {
180346
+ group: groupArg,
180347
+ clientX: event.clientX,
180348
+ clientY: event.clientY,
180349
+ originalEvent: event
180350
+ };
180351
+ this.dispatchEvent(
180352
+ new CustomEvent("harness-group-context", { detail, bubbles: true, composed: true })
180353
+ );
180354
+ }}
180355
+ >
180356
+ <dees-icon class="chevron" icon="lucide:ChevronDown" iconSize="12"></dees-icon>
180357
+ <span>${groupArg.name}</span>
180358
+ ${attentionCount ? b2`<span class="groupAttention" aria-label=${`${attentionCount} need attention`}>
180359
+ <dees-icon aria-hidden="true" icon="lucide:CircleAlert" iconSize="11"></dees-icon>${attentionCount}
180360
+ </span>` : ""}
180361
+ <span class="groupCount">${members.length}</span>
180362
+ </button>
180363
+ ${collapsed ? "" : this.renderSection(members, groupArg.id, true)}
180268
180364
  `;
180269
180365
  }
180270
- renderSection(sessions, groupId) {
180271
- const slot = this.dropSlot;
180366
+ renderSection(itemsArg, groupIdArg, sortableArg) {
180367
+ const slot = sortableArg ? this.dropSlot : void 0;
180272
180368
  const entries = [];
180273
180369
  let logicalIndex = 0;
180274
- for (const session of sessions) {
180275
- const isDragging = session.id === this.draggingSessionId;
180276
- const sortable = session.draggable !== false;
180277
- if (slot && slot.groupId === groupId && slot.index === logicalIndex && !isDragging && sortable) {
180278
- entries.push({ type: "placeholder", key: `placeholder:${groupId ?? "ungrouped"}` });
180370
+ for (const item of itemsArg) {
180371
+ const isDragging = sameItem(this.draggingItem, item);
180372
+ const sortable = sortableArg && item.sortable;
180373
+ if (slot && slot.groupId === groupIdArg && slot.index === logicalIndex && !isDragging && sortable) {
180374
+ entries.push({ type: "placeholder", key: `placeholder:${groupIdArg ?? "ungrouped"}` });
180279
180375
  }
180280
180376
  entries.push({
180281
- type: "session",
180282
- key: `session:${session.id}`,
180283
- session,
180377
+ type: "item",
180378
+ key: item.key,
180379
+ item,
180284
180380
  logicalIndex: sortable ? logicalIndex : -1
180285
180381
  });
180286
180382
  if (sortable && !isDragging) logicalIndex += 1;
180287
180383
  }
180288
- if (slot && slot.groupId === groupId && slot.index === logicalIndex) {
180289
- entries.push({ type: "placeholder", key: `placeholder:${groupId ?? "ungrouped"}` });
180384
+ if (slot && slot.groupId === groupIdArg && slot.index === logicalIndex) {
180385
+ entries.push({ type: "placeholder", key: `placeholder:${groupIdArg ?? "ungrouped"}` });
180290
180386
  }
180291
180387
  const hasPlaceholder = entries.some((entry) => entry.type === "placeholder");
180388
+ const associations = this.acceptedResourceAssociations;
180292
180389
  return b2`
180293
- <div class="section" data-group-id=${groupId ?? ""}>
180390
+ <div class="section" data-group-id=${groupIdArg ?? ""}>
180294
180391
  ${repeat6(
180295
180392
  entries,
180296
180393
  (entry) => entry.key,
180297
- (entry) => entry.type === "placeholder" ? this.renderDropPlaceholder(groupId, slot?.index ?? 0) : this.renderItem(entry.session, groupId, entry.logicalIndex)
180394
+ (entry) => entry.type === "placeholder" ? this.renderDropPlaceholder(groupIdArg, slot?.index ?? 0) : entry.item.kind === "session" ? this.renderSessionItem(entry.item.session, groupIdArg, entry.logicalIndex) : this.renderResourceItem(
180395
+ entry.item.resource,
180396
+ groupIdArg,
180397
+ entry.logicalIndex,
180398
+ associations.get(entry.item.id) ?? null
180399
+ )
180298
180400
  )}
180299
- ${this.draggingSessionId && !hasPlaceholder && this.sortableSessions(sessions).length === 0 ? b2`
180401
+ ${this.draggingItem && sortableArg && !hasPlaceholder && this.sortableItems(itemsArg).length === 0 ? b2`
180300
180402
  <div
180301
180403
  class="emptyDropZone"
180302
- data-drop-group-id=${groupId ?? ""}
180404
+ data-drop-group-id=${groupIdArg ?? ""}
180303
180405
  data-drop-index="0"
180304
180406
  data-drop-kind="slot"
180305
180407
  ></div>
@@ -180314,30 +180416,56 @@ var _DeesHarnessSessionList = class _DeesHarnessSessionList extends (_a100 = Dee
180314
180416
  data-drop-group-id=${groupId ?? ""}
180315
180417
  data-drop-index=${index3}
180316
180418
  data-drop-kind="slot"
180317
- style=${`height: ${Math.max(46, this.draggedItemHeight)}px`}
180419
+ style=${`height: ${Math.max(24, this.draggedItemHeight)}px`}
180318
180420
  ></div>
180319
180421
  `;
180320
180422
  }
180321
- renderItem(session, groupId, index3) {
180322
- const draggable = this.enableGrouping && session.draggable !== false && index3 >= 0;
180423
+ /** One grip for both kinds; only its size and extra class differ. */
180424
+ renderDragHandle(refArg, titleArg, groupIdArg, logicalIndexArg) {
180425
+ const isResource = refArg.kind === "resource";
180426
+ return b2`
180427
+ <button
180428
+ class="dragHandle ${isResource ? "resourceDragHandle" : ""}"
180429
+ type="button"
180430
+ title="Drag to reorder; use arrow, Home, or End keys for keyboard reordering"
180431
+ aria-label=${`Reorder ${titleArg}`}
180432
+ aria-keyshortcuts="ArrowUp ArrowDown Home End"
180433
+ @pointerdown=${(event) => {
180434
+ this.handlePointerDown(event, refArg, groupIdArg, logicalIndexArg);
180435
+ }}
180436
+ @pointermove=${this.handlePointerMove}
180437
+ @pointerup=${this.handlePointerUp}
180438
+ @pointercancel=${this.handlePointerCancel}
180439
+ @lostpointercapture=${this.handleLostPointerCapture}
180440
+ @keydown=${(event) => {
180441
+ this.handleKeyboardMove(event, refArg, titleArg, groupIdArg);
180442
+ }}
180443
+ >
180444
+ <dees-icon icon="lucide:GripVertical" iconSize=${isResource ? "13" : "14"}></dees-icon>
180445
+ </button>
180446
+ `;
180447
+ }
180448
+ renderSessionItem(session, groupId, index3) {
180449
+ const draggable = index3 >= 0;
180323
180450
  const expanded = this.expandedSessionIds.has(session.id);
180324
180451
  const state4 = session.state ?? "normal";
180325
180452
  const statusLabel = this.sessionStatusLabel(session);
180326
180453
  const active = (state4 === "normal" || state4 === "working") && (session.working ?? state4 === "working");
180327
180454
  const detailsId = `session-details-${session.id}`;
180328
180455
  const dropIndex = index3 < 0 ? 0 : index3;
180329
- const resources = this.resourcesForSession(session);
180330
- const isResourceDropTarget = this.resourceDropTargetSessionId === session.id;
180456
+ const title = session.title || session.id;
180331
180457
  return b2`
180332
180458
  <article
180333
- class="item state-${state4} ${active ? "active" : ""} ${expanded ? "expanded" : ""} ${session.id === this.selectedSessionId ? "selected" : ""} ${this.draggingSessionId === session.id ? "dragging" : ""} ${isResourceDropTarget ? "resourceDropTarget" : ""}"
180459
+ class="item state-${state4} ${active ? "active" : ""} ${expanded ? "expanded" : ""} ${session.id === this.selectedSessionId ? "selected" : ""} ${sameItem(this.draggingItem, { kind: "session", id: session.id }) ? "dragging" : ""}"
180334
180460
  data-session-id=${session.id}
180461
+ data-item-kind="session"
180462
+ data-item-id=${session.id}
180335
180463
  data-drop-group-id=${groupId ?? ""}
180336
180464
  data-drop-index=${dropIndex}
180337
180465
  data-drop-kind=${index3 < 0 ? "slot" : "card"}
180338
180466
  @dblclick=${(event) => {
180339
180467
  if (this.eventTargetsExpandToggle(event) || this.eventTargetsDragHandle(event) || this.eventTargetsSessionActions(event)) return;
180340
- this.emit("harness-session-open", session);
180468
+ this.emitSession("harness-session-open", session);
180341
180469
  }}
180342
180470
  @contextmenu=${(event) => {
180343
180471
  if (this.eventTargetsExpandToggle(event)) return;
@@ -180356,38 +180484,18 @@ var _DeesHarnessSessionList = class _DeesHarnessSessionList extends (_a100 = Dee
180356
180484
  >
180357
180485
  <div class="itemInner">
180358
180486
  <div class="itemHeader ${draggable ? "draggable" : ""}">
180359
- ${draggable ? b2`
180360
- <button
180361
- class="dragHandle"
180362
- type="button"
180363
- title="Drag to reorder; use arrow, Home, or End keys for keyboard reordering"
180364
- aria-label=${`Reorder ${session.title || session.id}`}
180365
- aria-keyshortcuts="ArrowUp ArrowDown Home End"
180366
- @pointerdown=${(event) => {
180367
- this.handlePointerDown(event, session, groupId, index3);
180368
- }}
180369
- @pointermove=${this.handlePointerMove}
180370
- @pointerup=${this.handlePointerUp}
180371
- @pointercancel=${this.handlePointerCancel}
180372
- @lostpointercapture=${this.handleLostPointerCapture}
180373
- @keydown=${(event) => {
180374
- this.handleKeyboardMove(event, session, groupId);
180375
- }}
180376
- >
180377
- <dees-icon icon="lucide:GripVertical" iconSize="14"></dees-icon>
180378
- </button>
180379
- ` : ""}
180487
+ ${draggable ? this.renderDragHandle({ kind: "session", id: session.id }, title, groupId, index3) : ""}
180380
180488
  <button
180381
180489
  class="itemPrimary"
180382
180490
  type="button"
180383
180491
  aria-keyshortcuts="ContextMenu Shift+F10"
180384
180492
  aria-current=${session.id === this.selectedSessionId ? "true" : "false"}
180385
- @click=${() => this.emit("harness-session-select", session)}
180493
+ @click=${() => this.emitSession("harness-session-select", session)}
180386
180494
  @keydown=${(event) => {
180387
180495
  if (this.handleSessionContextKey(event)) return;
180388
180496
  if (event.key !== "Enter") return;
180389
180497
  event.preventDefault();
180390
- this.emit("harness-session-open", session);
180498
+ this.emitSession("harness-session-open", session);
180391
180499
  }}
180392
180500
  >
180393
180501
  <span class="stateDot" aria-hidden="true">
@@ -180396,7 +180504,7 @@ var _DeesHarnessSessionList = class _DeesHarnessSessionList extends (_a100 = Dee
180396
180504
  <span class="itemCopy">
180397
180505
  <span class="itemTitle">
180398
180506
  ${session.icon ? b2`<dees-icon class="itemIcon" icon=${session.icon} iconSize="13"></dees-icon>` : ""}
180399
- <span class="titleText">${session.title || session.id}</span>
180507
+ <span class="titleText">${title}</span>
180400
180508
  </span>
180401
180509
  <span class="itemStatus" title=${statusLabel}>${statusLabel}</span>
180402
180510
  <span class="itemIdentity">
@@ -180413,7 +180521,7 @@ var _DeesHarnessSessionList = class _DeesHarnessSessionList extends (_a100 = Dee
180413
180521
  class="sessionActions"
180414
180522
  type="button"
180415
180523
  title="Actions"
180416
- aria-label=${`Actions for ${session.title || session.id}`}
180524
+ aria-label=${`Actions for ${title}`}
180417
180525
  aria-haspopup="menu"
180418
180526
  aria-keyshortcuts="ContextMenu Shift+F10"
180419
180527
  @click=${this.invokeSessionContext}
@@ -180435,16 +180543,6 @@ var _DeesHarnessSessionList = class _DeesHarnessSessionList extends (_a100 = Dee
180435
180543
  <dees-icon icon="lucide:ChevronDown" iconSize="15"></dees-icon>
180436
180544
  </button>
180437
180545
  </div>
180438
- ${isResourceDropTarget ? b2`<div class="resourceDropLabel">Associate resource with ${session.title || session.id}</div>` : ""}
180439
- ${resources.length ? b2`
180440
- <ul class="resourceChildren" aria-label=${`Resources for ${session.title || session.id}`}>
180441
- ${repeat6(
180442
- resources,
180443
- (resource) => resource.id,
180444
- (resource) => this.renderResource(resource, session.id)
180445
- )}
180446
- </ul>
180447
- ` : ""}
180448
180546
  ${expanded ? b2`
180449
180547
  <div class="itemDetails" id=${detailsId}>
180450
180548
  ${session.preview ? b2`<div class="itemPreview">${session.preview}</div>` : ""}
@@ -180457,77 +180555,54 @@ var _DeesHarnessSessionList = class _DeesHarnessSessionList extends (_a100 = Dee
180457
180555
  </article>
180458
180556
  `;
180459
180557
  }
180460
- renderUnattachedResources(resourcesArg) {
180461
- if (!resourcesArg.length) return b2``;
180462
- return b2`
180463
- <section class="resourceSection" aria-labelledby="unattached-resources-heading">
180464
- <h2 class="resourceSectionTitle" id="unattached-resources-heading">Resources</h2>
180465
- <ul class="resourceList" aria-label="Unattached resources">
180466
- ${repeat6(
180467
- resourcesArg,
180468
- (resource) => resource.id,
180469
- (resource) => this.renderResource(resource, null)
180470
- )}
180471
- </ul>
180472
- </section>
180473
- `;
180474
- }
180475
- renderResource(resourceArg, sessionIdArg) {
180558
+ renderResourceItem(resourceArg, groupIdArg, indexArg, attachedTarget) {
180476
180559
  const selected = resourceArg.id === this.selectedResourceId;
180477
- const dragging = resourceArg.id === this.draggingResourceId;
180478
- const eligibleTargetCount = this.eligibleSessionIds(resourceArg.id).filter(
180479
- (sessionId) => sessionId !== sessionIdArg
180480
- ).length;
180560
+ const draggable = indexArg >= 0;
180561
+ const dragging = sameItem(this.draggingItem, { kind: "resource", id: resourceArg.id });
180481
180562
  const contextOpen = resourceArg.id === this.resourceContextResourceId;
180563
+ const attachedTitle = attachedTarget ? this.itemTitleFor(attachedTarget) : "";
180564
+ const title = resourceArg.title || resourceArg.id;
180565
+ const dropIndex = indexArg < 0 ? 0 : indexArg;
180482
180566
  return b2`
180483
- <li
180484
- class="resourceRow ${selected ? "selected" : ""} ${dragging ? "resourceDragging" : ""}"
180567
+ <article
180568
+ class="resourceRow ${selected ? "selected" : ""} ${draggable ? "draggable" : ""} ${dragging ? "dragging" : ""}"
180485
180569
  data-resource-id=${resourceArg.id}
180486
- data-resource-session-id=${sessionIdArg ?? ""}
180570
+ data-item-kind="resource"
180571
+ data-item-id=${resourceArg.id}
180572
+ data-resource-target=${attachedTarget ? `${attachedTarget.kind}:${attachedTarget.id}` : ""}
180573
+ data-drop-group-id=${groupIdArg ?? ""}
180574
+ data-drop-index=${dropIndex}
180575
+ data-drop-kind=${indexArg < 0 ? "slot" : "card"}
180487
180576
  @dblclick=${(event) => {
180488
180577
  event.stopPropagation();
180489
- if (this.eventTargetsResourceControl(event)) return;
180490
- this.emitResource("harness-resource-open", resourceArg, sessionIdArg);
180578
+ if (this.eventTargetsResourceControl(event) || this.eventTargetsDragHandle(event)) return;
180579
+ this.emitResource("harness-resource-open", resourceArg, attachedTarget);
180491
180580
  }}
180492
180581
  @contextmenu=${(event) => {
180493
180582
  event.preventDefault();
180494
180583
  event.stopPropagation();
180495
180584
  const focusTarget = event.composedPath().find((target) => target instanceof HTMLElement && target.matches("button:not(:disabled)")) ?? event.currentTarget.querySelector(".resourcePrimary") ?? event.currentTarget;
180496
- this.emitResourceContext(event, resourceArg, sessionIdArg, "pointer", focusTarget);
180585
+ this.emitResourceContext(event, resourceArg, attachedTarget, "pointer", focusTarget);
180497
180586
  }}
180498
180587
  >
180499
- <button
180500
- class="resourceDragHandle"
180501
- type="button"
180502
- title=${eligibleTargetCount ? "Drag to associate with an eligible conversation" : "No eligible conversations"}
180503
- aria-label=${`Associate ${resourceArg.title || resourceArg.id} by dragging`}
180504
- aria-keyshortcuts="ContextMenu Shift+F10"
180505
- ?disabled=${eligibleTargetCount === 0}
180506
- @pointerdown=${(event) => {
180507
- this.handleResourcePointerDown(event, resourceArg, sessionIdArg);
180508
- }}
180509
- @pointermove=${this.handlePointerMove}
180510
- @pointerup=${this.handlePointerUp}
180511
- @pointercancel=${this.handlePointerCancel}
180512
- @lostpointercapture=${this.handleLostPointerCapture}
180513
- @keydown=${(event) => {
180514
- this.handleResourceContextKey(event, resourceArg, sessionIdArg);
180515
- }}
180516
- >
180517
- <dees-icon icon="lucide:GripVertical" iconSize="13"></dees-icon>
180518
- </button>
180588
+ ${draggable ? this.renderDragHandle(
180589
+ { kind: "resource", id: resourceArg.id },
180590
+ title,
180591
+ groupIdArg,
180592
+ indexArg
180593
+ ) : ""}
180519
180594
  <button
180520
180595
  class="resourcePrimary"
180521
180596
  type="button"
180522
180597
  aria-current=${selected ? "true" : "false"}
180523
- @click=${() => this.emitResource("harness-resource-select", resourceArg, sessionIdArg)}
180598
+ @click=${() => this.emitResource("harness-resource-select", resourceArg, attachedTarget)}
180524
180599
  @keydown=${(event) => {
180525
180600
  if (event.key === "Enter") {
180526
180601
  event.preventDefault();
180527
- this.emitResource("harness-resource-open", resourceArg, sessionIdArg);
180602
+ this.emitResource("harness-resource-open", resourceArg, attachedTarget);
180528
180603
  return;
180529
180604
  }
180530
- this.handleResourceContextKey(event, resourceArg, sessionIdArg);
180605
+ this.handleResourceContextKey(event, resourceArg, attachedTarget);
180531
180606
  }}
180532
180607
  >
180533
180608
  <dees-icon
@@ -180536,32 +180611,45 @@ var _DeesHarnessSessionList = class _DeesHarnessSessionList extends (_a100 = Dee
180536
180611
  iconSize="14"
180537
180612
  ></dees-icon>
180538
180613
  <span class="resourceCopy">
180539
- <span class="resourceTitle">${resourceArg.title || resourceArg.id}</span>
180614
+ <span class="resourceTitle">${title}</span>
180540
180615
  ${resourceArg.preview ? b2`<span class="resourcePreview">${resourceArg.preview}</span>` : ""}
180541
180616
  <span class="resourceMeta">
180542
180617
  ${resourceArg.kind}${resourceArg.state ? ` \xB7 ${resourceArg.state}` : ""}${resourceArg.updatedAt || resourceArg.createdAt ? ` \xB7 ${harnessFormatRelativeTime(resourceArg.updatedAt ?? resourceArg.createdAt)}` : ""}
180543
180618
  </span>
180619
+ ${attachedTarget ? b2`
180620
+ <span class="resourceAttachment" title=${`Attached to ${attachedTitle}`}>
180621
+ <dees-icon aria-hidden="true" icon="lucide:Link" iconSize="10"></dees-icon>
180622
+ <span class="visuallyHidden">Attached to </span>
180623
+ <span class="resourceAttachmentName">${attachedTitle}</span>
180624
+ </span>
180625
+ ` : ""}
180544
180626
  </span>
180545
180627
  </button>
180546
180628
  <button
180547
180629
  class="resourceActions"
180548
180630
  type="button"
180549
180631
  title="Resource actions"
180550
- aria-label=${`Actions for ${resourceArg.title || resourceArg.id}`}
180632
+ aria-label=${`Actions for ${title}`}
180551
180633
  aria-haspopup="menu"
180552
180634
  aria-expanded=${contextOpen ? "true" : "false"}
180553
180635
  aria-keyshortcuts="ContextMenu Shift+F10"
180554
180636
  @click=${(event) => {
180555
180637
  event.stopPropagation();
180556
- this.emitResourceContext(event, resourceArg, sessionIdArg, "action", event.currentTarget);
180638
+ this.emitResourceContext(
180639
+ event,
180640
+ resourceArg,
180641
+ attachedTarget,
180642
+ "action",
180643
+ event.currentTarget
180644
+ );
180557
180645
  }}
180558
180646
  @keydown=${(event) => {
180559
- this.handleResourceContextKey(event, resourceArg, sessionIdArg);
180647
+ this.handleResourceContextKey(event, resourceArg, attachedTarget);
180560
180648
  }}
180561
180649
  >
180562
180650
  <dees-icon icon="lucide:Ellipsis" iconSize="15"></dees-icon>
180563
180651
  </button>
180564
- </li>
180652
+ </article>
180565
180653
  `;
180566
180654
  }
180567
180655
  invokeSessionContext(event) {
@@ -180599,7 +180687,7 @@ var _DeesHarnessSessionList = class _DeesHarnessSessionList extends (_a100 = Dee
180599
180687
  }
180600
180688
  eventTargetsResourceControl(event) {
180601
180689
  return event.composedPath().some(
180602
- (target) => target instanceof HTMLElement && (target.classList.contains("resourceDragHandle") || target.classList.contains("resourceActions"))
180690
+ (target) => target instanceof HTMLElement && target.classList.contains("resourceActions")
180603
180691
  );
180604
180692
  }
180605
180693
  sessionStateLabel(state4) {
@@ -180648,28 +180736,17 @@ var _DeesHarnessSessionList = class _DeesHarnessSessionList extends (_a100 = Dee
180648
180736
  }
180649
180737
  this.collapsedGroupIds = next2;
180650
180738
  }
180651
- sortableSessions(sessionsArg, excludeDraggingArg = true) {
180652
- return sessionsArg.filter((session) => session.draggable !== false && (!excludeDraggingArg || session.id !== this.draggingSessionId));
180653
- }
180654
- sessionsForGroup(groupIdArg) {
180655
- if (groupIdArg === null) return this.ungroupedSessions;
180656
- const group = this.groups.find((candidate) => candidate.id === groupIdArg);
180657
- if (!group) return [];
180658
- const byId = this.sessionsById;
180659
- return group.sessionIds.map((sessionId) => byId.get(sessionId)).filter((session) => session !== void 0);
180660
- }
180661
- handlePointerDown(eventArg, sessionArg, groupIdArg, logicalIndexArg) {
180739
+ handlePointerDown(eventArg, refArg, groupIdArg, logicalIndexArg) {
180662
180740
  if (this.pointerDragGesture || eventArg.button !== 0 || !eventArg.isPrimary || logicalIndexArg < 0) return;
180663
180741
  const handle3 = eventArg.currentTarget;
180664
- const source = handle3.closest(".item");
180742
+ const source = handle3.closest(".item, .resourceRow");
180665
180743
  if (!source) return;
180666
180744
  const sourceRect = source.getBoundingClientRect();
180667
180745
  this.pointerDragGesture = {
180668
- type: "session",
180669
180746
  pointerId: eventArg.pointerId,
180670
180747
  handle: handle3,
180671
180748
  source,
180672
- sessionId: sessionArg.id,
180749
+ item: itemRef(refArg),
180673
180750
  sourceGroupId: groupIdArg,
180674
180751
  sourceLogicalIndex: logicalIndexArg,
180675
180752
  startClientX: eventArg.clientX,
@@ -180686,34 +180763,6 @@ var _DeesHarnessSessionList = class _DeesHarnessSessionList extends (_a100 = Dee
180686
180763
  this.finishPointerDrag(false);
180687
180764
  }
180688
180765
  }
180689
- handleResourcePointerDown(eventArg, resourceArg, fromSessionIdArg) {
180690
- if (this.pointerDragGesture || eventArg.button !== 0 || !eventArg.isPrimary || this.eligibleSessionIds(resourceArg.id).every((sessionId) => sessionId === fromSessionIdArg)) return;
180691
- const handle3 = eventArg.currentTarget;
180692
- const source = handle3.closest(".resourceRow");
180693
- if (!source) return;
180694
- const sourceRect = source.getBoundingClientRect();
180695
- this.pointerDragGesture = {
180696
- type: "resource",
180697
- pointerId: eventArg.pointerId,
180698
- handle: handle3,
180699
- source,
180700
- resourceId: resourceArg.id,
180701
- fromSessionId: fromSessionIdArg,
180702
- eligibleSessionIds: new Set(this.eligibleSessionIds(resourceArg.id)),
180703
- startClientX: eventArg.clientX,
180704
- startClientY: eventArg.clientY,
180705
- grabOffsetX: eventArg.clientX - sourceRect.left,
180706
- grabOffsetY: eventArg.clientY - sourceRect.top,
180707
- phase: "pending"
180708
- };
180709
- window.addEventListener("keydown", this.handleDragKeyDown, true);
180710
- window.addEventListener("blur", this.handleDragWindowBlur);
180711
- try {
180712
- handle3.setPointerCapture(eventArg.pointerId);
180713
- } catch {
180714
- this.finishPointerDrag(false);
180715
- }
180716
- }
180717
180766
  startPointerDrag(eventArg, gestureArg) {
180718
180767
  const sourceRect = gestureArg.source.getBoundingClientRect();
180719
180768
  gestureArg.source.classList.add("dragging");
@@ -180730,32 +180779,15 @@ var _DeesHarnessSessionList = class _DeesHarnessSessionList extends (_a100 = Dee
180730
180779
  gestureArg.phase = "active";
180731
180780
  this.reflowGeneration += 1;
180732
180781
  this.cancelReflowAnimations();
180733
- this.draggedItemHeight = Math.ceil(sourceRect.height);
180734
- this.draggingSessionId = gestureArg.sessionId;
180735
- const remainingCount = this.sortableSessions(this.sessionsForGroup(gestureArg.sourceGroupId)).length;
180782
+ this.draggedItemHeight = sourceRect.height;
180783
+ this.draggingItem = itemRef(gestureArg.item);
180784
+ const remainingCount = this.sortableItems(this.itemsForGroup(gestureArg.sourceGroupId)).length;
180736
180785
  this.dropSlot = {
180737
180786
  groupId: gestureArg.sourceGroupId,
180738
180787
  index: Math.min(gestureArg.sourceLogicalIndex, remainingCount)
180739
180788
  };
180740
180789
  return true;
180741
180790
  }
180742
- startResourcePointerDrag(eventArg, gestureArg) {
180743
- const sourceRect = gestureArg.source.getBoundingClientRect();
180744
- gestureArg.source.classList.add("resourceDragging");
180745
- gestureArg.source.style.setProperty("--resource-drag-preview-width", `${sourceRect.width}px`);
180746
- this.moveResourceDragPreview(eventArg.clientX, eventArg.clientY, gestureArg);
180747
- gestureArg.source.setAttribute("popover", "manual");
180748
- try {
180749
- gestureArg.source.showPopover();
180750
- } catch {
180751
- this.finishPointerDrag(false);
180752
- return false;
180753
- }
180754
- gestureArg.phase = "active";
180755
- this.draggingResourceId = gestureArg.resourceId;
180756
- this.resourceDropTargetSessionId = "";
180757
- return true;
180758
- }
180759
180791
  moveDragPreview(clientXArg, clientYArg, gestureArg) {
180760
180792
  gestureArg.source.style.setProperty(
180761
180793
  "--drag-preview-x",
@@ -180766,38 +180798,20 @@ var _DeesHarnessSessionList = class _DeesHarnessSessionList extends (_a100 = Dee
180766
180798
  `${clientYArg - gestureArg.grabOffsetY}px`
180767
180799
  );
180768
180800
  }
180769
- moveResourceDragPreview(clientXArg, clientYArg, gestureArg) {
180770
- gestureArg.source.style.setProperty(
180771
- "--resource-drag-preview-x",
180772
- `${clientXArg - gestureArg.grabOffsetX}px`
180773
- );
180774
- gestureArg.source.style.setProperty(
180775
- "--resource-drag-preview-y",
180776
- `${clientYArg - gestureArg.grabOffsetY}px`
180777
- );
180778
- }
180779
- updateResourceDropTargetFromPointer(clientXArg, clientYArg) {
180780
- const gesture = this.pointerDragGesture;
180781
- if (gesture?.type !== "resource" || gesture.phase !== "active") return;
180782
- const hit = this.shadowRoot?.elementFromPoint(clientXArg, clientYArg);
180783
- const target = hit?.closest(".item[data-session-id]");
180784
- const sessionId = target?.dataset.sessionId ?? "";
180785
- this.resourceDropTargetSessionId = sessionId && sessionId !== gesture.fromSessionId && this.isResourceTargetEligible(gesture.resourceId, sessionId) ? sessionId : "";
180786
- }
180787
180801
  setDropSlot(groupIdArg, indexArg) {
180788
180802
  const current = this.dropSlot;
180789
180803
  if (current && current.groupId === groupIdArg && current.index === indexArg) return;
180790
- const previousRects = this.captureCardRects();
180804
+ const previousRects = this.captureRowRects();
180791
180805
  const generation = ++this.reflowGeneration;
180792
180806
  this.dropSlot = { groupId: groupIdArg, index: indexArg };
180793
- void this.animateCardReflow(previousRects, generation);
180807
+ void this.animateRowReflow(previousRects, generation);
180794
180808
  }
180795
180809
  clearDropSlot() {
180796
180810
  if (!this.dropSlot) return;
180797
- const previousRects = this.captureCardRects();
180811
+ const previousRects = this.captureRowRects();
180798
180812
  const generation = ++this.reflowGeneration;
180799
180813
  this.dropSlot = void 0;
180800
- void this.animateCardReflow(previousRects, generation);
180814
+ void this.animateRowReflow(previousRects, generation);
180801
180815
  }
180802
180816
  updateDragAutoScrollVelocity() {
180803
180817
  const container = this.scrollContainer;
@@ -180842,6 +180856,7 @@ var _DeesHarnessSessionList = class _DeesHarnessSessionList extends (_a100 = Dee
180842
180856
  }
180843
180857
  }
180844
180858
  const selector = "[data-drop-group-id][data-drop-index][data-drop-kind]";
180859
+ const dragging = this.draggingItem;
180845
180860
  let target;
180846
180861
  const offsets = this.dragAutoScrollVelocity === 0 ? [0, -8, 8, -16, 16, -32, 32] : [0, 8, 16, 32, 48, 64, 96].map(
180847
180862
  (value2) => value2 * (this.dragAutoScrollVelocity < 0 ? 1 : -1)
@@ -180849,7 +180864,7 @@ var _DeesHarnessSessionList = class _DeesHarnessSessionList extends (_a100 = Dee
180849
180864
  for (const offset of offsets) {
180850
180865
  const hit = this.shadowRoot?.elementFromPoint(pointerX, pointerY + offset);
180851
180866
  const candidate = hit?.closest(selector);
180852
- if (candidate && candidate.dataset.sessionId !== this.draggingSessionId && Number(candidate.dataset.dropIndex) >= 0) {
180867
+ if (candidate && !(dragging && candidate.dataset.itemKind === dragging.kind && candidate.dataset.itemId === dragging.id) && Number(candidate.dataset.dropIndex) >= 0) {
180853
180868
  target = candidate;
180854
180869
  break;
180855
180870
  }
@@ -180886,83 +180901,79 @@ var _DeesHarnessSessionList = class _DeesHarnessSessionList extends (_a100 = Dee
180886
180901
  this.dragAutoScrollVelocity = 0;
180887
180902
  this.dragAutoScrollLastFrame = 0;
180888
180903
  }
180889
- createMoveDetail(sessionIdArg, groupIdArg, indexArg) {
180890
- const targetSessions = this.sortableSessions(this.sessionsForGroup(groupIdArg));
180891
- const beforeSessionId = targetSessions[Math.max(0, indexArg)]?.id;
180892
- const sourceGroupId = this.groups.find((group) => group.sessionIds.includes(sessionIdArg))?.id ?? null;
180893
- const sourceSessions = this.sortableSessions(this.sessionsForGroup(sourceGroupId), false);
180894
- const sourceIndex = sourceSessions.findIndex((session) => session.id === sessionIdArg);
180895
- const compatibilityIndex = sourceGroupId === groupIdArg && sourceIndex >= 0 && indexArg > sourceIndex ? indexArg + 1 : indexArg;
180904
+ createMoveDetail(refArg, toGroupIdArg, indexArg, sourceArg) {
180905
+ const targetItems = this.sortableItems(this.itemsForGroup(toGroupIdArg));
180906
+ const beforeItem = targetItems[Math.max(0, indexArg)];
180896
180907
  return {
180897
- sessionId: sessionIdArg,
180898
- groupId: groupIdArg,
180899
- index: Math.max(0, compatibilityIndex),
180900
- ...beforeSessionId ? { beforeSessionId } : {}
180908
+ item: itemRef(refArg),
180909
+ fromGroupId: this.groupIdForItem(refArg),
180910
+ toGroupId: toGroupIdArg,
180911
+ beforeItem: beforeItem ? itemRef(beforeItem) : null,
180912
+ source: sourceArg
180901
180913
  };
180902
180914
  }
180903
- handleKeyboardMove(eventArg, sessionArg, groupIdArg) {
180915
+ emitItemMove(detailArg) {
180916
+ this.dispatchEvent(
180917
+ new CustomEvent("harness-item-move", { detail: detailArg, bubbles: true, composed: true })
180918
+ );
180919
+ }
180920
+ handleKeyboardMove(eventArg, refArg, titleArg, groupIdArg) {
180904
180921
  if (!["ArrowUp", "ArrowDown", "Home", "End"].includes(eventArg.key)) return;
180905
180922
  eventArg.preventDefault();
180906
180923
  eventArg.stopPropagation();
180907
- const sessions = this.sortableSessions(this.sessionsForGroup(groupIdArg), false);
180908
- const sourceIndex = sessions.findIndex((session) => session.id === sessionArg.id);
180924
+ const items = this.sortableItems(this.itemsForGroup(groupIdArg), false);
180925
+ const sourceIndex = items.findIndex((item) => sameItem(item, refArg));
180909
180926
  if (sourceIndex < 0) return;
180910
- const sectionIds = [...this.groups.map((group) => group.id), null];
180927
+ const sectionIds = [...this.effectiveGroups.map((group) => group.id), null];
180911
180928
  const sectionIndex = sectionIds.indexOf(groupIdArg);
180912
- const adjacentGroupId = eventArg.key === "ArrowUp" && sourceIndex === 0 && sectionIndex > 0 ? sectionIds[sectionIndex - 1] : eventArg.key === "ArrowDown" && sourceIndex === sessions.length - 1 && sectionIndex >= 0 && sectionIndex < sectionIds.length - 1 ? sectionIds[sectionIndex + 1] : void 0;
180929
+ const adjacentGroupId = eventArg.key === "ArrowUp" && sourceIndex === 0 && sectionIndex > 0 ? sectionIds[sectionIndex - 1] : eventArg.key === "ArrowDown" && sourceIndex === items.length - 1 && sectionIndex >= 0 && sectionIndex < sectionIds.length - 1 ? sectionIds[sectionIndex + 1] : void 0;
180913
180930
  if (adjacentGroupId !== void 0) {
180914
- const targetSessions = this.sortableSessions(this.sessionsForGroup(adjacentGroupId), false);
180915
- const targetIndex2 = eventArg.key === "ArrowUp" ? targetSessions.length : 0;
180916
- const beforeSession2 = targetSessions[targetIndex2];
180917
- const detail2 = {
180918
- sessionId: sessionArg.id,
180919
- groupId: adjacentGroupId,
180920
- index: targetIndex2,
180921
- ...beforeSession2 ? { beforeSessionId: beforeSession2.id } : {}
180922
- };
180923
- const groupName = adjacentGroupId === null ? "Ungrouped" : this.groups.find((group) => group.id === adjacentGroupId)?.name ?? adjacentGroupId;
180924
- this.moveAnnouncement = `Moved ${sessionArg.title || sessionArg.id} to ${groupName}.`;
180925
- this.keyboardMoveFocus = { sessionId: sessionArg.id, groupId: adjacentGroupId };
180926
- this.dispatchEvent(
180927
- new CustomEvent("harness-session-move", { detail: detail2, bubbles: true, composed: true })
180928
- );
180931
+ const targetItems = this.sortableItems(this.itemsForGroup(adjacentGroupId), false);
180932
+ const targetIndex2 = eventArg.key === "ArrowUp" ? targetItems.length : 0;
180933
+ const beforeItem2 = targetItems[targetIndex2];
180934
+ const groupName = adjacentGroupId === null ? "Ungrouped" : this.effectiveGroups.find((group) => group.id === adjacentGroupId)?.name ?? adjacentGroupId;
180935
+ this.moveAnnouncement = `Moved ${titleArg} to ${groupName}.`;
180936
+ this.keyboardMoveFocus = { item: itemRef(refArg), groupId: adjacentGroupId };
180937
+ this.emitItemMove({
180938
+ item: itemRef(refArg),
180939
+ fromGroupId: groupIdArg,
180940
+ toGroupId: adjacentGroupId,
180941
+ beforeItem: beforeItem2 ? itemRef(beforeItem2) : null,
180942
+ source: "keyboard"
180943
+ });
180929
180944
  return;
180930
180945
  }
180931
- const remaining = sessions.filter((session) => session.id !== sessionArg.id);
180946
+ const remaining = items.filter((item) => !sameItem(item, refArg));
180932
180947
  const targetIndex = eventArg.key === "Home" ? 0 : eventArg.key === "End" ? remaining.length : eventArg.key === "ArrowUp" ? Math.max(0, sourceIndex - 1) : Math.min(remaining.length, sourceIndex + 1);
180933
180948
  if (targetIndex === sourceIndex) return;
180934
- const beforeSession = remaining[targetIndex];
180935
- const compatibilityIndex = targetIndex > sourceIndex ? targetIndex + 1 : targetIndex;
180936
- const detail = {
180937
- sessionId: sessionArg.id,
180938
- groupId: groupIdArg,
180939
- index: compatibilityIndex,
180940
- ...beforeSession ? { beforeSessionId: beforeSession.id } : {}
180941
- };
180942
- this.moveAnnouncement = beforeSession ? `Moved ${sessionArg.title || sessionArg.id} before ${beforeSession.title || beforeSession.id}.` : `Moved ${sessionArg.title || sessionArg.id} to the end.`;
180943
- this.dispatchEvent(
180944
- new CustomEvent("harness-session-move", { detail, bubbles: true, composed: true })
180945
- );
180949
+ const beforeItem = remaining[targetIndex];
180950
+ this.moveAnnouncement = beforeItem ? `Moved ${titleArg} before ${beforeItem.title}.` : `Moved ${titleArg} to the end.`;
180951
+ this.emitItemMove({
180952
+ item: itemRef(refArg),
180953
+ fromGroupId: groupIdArg,
180954
+ toGroupId: groupIdArg,
180955
+ beforeItem: beforeItem ? itemRef(beforeItem) : null,
180956
+ source: "keyboard"
180957
+ });
180946
180958
  }
180947
- captureCardRects() {
180959
+ rowKey(rowArg) {
180960
+ return `${rowArg.dataset.itemKind}:${rowArg.dataset.itemId}`;
180961
+ }
180962
+ captureRowRects() {
180948
180963
  const result = /* @__PURE__ */ new Map();
180949
- for (const item of this.shadowRoot?.querySelectorAll(".item[data-session-id]") ?? []) {
180950
- if (item.dataset.sessionId === this.draggingSessionId) continue;
180951
- result.set(item.dataset.sessionId ?? "", item.getBoundingClientRect());
180964
+ const draggingKey = this.draggingItem ? itemKey(this.draggingItem) : "";
180965
+ for (const row of this.shadowRoot?.querySelectorAll("[data-item-kind][data-item-id]") ?? []) {
180966
+ const key2 = this.rowKey(row);
180967
+ if (key2 === draggingKey) continue;
180968
+ result.set(key2, row.getBoundingClientRect());
180952
180969
  }
180953
180970
  return result;
180954
180971
  }
180955
180972
  restoreKeyboardMoveFocus() {
180956
180973
  const pending = this.keyboardMoveFocus;
180957
180974
  if (!pending) return;
180958
- const currentGroupId = this.groups.find(
180959
- (group) => group.sessionIds.includes(pending.sessionId)
180960
- )?.id ?? null;
180961
- if (currentGroupId !== pending.groupId) return;
180962
- const item = Array.from(
180963
- this.shadowRoot?.querySelectorAll(".item[data-session-id]") ?? []
180964
- ).find((candidate) => candidate.dataset.sessionId === pending.sessionId);
180965
- const handle3 = item?.querySelector(".dragHandle");
180975
+ if (this.groupIdForItem(pending.item) !== pending.groupId) return;
180976
+ const handle3 = this.rowElementFor(pending.item)?.querySelector(".dragHandle");
180966
180977
  if (handle3) {
180967
180978
  handle3.focus();
180968
180979
  this.keyboardMoveFocus = void 0;
@@ -180976,43 +180987,52 @@ var _DeesHarnessSessionList = class _DeesHarnessSessionList extends (_a100 = Dee
180976
180987
  this.keyboardMoveFocus = void 0;
180977
180988
  }
180978
180989
  }
180979
- eligibleSessionIds(resourceIdArg) {
180980
- const knownSessionIds = new Set(this.sessions.map((session) => session.id));
180990
+ /** Known, de-duplicated targets the host allows; an absent entry means unrestricted. */
180991
+ eligibleTargets(resourceIdArg) {
180992
+ const declared = this.eligibleTargetsByResourceId[resourceIdArg];
180993
+ if (!declared) return void 0;
180994
+ const itemsByKey = this.itemsByKey;
180981
180995
  const result = [];
180982
180996
  const seen = /* @__PURE__ */ new Set();
180983
- for (const sessionId of this.eligibleSessionIdsByResourceId[resourceIdArg] ?? []) {
180984
- if (!knownSessionIds.has(sessionId) || seen.has(sessionId)) continue;
180985
- seen.add(sessionId);
180986
- result.push(sessionId);
180997
+ for (const target of declared) {
180998
+ const key2 = target && itemKey(target);
180999
+ if (!key2 || seen.has(key2) || !itemsByKey.has(key2) || sameItem(target, { kind: "resource", id: resourceIdArg })) continue;
181000
+ seen.add(key2);
181001
+ result.push(itemRef(target));
180987
181002
  }
180988
181003
  return result;
180989
181004
  }
180990
- sameSessionIds(firstArg, secondArg) {
180991
- return firstArg.size === secondArg.size && [...firstArg].every((sessionId) => secondArg.has(sessionId));
181005
+ isResourceTargetEligible(resourceIdArg, targetArg) {
181006
+ const eligible = this.eligibleTargets(resourceIdArg);
181007
+ return eligible === void 0 || eligible.some((candidate) => sameItem(candidate, targetArg));
180992
181008
  }
180993
- isResourceTargetEligible(resourceIdArg, sessionIdArg) {
180994
- return this.eligibleSessionIds(resourceIdArg).includes(sessionIdArg);
181009
+ itemTitleFor(refArg) {
181010
+ return this.itemsByKey.get(itemKey(refArg))?.title ?? refArg.id;
180995
181011
  }
180996
- emitResource(nameArg, resourceArg, sessionIdArg) {
181012
+ emitSession(nameArg, sessionArg) {
181013
+ const detail = { session: sessionArg };
181014
+ this.dispatchEvent(new CustomEvent(nameArg, { detail, bubbles: true, composed: true }));
181015
+ }
181016
+ emitResource(nameArg, resourceArg, targetArg) {
180997
181017
  const detail = {
180998
181018
  resource: resourceArg,
180999
- sessionId: sessionIdArg
181019
+ target: targetArg
181000
181020
  };
181001
181021
  this.dispatchEvent(new CustomEvent(nameArg, { detail, bubbles: true, composed: true }));
181002
181022
  }
181003
- handleResourceContextKey(eventArg, resourceArg, sessionIdArg) {
181023
+ handleResourceContextKey(eventArg, resourceArg, targetArg) {
181004
181024
  if (!(eventArg.key === "ContextMenu" || eventArg.key === "F10" && eventArg.shiftKey)) return;
181005
181025
  eventArg.preventDefault();
181006
181026
  eventArg.stopPropagation();
181007
181027
  this.emitResourceContext(
181008
181028
  eventArg,
181009
181029
  resourceArg,
181010
- sessionIdArg,
181030
+ targetArg,
181011
181031
  "keyboard",
181012
181032
  eventArg.currentTarget
181013
181033
  );
181014
181034
  }
181015
- emitResourceContext(eventArg, resourceArg, sessionIdArg, sourceArg, focusTargetArg) {
181035
+ emitResourceContext(eventArg, resourceArg, targetArg, sourceArg, focusTargetArg) {
181016
181036
  const rect = focusTargetArg.getBoundingClientRect();
181017
181037
  const contextGeneration = ++this.resourceContextGeneration;
181018
181038
  this.resourceContextResourceId = resourceArg.id;
@@ -181024,14 +181044,14 @@ var _DeesHarnessSessionList = class _DeesHarnessSessionList extends (_a100 = Dee
181024
181044
  ].find((className) => focusTargetArg.classList.contains(className)) ?? "resourcePrimary";
181025
181045
  const detail = {
181026
181046
  resource: resourceArg,
181027
- sessionId: sessionIdArg,
181047
+ target: targetArg,
181028
181048
  clientX: sourceArg === "pointer" && eventArg instanceof MouseEvent ? eventArg.clientX : rect.left + rect.width / 2,
181029
181049
  clientY: sourceArg === "pointer" && eventArg instanceof MouseEvent ? eventArg.clientY : rect.bottom,
181030
181050
  source: sourceArg,
181031
181051
  originalEvent: eventArg,
181032
- requestAssociation: /* @__PURE__ */ __name((toSessionIdArg) => this.requestResourceAssociation(
181052
+ requestAssociation: /* @__PURE__ */ __name((toTargetArg) => this.requestResourceAssociation(
181033
181053
  resourceArg.id,
181034
- toSessionIdArg,
181054
+ toTargetArg,
181035
181055
  sourceArg === "keyboard" ? "keyboard" : "action"
181036
181056
  ), "requestAssociation"),
181037
181057
  close: /* @__PURE__ */ __name(() => this.closeResourceContext(contextGeneration), "close")
@@ -181053,9 +181073,7 @@ var _DeesHarnessSessionList = class _DeesHarnessSessionList extends (_a100 = Dee
181053
181073
  focusTarget.focus();
181054
181074
  return;
181055
181075
  }
181056
- const row = Array.from(
181057
- this.shadowRoot?.querySelectorAll(".resourceRow[data-resource-id]") ?? []
181058
- ).find((candidate) => candidate.dataset.resourceId === resourceId);
181076
+ const row = this.rowElementFor({ kind: "resource", id: resourceId });
181059
181077
  row?.querySelector(`.${focusClass || "resourcePrimary"}`)?.focus();
181060
181078
  });
181061
181079
  }
@@ -181072,40 +181090,41 @@ var _DeesHarnessSessionList = class _DeesHarnessSessionList extends (_a100 = Dee
181072
181090
  this.pendingResourceAssociationRequest = void 0;
181073
181091
  return;
181074
181092
  }
181075
- const currentSessionId = this.acceptedResourceAssociations.get(pending.resourceId) ?? null;
181076
- if (currentSessionId !== pending.toSessionId) {
181077
- if (currentSessionId !== pending.fromSessionId) {
181078
- const controlledSession = currentSessionId ? this.sessionsById.get(currentSessionId)?.title ?? currentSessionId : "unattached";
181079
- this.moveAnnouncement = `Association request for ${pending.resourceTitle} was not applied; controlled association is ${controlledSession}.`;
181093
+ const currentTarget = this.acceptedResourceAssociations.get(pending.resourceId) ?? null;
181094
+ if (!sameItem(currentTarget, pending.toTarget) && !(currentTarget === null && pending.toTarget === null)) {
181095
+ if (!sameItem(currentTarget, pending.fromTarget) && !(currentTarget === null && pending.fromTarget === null)) {
181096
+ const controlledTitle = currentTarget ? this.itemTitleFor(currentTarget) : "unattached";
181097
+ this.moveAnnouncement = `Association request for ${pending.resourceTitle} was not applied; controlled association is ${controlledTitle}.`;
181080
181098
  this.pendingResourceAssociationRequest = void 0;
181081
181099
  }
181082
181100
  return;
181083
181101
  }
181084
- const fromSession = pending.fromSessionId ? this.sessionsById.get(pending.fromSessionId)?.title ?? pending.fromSessionId : "";
181085
- const toSession = pending.toSessionId ? this.sessionsById.get(pending.toSessionId)?.title ?? pending.toSessionId : "";
181086
- this.moveAnnouncement = pending.intent === "attach" ? `${pending.resourceTitle} is now attached to ${toSession}.` : pending.intent === "detach" ? `${pending.resourceTitle} is now detached from ${fromSession}.` : `${pending.resourceTitle} is now reassigned from ${fromSession} to ${toSession}.`;
181102
+ const fromTitle = pending.fromTarget ? this.itemTitleFor(pending.fromTarget) : "";
181103
+ const toTitle = pending.toTarget ? this.itemTitleFor(pending.toTarget) : "";
181104
+ this.moveAnnouncement = pending.intent === "attach" ? `${pending.resourceTitle} is now attached to ${toTitle}.` : pending.intent === "detach" ? `${pending.resourceTitle} is now detached from ${fromTitle}.` : `${pending.resourceTitle} is now reassigned from ${fromTitle} to ${toTitle}.`;
181087
181105
  this.pendingResourceAssociationRequest = void 0;
181088
181106
  }
181089
181107
  resourceAssociationAnnouncement(detailArg, completedArg) {
181090
181108
  const resourceTitle = detailArg.resource.title || detailArg.resource.id;
181091
- const fromTitle = detailArg.fromSessionId ? this.sessionsById.get(detailArg.fromSessionId)?.title ?? detailArg.fromSessionId : "";
181092
- const toTitle = detailArg.toSessionId ? this.sessionsById.get(detailArg.toSessionId)?.title ?? detailArg.toSessionId : "";
181109
+ const fromTitle = detailArg.fromTarget ? this.itemTitleFor(detailArg.fromTarget) : "";
181110
+ const toTitle = detailArg.toTarget ? this.itemTitleFor(detailArg.toTarget) : "";
181093
181111
  const verb = completedArg ? "completed" : "requested";
181094
181112
  return detailArg.intent === "attach" ? `Attach ${verb} for ${resourceTitle} to ${toTitle}.` : detailArg.intent === "detach" ? `Detach ${verb} for ${resourceTitle} from ${fromTitle}.` : `Reassign ${verb} for ${resourceTitle} from ${fromTitle} to ${toTitle}.`;
181095
181113
  }
181096
- async animateCardReflow(previousRectsArg, generationArg) {
181114
+ async animateRowReflow(previousRectsArg, generationArg) {
181097
181115
  await this.updateComplete;
181098
181116
  if (generationArg !== this.reflowGeneration || !this.isConnected || globalThis.matchMedia?.("(prefers-reduced-motion: reduce)").matches) return;
181099
181117
  this.cancelReflowAnimations();
181100
- for (const item of this.shadowRoot?.querySelectorAll(".item[data-session-id]") ?? []) {
181101
- const sessionId = item.dataset.sessionId ?? "";
181102
- if (!sessionId || sessionId === this.draggingSessionId) continue;
181103
- const previous3 = previousRectsArg.get(sessionId);
181118
+ const draggingKey = this.draggingItem ? itemKey(this.draggingItem) : "";
181119
+ for (const row of this.shadowRoot?.querySelectorAll("[data-item-kind][data-item-id]") ?? []) {
181120
+ const key2 = this.rowKey(row);
181121
+ if (key2 === draggingKey) continue;
181122
+ const previous3 = previousRectsArg.get(key2);
181104
181123
  if (!previous3) continue;
181105
- const current = item.getBoundingClientRect();
181124
+ const current = row.getBoundingClientRect();
181106
181125
  const deltaY = previous3.top - current.top;
181107
181126
  if (Math.abs(deltaY) < 0.5) continue;
181108
- const animation = item.animate(
181127
+ const animation = row.animate(
181109
181128
  [
181110
181129
  { transform: `translateY(${deltaY}px)` },
181111
181130
  { transform: "translateY(0)" }
@@ -181125,11 +181144,7 @@ var _DeesHarnessSessionList = class _DeesHarnessSessionList extends (_a100 = Dee
181125
181144
  finishPointerDrag(commitArg) {
181126
181145
  const gesture = this.pointerDragGesture;
181127
181146
  if (!gesture) return;
181128
- const sessionMoveDetail = gesture.type === "session" && commitArg && gesture.phase === "active" && this.dropSlot ? this.createMoveDetail(gesture.sessionId, this.dropSlot.groupId, this.dropSlot.index) : void 0;
181129
- const resourceRequest = gesture.type === "resource" && commitArg && gesture.phase === "active" && this.resourceDropTargetSessionId ? {
181130
- resourceId: gesture.resourceId,
181131
- toSessionId: this.resourceDropTargetSessionId
181132
- } : void 0;
181147
+ const moveDetail = commitArg && gesture.phase === "active" && this.dropSlot ? this.createMoveDetail(gesture.item, this.dropSlot.groupId, this.dropSlot.index, "pointer") : void 0;
181133
181148
  this.pointerDragGesture = void 0;
181134
181149
  window.removeEventListener("keydown", this.handleDragKeyDown, true);
181135
181150
  window.removeEventListener("blur", this.handleDragWindowBlur);
@@ -181138,19 +181153,14 @@ var _DeesHarnessSessionList = class _DeesHarnessSessionList extends (_a100 = Dee
181138
181153
  this.cancelReflowAnimations();
181139
181154
  if (gesture.source.matches(":popover-open")) gesture.source.hidePopover();
181140
181155
  gesture.source.removeAttribute("popover");
181141
- gesture.source.classList.remove("dragging", "resourceDragging");
181156
+ gesture.source.classList.remove("dragging");
181142
181157
  for (const property of [
181143
181158
  "--drag-preview-width",
181144
181159
  "--drag-preview-height",
181145
181160
  "--drag-preview-x",
181146
- "--drag-preview-y",
181147
- "--resource-drag-preview-width",
181148
- "--resource-drag-preview-x",
181149
- "--resource-drag-preview-y"
181161
+ "--drag-preview-y"
181150
181162
  ]) gesture.source.style.removeProperty(property);
181151
- this.draggingSessionId = "";
181152
- this.draggingResourceId = "";
181153
- this.resourceDropTargetSessionId = "";
181163
+ this.draggingItem = void 0;
181154
181164
  this.draggedItemHeight = 0;
181155
181165
  this.dropSlot = void 0;
181156
181166
  try {
@@ -181159,21 +181169,7 @@ var _DeesHarnessSessionList = class _DeesHarnessSessionList extends (_a100 = Dee
181159
181169
  }
181160
181170
  } catch {
181161
181171
  }
181162
- if (sessionMoveDetail) {
181163
- this.dispatchEvent(
181164
- new CustomEvent("harness-session-move", {
181165
- detail: sessionMoveDetail,
181166
- bubbles: true,
181167
- composed: true
181168
- })
181169
- );
181170
- }
181171
- if (resourceRequest) {
181172
- this.requestResourceAssociation(resourceRequest.resourceId, resourceRequest.toSessionId, "drop");
181173
- }
181174
- }
181175
- emit(name, session) {
181176
- this.dispatchEvent(new CustomEvent(name, { detail: { session }, bubbles: true, composed: true }));
181172
+ if (moveDetail) this.emitItemMove(moveDetail);
181177
181173
  }
181178
181174
  };
181179
181175
  _init102 = __decoratorStart(_a100);
@@ -181183,15 +181179,13 @@ _loading5 = new WeakMap();
181183
181179
  _emptyText2 = new WeakMap();
181184
181180
  _groups3 = new WeakMap();
181185
181181
  _enableGrouping = new WeakMap();
181186
- _ungroupedSessionIds2 = new WeakMap();
181182
+ _ungroupedItemIds2 = new WeakMap();
181187
181183
  _resources = new WeakMap();
181188
181184
  _resourceAssociations = new WeakMap();
181189
181185
  _selectedResourceId = new WeakMap();
181190
- _eligibleSessionIdsByResourceId = new WeakMap();
181186
+ _eligibleTargetsByResourceId = new WeakMap();
181191
181187
  _search = new WeakMap();
181192
- _draggingSessionId = new WeakMap();
181193
- _draggingResourceId = new WeakMap();
181194
- _resourceDropTargetSessionId = new WeakMap();
181188
+ _draggingItem = new WeakMap();
181195
181189
  _dropSlot = new WeakMap();
181196
181190
  _draggedItemHeight = new WeakMap();
181197
181191
  _expandedSessionIds = new WeakMap();
@@ -181206,15 +181200,13 @@ __decorateElement(_init102, 4, "loading", _loading_dec5, _DeesHarnessSessionList
181206
181200
  __decorateElement(_init102, 4, "emptyText", _emptyText_dec2, _DeesHarnessSessionList, _emptyText2);
181207
181201
  __decorateElement(_init102, 4, "groups", _groups_dec3, _DeesHarnessSessionList, _groups3);
181208
181202
  __decorateElement(_init102, 4, "enableGrouping", _enableGrouping_dec, _DeesHarnessSessionList, _enableGrouping);
181209
- __decorateElement(_init102, 4, "ungroupedSessionIds", _ungroupedSessionIds_dec2, _DeesHarnessSessionList, _ungroupedSessionIds2);
181203
+ __decorateElement(_init102, 4, "ungroupedItemIds", _ungroupedItemIds_dec2, _DeesHarnessSessionList, _ungroupedItemIds2);
181210
181204
  __decorateElement(_init102, 4, "resources", _resources_dec, _DeesHarnessSessionList, _resources);
181211
181205
  __decorateElement(_init102, 4, "resourceAssociations", _resourceAssociations_dec, _DeesHarnessSessionList, _resourceAssociations);
181212
181206
  __decorateElement(_init102, 4, "selectedResourceId", _selectedResourceId_dec, _DeesHarnessSessionList, _selectedResourceId);
181213
- __decorateElement(_init102, 4, "eligibleSessionIdsByResourceId", _eligibleSessionIdsByResourceId_dec, _DeesHarnessSessionList, _eligibleSessionIdsByResourceId);
181207
+ __decorateElement(_init102, 4, "eligibleTargetsByResourceId", _eligibleTargetsByResourceId_dec, _DeesHarnessSessionList, _eligibleTargetsByResourceId);
181214
181208
  __decorateElement(_init102, 4, "search", _search_dec, _DeesHarnessSessionList, _search);
181215
- __decorateElement(_init102, 4, "draggingSessionId", _draggingSessionId_dec, _DeesHarnessSessionList, _draggingSessionId);
181216
- __decorateElement(_init102, 4, "draggingResourceId", _draggingResourceId_dec, _DeesHarnessSessionList, _draggingResourceId);
181217
- __decorateElement(_init102, 4, "resourceDropTargetSessionId", _resourceDropTargetSessionId_dec, _DeesHarnessSessionList, _resourceDropTargetSessionId);
181209
+ __decorateElement(_init102, 4, "draggingItem", _draggingItem_dec, _DeesHarnessSessionList, _draggingItem);
181218
181210
  __decorateElement(_init102, 4, "dropSlot", _dropSlot_dec, _DeesHarnessSessionList, _dropSlot);
181219
181211
  __decorateElement(_init102, 4, "draggedItemHeight", _draggedItemHeight_dec, _DeesHarnessSessionList, _draggedItemHeight);
181220
181212
  __decorateElement(_init102, 4, "expandedSessionIds", _expandedSessionIds_dec, _DeesHarnessSessionList, _expandedSessionIds);
@@ -181391,7 +181383,9 @@ __publicField(_DeesHarnessSessionList, "styles", [
181391
181383
  border-color var(--dees-transition-fast) var(--dees-ease-standard);
181392
181384
  }
181393
181385
 
181394
- .item.dragging {
181386
+ /* One drag preview for both item kinds. */
181387
+ .item.dragging,
181388
+ .resourceRow.dragging {
181395
181389
  position: fixed;
181396
181390
  inset: 0 auto auto 0;
181397
181391
  width: var(--drag-preview-width);
@@ -181434,12 +181428,6 @@ __publicField(_DeesHarnessSessionList, "styles", [
181434
181428
  box-shadow: inset 3px 0 var(--card-accent);
181435
181429
  }
181436
181430
 
181437
- .item.resourceDropTarget {
181438
- outline: 2px solid var(--dees-color-accent-primary);
181439
- outline-offset: 2px;
181440
- box-shadow: 0 0 0 5px var(--dees-color-focus-ring), var(--dees-shadow-lg);
181441
- }
181442
-
181443
181431
  .itemHeader {
181444
181432
  display: grid;
181445
181433
  grid-template-columns: minmax(0, 1fr) 30px 30px;
@@ -181616,75 +181604,31 @@ __publicField(_DeesHarnessSessionList, "styles", [
181616
181604
  font-size: var(--dees-font-caption2-size, 10px);
181617
181605
  }
181618
181606
 
181619
- .resourceDropLabel {
181620
- margin: 0 10px 10px;
181621
- padding: 6px 9px;
181622
- border-radius: var(--dees-radius-md);
181623
- background: color-mix(in srgb, var(--dees-color-accent-primary) 14%, transparent);
181624
- color: var(--dees-color-accent-primary);
181625
- font-size: var(--dees-font-caption1-size, 11px);
181626
- font-weight: 680;
181627
- text-align: center;
181628
- }
181629
-
181630
- .resourceChildren {
181631
- display: grid;
181632
- gap: 4px;
181633
- margin: 0 8px 8px 24px;
181634
- padding: 0;
181635
- list-style: none;
181636
- }
181637
-
181638
- .resourceSection {
181639
- margin-top: var(--dees-spacing-md);
181640
- }
181641
-
181642
- .resourceSectionTitle {
181643
- margin: 0 0 7px;
181644
- padding: var(--dees-spacing-xs) 6px;
181645
- color: var(--dees-color-text-secondary);
181646
- font-size: var(--dees-font-caption1-size, 11px);
181647
- font-weight: 600;
181648
- }
181649
-
181650
- .resourceList {
181651
- display: grid;
181652
- gap: var(--dees-spacing-sm);
181653
- margin: 0;
181654
- padding: 0;
181655
- list-style: none;
181656
- }
181657
-
181607
+ /* Resource rows are peers of session cards in the same ordered section. */
181658
181608
  .resourceRow {
181609
+ position: relative;
181659
181610
  display: grid;
181660
- grid-template-columns: 26px minmax(0, 1fr) 38px;
181611
+ grid-template-columns: minmax(0, 1fr) 38px;
181661
181612
  min-width: 0;
181662
181613
  overflow: hidden;
181663
181614
  border: 1px solid var(--dees-color-border-subtle);
181664
181615
  border-radius: var(--dees-radius-lg);
181616
+ corner-shape: var(--dees-corner-shape);
181665
181617
  background: color-mix(in srgb, var(--dees-color-bg-secondary) 76%, transparent);
181666
181618
  color: var(--dees-color-text-primary);
181667
181619
  box-shadow: var(--dees-shadow-xs);
181668
181620
  box-sizing: border-box;
181669
181621
  }
181670
181622
 
181623
+ .resourceRow.draggable {
181624
+ grid-template-columns: 26px minmax(0, 1fr) 38px;
181625
+ }
181626
+
181671
181627
  .resourceRow.selected {
181672
181628
  border-color: var(--dees-color-accent-primary);
181673
181629
  background: color-mix(in srgb, var(--dees-color-accent-primary) 10%, var(--dees-color-bg-secondary));
181674
181630
  }
181675
181631
 
181676
- .resourceRow.resourceDragging {
181677
- position: fixed;
181678
- inset: 0 auto auto 0;
181679
- width: var(--resource-drag-preview-width);
181680
- max-width: none;
181681
- margin: 0;
181682
- opacity: 0.96;
181683
- pointer-events: none;
181684
- transform: translate3d(var(--resource-drag-preview-x), var(--resource-drag-preview-y), 0);
181685
- box-shadow: var(--dees-shadow-xl);
181686
- }
181687
-
181688
181632
  .resourceDragHandle,
181689
181633
  .resourcePrimary,
181690
181634
  .resourceActions {
@@ -181696,22 +181640,7 @@ __publicField(_DeesHarnessSessionList, "styles", [
181696
181640
  }
181697
181641
 
181698
181642
  .resourceDragHandle {
181699
- display: grid;
181700
- place-items: center;
181701
181643
  min-width: 26px;
181702
- padding: 0;
181703
- color: var(--dees-color-text-muted);
181704
- cursor: grab;
181705
- touch-action: none;
181706
- }
181707
-
181708
- .resourceDragHandle:disabled {
181709
- opacity: 0.35;
181710
- cursor: default;
181711
- }
181712
-
181713
- .resourceDragHandle:not(:disabled):active {
181714
- cursor: grabbing;
181715
181644
  }
181716
181645
 
181717
181646
  .resourcePrimary {
@@ -181765,6 +181694,29 @@ __publicField(_DeesHarnessSessionList, "styles", [
181765
181694
  white-space: nowrap;
181766
181695
  }
181767
181696
 
181697
+ /* Decorative marker for the controlled association; never interactive. */
181698
+ .resourceAttachment {
181699
+ display: flex;
181700
+ min-width: 0;
181701
+ align-items: center;
181702
+ gap: 4px;
181703
+ margin-top: 2px;
181704
+ color: var(--dees-color-link);
181705
+ font-size: var(--dees-font-caption2-size, 10px);
181706
+ font-weight: 600;
181707
+ }
181708
+
181709
+ .resourceAttachment dees-icon {
181710
+ flex: 0 0 auto;
181711
+ }
181712
+
181713
+ .resourceAttachmentName {
181714
+ min-width: 0;
181715
+ overflow: hidden;
181716
+ text-overflow: ellipsis;
181717
+ white-space: nowrap;
181718
+ }
181719
+
181768
181720
  .resourceActions {
181769
181721
  display: grid;
181770
181722
  place-items: center;
@@ -181802,7 +181754,7 @@ __publicField(_DeesHarnessSessionList, "styles", [
181802
181754
  .emptyDropZone {
181803
181755
  display: grid;
181804
181756
  place-items: center;
181805
- min-height: 46px;
181757
+ overflow: hidden;
181806
181758
  border: 1px dashed color-mix(in srgb, var(--dees-color-accent-primary) 68%, transparent);
181807
181759
  border-radius: var(--dees-radius-xl);
181808
181760
  background: color-mix(in srgb, var(--dees-color-accent-primary) 8%, transparent);
@@ -181810,9 +181762,14 @@ __publicField(_DeesHarnessSessionList, "styles", [
181810
181762
  box-sizing: border-box;
181811
181763
  }
181812
181764
 
181765
+ /* The placeholder matches the dragged row exactly; only the empty zone has a floor. */
181766
+ .emptyDropZone {
181767
+ min-height: 46px;
181768
+ }
181769
+
181813
181770
  .dropPlaceholder::after,
181814
181771
  .emptyDropZone::after {
181815
- content: 'Drop conversation here';
181772
+ content: 'Drop here';
181816
181773
  font-size: var(--dees-font-caption2-size, 10px);
181817
181774
  font-weight: 650;
181818
181775
  letter-spacing: 0.02em;
@@ -181955,6 +181912,10 @@ __publicField(_DeesHarnessSessionList, "styles", [
181955
181912
  .expandToggle { margin: 0 3px 0 0; }
181956
181913
 
181957
181914
  .resourceRow {
181915
+ grid-template-columns: minmax(0, 1fr) 44px;
181916
+ }
181917
+
181918
+ .resourceRow.draggable {
181958
181919
  grid-template-columns: 44px minmax(0, 1fr) 44px;
181959
181920
  }
181960
181921
 
@@ -181971,10 +181932,6 @@ __publicField(_DeesHarnessSessionList, "styles", [
181971
181932
  }
181972
181933
 
181973
181934
  @media (max-width: 280px) {
181974
- .resourceChildren {
181975
- margin-left: 8px;
181976
- }
181977
-
181978
181935
  .resourcePreview {
181979
181936
  display: none;
181980
181937
  }
@@ -182015,10 +181972,13 @@ init_dist_ts26();
182015
181972
  init_theme();
182016
181973
  init_services();
182017
181974
  var _disabled_dec10, _fontSize_dec, _a101, _DeesTerminalView_decorators, _init103, _fontSize, _disabled10;
181975
+ var maxPendingWriteBytes = 8 * 1024 * 1024;
181976
+ var RIS = "\x1Bc";
181977
+ var chunkByteLength = /* @__PURE__ */ __name((chunkArg) => typeof chunkArg === "string" ? chunkArg.length * 2 : chunkArg.byteLength, "chunkByteLength");
182018
181978
  _DeesTerminalView_decorators = [customElement("dees-terminal-view")];
182019
181979
  var _DeesTerminalView = class _DeesTerminalView extends (_a101 = DeesElement, _fontSize_dec = [n5({ type: Number })], _disabled_dec10 = [n5({ type: Boolean })], _a101) {
182020
181980
  constructor() {
182021
- super(...arguments);
181981
+ super();
182022
181982
  __privateAdd(this, _fontSize, __runInitializers(_init103, 8, this, 13)), __runInitializers(_init103, 11, this);
182023
181983
  __privateAdd(this, _disabled10, __runInitializers(_init103, 12, this, false)), __runInitializers(_init103, 15, this);
182024
181984
  __publicField(this, "terminal");
@@ -182026,45 +181986,138 @@ var _DeesTerminalView = class _DeesTerminalView extends (_a101 = DeesElement, _f
182026
181986
  __publicField(this, "resizeObserver");
182027
181987
  __publicField(this, "inputDisposable");
182028
181988
  __publicField(this, "lastReportedSize", "");
182029
- // Output that arrives before xterm finished loading is replayed in order.
181989
+ // Output that arrives before xterm is live is replayed in order, bounded by
181990
+ // maxPendingWriteBytes and retained across a disconnect.
182030
181991
  __publicField(this, "pendingWrites", []);
181992
+ __publicField(this, "pendingWriteBytes", 0);
181993
+ __publicField(this, "pendingWritesDropped", false);
182031
181994
  __publicField(this, "setupPromise");
181995
+ __publicField(this, "readyPending", true);
181996
+ __publicField(this, "readyResolve", /* @__PURE__ */ __name(() => void 0, "readyResolve"));
181997
+ __publicField(this, "readyReject", /* @__PURE__ */ __name(() => void 0, "readyReject"));
181998
+ /**
181999
+ * Resolves once the terminal of the current connection is live; a fresh
182000
+ * promise is created for every connection. It rejects with the load error
182001
+ * when xterm cannot be loaded (`terminal-error` carries the same error), and
182002
+ * when the element is disconnected before the terminal came up.
182003
+ */
182004
+ __publicField(this, "ready");
182005
+ this.ready = this.createReadyPromise();
182006
+ this.registerStartupFunction(async (signalArg) => {
182007
+ await this.ensureTerminal(signalArg);
182008
+ });
182009
+ this.registerGarbageFunction(() => {
182010
+ this.teardownTerminal();
182011
+ });
182032
182012
  }
182033
182013
  render() {
182034
182014
  return b2`<div class="terminalHost"></div>`;
182035
182015
  }
182036
- async firstUpdated() {
182037
- this.setupPromise = this.setupTerminal();
182038
- await this.setupPromise;
182016
+ connectedCallback() {
182017
+ if (!this.readyPending) this.ready = this.createReadyPromise();
182018
+ return super.connectedCallback();
182039
182019
  }
182040
182020
  /** Feed remote output into the terminal; safe to call before setup finishes. */
182041
182021
  write(dataArg) {
182042
- if (this.terminal) {
182043
- this.terminal.write(dataArg);
182044
- } else {
182045
- this.pendingWrites.push(dataArg);
182022
+ if (this.terminal && this.isConnected) {
182023
+ this.writeToTerminal(this.terminal, dataArg);
182024
+ return;
182046
182025
  }
182026
+ this.bufferWrite(dataArg);
182047
182027
  }
182048
182028
  /** Reset the screen and scrollback, e.g. before a full replay. */
182049
182029
  clear() {
182050
- this.pendingWrites = [];
182051
- this.terminal?.reset();
182030
+ const terminal = this.terminal;
182031
+ if (terminal && this.isConnected) {
182032
+ this.writeToTerminal(terminal, RIS);
182033
+ return;
182034
+ }
182035
+ this.pendingWrites = [RIS];
182036
+ this.pendingWriteBytes = chunkByteLength(RIS);
182037
+ this.pendingWritesDropped = false;
182052
182038
  }
182053
182039
  focus() {
182054
182040
  this.terminal?.focus();
182055
182041
  }
182056
- /** Current grid size, or undefined while xterm is still loading. */
182042
+ /** Current grid size, or undefined while no terminal is live. */
182057
182043
  get currentSize() {
182058
182044
  if (!this.terminal) return void 0;
182059
182045
  return { rows: this.terminal.rows, cols: this.terminal.cols };
182060
182046
  }
182061
- async setupTerminal() {
182047
+ createReadyPromise() {
182048
+ this.readyPending = true;
182049
+ const promise = new Promise((resolveArg, rejectArg) => {
182050
+ this.readyResolve = () => {
182051
+ this.readyPending = false;
182052
+ resolveArg();
182053
+ };
182054
+ this.readyReject = (reasonArg) => {
182055
+ this.readyPending = false;
182056
+ rejectArg(reasonArg);
182057
+ };
182058
+ });
182059
+ promise.catch(() => void 0);
182060
+ return promise;
182061
+ }
182062
+ bufferWrite(chunkArg) {
182063
+ this.pendingWrites.push(chunkArg);
182064
+ this.pendingWriteBytes += chunkByteLength(chunkArg);
182065
+ while (this.pendingWriteBytes > maxPendingWriteBytes && this.pendingWrites.length > 1) {
182066
+ const droppedChunk = this.pendingWrites.shift();
182067
+ this.pendingWriteBytes -= chunkByteLength(droppedChunk);
182068
+ this.pendingWritesDropped = true;
182069
+ }
182070
+ }
182071
+ flushPendingWrites(terminalArg) {
182072
+ const pending = this.pendingWrites;
182073
+ const dropped = this.pendingWritesDropped;
182074
+ this.pendingWrites = [];
182075
+ this.pendingWriteBytes = 0;
182076
+ this.pendingWritesDropped = false;
182077
+ if (dropped && !this.writeToTerminal(terminalArg, RIS)) return;
182078
+ for (const chunk of pending) {
182079
+ if (!this.writeToTerminal(terminalArg, chunk)) return;
182080
+ }
182081
+ }
182082
+ /** xterm throws at its own flow-control watermark; that has to reach the host. */
182083
+ writeToTerminal(terminalArg, chunkArg) {
182084
+ try {
182085
+ terminalArg.write(chunkArg);
182086
+ return true;
182087
+ } catch (error) {
182088
+ this.reportError(error);
182089
+ return false;
182090
+ }
182091
+ }
182092
+ reportError(errorArg) {
182093
+ if (this.readyPending) this.readyReject(errorArg);
182094
+ const detail = { error: errorArg };
182095
+ this.dispatchEvent(
182096
+ new CustomEvent("terminal-error", { detail, bubbles: true, composed: true })
182097
+ );
182098
+ }
182099
+ ensureTerminal(signalArg) {
182100
+ if (this.terminal) return Promise.resolve();
182101
+ if (!this.setupPromise) this.setupPromise = this.setupTerminal(signalArg);
182102
+ return this.setupPromise;
182103
+ }
182104
+ async setupTerminal(signalArg) {
182105
+ try {
182106
+ await this.createTerminal(signalArg);
182107
+ } catch (error) {
182108
+ this.reportError(error);
182109
+ } finally {
182110
+ if (!this.terminal) this.setupPromise = void 0;
182111
+ }
182112
+ }
182113
+ async createTerminal(signalArg) {
182114
+ await this.updateComplete;
182062
182115
  const libLoader = DeesServiceLibLoader.getInstance();
182063
182116
  const [xterm, fit] = await Promise.all([
182064
182117
  libLoader.loadXterm(),
182065
182118
  libLoader.loadXtermFitAddon()
182066
182119
  ]);
182067
- if (!this.isConnected) return;
182120
+ if (signalArg.aborted || !this.isConnected) return;
182068
182121
  const host = this.shadowRoot?.querySelector(".terminalHost");
182069
182122
  if (!host) return;
182070
182123
  const computed2 = getComputedStyle(this);
@@ -182084,9 +182137,18 @@ var _DeesTerminalView = class _DeesTerminalView extends (_a101 = DeesElement, _f
182084
182137
  cursor: themeColor("--dees-color-accent-primary", "#e6e6e6")
182085
182138
  }
182086
182139
  });
182087
- const fitAddon = new fit.FitAddon();
182088
- terminal.loadAddon(fitAddon);
182089
- terminal.open(host);
182140
+ let fitAddon;
182141
+ try {
182142
+ fitAddon = new fit.FitAddon();
182143
+ terminal.loadAddon(fitAddon);
182144
+ terminal.open(host);
182145
+ } catch (error) {
182146
+ try {
182147
+ terminal.dispose();
182148
+ } catch {
182149
+ }
182150
+ throw error;
182151
+ }
182090
182152
  this.terminal = terminal;
182091
182153
  this.fitAddon = fitAddon;
182092
182154
  this.inputDisposable = terminal.onData((dataArg) => {
@@ -182096,11 +182158,11 @@ var _DeesTerminalView = class _DeesTerminalView extends (_a101 = DeesElement, _f
182096
182158
  new CustomEvent("terminal-input", { detail, bubbles: true, composed: true })
182097
182159
  );
182098
182160
  });
182099
- for (const pending of this.pendingWrites) terminal.write(pending);
182100
- this.pendingWrites = [];
182161
+ this.flushPendingWrites(terminal);
182101
182162
  this.refit();
182102
182163
  this.resizeObserver = new ResizeObserver(() => this.refit());
182103
182164
  this.resizeObserver.observe(host);
182165
+ this.readyResolve();
182104
182166
  }
182105
182167
  refit() {
182106
182168
  if (!this.terminal || !this.fitAddon) return;
@@ -182120,8 +182182,7 @@ var _DeesTerminalView = class _DeesTerminalView extends (_a101 = DeesElement, _f
182120
182182
  new CustomEvent("terminal-resize", { detail, bubbles: true, composed: true })
182121
182183
  );
182122
182184
  }
182123
- async disconnectedCallback() {
182124
- await super.disconnectedCallback();
182185
+ teardownTerminal() {
182125
182186
  this.resizeObserver?.disconnect();
182126
182187
  this.resizeObserver = void 0;
182127
182188
  this.inputDisposable?.dispose();
@@ -182129,7 +182190,13 @@ var _DeesTerminalView = class _DeesTerminalView extends (_a101 = DeesElement, _f
182129
182190
  this.terminal?.dispose();
182130
182191
  this.terminal = void 0;
182131
182192
  this.fitAddon = void 0;
182132
- this.pendingWrites = [];
182193
+ this.lastReportedSize = "";
182194
+ this.setupPromise = void 0;
182195
+ if (this.readyPending) {
182196
+ this.readyReject(
182197
+ new Error("dees-terminal-view was disconnected before the terminal became ready")
182198
+ );
182199
+ }
182133
182200
  }
182134
182201
  };
182135
182202
  _init103 = __decoratorStart(_a101);
@@ -223678,7 +223745,7 @@ init_group_runtime();
223678
223745
  // ts_web/00_commitinfo_data.ts
223679
223746
  var commitinfo = {
223680
223747
  name: "@design.estate/dees-catalog",
223681
- version: "10.0.0",
223748
+ version: "11.0.0",
223682
223749
  description: "A comprehensive library that provides dynamic web components for building sophisticated and modern web applications using JavaScript and TypeScript."
223683
223750
  };
223684
223751
 
@@ -223889,6 +223956,7 @@ export {
223889
223956
  isInViewport,
223890
223957
  makeStreamingSimulator,
223891
223958
  markdownStyles,
223959
+ maxPendingWriteBytes,
223892
223960
  mosaicEqualize,
223893
223961
  mosaicFindLeaf,
223894
223962
  mosaicFindLeafBySurface,