dsh-flyout-sidebar 0.1.7 → 0.1.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client.js +114 -36
- package/package.json +1 -1
package/dist/client.js
CHANGED
|
@@ -62,19 +62,27 @@
|
|
|
62
62
|
* --dsw-alias-* 设计令牌,深浅主题自动跟随。
|
|
63
63
|
*/
|
|
64
64
|
const styleCss = `
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
65
|
+
/* 面板关闭时:corner 触发按钮滑回右上角(占 right 12~48px 区间),左上角
|
|
66
|
+
panel 不动,日志按钮让位留白 —— 与 better-sidebar 折叠态给右上角按钮组
|
|
67
|
+
让位(right 10→70px)的思路一致,避免两块按钮挤在一起(见下方 64px 规则)。 */
|
|
68
|
+
/* 面板打开:header 已被 AppFrame grid 推挤到面板左缘(components.tsx 追加
|
|
69
|
+
轨道),这里只需再留固定 16px 间距,日志按钮与面板保持恒定距离 —— 不能
|
|
70
|
+
再按面板宽让位一次,否则推挤 + padding 叠加,日志按钮会被推出去两倍
|
|
71
|
+
面板宽(距面板过远)。用 !important 压过宿主/其它插件的同规则。 */
|
|
72
|
+
body.dsh-flyout-sidebar-open header:has([data-slot="conversation.session.header.utilities"]) {
|
|
73
|
+
padding-right: 16px !important;
|
|
74
|
+
transition: padding-right var(--ds-transition-duration-slow, 200ms) var(--ds-ease-in-out, ease);
|
|
71
75
|
}
|
|
72
|
-
|
|
73
|
-
|
|
76
|
+
/* 面板收起:日志按钮让位到 64px(= corner 按钮 48px 左缘 + 16px 间距)。
|
|
77
|
+
声明在 open 规则之后,同特异性时保证 open 状态生效。 */
|
|
78
|
+
body:not(.dsh-flyout-sidebar-open) header:has([data-slot="conversation.session.header.utilities"]) {
|
|
79
|
+
padding-right: 64px !important;
|
|
74
80
|
transition: padding-right var(--ds-transition-duration-slow, 200ms) var(--ds-ease-in-out, ease);
|
|
75
81
|
}
|
|
82
|
+
body[data-dsh-flyout-dragging] header:has([data-slot="conversation.session.header.utilities"]) {
|
|
83
|
+
transition: none;
|
|
84
|
+
}
|
|
76
85
|
@media (prefers-reduced-motion: reduce) {
|
|
77
|
-
html #root { transition: none; }
|
|
78
86
|
header:has([data-slot="conversation.session.header.utilities"]) { transition: none; }
|
|
79
87
|
.artifacts-preview-overlay, .artifacts-panel, .artifacts-corner-btn { transition: none; }
|
|
80
88
|
}
|
|
@@ -211,11 +219,19 @@ body[data-dsh-flyout-dragging] .artifacts-preview-overlay { transition: none; }
|
|
|
211
219
|
.artifacts-corner-btn {
|
|
212
220
|
position: fixed; top: 0; right: calc(var(--dsh-sidebar-width, 0px) + 12px);
|
|
213
221
|
z-index: 10000; width: 36px; height: 28px; padding: 0;
|
|
214
|
-
border: none; background: transparent;
|
|
222
|
+
border: none; background: transparent;
|
|
223
|
+
/* 颜色带多级回退:某些宿主的 --dsw-alias-* 令牌缺失时兜底到常规文字色,
|
|
224
|
+
保证触发图标始终可见(曾被误报为“图标不显示”)。 */
|
|
225
|
+
color: var(--dsw-alias-label-secondary, var(--dsw-alias-label-tertiary, var(--ds-text-2, #555)));
|
|
215
226
|
cursor: pointer; align-items: center; justify-content: center; display: inline-flex;
|
|
216
227
|
transition: transform var(--ds-transition-duration-slow, 200ms) var(--ds-ease-in-out, ease),
|
|
217
228
|
right var(--ds-transition-duration-slow, 200ms) var(--ds-ease-in-out, ease), color .15s;
|
|
218
229
|
}
|
|
230
|
+
/* better-sidebar 折叠时其右上角折叠按钮组占 right 10→70px;触发按钮避开它,
|
|
231
|
+
否则两者重叠抢点击(坐标约定见 better-sidebar layout.css 的 78px 注释)。 */
|
|
232
|
+
body[data-dsh-sidebar-collapsed] .artifacts-corner-btn {
|
|
233
|
+
right: 78px;
|
|
234
|
+
}
|
|
219
235
|
/* 面板打开时随面板一起滑出屏右缘(推拉动画的另一半) */
|
|
220
236
|
.artifacts-corner-btn.artifacts-slid-out {
|
|
221
237
|
transform: translateX(calc(100% + 24px));
|
|
@@ -378,15 +394,17 @@ body[data-ds-dark-theme] .tok-property { color: #ced4da; }
|
|
|
378
394
|
}
|
|
379
395
|
.fs-settings-toggle[data-on="true"]::after { transform: translateX(18px); }
|
|
380
396
|
`;
|
|
381
|
-
/**
|
|
397
|
+
/** 注入样式(幂等:内容不一致时替换,使热重载后新样式必然生效) */
|
|
382
398
|
function insertStyles() {
|
|
383
399
|
if (typeof document === "undefined") return;
|
|
384
400
|
const id = "dsh-flyout-sidebar-styles";
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
401
|
+
let el = document.getElementById(id);
|
|
402
|
+
if (!el) {
|
|
403
|
+
el = document.createElement("style");
|
|
404
|
+
el.id = id;
|
|
405
|
+
document.head.appendChild(el);
|
|
406
|
+
}
|
|
407
|
+
if (el.textContent !== styleCss) el.textContent = styleCss;
|
|
390
408
|
}
|
|
391
409
|
//#endregion
|
|
392
410
|
//#region src/shared/ext.js
|
|
@@ -859,21 +877,26 @@ body[data-ds-dark-theme] .tok-property { color: #ced4da; }
|
|
|
859
877
|
/**
|
|
860
878
|
* 从宿主拉取插件配置(config 已由 cordis 校验填充默认值)并通知订阅者。
|
|
861
879
|
* 配置保存在宿主侧,页面内不持久化;面板打开即用最新值。
|
|
880
|
+
*
|
|
881
|
+
* syncDefaultOpen=true(启动首次加载、settings scope 配置变更回调)时,
|
|
882
|
+
* 若本次拉取确实改动了 defaultOpen 字段,则实时同步边栏开合 —— 用户在
|
|
883
|
+
* 设置卡片切换「默认展开」开关后边栏立即跟随展开/收起。面板摊开时例行
|
|
884
|
+
* 拉取(刷新 minPanelWidth 等设置)不传此 flag:只刷新配置,绝不回写
|
|
885
|
+
* 开合状态,否则刚点开的边栏会被 defaultOpen 当场压回(点击无反应)。
|
|
862
886
|
*/
|
|
863
|
-
load() {
|
|
887
|
+
load(opts) {
|
|
888
|
+
const syncDefaultOpen = !!(opts && opts.syncDefaultOpen);
|
|
864
889
|
fetch("/flyout-sidebar/config").then((res) => res.ok ? res.json() : Promise.reject(/* @__PURE__ */ new Error("HTTP " + res.status))).then((out) => {
|
|
865
890
|
const next = {
|
|
866
891
|
...this.data,
|
|
867
892
|
...out.config || {}
|
|
868
893
|
};
|
|
894
|
+
const defaultOpenChanged = typeof next.defaultOpen === "boolean" && next.defaultOpen !== this.data.defaultOpen;
|
|
869
895
|
this.data = next;
|
|
870
896
|
for (const fn of this.listeners) try {
|
|
871
897
|
fn(next);
|
|
872
898
|
} catch {}
|
|
873
|
-
if (
|
|
874
|
-
store.open = next.defaultOpen;
|
|
875
|
-
setSlide({ slidOut: !next.defaultOpen });
|
|
876
|
-
}
|
|
899
|
+
if (syncDefaultOpen && defaultOpenChanged && next.defaultOpen !== store.open) store.setOpen(next.defaultOpen);
|
|
877
900
|
}).catch(() => {});
|
|
878
901
|
},
|
|
879
902
|
subscribe(fn) {
|
|
@@ -2415,6 +2438,20 @@ body[data-ds-dark-theme] .tok-property { color: #ced4da; }
|
|
|
2415
2438
|
});
|
|
2416
2439
|
return /* @__PURE__ */ h(Fragment, null, rows);
|
|
2417
2440
|
}
|
|
2441
|
+
/** 定位 DSH AppFrame:CSS Grid 容器,内联 style 设 gridTemplateColumns,
|
|
2442
|
+
* 第一列即左侧栏宽(折叠时为 0px)。 */
|
|
2443
|
+
function findAppFrame() {
|
|
2444
|
+
const nodes = document.querySelectorAll("#root *");
|
|
2445
|
+
for (let i = 0; i < nodes.length; i++) {
|
|
2446
|
+
const el = nodes[i];
|
|
2447
|
+
const cols = el.style.gridTemplateColumns;
|
|
2448
|
+
if (cols) {
|
|
2449
|
+
const first = cols.split(/\s+/)[0];
|
|
2450
|
+
if (first && first.endsWith("px")) return el;
|
|
2451
|
+
}
|
|
2452
|
+
}
|
|
2453
|
+
return null;
|
|
2454
|
+
}
|
|
2418
2455
|
function ArtifactsPanel() {
|
|
2419
2456
|
const open = useOpen();
|
|
2420
2457
|
const settings = useSettings();
|
|
@@ -2620,18 +2657,6 @@ body[data-ds-dark-theme] .tok-property { color: #ced4da; }
|
|
|
2620
2657
|
}, []);
|
|
2621
2658
|
React.useEffect(() => {
|
|
2622
2659
|
const root = document.documentElement;
|
|
2623
|
-
const findAppFrame = () => {
|
|
2624
|
-
const nodes = document.querySelectorAll("#root *");
|
|
2625
|
-
for (let i = 0; i < nodes.length; i++) {
|
|
2626
|
-
const el = nodes[i];
|
|
2627
|
-
const cols = el.style.gridTemplateColumns;
|
|
2628
|
-
if (cols) {
|
|
2629
|
-
const first = cols.split(/\s+/)[0];
|
|
2630
|
-
if (first && first.endsWith("px")) return el;
|
|
2631
|
-
}
|
|
2632
|
-
}
|
|
2633
|
-
return null;
|
|
2634
|
-
};
|
|
2635
2660
|
const readAndSet = (frame) => {
|
|
2636
2661
|
if (!frame) return 0;
|
|
2637
2662
|
const cols = frame.style.gridTemplateColumns;
|
|
@@ -2685,8 +2710,58 @@ body[data-ds-dark-theme] .tok-property { color: #ced4da; }
|
|
|
2685
2710
|
React.useEffect(() => {
|
|
2686
2711
|
const root = document.documentElement;
|
|
2687
2712
|
root.style.setProperty("--dsh-flyout-sidebar-width", open ? widthPx + "px" : "0px");
|
|
2713
|
+
document.body.classList.toggle("dsh-flyout-sidebar-open", open);
|
|
2714
|
+
const push = {
|
|
2715
|
+
frame: null,
|
|
2716
|
+
suffix: null
|
|
2717
|
+
};
|
|
2718
|
+
const applyPush = (frame, w) => {
|
|
2719
|
+
if (!frame) return;
|
|
2720
|
+
push.frame = frame;
|
|
2721
|
+
let cols = frame.style.gridTemplateColumns || "";
|
|
2722
|
+
if (push.suffix && cols.endsWith(push.suffix)) cols = cols.slice(0, cols.length - push.suffix.length);
|
|
2723
|
+
const next = w > 0 ? cols.trim() !== "" ? cols + " " + w + "px" : w + "px" : cols;
|
|
2724
|
+
push.suffix = w > 0 ? " " + w + "px" : null;
|
|
2725
|
+
if (frame.style.gridTemplateColumns !== next) frame.style.gridTemplateColumns = next;
|
|
2726
|
+
};
|
|
2727
|
+
const observeFrame = (frame) => {
|
|
2728
|
+
if (!frame) return null;
|
|
2729
|
+
const obs = new MutationObserver(() => {
|
|
2730
|
+
if (frame && document.contains(frame)) applyPush(frame, open ? widthPx : 0);
|
|
2731
|
+
});
|
|
2732
|
+
obs.observe(frame, {
|
|
2733
|
+
attributes: true,
|
|
2734
|
+
attributeFilter: ["style"]
|
|
2735
|
+
});
|
|
2736
|
+
return obs;
|
|
2737
|
+
};
|
|
2738
|
+
let frame = findAppFrame();
|
|
2739
|
+
applyPush(frame, open ? widthPx : 0);
|
|
2740
|
+
let styleObs = observeFrame(frame);
|
|
2741
|
+
let subtreeObs = null;
|
|
2742
|
+
if (typeof MutationObserver === "function") {
|
|
2743
|
+
subtreeObs = new MutationObserver(() => {
|
|
2744
|
+
if (!frame || !document.contains(frame)) {
|
|
2745
|
+
styleObs?.disconnect();
|
|
2746
|
+
frame = findAppFrame();
|
|
2747
|
+
if (frame) {
|
|
2748
|
+
applyPush(frame, open ? widthPx : 0);
|
|
2749
|
+
styleObs = observeFrame(frame);
|
|
2750
|
+
}
|
|
2751
|
+
}
|
|
2752
|
+
});
|
|
2753
|
+
subtreeObs.observe(document.body, {
|
|
2754
|
+
childList: true,
|
|
2755
|
+
subtree: true,
|
|
2756
|
+
attributes: false
|
|
2757
|
+
});
|
|
2758
|
+
}
|
|
2688
2759
|
return () => {
|
|
2760
|
+
styleObs?.disconnect();
|
|
2761
|
+
subtreeObs?.disconnect();
|
|
2762
|
+
applyPush(push.frame, 0);
|
|
2689
2763
|
root.style.setProperty("--dsh-flyout-sidebar-width", "0px");
|
|
2764
|
+
document.body.classList.remove("dsh-flyout-sidebar-open");
|
|
2690
2765
|
};
|
|
2691
2766
|
}, [open, widthPx]);
|
|
2692
2767
|
React.useEffect(() => {
|
|
@@ -2738,16 +2813,19 @@ body[data-ds-dark-theme] .tok-property { color: #ced4da; }
|
|
|
2738
2813
|
(ctx.reflect?.inject("layout"))?.toggleSidebar?.();
|
|
2739
2814
|
} catch {}
|
|
2740
2815
|
};
|
|
2816
|
+
const startX = e.clientX;
|
|
2741
2817
|
let lastMouseX = e.clientX;
|
|
2742
2818
|
let rafId = null;
|
|
2743
2819
|
let collapseTriggered = false;
|
|
2820
|
+
let draggedLeft = false;
|
|
2744
2821
|
const tick = () => {
|
|
2745
2822
|
rafId = requestAnimationFrame(tick);
|
|
2746
2823
|
const cursorW = window.innerWidth - lastMouseX - rightOffset;
|
|
2747
2824
|
const sidebarW = getSidebarWidth();
|
|
2748
2825
|
const maxW = window.innerWidth - sidebarW - rightOffset;
|
|
2749
2826
|
const w = Math.min(cursorW, maxW);
|
|
2750
|
-
if (
|
|
2827
|
+
if (lastMouseX < startX - 8) draggedLeft = true;
|
|
2828
|
+
if (!collapseTriggered && sidebarW > 0 && draggedLeft && cursorW >= maxW - 2) {
|
|
2751
2829
|
collapseTriggered = true;
|
|
2752
2830
|
triggerSidebarCollapse();
|
|
2753
2831
|
}
|
|
@@ -3032,7 +3110,7 @@ body[data-ds-dark-theme] .tok-property { color: #ced4da; }
|
|
|
3032
3110
|
order: 50,
|
|
3033
3111
|
label: "Artifacts Panel"
|
|
3034
3112
|
}, () => /* @__PURE__ */ h(ArtifactsPanel, null)));
|
|
3035
|
-
settingsStore.load();
|
|
3113
|
+
settingsStore.load({ syncDefaultOpen: true });
|
|
3036
3114
|
ctx.inject(["settingsScope"], (sctx) => {
|
|
3037
3115
|
const binder = sctx.get("settingsScope");
|
|
3038
3116
|
if (!binder) return;
|
|
@@ -3050,7 +3128,7 @@ body[data-ds-dark-theme] .tok-property { color: #ced4da; }
|
|
|
3050
3128
|
};
|
|
3051
3129
|
sctx.effect(() => scope.subscribe(() => {
|
|
3052
3130
|
publishLocal(scope.getSnapshot());
|
|
3053
|
-
settingsStore.load();
|
|
3131
|
+
settingsStore.load({ syncDefaultOpen: true });
|
|
3054
3132
|
}), "flyout: settings scope");
|
|
3055
3133
|
const useSettingsSnapshot = (selector) => React.useSyncExternalStore((cb) => {
|
|
3056
3134
|
localListeners.add(cb);
|