@anionex/dsh-pinned-sessions 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +41 -0
- package/README.md +79 -20
- package/README.zh.md +81 -22
- package/assets/hero.png +0 -0
- package/assets/pinned-session-menu.png +0 -0
- package/assets/social-preview.png +0 -0
- package/lib/client.js +534 -46
- package/lib/client.js.map +1 -1
- package/lib/types/client/index.d.ts +35 -2
- package/package.json +10 -5
- package/src/client/dsh-primitives.d.ts +51 -0
- package/src/client/index.tsx +516 -53
package/lib/client.js
CHANGED
|
@@ -28,6 +28,7 @@ __export(index_exports, {
|
|
|
28
28
|
});
|
|
29
29
|
module.exports = __toCommonJS(index_exports);
|
|
30
30
|
var import_react3 = require("react");
|
|
31
|
+
var import_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
|
|
31
32
|
|
|
32
33
|
// node_modules/lucide-react/dist/esm/createLucideIcon.js
|
|
33
34
|
var import_react2 = require("react");
|
|
@@ -100,6 +101,54 @@ var createLucideIcon = (iconName, iconNode) => {
|
|
|
100
101
|
return Component;
|
|
101
102
|
};
|
|
102
103
|
|
|
104
|
+
// node_modules/lucide-react/dist/esm/icons/archive.js
|
|
105
|
+
var Archive = createLucideIcon("Archive", [
|
|
106
|
+
["rect", { width: "20", height: "5", x: "2", y: "3", rx: "1", key: "1wp1u1" }],
|
|
107
|
+
["path", { d: "M4 8v11a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8", key: "1s80jp" }],
|
|
108
|
+
["path", { d: "M10 12h4", key: "a56b0p" }]
|
|
109
|
+
]);
|
|
110
|
+
|
|
111
|
+
// node_modules/lucide-react/dist/esm/icons/ellipsis.js
|
|
112
|
+
var Ellipsis = createLucideIcon("Ellipsis", [
|
|
113
|
+
["circle", { cx: "12", cy: "12", r: "1", key: "41hilf" }],
|
|
114
|
+
["circle", { cx: "19", cy: "12", r: "1", key: "1wjl8i" }],
|
|
115
|
+
["circle", { cx: "5", cy: "12", r: "1", key: "1pcz8c" }]
|
|
116
|
+
]);
|
|
117
|
+
|
|
118
|
+
// node_modules/lucide-react/dist/esm/icons/git-branch.js
|
|
119
|
+
var GitBranch = createLucideIcon("GitBranch", [
|
|
120
|
+
["line", { x1: "6", x2: "6", y1: "3", y2: "15", key: "17qcm7" }],
|
|
121
|
+
["circle", { cx: "18", cy: "6", r: "3", key: "1h7g24" }],
|
|
122
|
+
["circle", { cx: "6", cy: "18", r: "3", key: "fqmcym" }],
|
|
123
|
+
["path", { d: "M18 9a9 9 0 0 1-9 9", key: "n2h4wq" }]
|
|
124
|
+
]);
|
|
125
|
+
|
|
126
|
+
// node_modules/lucide-react/dist/esm/icons/pencil.js
|
|
127
|
+
var Pencil = createLucideIcon("Pencil", [
|
|
128
|
+
[
|
|
129
|
+
"path",
|
|
130
|
+
{
|
|
131
|
+
d: "M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z",
|
|
132
|
+
key: "1a8usu"
|
|
133
|
+
}
|
|
134
|
+
],
|
|
135
|
+
["path", { d: "m15 5 4 4", key: "1mk7zo" }]
|
|
136
|
+
]);
|
|
137
|
+
|
|
138
|
+
// node_modules/lucide-react/dist/esm/icons/pin-off.js
|
|
139
|
+
var PinOff = createLucideIcon("PinOff", [
|
|
140
|
+
["path", { d: "M12 17v5", key: "bb1du9" }],
|
|
141
|
+
["path", { d: "M15 9.34V7a1 1 0 0 1 1-1 2 2 0 0 0 0-4H7.89", key: "znwnzq" }],
|
|
142
|
+
["path", { d: "m2 2 20 20", key: "1ooewy" }],
|
|
143
|
+
[
|
|
144
|
+
"path",
|
|
145
|
+
{
|
|
146
|
+
d: "M9 9v1.76a2 2 0 0 1-1.11 1.79l-1.78.9A2 2 0 0 0 5 15.24V16a1 1 0 0 0 1 1h11",
|
|
147
|
+
key: "c9qhm2"
|
|
148
|
+
}
|
|
149
|
+
]
|
|
150
|
+
]);
|
|
151
|
+
|
|
103
152
|
// node_modules/lucide-react/dist/esm/icons/pin.js
|
|
104
153
|
var Pin = createLucideIcon("Pin", [
|
|
105
154
|
["path", { d: "M12 17v5", key: "bb1du9" }],
|
|
@@ -112,10 +161,13 @@ var Pin = createLucideIcon("Pin", [
|
|
|
112
161
|
]
|
|
113
162
|
]);
|
|
114
163
|
|
|
115
|
-
// node_modules/lucide-react/dist/esm/icons/
|
|
116
|
-
var
|
|
117
|
-
["path", { d: "
|
|
118
|
-
["path", { d: "
|
|
164
|
+
// node_modules/lucide-react/dist/esm/icons/trash-2.js
|
|
165
|
+
var Trash2 = createLucideIcon("Trash2", [
|
|
166
|
+
["path", { d: "M3 6h18", key: "d0wm0j" }],
|
|
167
|
+
["path", { d: "M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6", key: "4alrt4" }],
|
|
168
|
+
["path", { d: "M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2", key: "v07s0e" }],
|
|
169
|
+
["line", { x1: "10", x2: "10", y1: "11", y2: "17", key: "1uufr5" }],
|
|
170
|
+
["line", { x1: "14", x2: "14", y1: "11", y2: "17", key: "xtxkd" }]
|
|
119
171
|
]);
|
|
120
172
|
|
|
121
173
|
// src/client/index.tsx
|
|
@@ -135,7 +187,7 @@ var defaultAttributes2 = {
|
|
|
135
187
|
};
|
|
136
188
|
|
|
137
189
|
// node_modules/lucide/dist/esm/icons/pin-off.js
|
|
138
|
-
var
|
|
190
|
+
var PinOff2 = [
|
|
139
191
|
"svg",
|
|
140
192
|
defaultAttributes2,
|
|
141
193
|
[
|
|
@@ -271,7 +323,7 @@ function updateSessionMenuItem(target, pinned, label) {
|
|
|
271
323
|
target.label.textContent = label;
|
|
272
324
|
target.icon.replaceChildren(createLucideIcon2(
|
|
273
325
|
target.menu.ownerDocument,
|
|
274
|
-
pinned ?
|
|
326
|
+
pinned ? PinOff2 : Pin2,
|
|
275
327
|
pinned ? "pin-off" : "pin"
|
|
276
328
|
));
|
|
277
329
|
}
|
|
@@ -429,23 +481,69 @@ function sessionDisplayTitle(session, workspaceTitle) {
|
|
|
429
481
|
|
|
430
482
|
// src/client/index.tsx
|
|
431
483
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
484
|
+
var BooleanStore = class {
|
|
485
|
+
value = false;
|
|
486
|
+
listeners = /* @__PURE__ */ new Set();
|
|
487
|
+
getSnapshot = () => this.value;
|
|
488
|
+
subscribe = (listener) => {
|
|
489
|
+
this.listeners.add(listener);
|
|
490
|
+
return () => {
|
|
491
|
+
this.listeners.delete(listener);
|
|
492
|
+
};
|
|
493
|
+
};
|
|
494
|
+
set(value) {
|
|
495
|
+
if (value === this.value) return;
|
|
496
|
+
this.value = value;
|
|
497
|
+
for (const listener of this.listeners) listener();
|
|
498
|
+
}
|
|
499
|
+
};
|
|
432
500
|
var NS = "pinnedSessions";
|
|
433
501
|
var STYLE_ID = "@anionex/dsh-pinned-sessions";
|
|
434
502
|
var MENU_ASSOCIATION_MS = 2e3;
|
|
435
503
|
var zh = {
|
|
436
|
-
"menu.
|
|
437
|
-
"menu.
|
|
504
|
+
"menu.rename": "\u91CD\u547D\u540D",
|
|
505
|
+
"menu.fork": "\u5206\u53C9\u4F1A\u8BDD",
|
|
506
|
+
"menu.pin": "\u7F6E\u9876\u5230\u9876\u90E8\u5206\u7EC4",
|
|
507
|
+
"menu.unpin": "\u4ECE\u9876\u90E8\u5206\u7EC4\u53D6\u6D88\u7F6E\u9876",
|
|
508
|
+
"menu.archive": "\u5F52\u6863\u4F1A\u8BDD",
|
|
509
|
+
"menu.delete": "\u5220\u9664\u4F1A\u8BDD",
|
|
438
510
|
"section.label": "\u7F6E\u9876\u4F1A\u8BDD",
|
|
439
511
|
"session.open": "\u6253\u5F00\u7F6E\u9876\u4F1A\u8BDD\u201C{name}\u201D",
|
|
512
|
+
"session.actions": "\u7F6E\u9876\u4F1A\u8BDD\u201C{name}\u201D\u7684\u64CD\u4F5C",
|
|
513
|
+
"session.archiveFailed": "\u5F52\u6863\u4F1A\u8BDD\u5931\u8D25\uFF1A{detail}",
|
|
514
|
+
"session.forkFailed": "\u5206\u53C9\u4F1A\u8BDD\u5931\u8D25\uFF1A{detail}",
|
|
440
515
|
"session.unpin": "\u53D6\u6D88\u7F6E\u9876\u201C{name}\u201D",
|
|
516
|
+
"dialog.close": "\u5173\u95ED",
|
|
517
|
+
"dialog.cancel": "\u53D6\u6D88",
|
|
518
|
+
"rename.title": "\u91CD\u547D\u540D\u4F1A\u8BDD",
|
|
519
|
+
"rename.field": "\u4F1A\u8BDD\u540D\u79F0",
|
|
520
|
+
"rename.confirm": "\u91CD\u547D\u540D",
|
|
521
|
+
"delete.title": "\u5220\u9664\u4F1A\u8BDD",
|
|
522
|
+
"delete.description": "\u5C06\u6C38\u4E45\u5220\u9664\u4F1A\u8BDD\u201C{name}\u201D\u53CA\u5176\u5B50\u4EE3\u7406\uFF08\u542B\u6B63\u5728\u8FD0\u884C\u7684\uFF09\u548C\u5168\u90E8\u8BB0\u5F55\uFF08\u5BF9\u8BDD\u5185\u5BB9\u3001\u7EDF\u8BA1\u3001\u7F13\u5B58\uFF09\uFF0C\u6B64\u64CD\u4F5C\u4E0D\u53EF\u6062\u590D\u3002",
|
|
523
|
+
"delete.pending": "\u6B63\u5728\u5220\u9664\u4F1A\u8BDD\u2026",
|
|
441
524
|
"workspace.ungrouped": "\u672A\u5206\u7EC4"
|
|
442
525
|
};
|
|
443
526
|
var en = {
|
|
444
|
-
"menu.
|
|
445
|
-
"menu.
|
|
527
|
+
"menu.rename": "Rename",
|
|
528
|
+
"menu.fork": "Fork session",
|
|
529
|
+
"menu.pin": "Pin to top section",
|
|
530
|
+
"menu.unpin": "Unpin from top section",
|
|
531
|
+
"menu.archive": "Archive session",
|
|
532
|
+
"menu.delete": "Delete session",
|
|
446
533
|
"section.label": "Pinned sessions",
|
|
447
534
|
"session.open": "Open pinned session \u201C{name}\u201D",
|
|
535
|
+
"session.actions": "Actions for pinned session \u201C{name}\u201D",
|
|
536
|
+
"session.archiveFailed": "Could not archive session: {detail}",
|
|
537
|
+
"session.forkFailed": "Could not fork session: {detail}",
|
|
448
538
|
"session.unpin": "Unpin \u201C{name}\u201D",
|
|
539
|
+
"dialog.close": "Close",
|
|
540
|
+
"dialog.cancel": "Cancel",
|
|
541
|
+
"rename.title": "Rename session",
|
|
542
|
+
"rename.field": "Session name",
|
|
543
|
+
"rename.confirm": "Rename",
|
|
544
|
+
"delete.title": "Delete session",
|
|
545
|
+
"delete.description": "This permanently deletes session \u201C{name}\u201D, its child agents (including any that are still running), and all of its records (conversation, stats, cache). This cannot be undone.",
|
|
546
|
+
"delete.pending": "Deleting session\u2026",
|
|
449
547
|
"workspace.ungrouped": "Ungrouped"
|
|
450
548
|
};
|
|
451
549
|
var styles = `
|
|
@@ -455,19 +553,58 @@ var styles = `
|
|
|
455
553
|
.dsh-pins-header svg{flex:none;color:var(--dsw-alias-state-business-primary)}
|
|
456
554
|
.dsh-pins-list{box-sizing:border-box;max-height:192px;min-width:0;margin:0;padding:0;overflow-y:auto;overscroll-behavior:contain;list-style:none}
|
|
457
555
|
.dsh-pins-row{box-sizing:border-box;display:flex;align-items:center;gap:0;height:32px;min-width:0;border-radius:6px;color:var(--dsw-alias-label-primary)}
|
|
458
|
-
.dsh-pins-row:hover,.dsh-pins-row[data-current="true"]{background:var(--dsw-alias-interactive-bg-hover)}
|
|
556
|
+
.dsh-pins-row:hover,.dsh-pins-row[data-current="true"],.dsh-pins-row[data-menu-open="true"]{background:var(--dsw-alias-interactive-bg-hover)}
|
|
459
557
|
.dsh-pins-open{box-sizing:border-box;display:flex;align-items:center;gap:6px;min-width:0;height:32px;padding:0 4px 0 8px;border:0;background:transparent;color:inherit;cursor:pointer;flex:1;text-align:left}
|
|
460
|
-
.dsh-pins-open:focus-visible,.dsh-pins-
|
|
558
|
+
.dsh-pins-open:focus-visible,.dsh-pins-actions:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary);outline-offset:-2px}
|
|
461
559
|
.dsh-pins-open>svg{flex:none;color:var(--dsw-alias-state-business-primary)}
|
|
462
560
|
.dsh-pins-title{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:14px;line-height:20px;flex:1}
|
|
463
561
|
.dsh-pins-workspace{max-width:34%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--dsw-alias-label-tertiary);font-size:11px;line-height:18px;flex:none}
|
|
464
|
-
.dsh-pins-
|
|
465
|
-
.dsh-pins-row:hover .dsh-pins-
|
|
466
|
-
.dsh-pins-
|
|
467
|
-
.dsh-pins-menu
|
|
468
|
-
|
|
562
|
+
.dsh-pins-actions{display:inline-flex;align-items:center;justify-content:center;width:26px;height:26px;margin-right:3px;padding:0;border:0;border-radius:6px;background:transparent;color:var(--dsw-alias-label-tertiary);cursor:pointer;opacity:0;pointer-events:none;flex:none}
|
|
563
|
+
.dsh-pins-row:hover .dsh-pins-actions,.dsh-pins-row:focus-within .dsh-pins-actions,.dsh-pins-row[data-menu-open="true"] .dsh-pins-actions{opacity:1;pointer-events:auto}
|
|
564
|
+
.dsh-pins-actions:hover,.dsh-pins-row[data-menu-open="true"] .dsh-pins-actions{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}
|
|
565
|
+
.dsh-pins-action-menu{display:inline-flex;flex:none}
|
|
566
|
+
.dsh-pins-rename-input{box-sizing:border-box;width:100%;height:36px;padding:0 11px;border:1px solid var(--dsw-alias-border-l2);border-radius:8px;outline:0;background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-primary);font:inherit}
|
|
567
|
+
.dsh-pins-rename-input:focus{border-color:var(--dsw-alias-state-business-primary)}
|
|
568
|
+
.dsh-pins-dialog-error{margin-top:8px;color:var(--dsw-alias-state-error-primary);font-size:12px;line-height:18px}
|
|
569
|
+
.dsh-pins-dialog-status{color:var(--dsw-alias-label-secondary);font-size:12px;line-height:18px}
|
|
570
|
+
.dsh-pins-delete-action{color:var(--dsw-alias-state-error-primary)!important;border-color:var(--dsw-alias-state-error-primary)!important}
|
|
571
|
+
@media (max-width:767px){.dsh-pins-workspace{display:none}}
|
|
572
|
+
@media (hover:none),(max-width:767px){.dsh-pins-actions{opacity:1;pointer-events:auto}}
|
|
469
573
|
`;
|
|
470
|
-
var inject = ["slots", "sessions", "locale"];
|
|
574
|
+
var inject = ["slots", "sessions", "workspaces", "locale"];
|
|
575
|
+
function deleteSessionService(ctx) {
|
|
576
|
+
try {
|
|
577
|
+
const service = ctx.get("remote.workspaceRegistry");
|
|
578
|
+
return typeof service?.deleteSession === "function" ? service : null;
|
|
579
|
+
} catch {
|
|
580
|
+
return null;
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
function makePinnedSessionActions(ctx, deleteAvailability) {
|
|
584
|
+
const workspaces = ctx.get("workspaces");
|
|
585
|
+
return {
|
|
586
|
+
renameSession: async (sessionId, title) => {
|
|
587
|
+
const session = ctx.sessions.binding(sessionId)?.session;
|
|
588
|
+
if (session === void 0) throw new Error(`unknown session "${sessionId}"`);
|
|
589
|
+
const result = await session.rename(title);
|
|
590
|
+
if (!result.ok) throw new Error(result.error?.message ?? "Session rename failed");
|
|
591
|
+
},
|
|
592
|
+
forkSession: async (sessionId) => {
|
|
593
|
+
const childId = await ctx.sessions.fork({ sessionId, increaseTitle: true });
|
|
594
|
+
ctx.sessions.open(childId);
|
|
595
|
+
},
|
|
596
|
+
archiveSession: async (sessionId) => {
|
|
597
|
+
await workspaces.archiveSession(sessionId);
|
|
598
|
+
},
|
|
599
|
+
deleteAvailability,
|
|
600
|
+
deleteSession: async (sessionId) => {
|
|
601
|
+
const service = deleteSessionService(ctx);
|
|
602
|
+
if (service === null) throw new Error("Session deletion is unavailable");
|
|
603
|
+
const result = await service.deleteSession(sessionId);
|
|
604
|
+
if (!result.ok) throw new Error(result.error?.message ?? "Session deletion failed");
|
|
605
|
+
}
|
|
606
|
+
};
|
|
607
|
+
}
|
|
471
608
|
function apply(ctx) {
|
|
472
609
|
let storage;
|
|
473
610
|
try {
|
|
@@ -476,6 +613,53 @@ function apply(ctx) {
|
|
|
476
613
|
storage = void 0;
|
|
477
614
|
}
|
|
478
615
|
const store = new PinStore(storage);
|
|
616
|
+
const deleteAvailability = new BooleanStore();
|
|
617
|
+
const actions = makePinnedSessionActions(ctx, deleteAvailability);
|
|
618
|
+
const modernMenus = new BooleanStore();
|
|
619
|
+
let openSession = (sessionId) => {
|
|
620
|
+
ctx.sessions.open(sessionId);
|
|
621
|
+
};
|
|
622
|
+
const navigationActions = {
|
|
623
|
+
...actions,
|
|
624
|
+
openSession: (id) => {
|
|
625
|
+
openSession(id);
|
|
626
|
+
},
|
|
627
|
+
forkSession: async (id) => {
|
|
628
|
+
openSession(await ctx.sessions.fork({ sessionId: id, increaseTitle: true }));
|
|
629
|
+
}
|
|
630
|
+
};
|
|
631
|
+
ctx.inject(["uiWorkspace"], (navigation) => {
|
|
632
|
+
const service = navigation.get("uiWorkspace");
|
|
633
|
+
openSession = (id) => {
|
|
634
|
+
service.openSession(id);
|
|
635
|
+
};
|
|
636
|
+
navigation.effect(() => () => {
|
|
637
|
+
openSession = (id) => {
|
|
638
|
+
ctx.sessions.open(id);
|
|
639
|
+
};
|
|
640
|
+
});
|
|
641
|
+
});
|
|
642
|
+
ctx.slots.inject("sidebar.workspaces.session.menu.item", () => {
|
|
643
|
+
modernMenus.set(true);
|
|
644
|
+
const dispose = ctx.slots.register({
|
|
645
|
+
name: "sidebar.workspaces.session.menu.item",
|
|
646
|
+
id: "pinned-sessions",
|
|
647
|
+
order: 90,
|
|
648
|
+
locale: NS,
|
|
649
|
+
inject: () => ({ store })
|
|
650
|
+
}, PinTopSectionMenuItem);
|
|
651
|
+
return () => {
|
|
652
|
+
dispose();
|
|
653
|
+
modernMenus.set(false);
|
|
654
|
+
};
|
|
655
|
+
});
|
|
656
|
+
ctx.inject(["remote.workspaceRegistry"], (serviceCtx) => {
|
|
657
|
+
const available = deleteSessionService(serviceCtx) !== null;
|
|
658
|
+
deleteAvailability.set(available);
|
|
659
|
+
serviceCtx.effect(() => () => {
|
|
660
|
+
deleteAvailability.set(false);
|
|
661
|
+
}, "pinned-sessions: delete capability");
|
|
662
|
+
});
|
|
479
663
|
ctx.effect(() => {
|
|
480
664
|
const onStorage = (event) => {
|
|
481
665
|
if (event.key === PIN_STORAGE_KEY || event.key === null) store.reload();
|
|
@@ -503,10 +687,19 @@ function apply(ctx) {
|
|
|
503
687
|
id: "pinned-sessions-bridge",
|
|
504
688
|
order: 40,
|
|
505
689
|
locale: NS,
|
|
506
|
-
inject: () => ({ store, sessions: ctx.sessions })
|
|
690
|
+
inject: () => ({ store, sessions: ctx.sessions, actions: navigationActions, modernMenus })
|
|
507
691
|
}, PinnedSessionsBridge));
|
|
508
692
|
}
|
|
509
|
-
function
|
|
693
|
+
function PinTopSectionMenuItem({ sessionId, store, useMenuOpenState, t }) {
|
|
694
|
+
(0, import_react3.useSyncExternalStore)(store.subscribe, store.getSnapshot, store.getSnapshot);
|
|
695
|
+
const [, setMenuOpen] = useMenuOpenState();
|
|
696
|
+
const pinned = store.isPinned(sessionId);
|
|
697
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.MenuItemButton, { icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(PinIcon, {}), onSelect: () => {
|
|
698
|
+
store.toggle(sessionId);
|
|
699
|
+
setMenuOpen(false);
|
|
700
|
+
}, children: t(pinned ? "menu.unpin" : "menu.pin") });
|
|
701
|
+
}
|
|
702
|
+
function PinnedSessionsBridge({ store, sessions, actions, useSessions, useWorkspaces, t, modernMenus }) {
|
|
510
703
|
const sessionSnapshot = useSessions((snapshot) => snapshot);
|
|
511
704
|
const workspaceSnapshot = useWorkspaces((snapshot) => snapshot);
|
|
512
705
|
const pins = (0, import_react3.useSyncExternalStore)(store.subscribe, store.getSnapshot, store.getSnapshot);
|
|
@@ -514,7 +707,7 @@ function PinnedSessionsBridge({ store, sessions, useSessions, useWorkspaces, t }
|
|
|
514
707
|
const [sidebarWide, setSidebarWide] = (0, import_react3.useState)(true);
|
|
515
708
|
const pending = (0, import_react3.useRef)(null);
|
|
516
709
|
const activeMenu = (0, import_react3.useRef)(null);
|
|
517
|
-
const
|
|
710
|
+
const focusAfterRemoval = (0, import_react3.useRef)(null);
|
|
518
711
|
(0, import_react3.useLayoutEffect)(() => {
|
|
519
712
|
let active = true;
|
|
520
713
|
let queued = false;
|
|
@@ -603,6 +796,7 @@ function PinnedSessionsBridge({ store, sessions, useSessions, useWorkspaces, t }
|
|
|
603
796
|
}
|
|
604
797
|
const onClickCapture = (event) => {
|
|
605
798
|
pending.current = null;
|
|
799
|
+
if (modernMenus?.getSnapshot()) return;
|
|
606
800
|
const target = findSessionActionTarget(event.target);
|
|
607
801
|
if (target === null) return;
|
|
608
802
|
const sessionId = captureSessionId(target.row, sessions);
|
|
@@ -646,7 +840,7 @@ function PinnedSessionsBridge({ store, sessions, useSessions, useWorkspaces, t }
|
|
|
646
840
|
disposeActiveMenu();
|
|
647
841
|
removeBridgeArtifacts(document);
|
|
648
842
|
};
|
|
649
|
-
}, [sessions, store, t]);
|
|
843
|
+
}, [sessions, store, t, modernMenus]);
|
|
650
844
|
(0, import_react3.useLayoutEffect)(() => {
|
|
651
845
|
if (sidebarHost === null) return;
|
|
652
846
|
const root = sidebarHost.parentElement;
|
|
@@ -684,22 +878,30 @@ function PinnedSessionsBridge({ store, sessions, useSessions, useWorkspaces, t }
|
|
|
684
878
|
});
|
|
685
879
|
}, [pins, sessionSnapshot.byId, t, workspaceSnapshot.items]);
|
|
686
880
|
(0, import_react3.useLayoutEffect)(() => {
|
|
687
|
-
const
|
|
688
|
-
if (
|
|
689
|
-
|
|
690
|
-
focusAfterPinnedRemoval(document, sidebarHost,
|
|
881
|
+
const pendingRemoval = focusAfterRemoval.current;
|
|
882
|
+
if (pendingRemoval === null || rows.some((row) => row.session.id === pendingRemoval.sessionId)) return;
|
|
883
|
+
focusAfterRemoval.current = null;
|
|
884
|
+
focusAfterPinnedRemoval(document, sidebarHost, pendingRemoval.index);
|
|
691
885
|
}, [rows, sidebarHost]);
|
|
692
886
|
return sidebarHost !== null && sidebarHost.isConnected && sidebarWide && rows.length > 0 ? (0, import_react_dom.createPortal)(
|
|
693
887
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
694
888
|
PinnedSessionSection,
|
|
695
889
|
{
|
|
890
|
+
actions,
|
|
891
|
+
cancelRemoval: (sessionId) => {
|
|
892
|
+
if (focusAfterRemoval.current?.sessionId === sessionId) focusAfterRemoval.current = null;
|
|
893
|
+
},
|
|
696
894
|
currentId: sessionSnapshot.current,
|
|
697
895
|
rows,
|
|
698
896
|
open: (sessionId) => {
|
|
699
|
-
|
|
897
|
+
if (actions.openSession) actions.openSession(sessionId);
|
|
898
|
+
else sessions.open(sessionId);
|
|
899
|
+
},
|
|
900
|
+
prepareRemoval: (sessionId, index) => {
|
|
901
|
+
focusAfterRemoval.current = { sessionId, index };
|
|
700
902
|
},
|
|
701
903
|
unpin: (sessionId, index) => {
|
|
702
|
-
|
|
904
|
+
focusAfterRemoval.current = { sessionId, index };
|
|
703
905
|
store.toggle(sessionId);
|
|
704
906
|
},
|
|
705
907
|
t
|
|
@@ -708,24 +910,213 @@ function PinnedSessionsBridge({ store, sessions, useSessions, useWorkspaces, t }
|
|
|
708
910
|
sidebarHost
|
|
709
911
|
) : null;
|
|
710
912
|
}
|
|
711
|
-
function PinnedSessionSection({ currentId, rows, open, unpin, t }) {
|
|
913
|
+
function PinnedSessionSection({ actions, cancelRemoval, currentId, rows, open, prepareRemoval, unpin, t }) {
|
|
712
914
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { className: "dsh-pins-section", "aria-label": t("section.label"), children: [
|
|
713
915
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "dsh-pins-header", children: [
|
|
714
916
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(PinIcon, { size: 13 }),
|
|
715
917
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: t("section.label") })
|
|
716
918
|
] }),
|
|
717
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("ul", { className: "dsh-pins-list", children: rows.map(({ session, title, workspace }, index) => /* @__PURE__ */ (0, import_jsx_runtime.
|
|
919
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("ul", { className: "dsh-pins-list", children: rows.map(({ session, title, workspace }, index) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
920
|
+
PinnedSessionRow,
|
|
921
|
+
{
|
|
922
|
+
actions,
|
|
923
|
+
cancelRemoval,
|
|
924
|
+
current: session.id === currentId,
|
|
925
|
+
index,
|
|
926
|
+
open,
|
|
927
|
+
prepareRemoval,
|
|
928
|
+
session,
|
|
929
|
+
t,
|
|
930
|
+
title,
|
|
931
|
+
unpin,
|
|
932
|
+
workspace
|
|
933
|
+
},
|
|
934
|
+
session.id
|
|
935
|
+
)) })
|
|
936
|
+
] });
|
|
937
|
+
}
|
|
938
|
+
function PinnedSessionRow({ actions, cancelRemoval, current, index, open, prepareRemoval, session, t, title, unpin, workspace }) {
|
|
939
|
+
const [menuOpen, setMenuOpen] = (0, import_react3.useState)(false);
|
|
940
|
+
const [renameOpen, setRenameOpen] = (0, import_react3.useState)(false);
|
|
941
|
+
const [renameDraft, setRenameDraft] = (0, import_react3.useState)("");
|
|
942
|
+
const [renaming, setRenaming] = (0, import_react3.useState)(false);
|
|
943
|
+
const [renameError, setRenameError] = (0, import_react3.useState)(null);
|
|
944
|
+
const [deleteOpen, setDeleteOpen] = (0, import_react3.useState)(false);
|
|
945
|
+
const [deleting, setDeleting] = (0, import_react3.useState)(false);
|
|
946
|
+
const [deleteError, setDeleteError] = (0, import_react3.useState)(null);
|
|
947
|
+
const [actionToast, setActionToast] = (0, import_react3.useState)(null);
|
|
948
|
+
const toastSeq = (0, import_react3.useRef)(0);
|
|
949
|
+
const composing = (0, import_react3.useRef)(false);
|
|
950
|
+
const trigger = (0, import_react3.useRef)(null);
|
|
951
|
+
const menusBeforeOpen = (0, import_react3.useRef)(/* @__PURE__ */ new Set());
|
|
952
|
+
const focusMenuEdge = (0, import_react3.useRef)(null);
|
|
953
|
+
const actionLabel = t("session.actions", { name: title });
|
|
954
|
+
const renameTrimmed = renameDraft.trim();
|
|
955
|
+
const renameBlocked = renaming || renameTrimmed === "";
|
|
956
|
+
const canDelete = (0, import_react3.useSyncExternalStore)(
|
|
957
|
+
actions.deleteAvailability.subscribe,
|
|
958
|
+
actions.deleteAvailability.getSnapshot,
|
|
959
|
+
actions.deleteAvailability.getSnapshot
|
|
960
|
+
);
|
|
961
|
+
const showDesktopActionError = (key, reason) => {
|
|
962
|
+
if (!canDelete) return;
|
|
963
|
+
toastSeq.current += 1;
|
|
964
|
+
setActionToast({
|
|
965
|
+
text: t(key, { detail: reason instanceof Error ? reason.message : String(reason) }),
|
|
966
|
+
seq: toastSeq.current
|
|
967
|
+
});
|
|
968
|
+
};
|
|
969
|
+
const restoreTriggerFocus = () => {
|
|
970
|
+
queueMicrotask(() => {
|
|
971
|
+
trigger.current?.focus({ preventScroll: true });
|
|
972
|
+
});
|
|
973
|
+
};
|
|
974
|
+
const openActionMenu = (focusEdge) => {
|
|
975
|
+
menusBeforeOpen.current = new Set(document.querySelectorAll('[role="menu"]'));
|
|
976
|
+
focusMenuEdge.current = focusEdge;
|
|
977
|
+
setMenuOpen(true);
|
|
978
|
+
};
|
|
979
|
+
(0, import_react3.useLayoutEffect)(() => {
|
|
980
|
+
if (!menuOpen) return;
|
|
981
|
+
let menu;
|
|
982
|
+
let observer;
|
|
983
|
+
let disposed = false;
|
|
984
|
+
const items = () => menu === void 0 ? [] : [...menu.querySelectorAll('[role="menuitem"]:not(:disabled)')];
|
|
985
|
+
const onMenuKeyDown = (event) => {
|
|
986
|
+
if (!["ArrowDown", "ArrowUp", "Home", "End"].includes(event.key)) return;
|
|
987
|
+
const available = items();
|
|
988
|
+
if (available.length === 0) return;
|
|
989
|
+
const currentIndex = available.indexOf(document.activeElement);
|
|
990
|
+
let nextIndex;
|
|
991
|
+
if (event.key === "Home") nextIndex = 0;
|
|
992
|
+
else if (event.key === "End") nextIndex = available.length - 1;
|
|
993
|
+
else if (event.key === "ArrowDown") nextIndex = currentIndex < 0 ? 0 : (currentIndex + 1) % available.length;
|
|
994
|
+
else nextIndex = currentIndex <= 0 ? available.length - 1 : currentIndex - 1;
|
|
995
|
+
event.preventDefault();
|
|
996
|
+
available[nextIndex]?.focus({ preventScroll: true });
|
|
997
|
+
};
|
|
998
|
+
const onDocumentKeyDown = (event) => {
|
|
999
|
+
if (event.key === "Escape") restoreTriggerFocus();
|
|
1000
|
+
};
|
|
1001
|
+
const install = () => {
|
|
1002
|
+
if (disposed) return;
|
|
1003
|
+
menu = [...document.querySelectorAll('[role="menu"]')].find((candidate) => !menusBeforeOpen.current.has(candidate));
|
|
1004
|
+
if (menu === void 0) return;
|
|
1005
|
+
observer?.disconnect();
|
|
1006
|
+
menu.addEventListener("keydown", onMenuKeyDown);
|
|
1007
|
+
const edge = focusMenuEdge.current;
|
|
1008
|
+
focusMenuEdge.current = null;
|
|
1009
|
+
if (edge === null) return;
|
|
1010
|
+
const available = items();
|
|
1011
|
+
const target = edge === "first" ? available[0] : available.at(-1);
|
|
1012
|
+
queueMicrotask(() => {
|
|
1013
|
+
if (!disposed && target?.isConnected === true) target.focus({ preventScroll: true });
|
|
1014
|
+
});
|
|
1015
|
+
};
|
|
1016
|
+
document.addEventListener("keydown", onDocumentKeyDown, true);
|
|
1017
|
+
install();
|
|
1018
|
+
if (menu === void 0) {
|
|
1019
|
+
observer = new MutationObserver(install);
|
|
1020
|
+
observer.observe(document.body, { childList: true, subtree: true });
|
|
1021
|
+
install();
|
|
1022
|
+
}
|
|
1023
|
+
return () => {
|
|
1024
|
+
disposed = true;
|
|
1025
|
+
observer?.disconnect();
|
|
1026
|
+
menu?.removeEventListener("keydown", onMenuKeyDown);
|
|
1027
|
+
document.removeEventListener("keydown", onDocumentKeyDown, true);
|
|
1028
|
+
};
|
|
1029
|
+
}, [menuOpen]);
|
|
1030
|
+
const menuItems = [
|
|
1031
|
+
{ id: "rename", label: t("menu.rename"), icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Pencil, { size: 16 }) },
|
|
1032
|
+
{ id: "fork", label: t("menu.fork"), icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(GitBranch, { size: 16 }) },
|
|
1033
|
+
{ id: "unpin", label: t("menu.unpin"), icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(PinOff, { size: 16, strokeWidth: 1.8, "aria-hidden": "true" }) },
|
|
1034
|
+
{ id: "archive", label: t("menu.archive"), icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Archive, { size: 16 }) },
|
|
1035
|
+
...canDelete ? [{ id: "delete", label: t("menu.delete"), icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Trash2, { size: 16 }), danger: true }] : []
|
|
1036
|
+
];
|
|
1037
|
+
const closeRename = () => {
|
|
1038
|
+
if (renaming) return;
|
|
1039
|
+
setRenameOpen(false);
|
|
1040
|
+
setRenameError(null);
|
|
1041
|
+
restoreTriggerFocus();
|
|
1042
|
+
};
|
|
1043
|
+
const confirmRename = () => {
|
|
1044
|
+
if (renameBlocked) return;
|
|
1045
|
+
setRenaming(true);
|
|
1046
|
+
setRenameError(null);
|
|
1047
|
+
void actions.renameSession(session.id, renameTrimmed).then(() => {
|
|
1048
|
+
setRenaming(false);
|
|
1049
|
+
setRenameOpen(false);
|
|
1050
|
+
restoreTriggerFocus();
|
|
1051
|
+
}).catch((reason) => {
|
|
1052
|
+
setRenaming(false);
|
|
1053
|
+
setRenameError(reason instanceof Error ? reason.message : String(reason));
|
|
1054
|
+
});
|
|
1055
|
+
};
|
|
1056
|
+
const closeDelete = () => {
|
|
1057
|
+
if (deleting) return;
|
|
1058
|
+
setDeleteOpen(false);
|
|
1059
|
+
setDeleteError(null);
|
|
1060
|
+
restoreTriggerFocus();
|
|
1061
|
+
};
|
|
1062
|
+
const confirmDelete = () => {
|
|
1063
|
+
if (deleting) return;
|
|
1064
|
+
prepareRemoval(session.id, index);
|
|
1065
|
+
setDeleting(true);
|
|
1066
|
+
setDeleteError(null);
|
|
1067
|
+
void actions.deleteSession(session.id).then(() => {
|
|
1068
|
+
setDeleting(false);
|
|
1069
|
+
setDeleteOpen(false);
|
|
1070
|
+
restoreTriggerFocus();
|
|
1071
|
+
}).catch((reason) => {
|
|
1072
|
+
cancelRemoval(session.id);
|
|
1073
|
+
setDeleting(false);
|
|
1074
|
+
setDeleteError(reason instanceof Error ? reason.message : String(reason));
|
|
1075
|
+
});
|
|
1076
|
+
};
|
|
1077
|
+
const onSelect = (id) => {
|
|
1078
|
+
setMenuOpen(false);
|
|
1079
|
+
if (id === "rename") {
|
|
1080
|
+
setRenameDraft(session.title ?? title);
|
|
1081
|
+
setRenameError(null);
|
|
1082
|
+
setRenameOpen(true);
|
|
1083
|
+
}
|
|
1084
|
+
if (id === "fork") {
|
|
1085
|
+
restoreTriggerFocus();
|
|
1086
|
+
void actions.forkSession(session.id).catch((reason) => {
|
|
1087
|
+
showDesktopActionError("session.forkFailed", reason);
|
|
1088
|
+
});
|
|
1089
|
+
}
|
|
1090
|
+
if (id === "unpin") unpin(session.id, index);
|
|
1091
|
+
if (id === "archive") {
|
|
1092
|
+
prepareRemoval(session.id, index);
|
|
1093
|
+
restoreTriggerFocus();
|
|
1094
|
+
void actions.archiveSession(session.id).catch((reason) => {
|
|
1095
|
+
cancelRemoval(session.id);
|
|
1096
|
+
restoreTriggerFocus();
|
|
1097
|
+
showDesktopActionError("session.archiveFailed", reason);
|
|
1098
|
+
if (!canDelete) console.warn("session archive rejected:", reason);
|
|
1099
|
+
});
|
|
1100
|
+
}
|
|
1101
|
+
if (id === "delete" && canDelete) {
|
|
1102
|
+
setDeleteError(null);
|
|
1103
|
+
setDeleteOpen(true);
|
|
1104
|
+
}
|
|
1105
|
+
};
|
|
1106
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
1107
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
718
1108
|
"li",
|
|
719
1109
|
{
|
|
720
1110
|
className: "dsh-pins-row",
|
|
721
|
-
"data-current":
|
|
1111
|
+
"data-current": current ? "true" : "false",
|
|
1112
|
+
"data-menu-open": menuOpen ? "true" : void 0,
|
|
722
1113
|
children: [
|
|
723
1114
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
724
1115
|
"button",
|
|
725
1116
|
{
|
|
726
1117
|
type: "button",
|
|
727
1118
|
className: "dsh-pins-open",
|
|
728
|
-
"aria-current":
|
|
1119
|
+
"aria-current": current ? "page" : void 0,
|
|
729
1120
|
"aria-label": t("session.open", { name: title }),
|
|
730
1121
|
onClick: () => {
|
|
731
1122
|
open(session.id);
|
|
@@ -738,38 +1129,135 @@ function PinnedSessionSection({ currentId, rows, open, unpin, t }) {
|
|
|
738
1129
|
}
|
|
739
1130
|
),
|
|
740
1131
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
741
|
-
|
|
1132
|
+
import_dsh_client_ui_primitives.Menu,
|
|
742
1133
|
{
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
onClick: () => {
|
|
748
|
-
unpin(session.id, index);
|
|
1134
|
+
className: "dsh-pins-action-menu",
|
|
1135
|
+
open: menuOpen,
|
|
1136
|
+
onClose: () => {
|
|
1137
|
+
setMenuOpen(false);
|
|
749
1138
|
},
|
|
750
|
-
|
|
1139
|
+
items: menuItems,
|
|
1140
|
+
onSelect,
|
|
1141
|
+
portal: true,
|
|
1142
|
+
closeOnPointerLeave: true,
|
|
1143
|
+
anchor: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1144
|
+
"button",
|
|
1145
|
+
{
|
|
1146
|
+
ref: trigger,
|
|
1147
|
+
type: "button",
|
|
1148
|
+
className: "dsh-pins-actions",
|
|
1149
|
+
"aria-expanded": menuOpen,
|
|
1150
|
+
"aria-haspopup": "menu",
|
|
1151
|
+
"aria-label": actionLabel,
|
|
1152
|
+
title: actionLabel,
|
|
1153
|
+
onClick: (event) => {
|
|
1154
|
+
event.stopPropagation();
|
|
1155
|
+
if (menuOpen) setMenuOpen(false);
|
|
1156
|
+
else openActionMenu(null);
|
|
1157
|
+
},
|
|
1158
|
+
onKeyDown: (event) => {
|
|
1159
|
+
if (event.key !== "ArrowDown" && event.key !== "ArrowUp") return;
|
|
1160
|
+
event.preventDefault();
|
|
1161
|
+
openActionMenu(event.key === "ArrowDown" ? "first" : "last");
|
|
1162
|
+
},
|
|
1163
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Ellipsis, { size: 16 })
|
|
1164
|
+
}
|
|
1165
|
+
)
|
|
751
1166
|
}
|
|
752
1167
|
)
|
|
753
1168
|
]
|
|
1169
|
+
}
|
|
1170
|
+
),
|
|
1171
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1172
|
+
import_dsh_client_ui_primitives.Modal,
|
|
1173
|
+
{
|
|
1174
|
+
open: renameOpen,
|
|
1175
|
+
onClose: closeRename,
|
|
1176
|
+
closeLabel: t("dialog.close"),
|
|
1177
|
+
title: t("rename.title"),
|
|
1178
|
+
footer: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
1179
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Button, { variant: "outline", disabled: renaming, onClick: closeRename, children: t("dialog.cancel") }),
|
|
1180
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Button, { variant: "primary", disabled: renameBlocked, onClick: confirmRename, children: t("rename.confirm") })
|
|
1181
|
+
] }),
|
|
1182
|
+
children: [
|
|
1183
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1184
|
+
"input",
|
|
1185
|
+
{
|
|
1186
|
+
className: "dsh-pins-rename-input",
|
|
1187
|
+
value: renameDraft,
|
|
1188
|
+
"aria-label": t("rename.field"),
|
|
1189
|
+
autoFocus: true,
|
|
1190
|
+
disabled: renaming,
|
|
1191
|
+
onFocus: (event) => {
|
|
1192
|
+
event.currentTarget.select();
|
|
1193
|
+
},
|
|
1194
|
+
onChange: (event) => {
|
|
1195
|
+
setRenameDraft(event.currentTarget.value);
|
|
1196
|
+
setRenameError(null);
|
|
1197
|
+
},
|
|
1198
|
+
onCompositionStart: () => {
|
|
1199
|
+
composing.current = true;
|
|
1200
|
+
},
|
|
1201
|
+
onCompositionEnd: () => {
|
|
1202
|
+
composing.current = false;
|
|
1203
|
+
},
|
|
1204
|
+
onKeyDown: (event) => {
|
|
1205
|
+
if (event.key !== "Enter" || composing.current) return;
|
|
1206
|
+
event.preventDefault();
|
|
1207
|
+
confirmRename();
|
|
1208
|
+
}
|
|
1209
|
+
}
|
|
1210
|
+
),
|
|
1211
|
+
renameError !== null && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "dsh-pins-dialog-error", role: "alert", children: renameError })
|
|
1212
|
+
]
|
|
1213
|
+
}
|
|
1214
|
+
),
|
|
1215
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1216
|
+
import_dsh_client_ui_primitives.Modal,
|
|
1217
|
+
{
|
|
1218
|
+
open: deleteOpen,
|
|
1219
|
+
onClose: closeDelete,
|
|
1220
|
+
closeLabel: t("dialog.close"),
|
|
1221
|
+
title: t("delete.title"),
|
|
1222
|
+
description: t("delete.description", { name: title }),
|
|
1223
|
+
footer: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
1224
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Button, { variant: "outline", autoFocus: true, disabled: deleting, onClick: closeDelete, children: t("dialog.cancel") }),
|
|
1225
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Button, { variant: "outline", className: "dsh-pins-delete-action", disabled: deleting, onClick: confirmDelete, children: t("delete.title") })
|
|
1226
|
+
] }),
|
|
1227
|
+
children: [
|
|
1228
|
+
deleting && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "dsh-pins-dialog-status", role: "status", children: t("delete.pending") }),
|
|
1229
|
+
deleteError !== null && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "dsh-pins-dialog-error", role: "alert", children: deleteError })
|
|
1230
|
+
]
|
|
1231
|
+
}
|
|
1232
|
+
),
|
|
1233
|
+
actionToast !== null && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1234
|
+
import_dsh_client_ui_primitives.Toast,
|
|
1235
|
+
{
|
|
1236
|
+
text: actionToast.text,
|
|
1237
|
+
onDone: () => {
|
|
1238
|
+
setActionToast(null);
|
|
1239
|
+
}
|
|
754
1240
|
},
|
|
755
|
-
|
|
756
|
-
)
|
|
1241
|
+
actionToast.seq
|
|
1242
|
+
)
|
|
757
1243
|
] });
|
|
758
1244
|
}
|
|
759
1245
|
function PinIcon({ size = 16 }) {
|
|
760
1246
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Pin, { size, strokeWidth: 1.8, "aria-hidden": "true" });
|
|
761
1247
|
}
|
|
762
|
-
function CloseIcon() {
|
|
763
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(X, { size: 14, strokeWidth: 2, "aria-hidden": "true" });
|
|
764
|
-
}
|
|
765
1248
|
/*! Bundled license information:
|
|
766
1249
|
|
|
767
1250
|
lucide-react/dist/esm/shared/src/utils.js:
|
|
768
1251
|
lucide-react/dist/esm/defaultAttributes.js:
|
|
769
1252
|
lucide-react/dist/esm/Icon.js:
|
|
770
1253
|
lucide-react/dist/esm/createLucideIcon.js:
|
|
1254
|
+
lucide-react/dist/esm/icons/archive.js:
|
|
1255
|
+
lucide-react/dist/esm/icons/ellipsis.js:
|
|
1256
|
+
lucide-react/dist/esm/icons/git-branch.js:
|
|
1257
|
+
lucide-react/dist/esm/icons/pencil.js:
|
|
1258
|
+
lucide-react/dist/esm/icons/pin-off.js:
|
|
771
1259
|
lucide-react/dist/esm/icons/pin.js:
|
|
772
|
-
lucide-react/dist/esm/icons/
|
|
1260
|
+
lucide-react/dist/esm/icons/trash-2.js:
|
|
773
1261
|
lucide-react/dist/esm/lucide-react.js:
|
|
774
1262
|
(**
|
|
775
1263
|
* @license lucide-react v0.468.0 - ISC
|