@linxin666/dsh-pet 0.2.0 → 0.2.1
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/README.i18n.yaml +2 -2
- package/README.md +3 -3
- package/README.zh.md +3 -3
- package/lib/client.js +253 -49
- package/lib/client.js.map +1 -1
- package/lib/index.js +235 -83
- package/lib/invariant.js +1 -1
- package/lib/{state-Ch3f4luZ.js → state-DrMX22GL.js} +35 -5
- package/lib/types/chatter.d.ts.map +1 -1
- package/lib/types/chatter.js +167 -77
- package/lib/types/client/PetDockEntry.d.ts.map +1 -1
- package/lib/types/client/PetDockEntry.js +1 -1
- package/lib/types/client/PetSprite.d.ts.map +1 -1
- package/lib/types/client/PetSprite.js +51 -8
- package/lib/types/client/PluginSettingsCard.d.ts +22 -0
- package/lib/types/client/PluginSettingsCard.d.ts.map +1 -1
- package/lib/types/client/PluginSettingsCard.js +142 -3
- package/lib/types/client/index.d.ts.map +1 -1
- package/lib/types/client/index.js +1 -0
- package/lib/types/client/locales.d.ts +4 -0
- package/lib/types/client/locales.d.ts.map +1 -1
- package/lib/types/client/locales.js +4 -0
- package/lib/types/loopback.d.ts +25 -0
- package/lib/types/loopback.d.ts.map +1 -0
- package/lib/types/loopback.js +68 -0
- package/lib/types/registry.d.ts.map +1 -1
- package/lib/types/registry.js +11 -3
- package/lib/types/remarks.d.ts.map +1 -1
- package/lib/types/remarks.js +30 -0
- package/lib/types/routes.d.ts.map +1 -1
- package/lib/types/routes.js +14 -0
- package/package.json +1 -1
- package/src/chatter.ts +167 -77
- package/src/client/PetDockEntry.test.tsx +93 -0
- package/src/client/PetDockEntry.tsx +1 -0
- package/src/client/PetSprite.test.tsx +72 -11
- package/src/client/PetSprite.tsx +95 -27
- package/src/client/PluginSettingsCard.tsx +219 -18
- package/src/client/index.test.tsx +95 -0
- package/src/client/index.ts +1 -0
- package/src/client/locales.ts +4 -0
- package/src/client/pet-css.test.ts +15 -3
- package/src/client/pet.module.css +101 -71
- package/src/client/settings-card.module.css +90 -1
- package/src/loopback.ts +63 -0
- package/src/registry.test.ts +29 -1
- package/src/registry.ts +11 -3
- package/src/remarks.ts +30 -0
- package/src/routes.ts +11 -0
package/README.i18n.yaml
CHANGED
|
@@ -2,5 +2,5 @@
|
|
|
2
2
|
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
|
3
3
|
# after editing either side, bring the other along and re-record with:
|
|
4
4
|
# node scripts/verify-docs.mjs --write <dir>
|
|
5
|
-
README.md:
|
|
6
|
-
README.zh.md:
|
|
5
|
+
README.md: 21245dc766ce4b58319a1c7087f3dba1a6b81a9d
|
|
6
|
+
README.zh.md: 51b5c89489893197c8d691b843161a5334b2d8fd
|
package/README.md
CHANGED
|
@@ -23,8 +23,8 @@ Re-implemented from the pet feature of the Codex desktop app, as an official DSH
|
|
|
23
23
|
| Dragging | Hold and drag the pet to reposition; position persisted |
|
|
24
24
|
| Hide/Summon | The hover panel sits below the pet (lifted above the status bubbles when there is no room below) and provides 隐藏 (Hide); after hiding, a 召唤{name} (Summon {name}) button appears |
|
|
25
25
|
| Witty remarks | Built-in remark library (10 lines per event) plus per-pet custom lines; success lines rotate by persisted success counts and cooldown lines by persisted rejection counts |
|
|
26
|
-
| Status bubbles |
|
|
27
|
-
| Inner whispers | 碎碎念: while the model streams, the pet occasionally speaks its inner voice
|
|
26
|
+
| Status bubbles | Only the most recently active top-level session speaks by default — when several sessions run at once, the rest collapse behind a +N badge on the main bubble instead of stacking a tall column; hover the bubble (or tap the badge, for touch) to fan every session's bubble out above it and click one to jump to its session; subagent sessions report through their spawning conversation and never occupy a bubble of their own; transient interaction feedback temporarily takes priority. Bubble copy comes from generous rotating pools per scene (waiting / thinking / writing / done / failed...), tool calls map onto per-family witty lines carrying the real argument hint (e.g. 跑跑 npm test), and a long-lived scene re-phrases itself every few seconds |
|
|
27
|
+
| Inner whispers | 碎碎念: while the model streams, the pet occasionally speaks its inner voice through its own bubble — a fresh whisper takes over the display session's bubble and marks it with 「」 quotes — sharing the same DeepSeek-blue glass as every status bubble, so stacked bubbles never clash — instead of stacking a second bubble — keyword moods woken by the model output (errors, test greens, plans, victories...) plus ambient whispers earned by output volume; paced by a cooldown, the status copy returns after a few seconds |
|
|
28
28
|
| Multi-session activity | The pet is host-global: the most recent meaningful event drives the sprite animation while every active top-level session reports its own state in a separate bubble; completed turns from every session (subagents included) contribute affinity and treats |
|
|
29
29
|
|
|
30
30
|
## Pet contract
|
|
@@ -131,7 +131,7 @@ Install the family aggregate package `@linxin666/dsh-web-ui-all` (all plugins an
|
|
|
131
131
|
|
|
132
132
|
```sh
|
|
133
133
|
### From npm (recommended)
|
|
134
|
-
dsh plugin --profile web add @linxin666/dsh-pet
|
|
134
|
+
dsh plugin --profile web add @linxin666/dsh-pet@latest
|
|
135
135
|
|
|
136
136
|
### From the repository (development)
|
|
137
137
|
git clone https://github.com/zhu1090093659/dsh-web-ui.git
|
package/README.zh.md
CHANGED
|
@@ -23,8 +23,8 @@
|
|
|
23
23
|
| 拖动 | 按住拖动宠物换位置;位置持久化 |
|
|
24
24
|
| 隐藏/召唤 | 悬浮面板位于宠物下方(下方空间不足时上移到状态气泡之上)并提供 隐藏;隐藏后出现 召唤{name} 按钮 |
|
|
25
25
|
| 妙语库 | 内置默认妙语库(每类事件 10 句)+ 宠物自定义台词;成功文案按持久化成功次数轮换,冷却文案按持久化拒绝次数轮换 |
|
|
26
|
-
| 状态气泡 |
|
|
27
|
-
| 碎碎念 |
|
|
26
|
+
| 状态气泡 | 默认只有最近活动的顶层会话说话——多会话并行时,其余会话收进主气泡右上角的 +N 角标,不再叠出一长列;悬停气泡(触屏点按角标)即可向上展开所有会话的气泡,点击任一气泡跳转到对应会话;子代理会话借由其发起会话体现,不占用独立气泡;瞬时互动反馈临时优先。气泡文案按场景准备了大量轮换词库(等待 / 思考 / 整理 / 完成 / 失败……),工具调用按工具族映射俏皮文案并带上真实参数(如 跑跑 npm test),同一场景持续数秒会自动换一种说法 |
|
|
27
|
+
| 碎碎念 | 模型流式输出期间,宠物会偶尔借自己的气泡说出内心独白——新鲜的碎碎念会接管展示会话的气泡并以「」引号标记——与状态气泡共用同一片 DeepSeek 蓝黑玻璃,气泡栈内颜色统一不再色差——不再叠出第二只气泡——由模型输出里的关键词触发对应心境(报错、测试全绿、做计划、打胜仗……),输出量累积也会换来日常碎碎念;有冷却节制,数秒后气泡恢复状态文案 |
|
|
28
28
|
| 多会话活动 | 宠物是宿主全局的:最近一次有意义事件驱动精灵动画,同时每个活动的顶层会话用自己的气泡报告各自状态;每个会话(含子代理)完成的轮次都计入亲密度与小鱼干 |
|
|
29
29
|
|
|
30
30
|
## 宠物契约
|
|
@@ -131,7 +131,7 @@ dsh-pet/
|
|
|
131
131
|
|
|
132
132
|
```sh
|
|
133
133
|
### 从 npm 安装(推荐)
|
|
134
|
-
dsh plugin --profile web add @linxin666/dsh-pet
|
|
134
|
+
dsh plugin --profile web add @linxin666/dsh-pet@latest
|
|
135
135
|
|
|
136
136
|
### 从仓库安装(开发调试)
|
|
137
137
|
git clone https://github.com/zhu1090093659/dsh-web-ui.git
|
package/lib/client.js
CHANGED
|
@@ -165,7 +165,7 @@ window.__ModuleLoader__.load({
|
|
|
165
165
|
}
|
|
166
166
|
//#endregion
|
|
167
167
|
//#region \0dsh-css:packages/dsh-pet/src/client/pet.module.css.mjs
|
|
168
|
-
const css$2 = ".kz2Bea_float{pointer-events:auto;-webkit-user-select:none;user-select:none;flex-direction:column;align-items:center;display:flex;position:fixed}.kz2Bea_sprite{image-rendering:auto;touch-action:none;position:relative}.kz2Bea_bubble{white-space:nowrap;color:#
|
|
168
|
+
const css$2 = ".kz2Bea_float{pointer-events:auto;-webkit-user-select:none;user-select:none;flex-direction:column;align-items:center;display:flex;position:fixed}.kz2Bea_sprite{image-rendering:auto;touch-action:none;position:relative}.kz2Bea_bubble{white-space:nowrap;color:#f4f7ff;pointer-events:none;border-radius:999px;margin-bottom:6px;padding:4px 10px;font-size:12px;line-height:1.4;animation:2.6s ease-out forwards kz2Bea_pet-bubble-pop;position:absolute;bottom:100%;box-shadow:0 2px 8px #00000040}.kz2Bea_bubblePet{background:#4d6bfef2}.kz2Bea_bubbleFeed{background:#0369a1f2}.kz2Bea_bubbleStatus{text-overflow:ellipsis;backdrop-filter:blur(8px);letter-spacing:.02em;background:linear-gradient(160deg,#131c36e6,#070b1af0);border:1px solid #7e98ff73;max-width:min(280px,100vw - 24px);padding:5px 12px;animation:.24s ease-out kz2Bea_pet-bubble-in;overflow:hidden;box-shadow:0 4px 12px #02061759,inset 0 1px #e2e8ff1a,0 0 12px #4d6bfe2e}.kz2Bea_bubbleWhisper{letter-spacing:.03em;animation:.32s cubic-bezier(.22,1,.36,1) kz2Bea_pet-whisper-in}.kz2Bea_bubbleWhisper:before{content:\"「\";opacity:.7;margin-right:2px}.kz2Bea_bubbleWhisper:after{content:\"」\";opacity:.7;margin-left:2px}.kz2Bea_bubbleStack{pointer-events:auto;flex-direction:column-reverse;align-items:center;gap:4px;display:flex;position:absolute;bottom:100%}.kz2Bea_bubbleAnchor{display:inline-flex;position:relative}.kz2Bea_bubbleMore{z-index:1;color:#eef2ff;cursor:pointer;background:linear-gradient(160deg,#4a68f5f2,#2f44b8f2);border:1px solid #7e98ff8c;border-radius:999px;justify-content:center;align-items:center;min-width:18px;height:18px;padding:0 5px;font-size:10px;font-weight:600;line-height:1;transition:filter .12s;display:inline-flex;position:absolute;top:-9px;right:-10px;box-shadow:0 2px 6px #02061766}.kz2Bea_bubbleMore:hover{filter:brightness(1.15)}.kz2Bea_bubbleMore:focus-visible{outline:none;box-shadow:0 0 0 2px #7e98ffe6}.kz2Bea_bubbleStack .kz2Bea_bubble{pointer-events:auto;margin-bottom:0;position:relative;bottom:auto}.kz2Bea_bubbleClickable{cursor:pointer;font:inherit;text-align:center;appearance:none;transition:filter .12s,box-shadow .12s}.kz2Bea_bubbleClickable:hover{filter:brightness(1.12)}.kz2Bea_bubbleClickable:focus-visible{outline:none;box-shadow:0 0 0 2px #7e98ffe6}@keyframes kz2Bea_pet-bubble-in{0%{opacity:0;transform:translateY(6px)scale(.96)}to{opacity:1;transform:translateY(0)scale(1)}}@keyframes kz2Bea_pet-whisper-in{0%{opacity:0;transform:translateY(8px)scale(.9)}60%{transform:translateY(-1px)scale(1.02)}to{opacity:1;transform:translateY(0)scale(1)}}@keyframes kz2Bea_pet-panel-in{0%{opacity:0;transform:translateY(4px)scale(.97)}to{opacity:1;transform:translateY(0)scale(1)}}@keyframes kz2Bea_pet-bubble-pop{0%{opacity:0;transform:translateY(6px)scale(.85)}15%{opacity:1;transform:translateY(0)scale(1.05)}25%{transform:translateY(0)scale(1)}75%{opacity:1}to{opacity:0;transform:translateY(-8px)scale(.95)}}.kz2Bea_panel{color:#e6ebf8;backdrop-filter:blur(10px);transform-origin:50% 0;background:linear-gradient(165deg,#131c36f2,#070b1af7);border:1px solid #7e98ff4d;border-radius:12px;flex-direction:column;gap:7px;min-width:148px;margin-top:8px;padding:10px 12px;font-size:12px;animation:.2s cubic-bezier(.22,1,.36,1) kz2Bea_pet-panel-in;display:flex;position:absolute;top:100%;box-shadow:0 8px 24px #02061773,0 0 0 1px #4d6bfe1a,inset 0 1px #e2e8ff14}.kz2Bea_panel:after{content:\"\";height:14px;position:absolute;bottom:100%;left:0;right:0}.kz2Bea_panelAbove{transform-origin:50% 100%;margin-top:0;margin-bottom:8px;top:auto;bottom:100%}.kz2Bea_panelAbove:after{top:100%;bottom:auto}.kz2Bea_rankRow{white-space:nowrap;justify-content:space-between;gap:10px;display:flex}.kz2Bea_nameCell{letter-spacing:.02em;background:linear-gradient(90deg,#a9c1ff,#6c8bff 60%,#4d6bfe);color:#0000;-webkit-background-clip:text;background-clip:text;font-weight:600}.kz2Bea_statRank{color:#9db4ff;font-weight:600}.kz2Bea_statTreats{color:#7dd3fc;font-weight:600}.kz2Bea_statPoints{color:#fcd34d;font-weight:600}.kz2Bea_renameRow{align-items:center;gap:6px;display:flex}.kz2Bea_nameInput{color:#e6ebf8;background:#131c36e6;border:1px solid #7e98ff80;border-radius:6px;outline:none;flex:1;min-width:0;padding:3px 6px;font-size:12px}.kz2Bea_nameInput:focus{border-color:#4d6bfe;box-shadow:0 0 0 2px #4d6bfe73}.kz2Bea_actions{gap:6px;display:flex}.kz2Bea_action{cursor:pointer;color:#fff;background:linear-gradient(#4a68f5,#3a55e0);border:none;border-radius:6px;flex:1;padding:4px 8px;font-size:12px;font-weight:600;transition:filter .12s,box-shadow .12s,transform .12s;box-shadow:0 2px 6px #4d6bfe4d}.kz2Bea_action:hover{filter:brightness(1.08);transform:translateY(-1px);box-shadow:0 4px 10px #4d6bfe66}.kz2Bea_action:active{filter:brightness(.94);transform:translateY(0);box-shadow:0 1px 4px #4d6bfe4d}.kz2Bea_action:focus-visible{outline:none;box-shadow:0 0 0 2px #7e98ffe6}.kz2Bea_summon{color:#8ea6ff;cursor:pointer;background:#070b1abf;border:1px dashed #7e98ff99;border-radius:999px;padding:2px 10px;font-size:11px;transition:border-color .12s,color .12s,background .12s,box-shadow .12s}.kz2Bea_summon:hover{color:#c3d3ff;background:#070b1ae6;border-color:#7e98fff2}.kz2Bea_summon:active{color:#8ea6ff;border-color:#7e98ffcc}.kz2Bea_summon:focus-visible{outline:none;box-shadow:0 0 0 2px #7e98ffe6}@media (prefers-reduced-motion:reduce){.kz2Bea_bubble,.kz2Bea_bubbleStatus,.kz2Bea_bubbleWhisper,.kz2Bea_panel{opacity:1;animation:none}.kz2Bea_action,.kz2Bea_summon,.kz2Bea_bubbleMore{transition:none}}";
|
|
169
169
|
const tagId$2 = "@linxin666/dsh-pet/pet.module.css";
|
|
170
170
|
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$2) + "]") === null) {
|
|
171
171
|
const tag = document.createElement("style");
|
|
@@ -178,8 +178,10 @@ window.__ModuleLoader__.load({
|
|
|
178
178
|
"action": "kz2Bea_action",
|
|
179
179
|
"actions": "kz2Bea_actions",
|
|
180
180
|
"bubble": "kz2Bea_bubble",
|
|
181
|
+
"bubbleAnchor": "kz2Bea_bubbleAnchor",
|
|
181
182
|
"bubbleClickable": "kz2Bea_bubbleClickable",
|
|
182
183
|
"bubbleFeed": "kz2Bea_bubbleFeed",
|
|
184
|
+
"bubbleMore": "kz2Bea_bubbleMore",
|
|
183
185
|
"bubblePet": "kz2Bea_bubblePet",
|
|
184
186
|
"bubbleStack": "kz2Bea_bubbleStack",
|
|
185
187
|
"bubbleStatus": "kz2Bea_bubbleStatus",
|
|
@@ -231,6 +233,8 @@ window.__ModuleLoader__.load({
|
|
|
231
233
|
const bubbleRef = (0, react.useRef)(null);
|
|
232
234
|
const [imageReady, setImageReady] = (0, react.useState)(false);
|
|
233
235
|
const [hovered, setHovered] = (0, react.useState)(false);
|
|
236
|
+
const [stackPeek, setStackPeek] = (0, react.useState)(false);
|
|
237
|
+
const [stackPinned, setStackPinned] = (0, react.useState)(false);
|
|
234
238
|
const [renaming, setRenaming] = (0, react.useState)(false);
|
|
235
239
|
const [panelAbove, setPanelAbove] = (0, react.useState)(false);
|
|
236
240
|
const [panelLift, setPanelLift] = (0, react.useState)(0);
|
|
@@ -338,6 +342,7 @@ window.__ModuleLoader__.load({
|
|
|
338
342
|
hideTimerRef.current = null;
|
|
339
343
|
}
|
|
340
344
|
};
|
|
345
|
+
(0, react.useEffect)(() => () => clearHideTimer(), []);
|
|
341
346
|
const onPointerDown = (e) => {
|
|
342
347
|
e.preventDefault();
|
|
343
348
|
e.target.setPointerCapture?.(e.pointerId);
|
|
@@ -378,10 +383,15 @@ window.__ModuleLoader__.load({
|
|
|
378
383
|
const spriteWidth = Math.round(cell.width * spriteScale);
|
|
379
384
|
const spriteHeight = Math.round(cell.height * spriteScale);
|
|
380
385
|
const sessionBubbles = snapshot?.sessions ?? [];
|
|
386
|
+
const stackOpen = stackPeek || stackPinned;
|
|
387
|
+
const visibleSessions = !stackOpen && sessionBubbles.length > 1 ? sessionBubbles.slice(0, 1) : sessionBubbles;
|
|
381
388
|
const statusBubble = feedback === null && sessionBubbles.length === 0 ? snapshot?.bubble : void 0;
|
|
382
389
|
const whisper = feedback === null ? snapshot?.whisper : void 0;
|
|
383
390
|
const bubblePresent = feedback !== null || sessionBubbles.length > 0 || statusBubble !== void 0 || whisper !== void 0;
|
|
384
391
|
const displayName = snapshot?.name ?? definition.displayName;
|
|
392
|
+
(0, react.useEffect)(() => {
|
|
393
|
+
if (sessionBubbles.length <= 1) setStackPinned(false);
|
|
394
|
+
}, [sessionBubbles.length]);
|
|
385
395
|
(0, react.useLayoutEffect)(() => {
|
|
386
396
|
if (!hovered) {
|
|
387
397
|
setPanelAbove(false);
|
|
@@ -408,6 +418,7 @@ window.__ModuleLoader__.load({
|
|
|
408
418
|
display.size,
|
|
409
419
|
bubblePresent,
|
|
410
420
|
sessionBubbles.length,
|
|
421
|
+
stackOpen,
|
|
411
422
|
feedback
|
|
412
423
|
]);
|
|
413
424
|
return (0, react_dom.createPortal)(/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
@@ -460,27 +471,41 @@ window.__ModuleLoader__.load({
|
|
|
460
471
|
feedback === null && (sessionBubbles.length > 0 || statusBubble !== void 0 || whisper !== void 0) && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
461
472
|
ref: bubbleRef,
|
|
462
473
|
className: pet_module_css_default.bubbleStack,
|
|
463
|
-
|
|
464
|
-
|
|
474
|
+
onPointerEnter: () => setStackPeek(true),
|
|
475
|
+
onPointerLeave: () => setStackPeek(false),
|
|
476
|
+
children: [visibleSessions.map((session, index) => {
|
|
477
|
+
const speaksWhisper = index === 0 && whisper !== void 0;
|
|
478
|
+
const bubble = /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
465
479
|
type: "button",
|
|
466
|
-
className: clsx(pet_module_css_default.bubble, pet_module_css_default.bubbleStatus, pet_module_css_default.bubbleClickable),
|
|
480
|
+
className: clsx(pet_module_css_default.bubble, pet_module_css_default.bubbleStatus, pet_module_css_default.bubbleClickable, speaksWhisper && pet_module_css_default.bubbleWhisper),
|
|
467
481
|
title: props.t("pet.openSessionHint"),
|
|
468
482
|
onClick: () => {
|
|
469
483
|
props.onOpenSession(session.sessionId);
|
|
470
484
|
},
|
|
471
|
-
children: session.bubble
|
|
472
|
-
}, session.sessionId)
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
485
|
+
children: speaksWhisper ? whisper : session.bubble
|
|
486
|
+
}, speaksWhisper ? "whisper:" + whisper : session.sessionId);
|
|
487
|
+
if (index !== 0 || sessionBubbles.length <= 1) return bubble;
|
|
488
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
489
|
+
className: pet_module_css_default.bubbleAnchor,
|
|
490
|
+
children: [bubble, /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
491
|
+
type: "button",
|
|
492
|
+
className: pet_module_css_default.bubbleMore,
|
|
493
|
+
title: stackOpen ? props.t("pet.collapseSessions") : props.t("pet.moreSessions", { n: sessionBubbles.length - 1 }),
|
|
494
|
+
"aria-label": stackOpen ? props.t("pet.collapseSessions") : props.t("pet.moreSessions", { n: sessionBubbles.length - 1 }),
|
|
495
|
+
"aria-expanded": stackOpen,
|
|
496
|
+
onClick: (e) => {
|
|
497
|
+
e.stopPropagation();
|
|
498
|
+
setStackPinned((open) => !open);
|
|
499
|
+
},
|
|
500
|
+
children: stackOpen ? "×" : "+" + String(sessionBubbles.length - 1)
|
|
501
|
+
})]
|
|
502
|
+
}, "primary");
|
|
503
|
+
}), sessionBubbles.length === 0 && (statusBubble !== void 0 || whisper !== void 0) && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
504
|
+
className: clsx(pet_module_css_default.bubble, pet_module_css_default.bubbleStatus, whisper !== void 0 && pet_module_css_default.bubbleWhisper),
|
|
505
|
+
role: "status",
|
|
506
|
+
"aria-live": "polite",
|
|
507
|
+
children: whisper ?? statusBubble
|
|
508
|
+
}, whisper === void 0 ? "status" : "whisper:" + whisper)]
|
|
484
509
|
}),
|
|
485
510
|
hovered && dragRef.current === null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
486
511
|
ref: panelRef,
|
|
@@ -647,12 +672,13 @@ window.__ModuleLoader__.load({
|
|
|
647
672
|
},
|
|
648
673
|
onClick: props.summon,
|
|
649
674
|
"data-testid": "pet-summon",
|
|
675
|
+
"data-dsh-part": "summon-button",
|
|
650
676
|
children: props.t("pet.summon", { name: snapshot?.name ?? "" })
|
|
651
677
|
});
|
|
652
678
|
}
|
|
653
679
|
//#endregion
|
|
654
680
|
//#region \0dsh-css:packages/dsh-pet/src/client/settings-card.module.css.mjs
|
|
655
|
-
const css$1 = ".kKk9aW_card{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);border-radius:12px;list-style:none;transition:border-color .16s,background .16s}.kKk9aW_card:hover{border-color:var(--dsw-alias-label-dimmed)}.kKk9aW_cardOpen{background:var(--dsw-alias-bg-layer-2);border-color:var(--dsw-alias-label-dimmed)}.kKk9aW_header{appearance:none;width:100%;font:inherit;color:inherit;text-align:left;cursor:pointer;background:0 0;border:0;border-radius:12px;align-items:center;gap:12px;padding:14px 16px;display:flex}.kKk9aW_header:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:-2px}.kKk9aW_headerStatic{border-radius:12px;align-items:center;gap:12px;width:100%;padding:14px 16px;display:flex}.kKk9aW_headText{flex-direction:column;flex:1;gap:4px;min-width:0;display:flex}.kKk9aW_name{color:var(--dsw-alias-label-primary);font-size:15px;font-weight:600;line-height:1.4}.kKk9aW_description{color:var(--dsw-alias-label-tertiary);font-size:13px;line-height:1.5}.kKk9aW_pending{white-space:nowrap;background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-secondary);border-radius:999px;flex:none;padding:1px 8px;font-size:11px;font-weight:500;line-height:17px}.kKk9aW_chevron{color:var(--dsw-alias-label-tertiary);flex:none;transition:transform .16s}.kKk9aW_chevronOpen{transform:rotate(180deg)}.kKk9aW_body{border-top:1px solid var(--dsw-alias-border-l2);margin:0 16px;padding-bottom:8px}.kKk9aW_readOnly{color:var(--dsw-alias-label-tertiary);margin:12px 0 0;font-size:12px;line-height:1.5}.kKk9aW_notExposed{color:var(--dsw-alias-state-warn-primary);margin:12px 0 0;font-size:12px;line-height:1.5}.kKk9aW_footer{border-top:1px solid var(--dsw-alias-border-l2);justify-content:flex-end;align-items:center;gap:8px;padding:12px 0 4px;display:flex}.kKk9aW_failed{min-width:0;color:var(--dsw-alias-label-error);text-overflow:ellipsis;white-space:nowrap;flex:1;margin:0;font-size:12px;line-height:1.5;overflow:hidden}.kKk9aW_discard,.kKk9aW_save{appearance:none;font:inherit;cursor:pointer;border:1px solid #0000;border-radius:8px;padding:5px 14px;font-size:13px;line-height:1.5}.kKk9aW_discard{border-color:var(--dsw-alias-border-l2);color:var(--dsw-alias-label-secondary);background:0 0}.kKk9aW_discard:hover:not(:disabled){color:var(--dsw-alias-label-primary);border-color:var(--dsw-alias-label-dimmed)}.kKk9aW_save{background:var(--dsw-alias-label-primary);color:var(--dsw-alias-bg-layer-3)}.kKk9aW_discard:disabled,.kKk9aW_save:disabled{opacity:.4;cursor:default}.kKk9aW_discard:focus-visible,.kKk9aW_save:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:1px}.kKk9aW_field{flex-direction:column;gap:6px;padding:12px 0;display:flex}.kKk9aW_field+.kKk9aW_field{border-top:1px solid var(--dsw-alias-border-l2)}.kKk9aW_head{align-items:center;gap:8px;display:flex}.kKk9aW_label{min-width:0;color:var(--dsw-alias-label-primary);flex:1;font-size:13px;font-weight:500;line-height:1.5}.kKk9aW_badges{align-items:center;gap:8px;display:inline-flex}.kKk9aW_badge{white-space:nowrap;background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-secondary);border-radius:999px;padding:1px 8px;font-size:11px;font-weight:500;line-height:17px}.kKk9aW_reset{font:inherit;color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:none;padding:0;font-size:12px;line-height:1.5}.kKk9aW_reset:hover:not(:disabled){color:var(--dsw-alias-label-primary)}.kKk9aW_reset:disabled{cursor:default}.kKk9aW_reset:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:2px;outline:2px solid var(--dsw-alias-brand-primary);outline-offset:2px}.kKk9aW_input,.kKk9aW_select{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);height:34px;font:inherit;color:var(--dsw-alias-label-primary);border-radius:8px;padding:0 12px;font-size:13px;line-height:1.5}.kKk9aW_input:focus-visible,.kKk9aW_select:focus-visible{border-color:var(--dsw-alias-brand-primary);outline:none}.kKk9aW_input:disabled,.kKk9aW_select:disabled{color:var(--dsw-alias-label-tertiary);cursor:default}.kKk9aW_inputInvalid{border:1px solid var(--dsw-alias-label-error);background:var(--dsw-alias-bg-layer-3);height:34px;font:inherit;color:var(--dsw-alias-label-primary);border-radius:8px;padding:0 12px;font-size:13px;line-height:1.5}.kKk9aW_inputInvalid:focus-visible{outline:2px solid var(--dsw-alias-label-error);outline-offset:1px;border-color:var(--dsw-alias-label-error)}.kKk9aW_invalid{color:var(--dsw-alias-label-error);margin:0;font-size:12px;line-height:1.5}.kKk9aW_hint{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:1.5}@media (prefers-reduced-motion:reduce){.kKk9aW_card,.kKk9aW_header,.kKk9aW_chevron,.kKk9aW_chevronOpen,.kKk9aW_discard,.kKk9aW_save{transition:none}}";
|
|
681
|
+
const css$1 = ".kKk9aW_card{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);border-radius:12px;list-style:none;transition:border-color .16s,background .16s}.kKk9aW_card:hover{border-color:var(--dsw-alias-label-dimmed)}.kKk9aW_cardOpen{background:var(--dsw-alias-bg-layer-2);border-color:var(--dsw-alias-label-dimmed)}.kKk9aW_header{appearance:none;width:100%;font:inherit;color:inherit;text-align:left;cursor:pointer;background:0 0;border:0;border-radius:12px;align-items:center;gap:12px;padding:14px 16px;display:flex}.kKk9aW_header:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:-2px}.kKk9aW_headerStatic{border-radius:12px;align-items:center;gap:12px;width:100%;padding:14px 16px;display:flex}.kKk9aW_headText{flex-direction:column;flex:1;gap:4px;min-width:0;display:flex}.kKk9aW_name{color:var(--dsw-alias-label-primary);font-size:15px;font-weight:600;line-height:1.4}.kKk9aW_description{color:var(--dsw-alias-label-tertiary);font-size:13px;line-height:1.5}.kKk9aW_pending{white-space:nowrap;background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-secondary);border-radius:999px;flex:none;padding:1px 8px;font-size:11px;font-weight:500;line-height:17px}.kKk9aW_chevron{color:var(--dsw-alias-label-tertiary);flex:none;transition:transform .16s}.kKk9aW_chevronOpen{transform:rotate(180deg)}.kKk9aW_body{border-top:1px solid var(--dsw-alias-border-l2);margin:0 16px;padding-bottom:8px}.kKk9aW_readOnly{color:var(--dsw-alias-label-tertiary);margin:12px 0 0;font-size:12px;line-height:1.5}.kKk9aW_notExposed{color:var(--dsw-alias-state-warn-primary);margin:12px 0 0;font-size:12px;line-height:1.5}.kKk9aW_footer{border-top:1px solid var(--dsw-alias-border-l2);justify-content:flex-end;align-items:center;gap:8px;padding:12px 0 4px;display:flex}.kKk9aW_failed{min-width:0;color:var(--dsw-alias-label-error);text-overflow:ellipsis;white-space:nowrap;flex:1;margin:0;font-size:12px;line-height:1.5;overflow:hidden}.kKk9aW_discard,.kKk9aW_save{appearance:none;font:inherit;cursor:pointer;border:1px solid #0000;border-radius:8px;padding:5px 14px;font-size:13px;line-height:1.5}.kKk9aW_discard{border-color:var(--dsw-alias-border-l2);color:var(--dsw-alias-label-secondary);background:0 0}.kKk9aW_discard:hover:not(:disabled){color:var(--dsw-alias-label-primary);border-color:var(--dsw-alias-label-dimmed)}.kKk9aW_save{background:var(--dsw-alias-label-primary);color:var(--dsw-alias-bg-layer-3)}.kKk9aW_discard:disabled,.kKk9aW_save:disabled{opacity:.4;cursor:default}.kKk9aW_discard:focus-visible,.kKk9aW_save:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:1px}.kKk9aW_field{flex-direction:column;gap:6px;padding:12px 0;display:flex}.kKk9aW_field+.kKk9aW_field{border-top:1px solid var(--dsw-alias-border-l2)}.kKk9aW_head{align-items:center;gap:8px;display:flex}.kKk9aW_label{min-width:0;color:var(--dsw-alias-label-primary);flex:1;font-size:13px;font-weight:500;line-height:1.5}.kKk9aW_badges{align-items:center;gap:8px;display:inline-flex}.kKk9aW_badge{white-space:nowrap;background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-secondary);border-radius:999px;padding:1px 8px;font-size:11px;font-weight:500;line-height:17px}.kKk9aW_reset{font:inherit;color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:none;padding:0;font-size:12px;line-height:1.5}.kKk9aW_reset:hover:not(:disabled){color:var(--dsw-alias-label-primary)}.kKk9aW_reset:disabled{cursor:default}.kKk9aW_reset:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:2px;outline:2px solid var(--dsw-alias-brand-primary);outline-offset:2px}.kKk9aW_input,.kKk9aW_select{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);height:34px;font:inherit;color:var(--dsw-alias-label-primary);border-radius:8px;padding:0 12px;font-size:13px;line-height:1.5}.kKk9aW_input:focus-visible,.kKk9aW_select:focus-visible{border-color:var(--dsw-alias-brand-primary);outline:none}.kKk9aW_input:disabled,.kKk9aW_select:disabled{color:var(--dsw-alias-label-tertiary);cursor:default}.kKk9aW_inputInvalid{border:1px solid var(--dsw-alias-label-error);background:var(--dsw-alias-bg-layer-3);height:34px;font:inherit;color:var(--dsw-alias-label-primary);border-radius:8px;padding:0 12px;font-size:13px;line-height:1.5}.kKk9aW_inputInvalid:focus-visible{outline:2px solid var(--dsw-alias-label-error);outline-offset:1px;border-color:var(--dsw-alias-label-error)}.kKk9aW_selectWrap{position:relative}.kKk9aW_selectButton{appearance:none;text-align:left;cursor:pointer;justify-content:space-between;align-items:center;gap:8px;width:100%;display:flex}.kKk9aW_selectLabel{text-overflow:ellipsis;white-space:nowrap;min-width:0;overflow:hidden}.kKk9aW_selectChevron{color:var(--dsw-alias-label-tertiary);flex:none;transition:transform .16s}.kKk9aW_selectChevronOpen{transform:rotate(180deg)}.kKk9aW_selectPopup{z-index:40;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);max-height:240px;box-shadow:0 8px 24px var(--dsw-alias-bg-mask-2);opacity:0;border-radius:8px;flex-direction:column;padding:4px;transition:opacity .1s,transform .1s;display:flex;position:absolute;top:calc(100% + 4px);left:0;right:0;overflow-y:auto;transform:translateY(-4px)}.kKk9aW_selectPopupOpen{opacity:1;transform:none}.kKk9aW_selectPopupClose{opacity:0;pointer-events:none;transform:translateY(-4px)}.kKk9aW_selectOption{color:var(--dsw-alias-label-primary);cursor:pointer;white-space:nowrap;text-overflow:ellipsis;border-radius:6px;padding:6px 10px;font-size:13px;line-height:1.5;overflow:hidden}.kKk9aW_selectOption:hover,.kKk9aW_selectOptionActive{background:var(--dsw-alias-interactive-bg-hover)}.kKk9aW_selectOptionSelected{color:var(--dsw-alias-brand-primary);background:color-mix(in srgb, var(--dsw-alias-brand-primary-new-colorprimary-new-color) 10%, transparent);font-weight:500}.kKk9aW_invalid{color:var(--dsw-alias-label-error);margin:0;font-size:12px;line-height:1.5}.kKk9aW_hint{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:1.5}@media (prefers-reduced-motion:reduce){.kKk9aW_card,.kKk9aW_header,.kKk9aW_chevron,.kKk9aW_chevronOpen,.kKk9aW_discard,.kKk9aW_save,.kKk9aW_selectChevron,.kKk9aW_selectChevronOpen,.kKk9aW_selectPopup{transition:none}}";
|
|
656
682
|
const tagId$1 = "@linxin666/dsh-pet/settings-card.module.css";
|
|
657
683
|
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$1) + "]") === null) {
|
|
658
684
|
const tag = document.createElement("style");
|
|
@@ -689,7 +715,18 @@ window.__ModuleLoader__.load({
|
|
|
689
715
|
"readOnly": "kKk9aW_readOnly",
|
|
690
716
|
"reset": "kKk9aW_reset",
|
|
691
717
|
"save": "kKk9aW_save",
|
|
692
|
-
"select": "kKk9aW_select"
|
|
718
|
+
"select": "kKk9aW_select",
|
|
719
|
+
"selectButton": "kKk9aW_selectButton",
|
|
720
|
+
"selectChevron": "kKk9aW_selectChevron",
|
|
721
|
+
"selectChevronOpen": "kKk9aW_selectChevronOpen",
|
|
722
|
+
"selectLabel": "kKk9aW_selectLabel",
|
|
723
|
+
"selectOption": "kKk9aW_selectOption",
|
|
724
|
+
"selectOptionActive": "kKk9aW_selectOptionActive",
|
|
725
|
+
"selectOptionSelected": "kKk9aW_selectOptionSelected",
|
|
726
|
+
"selectPopup": "kKk9aW_selectPopup",
|
|
727
|
+
"selectPopupClose": "kKk9aW_selectPopupClose",
|
|
728
|
+
"selectPopupOpen": "kKk9aW_selectPopupOpen",
|
|
729
|
+
"selectWrap": "kKk9aW_selectWrap"
|
|
693
730
|
};
|
|
694
731
|
//#endregion
|
|
695
732
|
//#region src/client/PluginSettingsCard.tsx
|
|
@@ -868,6 +905,175 @@ window.__ModuleLoader__.load({
|
|
|
868
905
|
]
|
|
869
906
|
});
|
|
870
907
|
}
|
|
908
|
+
const NON_SKIN_BODY_MARKERS = /* @__PURE__ */ new Set(["dshSkinCenter", "dshSidebarCollapsed"]);
|
|
909
|
+
function isSkinActive() {
|
|
910
|
+
return Object.keys(document.body.dataset).some((key) => key.startsWith("dsh") && !NON_SKIN_BODY_MARKERS.has(key));
|
|
911
|
+
}
|
|
912
|
+
const SELECT_CLOSE_MS = 100;
|
|
913
|
+
/**
|
|
914
|
+
* The shared dual-mode select control. While an appearance skin is active it
|
|
915
|
+
* renders the legacy native `<select>` untouched, so element-level skin
|
|
916
|
+
* selectors keep working; under the default appearance it renders a
|
|
917
|
+
* self-drawn `role="listbox"` popup whose open/close is transition-animated.
|
|
918
|
+
* Staged cards reach it through BooleanField/ChoiceField; immediate-apply
|
|
919
|
+
* editors (the side-card prefs) bind it directly through onEdit.
|
|
920
|
+
* 双模式下拉框:皮肤激活时用原生 select,默认外观用自绘动画弹层。
|
|
921
|
+
*/
|
|
922
|
+
function SelectField(props) {
|
|
923
|
+
const { id, options, value } = props;
|
|
924
|
+
const [open, setOpen] = (0, react.useState)(false);
|
|
925
|
+
const [closing, setClosing] = (0, react.useState)(false);
|
|
926
|
+
const [phase, setPhase] = (0, react.useState)("initial");
|
|
927
|
+
const [activeIndex, setActiveIndex] = (0, react.useState)(0);
|
|
928
|
+
const closeTimer = (0, react.useRef)(void 0);
|
|
929
|
+
const wrapRef = (0, react.useRef)(null);
|
|
930
|
+
const popupRef = (0, react.useRef)(null);
|
|
931
|
+
const currentIndex = () => {
|
|
932
|
+
const index = options.findIndex((option) => option.value === value);
|
|
933
|
+
return index >= 0 ? index : 0;
|
|
934
|
+
};
|
|
935
|
+
const close = (0, react.useCallback)(() => {
|
|
936
|
+
if (closeTimer.current !== void 0) clearTimeout(closeTimer.current);
|
|
937
|
+
setClosing(true);
|
|
938
|
+
closeTimer.current = setTimeout(() => {
|
|
939
|
+
setClosing(false);
|
|
940
|
+
setOpen(false);
|
|
941
|
+
}, SELECT_CLOSE_MS);
|
|
942
|
+
}, []);
|
|
943
|
+
const openPopup = () => {
|
|
944
|
+
if (closeTimer.current !== void 0) clearTimeout(closeTimer.current);
|
|
945
|
+
setActiveIndex(currentIndex());
|
|
946
|
+
setPhase("initial");
|
|
947
|
+
setClosing(false);
|
|
948
|
+
setOpen(true);
|
|
949
|
+
};
|
|
950
|
+
const commit = (index) => {
|
|
951
|
+
const option = options[index];
|
|
952
|
+
if (option) props.onEdit(option.value);
|
|
953
|
+
close();
|
|
954
|
+
};
|
|
955
|
+
const onTriggerClick = () => {
|
|
956
|
+
if (props.disabled) return;
|
|
957
|
+
if (open && !closing) close();
|
|
958
|
+
else openPopup();
|
|
959
|
+
};
|
|
960
|
+
const onKeyDown = (event) => {
|
|
961
|
+
if (props.disabled) return;
|
|
962
|
+
const count = options.length;
|
|
963
|
+
switch (event.key) {
|
|
964
|
+
case "ArrowDown":
|
|
965
|
+
case "ArrowUp":
|
|
966
|
+
case "Enter":
|
|
967
|
+
case " ":
|
|
968
|
+
event.preventDefault();
|
|
969
|
+
if (!open) openPopup();
|
|
970
|
+
else if (!closing) if (event.key === "ArrowDown") setActiveIndex((index) => (index + 1) % count);
|
|
971
|
+
else if (event.key === "ArrowUp") setActiveIndex((index) => (index - 1 + count) % count);
|
|
972
|
+
else commit(activeIndex);
|
|
973
|
+
break;
|
|
974
|
+
case "Escape":
|
|
975
|
+
if (open) {
|
|
976
|
+
event.preventDefault();
|
|
977
|
+
event.stopPropagation();
|
|
978
|
+
close();
|
|
979
|
+
}
|
|
980
|
+
break;
|
|
981
|
+
case "Tab":
|
|
982
|
+
if (open) close();
|
|
983
|
+
break;
|
|
984
|
+
}
|
|
985
|
+
};
|
|
986
|
+
(0, react.useEffect)(() => () => {
|
|
987
|
+
if (closeTimer.current !== void 0) clearTimeout(closeTimer.current);
|
|
988
|
+
}, []);
|
|
989
|
+
(0, react.useLayoutEffect)(() => {
|
|
990
|
+
if (open && !closing && phase === "initial") {
|
|
991
|
+
popupRef.current?.offsetHeight;
|
|
992
|
+
setPhase("open");
|
|
993
|
+
}
|
|
994
|
+
}, [
|
|
995
|
+
open,
|
|
996
|
+
closing,
|
|
997
|
+
phase
|
|
998
|
+
]);
|
|
999
|
+
(0, react.useEffect)(() => {
|
|
1000
|
+
if (!open) return;
|
|
1001
|
+
const onPointerDown = (event) => {
|
|
1002
|
+
const target = event.target;
|
|
1003
|
+
if (target instanceof Node && !wrapRef.current?.contains(target)) close();
|
|
1004
|
+
};
|
|
1005
|
+
document.addEventListener("pointerdown", onPointerDown);
|
|
1006
|
+
return () => document.removeEventListener("pointerdown", onPointerDown);
|
|
1007
|
+
}, [open, close]);
|
|
1008
|
+
(0, react.useEffect)(() => {
|
|
1009
|
+
if (props.disabled && open) close();
|
|
1010
|
+
}, [
|
|
1011
|
+
props.disabled,
|
|
1012
|
+
open,
|
|
1013
|
+
close
|
|
1014
|
+
]);
|
|
1015
|
+
if (isSkinActive()) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("select", {
|
|
1016
|
+
id,
|
|
1017
|
+
className: settings_card_module_css_default.select,
|
|
1018
|
+
value,
|
|
1019
|
+
disabled: props.disabled,
|
|
1020
|
+
onChange: (event) => {
|
|
1021
|
+
props.onEdit(event.target.value);
|
|
1022
|
+
},
|
|
1023
|
+
children: options.map((option) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
1024
|
+
value: option.value,
|
|
1025
|
+
children: option.label
|
|
1026
|
+
}, option.value))
|
|
1027
|
+
});
|
|
1028
|
+
const label = options.find((option) => option.value === value)?.label ?? "";
|
|
1029
|
+
const popupClass = closing ? `${settings_card_module_css_default.selectPopup} ${settings_card_module_css_default.selectPopupClose}` : phase === "open" ? `${settings_card_module_css_default.selectPopup} ${settings_card_module_css_default.selectPopupOpen}` : settings_card_module_css_default.selectPopup;
|
|
1030
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1031
|
+
className: settings_card_module_css_default.selectWrap,
|
|
1032
|
+
ref: wrapRef,
|
|
1033
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
1034
|
+
type: "button",
|
|
1035
|
+
id,
|
|
1036
|
+
className: `${settings_card_module_css_default.select} ${settings_card_module_css_default.selectButton}`,
|
|
1037
|
+
disabled: props.disabled,
|
|
1038
|
+
"aria-haspopup": "listbox",
|
|
1039
|
+
"aria-expanded": open,
|
|
1040
|
+
"aria-activedescendant": open ? `${id}-o${activeIndex}` : void 0,
|
|
1041
|
+
"aria-invalid": props.invalid || void 0,
|
|
1042
|
+
onClick: onTriggerClick,
|
|
1043
|
+
onKeyDown,
|
|
1044
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1045
|
+
className: settings_card_module_css_default.selectLabel,
|
|
1046
|
+
children: label
|
|
1047
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
|
|
1048
|
+
width: "14",
|
|
1049
|
+
height: "14",
|
|
1050
|
+
viewBox: "0 0 14 14",
|
|
1051
|
+
fill: "none",
|
|
1052
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1053
|
+
className: open ? `${settings_card_module_css_default.selectChevron} ${settings_card_module_css_default.selectChevronOpen}` : settings_card_module_css_default.selectChevron,
|
|
1054
|
+
"aria-hidden": "true",
|
|
1055
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
|
|
1056
|
+
d: "M11.8486 5.5L11.4238 5.92383L8.69727 8.65137C8.44157 8.90706 8.21562 9.13382 8.01172 9.29785C7.79912 9.46883 7.55595 9.61756 7.25 9.66602C7.08435 9.69222 6.91565 9.69222 6.75 9.66602C6.44405 9.61756 6.20088 9.46883 5.98828 9.29785C5.78438 9.13382 5.55843 8.90706 5.30273 8.65137L2.57617 5.92383L2.15137 5.5L3 4.65137L3.42383 5.07617L6.15137 7.80273C6.42595 8.07732 6.59876 8.24849 6.74023 8.3623C6.87291 8.46904 6.92272 8.47813 6.9375 8.48047C6.97895 8.48703 7.02105 8.48703 7.0625 8.48047C7.07728 8.47813 7.12709 8.46904 7.25977 8.3623C7.40124 8.24849 7.57405 8.07732 7.84863 7.80273L10.5762 5.07617L11 4.65137L11.8486 5.5Z",
|
|
1057
|
+
fill: "currentColor"
|
|
1058
|
+
})
|
|
1059
|
+
})]
|
|
1060
|
+
}), open ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1061
|
+
className: popupClass,
|
|
1062
|
+
role: "listbox",
|
|
1063
|
+
ref: popupRef,
|
|
1064
|
+
children: options.map((option, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1065
|
+
id: `${id}-o${index}`,
|
|
1066
|
+
role: "option",
|
|
1067
|
+
"aria-selected": option.value === value,
|
|
1068
|
+
className: `${settings_card_module_css_default.selectOption}${option.value === value ? ` ${settings_card_module_css_default.selectOptionSelected}` : ""}${index === activeIndex && !closing ? ` ${settings_card_module_css_default.selectOptionActive}` : ""}`,
|
|
1069
|
+
onClick: () => {
|
|
1070
|
+
commit(index);
|
|
1071
|
+
},
|
|
1072
|
+
children: option.label
|
|
1073
|
+
}, option.value))
|
|
1074
|
+
}) : null]
|
|
1075
|
+
});
|
|
1076
|
+
}
|
|
871
1077
|
/** A staged boolean field: 继承 / 开 / 关. */
|
|
872
1078
|
function BooleanField(props) {
|
|
873
1079
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
@@ -893,28 +1099,26 @@ window.__ModuleLoader__.load({
|
|
|
893
1099
|
})]
|
|
894
1100
|
}) : null]
|
|
895
1101
|
}),
|
|
896
|
-
/* @__PURE__ */ (0, react_jsx_runtime.
|
|
1102
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(SelectField, {
|
|
897
1103
|
id: props.id,
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
disabled: props.disabled,
|
|
901
|
-
onChange: (event) => {
|
|
902
|
-
props.onEdit(event.target.value);
|
|
903
|
-
},
|
|
904
|
-
children: [
|
|
905
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
1104
|
+
options: [
|
|
1105
|
+
{
|
|
906
1106
|
value: "",
|
|
907
|
-
|
|
908
|
-
}
|
|
909
|
-
|
|
1107
|
+
label: props.inheritLabel
|
|
1108
|
+
},
|
|
1109
|
+
{
|
|
910
1110
|
value: "true",
|
|
911
|
-
|
|
912
|
-
}
|
|
913
|
-
|
|
1111
|
+
label: props.onLabel
|
|
1112
|
+
},
|
|
1113
|
+
{
|
|
914
1114
|
value: "false",
|
|
915
|
-
|
|
916
|
-
}
|
|
917
|
-
]
|
|
1115
|
+
label: props.offLabel
|
|
1116
|
+
}
|
|
1117
|
+
],
|
|
1118
|
+
value: props.text,
|
|
1119
|
+
disabled: props.disabled,
|
|
1120
|
+
invalid: props.invalid,
|
|
1121
|
+
onEdit: props.onEdit
|
|
918
1122
|
}),
|
|
919
1123
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
920
1124
|
className: settings_card_module_css_default.hint,
|
|
@@ -948,21 +1152,16 @@ window.__ModuleLoader__.load({
|
|
|
948
1152
|
})]
|
|
949
1153
|
}) : null]
|
|
950
1154
|
}),
|
|
951
|
-
/* @__PURE__ */ (0, react_jsx_runtime.
|
|
1155
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(SelectField, {
|
|
952
1156
|
id: props.id,
|
|
953
|
-
|
|
1157
|
+
options: [{
|
|
1158
|
+
value: "",
|
|
1159
|
+
label: props.inheritLabel
|
|
1160
|
+
}, ...props.choices],
|
|
954
1161
|
value: props.text,
|
|
955
1162
|
disabled: props.disabled,
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
},
|
|
959
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
960
|
-
value: "",
|
|
961
|
-
children: props.inheritLabel
|
|
962
|
-
}), props.choices.map((choice) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
963
|
-
value: choice.value,
|
|
964
|
-
children: choice.label
|
|
965
|
-
}, choice.value))]
|
|
1163
|
+
invalid: props.invalid,
|
|
1164
|
+
onEdit: props.onEdit
|
|
966
1165
|
}),
|
|
967
1166
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
968
1167
|
className: props.invalid ? settings_card_module_css_default.invalid : settings_card_module_css_default.hint,
|
|
@@ -1497,6 +1696,8 @@ window.__ModuleLoader__.load({
|
|
|
1497
1696
|
"pet.state.loading": "宠物正在赶来…",
|
|
1498
1697
|
"pet.state.error": "宠物迷路了(连接失败)",
|
|
1499
1698
|
"pet.openSessionHint": "点击跳转到对应会话",
|
|
1699
|
+
"pet.moreSessions": "展开其余 {n} 个会话的气泡",
|
|
1700
|
+
"pet.collapseSessions": "收起会话气泡",
|
|
1500
1701
|
"settings.title": "宠物",
|
|
1501
1702
|
"settings.description": "选择宠物并调整它的显示布局。",
|
|
1502
1703
|
"settings.pet": "宠物",
|
|
@@ -1541,6 +1742,8 @@ window.__ModuleLoader__.load({
|
|
|
1541
1742
|
"pet.state.loading": "The pet is on its way…",
|
|
1542
1743
|
"pet.state.error": "The pet is lost (connection failed)",
|
|
1543
1744
|
"pet.openSessionHint": "Click to jump to this session",
|
|
1745
|
+
"pet.moreSessions": "Expand {n} more session bubbles",
|
|
1746
|
+
"pet.collapseSessions": "Collapse session bubbles",
|
|
1544
1747
|
"settings.title": "Pet",
|
|
1545
1748
|
"settings.description": "Pick a pet and tune its display layout.",
|
|
1546
1749
|
"settings.pet": "Pet",
|
|
@@ -1764,6 +1967,7 @@ window.__ModuleLoader__.load({
|
|
|
1764
1967
|
});
|
|
1765
1968
|
const container = document.createElement("div");
|
|
1766
1969
|
container.dataset.dshPetRoot = "";
|
|
1970
|
+
container.dataset.dshPlugin = "pet";
|
|
1767
1971
|
document.body.appendChild(container);
|
|
1768
1972
|
const petRoot = (0, react_dom_client.createRoot)(container);
|
|
1769
1973
|
petRoot.render((0, react.createElement)(PetDockEntry, {
|