@dsh-plus/image-studio 0.1.23 → 0.1.25
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/lib/client.js +192 -293
- package/package.json +15 -15
- package/src/client/card.tsx +3 -12
- package/src/client/client.ts +2 -2
- package/src/client/styles.ts +3 -13
- package/src/ns.ts +2 -2
package/lib/client.js
CHANGED
|
@@ -4,9 +4,175 @@ window.__ModuleLoader__.load({
|
|
|
4
4
|
var module = { exports: {} };
|
|
5
5
|
var exports = module.exports;
|
|
6
6
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
7
|
-
let react = require("react");
|
|
8
7
|
let react_jsx_runtime = require("react/jsx-runtime");
|
|
8
|
+
let react = require("react");
|
|
9
9
|
let _deepseek_ai_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
|
|
10
|
+
//#region ../shared/src/client/card.tsx
|
|
11
|
+
const IDLE_STATUS = {
|
|
12
|
+
kind: "idle",
|
|
13
|
+
text: ""
|
|
14
|
+
};
|
|
15
|
+
function CardChrome(props) {
|
|
16
|
+
const p = props.prefix;
|
|
17
|
+
const badge = props.statusBadge;
|
|
18
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
19
|
+
className: `${p}-section`,
|
|
20
|
+
"aria-label": props.title,
|
|
21
|
+
children: [
|
|
22
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
23
|
+
className: `${p}-sectionHead`,
|
|
24
|
+
children: [
|
|
25
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", {
|
|
26
|
+
className: `${p}-sectionTitle`,
|
|
27
|
+
children: props.title
|
|
28
|
+
}),
|
|
29
|
+
badge !== void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
30
|
+
className: `${p}-sectionBadge ${badge.on ? `${p}-statusOn` : `${p}-statusOff`}`,
|
|
31
|
+
children: badge.text
|
|
32
|
+
}) : null,
|
|
33
|
+
props.dirty ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
34
|
+
className: `${p}-pending`,
|
|
35
|
+
children: props.dirtyLabel
|
|
36
|
+
}) : null
|
|
37
|
+
]
|
|
38
|
+
}),
|
|
39
|
+
props.description === "" ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
40
|
+
className: `${p}-sectionDesc`,
|
|
41
|
+
children: props.description
|
|
42
|
+
}),
|
|
43
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
44
|
+
className: `${p}-sectionBody`,
|
|
45
|
+
children: [
|
|
46
|
+
props.readOnlyNotice !== void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
47
|
+
className: `${p}-readOnly`,
|
|
48
|
+
role: "status",
|
|
49
|
+
children: props.readOnlyNotice
|
|
50
|
+
}) : null,
|
|
51
|
+
props.children,
|
|
52
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
53
|
+
className: `${p}-sectionFooter`,
|
|
54
|
+
children: [props.status !== void 0 && props.status.kind !== "idle" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
55
|
+
className: `${p}-status${props.status.kind === "error" ? ` ${p}-statusError` : ""}`,
|
|
56
|
+
role: "status",
|
|
57
|
+
children: props.status.text
|
|
58
|
+
}) : null, props.actions.map((action) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
59
|
+
type: "button",
|
|
60
|
+
className: `${p}-btn ${action.variant === "primary" ? `${p}-btnPrimary` : `${p}-btnGhost`}`,
|
|
61
|
+
disabled: action.disabled === true,
|
|
62
|
+
onClick: action.onClick,
|
|
63
|
+
children: action.label
|
|
64
|
+
}, action.key))]
|
|
65
|
+
})
|
|
66
|
+
]
|
|
67
|
+
})
|
|
68
|
+
]
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
/** 取值未到达时的占位:与 CardChrome 同形态,避免宿主页里闪一次卡片外壳。 */
|
|
72
|
+
function CardLoading(props) {
|
|
73
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("section", {
|
|
74
|
+
className: `${props.prefix}-section`,
|
|
75
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
76
|
+
className: `${props.prefix}-readOnly`,
|
|
77
|
+
role: "status",
|
|
78
|
+
children: props.text
|
|
79
|
+
})
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
//#endregion
|
|
83
|
+
//#region ../shared/src/client/config-slots.ts
|
|
84
|
+
/** dsh-plus 聚合 bundle 的包名(各插件 row 均经其补丁层插入 profile)。 */
|
|
85
|
+
const DSH_PLUS_BUNDLE = "@dsh-plus/bundle-main";
|
|
86
|
+
/**
|
|
87
|
+
* 把一张配置卡片注册进插件页的两个配置槽位。
|
|
88
|
+
* 两个槽位都由 0.2.1-alpha.1 的插件页声明,任一缺席即报错——不做版本探测。
|
|
89
|
+
*/
|
|
90
|
+
function injectPluginConfigCard(slots, reg) {
|
|
91
|
+
const base = {
|
|
92
|
+
locale: reg.ns,
|
|
93
|
+
inject: reg.inject
|
|
94
|
+
};
|
|
95
|
+
slots.inject("plugins.row.config", () => slots.register({
|
|
96
|
+
name: "plugins.row.config",
|
|
97
|
+
key: `${DSH_PLUS_BUNDLE}#${reg.rowId}`,
|
|
98
|
+
...base
|
|
99
|
+
}, reg.component));
|
|
100
|
+
slots.inject("plugins.bundle.config", () => slots.register({
|
|
101
|
+
name: "plugins.bundle.config",
|
|
102
|
+
key: reg.pkg,
|
|
103
|
+
...base
|
|
104
|
+
}, reg.component));
|
|
105
|
+
}
|
|
106
|
+
//#endregion
|
|
107
|
+
//#region ../shared/src/client/draft.ts
|
|
108
|
+
/**
|
|
109
|
+
* 单命名空间 staged 草稿(简单配置卡片共用):读 scope 快照、播种草稿、
|
|
110
|
+
* 脏判定、保存(revision fencing + 重新装载)与状态行。
|
|
111
|
+
*
|
|
112
|
+
* 语义与官方 staged 表单一致:Host 更新不覆盖在途编辑,只有保存才写回;
|
|
113
|
+
* 保存成功后按 Host 解析值重置草稿。`from`/`patch` 参与 effect 与 useMemo
|
|
114
|
+
* 依赖,必须是模块级稳定函数(不要内联箭头函数)。
|
|
115
|
+
* @module @dsh-plus/shared/client/draft
|
|
116
|
+
*/
|
|
117
|
+
//#endregion
|
|
118
|
+
//#region ../shared/src/client/fetch.ts
|
|
119
|
+
async function parse(res, guard) {
|
|
120
|
+
const body = await res.json();
|
|
121
|
+
if (!res.ok) throw new Error(body.error ?? `HTTP ${res.status}`);
|
|
122
|
+
if (guard !== void 0 && !guard(body)) throw new Error(`响应结构不符合预期(${res.url})`);
|
|
123
|
+
return body;
|
|
124
|
+
}
|
|
125
|
+
/** GET 同源 JSON 端点。 */
|
|
126
|
+
async function getJson(route, guard) {
|
|
127
|
+
return parse(await fetch(route, { credentials: "same-origin" }), guard);
|
|
128
|
+
}
|
|
129
|
+
/** POST 同源 JSON 端点(body 可省略)。 */
|
|
130
|
+
async function postJson(route, body, guard) {
|
|
131
|
+
return parse(await fetch(route, {
|
|
132
|
+
method: "POST",
|
|
133
|
+
credentials: "same-origin",
|
|
134
|
+
headers: { "content-type": "application/json" },
|
|
135
|
+
...body === void 0 ? {} : { body: JSON.stringify(body) }
|
|
136
|
+
}), guard);
|
|
137
|
+
}
|
|
138
|
+
//#endregion
|
|
139
|
+
//#region ../shared/src/client/fields.tsx
|
|
140
|
+
function TextField(props) {
|
|
141
|
+
const p = props.prefix ?? "dshp";
|
|
142
|
+
const invalid = props.invalid === true;
|
|
143
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
144
|
+
className: `${p}-field`,
|
|
145
|
+
children: [
|
|
146
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
147
|
+
className: `${p}-head`,
|
|
148
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
|
|
149
|
+
className: `${p}-label`,
|
|
150
|
+
htmlFor: props.id,
|
|
151
|
+
children: props.label
|
|
152
|
+
}), props.badge !== void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
153
|
+
className: `${p}-badge ${props.badge.set ? `${p}-badgeSet` : `${p}-badgeUnset`}`,
|
|
154
|
+
children: props.badge.text
|
|
155
|
+
}) : null]
|
|
156
|
+
}),
|
|
157
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
158
|
+
id: props.id,
|
|
159
|
+
className: `${p}-input${invalid ? ` ${p}-inputInvalid` : ""}`,
|
|
160
|
+
type: props.password === true ? "password" : "text",
|
|
161
|
+
inputMode: props.numeric === true ? "numeric" : void 0,
|
|
162
|
+
autoComplete: props.password === true ? "off" : void 0,
|
|
163
|
+
"aria-invalid": invalid || void 0,
|
|
164
|
+
value: props.value,
|
|
165
|
+
disabled: props.disabled === true,
|
|
166
|
+
onChange: (event) => props.onEdit(event.target.value)
|
|
167
|
+
}),
|
|
168
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
169
|
+
className: invalid ? `${p}-invalid` : `${p}-hint`,
|
|
170
|
+
children: invalid ? props.invalidLabel ?? "" : props.hint ?? ""
|
|
171
|
+
})
|
|
172
|
+
]
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
//#endregion
|
|
10
176
|
//#region ../../node_modules/.pnpm/lucide-react@1.38.0_react@18.2.0/node_modules/lucide-react/dist/esm/shared/src/utils/mergeClasses.mjs
|
|
11
177
|
/**
|
|
12
178
|
* @license lucide-react v1.38.0 - ISC
|
|
@@ -272,238 +438,6 @@ window.__ModuleLoader__.load({
|
|
|
272
438
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Layers, { ...lucideProps(props) });
|
|
273
439
|
}
|
|
274
440
|
//#endregion
|
|
275
|
-
//#region ../shared/src/client/card.tsx
|
|
276
|
-
const IDLE_STATUS = {
|
|
277
|
-
kind: "idle",
|
|
278
|
-
text: ""
|
|
279
|
-
};
|
|
280
|
-
/** 状态行 + 动作按钮(两种形态共用,类名随形态切换度量)。 */
|
|
281
|
-
function CardFoot(props) {
|
|
282
|
-
const p = props.prefix;
|
|
283
|
-
const section = props.variant === "section";
|
|
284
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
285
|
-
className: section ? `${p}-sectionFooter` : `${p}-footer`,
|
|
286
|
-
children: [props.status !== void 0 && props.status.kind !== "idle" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
287
|
-
className: `${p}-status${props.status.kind === "error" ? ` ${p}-statusError` : ""}`,
|
|
288
|
-
role: "status",
|
|
289
|
-
children: props.status.text
|
|
290
|
-
}) : null, props.actions.map((action) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
291
|
-
type: "button",
|
|
292
|
-
className: `${p}-btn ${action.variant === "primary" ? `${p}-btnPrimary` : `${p}-btnGhost`}`,
|
|
293
|
-
disabled: action.disabled === true,
|
|
294
|
-
onClick: action.onClick,
|
|
295
|
-
children: action.label
|
|
296
|
-
}, action.key))]
|
|
297
|
-
});
|
|
298
|
-
}
|
|
299
|
-
/** 只读提示 + 字段区 + 页脚(两种形态共用)。 */
|
|
300
|
-
function CardBody(props) {
|
|
301
|
-
const p = props.prefix;
|
|
302
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
303
|
-
props.readOnlyNotice !== void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
304
|
-
className: `${p}-readOnly`,
|
|
305
|
-
role: "status",
|
|
306
|
-
children: props.readOnlyNotice
|
|
307
|
-
}) : null,
|
|
308
|
-
props.children,
|
|
309
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(CardFoot, { ...props })
|
|
310
|
-
] });
|
|
311
|
-
}
|
|
312
|
-
function CardChrome(props) {
|
|
313
|
-
const p = props.prefix;
|
|
314
|
-
const badge = props.statusBadge;
|
|
315
|
-
if (props.variant === "section") return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
316
|
-
className: `${p}-section`,
|
|
317
|
-
"aria-label": props.title,
|
|
318
|
-
children: [
|
|
319
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
320
|
-
className: `${p}-sectionHead`,
|
|
321
|
-
children: [
|
|
322
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", {
|
|
323
|
-
className: `${p}-sectionTitle`,
|
|
324
|
-
children: props.title
|
|
325
|
-
}),
|
|
326
|
-
badge !== void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
327
|
-
className: `${p}-sectionBadge ${badge.on ? `${p}-statusOn` : `${p}-statusOff`}`,
|
|
328
|
-
children: badge.text
|
|
329
|
-
}) : null,
|
|
330
|
-
props.dirty ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
331
|
-
className: `${p}-pending`,
|
|
332
|
-
children: props.dirtyLabel
|
|
333
|
-
}) : null
|
|
334
|
-
]
|
|
335
|
-
}),
|
|
336
|
-
props.description === "" ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
337
|
-
className: `${p}-sectionDesc`,
|
|
338
|
-
children: props.description
|
|
339
|
-
}),
|
|
340
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
341
|
-
className: `${p}-sectionBody`,
|
|
342
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CardBody, { ...props })
|
|
343
|
-
})
|
|
344
|
-
]
|
|
345
|
-
});
|
|
346
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("li", {
|
|
347
|
-
className: `${p}-card${props.open ? ` ${p}-cardOpen` : ""}`,
|
|
348
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
349
|
-
type: "button",
|
|
350
|
-
className: `${p}-header`,
|
|
351
|
-
"aria-expanded": props.open,
|
|
352
|
-
"aria-label": props.title,
|
|
353
|
-
onClick: () => props.onToggle(!props.open),
|
|
354
|
-
children: [
|
|
355
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
356
|
-
className: `${p}-headText`,
|
|
357
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
358
|
-
className: `${p}-name`,
|
|
359
|
-
children: props.title
|
|
360
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
361
|
-
className: `${p}-description`,
|
|
362
|
-
children: props.description
|
|
363
|
-
})]
|
|
364
|
-
}),
|
|
365
|
-
badge !== void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
366
|
-
className: `${p}-statusBadge ${badge.on ? `${p}-statusOn` : `${p}-statusOff`}`,
|
|
367
|
-
children: badge.text
|
|
368
|
-
}) : null,
|
|
369
|
-
props.dirty ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
370
|
-
className: `${p}-pending`,
|
|
371
|
-
children: props.dirtyLabel
|
|
372
|
-
}) : null,
|
|
373
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronDownOutlineRegular, { className: `${p}-chevron${props.open ? ` ${p}-chevronOpen` : ""}` })
|
|
374
|
-
]
|
|
375
|
-
}), props.open ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
376
|
-
className: `${p}-body`,
|
|
377
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CardBody, { ...props })
|
|
378
|
-
}) : null]
|
|
379
|
-
});
|
|
380
|
-
}
|
|
381
|
-
/** 取值未到达时的占位:与 CardChrome 同形态,避免宿主页里闪一次卡片外壳。 */
|
|
382
|
-
function CardLoading(props) {
|
|
383
|
-
if (props.variant === "section") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("section", {
|
|
384
|
-
className: `${props.prefix}-section`,
|
|
385
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
386
|
-
className: `${props.prefix}-readOnly`,
|
|
387
|
-
role: "status",
|
|
388
|
-
children: props.text
|
|
389
|
-
})
|
|
390
|
-
});
|
|
391
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", {
|
|
392
|
-
className: `${props.prefix}-card`,
|
|
393
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
394
|
-
className: `${props.prefix}-readOnly`,
|
|
395
|
-
role: "status",
|
|
396
|
-
children: props.text
|
|
397
|
-
})
|
|
398
|
-
});
|
|
399
|
-
}
|
|
400
|
-
//#endregion
|
|
401
|
-
//#region ../shared/src/client/config-slots.ts
|
|
402
|
-
/** dsh-plus 聚合 bundle 的包名(各插件 row 均经其补丁层插入 profile)。 */
|
|
403
|
-
const DSH_PLUS_BUNDLE = "@dsh-plus/bundle-main";
|
|
404
|
-
/**
|
|
405
|
-
* 视图 → 外壳形态:插件页 page 视图渲染在官方页面容器内(宿主已画标题、图标、
|
|
406
|
-
* 面包屑与页面级内边距),再套卡片会形成卡片套卡片并压缩移动端可用宽度,
|
|
407
|
-
* 故用无边框分节;summary 与 legacy 槽位保持卡片形态。
|
|
408
|
-
*/
|
|
409
|
-
function cardVariantFor(view) {
|
|
410
|
-
return view === "page" ? "section" : "card";
|
|
411
|
-
}
|
|
412
|
-
/**
|
|
413
|
-
* 把一张配置卡片同时注册进 legacy 与新版三个槽位。
|
|
414
|
-
* 任一槽位在当前 dsh 版本未声明时对应 inject 挂起等待,版本不命中即 no-op。
|
|
415
|
-
*/
|
|
416
|
-
function injectPluginConfigCard(slots, reg) {
|
|
417
|
-
const base = {
|
|
418
|
-
locale: reg.ns,
|
|
419
|
-
inject: reg.inject
|
|
420
|
-
};
|
|
421
|
-
slots.inject("settings.plugin.item", () => slots.register({
|
|
422
|
-
name: "settings.plugin.item",
|
|
423
|
-
key: reg.ns,
|
|
424
|
-
...base
|
|
425
|
-
}, reg.component));
|
|
426
|
-
slots.inject("plugins.row.config", () => slots.register({
|
|
427
|
-
name: "plugins.row.config",
|
|
428
|
-
key: `${DSH_PLUS_BUNDLE}#${reg.rowId}`,
|
|
429
|
-
...base
|
|
430
|
-
}, reg.component));
|
|
431
|
-
slots.inject("plugins.bundle.config", () => slots.register({
|
|
432
|
-
name: "plugins.bundle.config",
|
|
433
|
-
key: reg.pkg,
|
|
434
|
-
...base
|
|
435
|
-
}, reg.component));
|
|
436
|
-
}
|
|
437
|
-
//#endregion
|
|
438
|
-
//#region ../shared/src/client/draft.ts
|
|
439
|
-
/**
|
|
440
|
-
* 单命名空间 staged 草稿(简单配置卡片共用):读 scope 快照、播种草稿、
|
|
441
|
-
* 脏判定、保存(revision fencing + 重新装载)与状态行。
|
|
442
|
-
*
|
|
443
|
-
* 语义与官方 staged 表单一致:Host 更新不覆盖在途编辑,只有保存才写回;
|
|
444
|
-
* 保存成功后按 Host 解析值重置草稿。`from`/`patch` 参与 effect 与 useMemo
|
|
445
|
-
* 依赖,必须是模块级稳定函数(不要内联箭头函数)。
|
|
446
|
-
* @module @dsh-plus/shared/client/draft
|
|
447
|
-
*/
|
|
448
|
-
//#endregion
|
|
449
|
-
//#region ../shared/src/client/fetch.ts
|
|
450
|
-
async function parse(res, guard) {
|
|
451
|
-
const body = await res.json();
|
|
452
|
-
if (!res.ok) throw new Error(body.error ?? `HTTP ${res.status}`);
|
|
453
|
-
if (guard !== void 0 && !guard(body)) throw new Error(`响应结构不符合预期(${res.url})`);
|
|
454
|
-
return body;
|
|
455
|
-
}
|
|
456
|
-
/** GET 同源 JSON 端点。 */
|
|
457
|
-
async function getJson(route, guard) {
|
|
458
|
-
return parse(await fetch(route, { credentials: "same-origin" }), guard);
|
|
459
|
-
}
|
|
460
|
-
/** POST 同源 JSON 端点(body 可省略)。 */
|
|
461
|
-
async function postJson(route, body, guard) {
|
|
462
|
-
return parse(await fetch(route, {
|
|
463
|
-
method: "POST",
|
|
464
|
-
credentials: "same-origin",
|
|
465
|
-
headers: { "content-type": "application/json" },
|
|
466
|
-
...body === void 0 ? {} : { body: JSON.stringify(body) }
|
|
467
|
-
}), guard);
|
|
468
|
-
}
|
|
469
|
-
//#endregion
|
|
470
|
-
//#region ../shared/src/client/fields.tsx
|
|
471
|
-
function TextField(props) {
|
|
472
|
-
const p = props.prefix ?? "dshp";
|
|
473
|
-
const invalid = props.invalid === true;
|
|
474
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
475
|
-
className: `${p}-field`,
|
|
476
|
-
children: [
|
|
477
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
478
|
-
className: `${p}-head`,
|
|
479
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
|
|
480
|
-
className: `${p}-label`,
|
|
481
|
-
htmlFor: props.id,
|
|
482
|
-
children: props.label
|
|
483
|
-
}), props.badge !== void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
484
|
-
className: `${p}-badge ${props.badge.set ? `${p}-badgeSet` : `${p}-badgeUnset`}`,
|
|
485
|
-
children: props.badge.text
|
|
486
|
-
}) : null]
|
|
487
|
-
}),
|
|
488
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
489
|
-
id: props.id,
|
|
490
|
-
className: `${p}-input${invalid ? ` ${p}-inputInvalid` : ""}`,
|
|
491
|
-
type: props.password === true ? "password" : "text",
|
|
492
|
-
inputMode: props.numeric === true ? "numeric" : void 0,
|
|
493
|
-
autoComplete: props.password === true ? "off" : void 0,
|
|
494
|
-
"aria-invalid": invalid || void 0,
|
|
495
|
-
value: props.value,
|
|
496
|
-
disabled: props.disabled === true,
|
|
497
|
-
onChange: (event) => props.onEdit(event.target.value)
|
|
498
|
-
}),
|
|
499
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
500
|
-
className: invalid ? `${p}-invalid` : `${p}-hint`,
|
|
501
|
-
children: invalid ? props.invalidLabel ?? "" : props.hint ?? ""
|
|
502
|
-
})
|
|
503
|
-
]
|
|
504
|
-
});
|
|
505
|
-
}
|
|
506
|
-
//#endregion
|
|
507
441
|
//#region ../shared/src/client/scope.ts
|
|
508
442
|
/**
|
|
509
443
|
* remote.settings 直连实现的命名空间 scope(官方配置页 tab 同款模式)。
|
|
@@ -594,36 +528,33 @@ window.__ModuleLoader__.load({
|
|
|
594
528
|
//#endregion
|
|
595
529
|
//#region ../shared/src/client/styles.ts
|
|
596
530
|
/**
|
|
597
|
-
*
|
|
598
|
-
*
|
|
599
|
-
*
|
|
531
|
+
* 配置分节样式工厂(各插件 client 的公共收编版)。
|
|
532
|
+
*
|
|
533
|
+
* 目标宿主 dsh 0.2.1-alpha.1:插件页把配置视图放进已有页面级内边距的容器里
|
|
534
|
+
* (`div.detailSections[data-plugin-config]` 或 `section.detailSection[data-plugin-config]`),
|
|
535
|
+
* 外层无边框——故这里输出的是**无边框分节**(小节标题 13px/600、字段 12px 0、
|
|
536
|
+
* 横向零内边距、页脚非 sticky),度量对齐官方设置页
|
|
537
|
+
* (`@deepseek-ai/dsh-client-ui-primitives` 的 settings-form)。
|
|
538
|
+
*
|
|
539
|
+
* 移动端与可达性(767px 断点 + pointer:coarse,对齐 ui-mobile-fit 约定):
|
|
600
540
|
* - 窄屏 input/textarea 16px(防 iOS 聚焦缩放)、可点目标 ≥44px;
|
|
601
|
-
* -
|
|
602
|
-
* - 展开态 body 底部 sticky 保存栏(长表单滚动中始终可达)。
|
|
603
|
-
* - 分节形态(-section,插件页 page 视图内嵌宿主页面):无边框/背景、横向零
|
|
604
|
-
* 内边距,页脚不 sticky——官方插件页已提供页面级内边距,再叠一层卡片会
|
|
605
|
-
* 缩窄移动端可用宽度(卡片套卡片)。
|
|
541
|
+
* - 页脚按钮等宽换行、状态文字独占一行。
|
|
606
542
|
* 沿用官方 data-plugin / data-plugin-css 约定(HMR 据此卸载),不覆盖上游选择器。
|
|
607
543
|
* @module @dsh-plus/shared/client/styles
|
|
608
544
|
*/
|
|
609
|
-
/**
|
|
545
|
+
/** 生成全套分节 CSS;prefix 为插件类名前缀(如 'dne'),extra 为插件特有规则。 */
|
|
610
546
|
function cardCss(prefix, extra = "") {
|
|
611
547
|
return `
|
|
612
|
-
.${prefix}-
|
|
613
|
-
.${prefix}-
|
|
614
|
-
.${prefix}-
|
|
615
|
-
.${prefix}-
|
|
616
|
-
.${prefix}-
|
|
617
|
-
.${prefix}-
|
|
618
|
-
.${prefix}-
|
|
619
|
-
.${prefix}-description{color:var(--dsw-alias-label-tertiary);font-size:13px;line-height:1.5}
|
|
620
|
-
.${prefix}-chevron{color:var(--dsw-alias-label-tertiary);flex:none;transition:transform .16s;display:inline-flex}
|
|
621
|
-
.${prefix}-chevronOpen{transform:rotate(180deg)}
|
|
548
|
+
.${prefix}-section{box-sizing:border-box;flex-direction:column;width:100%;min-width:0;padding:16px 0;display:flex}
|
|
549
|
+
.${prefix}-sectionHead{align-items:center;gap:8px;min-width:0;display:flex}
|
|
550
|
+
.${prefix}-sectionTitle{min-width:0;color:var(--dsw-alias-label-primary);flex:1;margin:0;font-size:13px;font-weight:600;line-height:1.5}
|
|
551
|
+
.${prefix}-sectionBadge{white-space:nowrap;border-radius:999px;flex:none;padding:1px 8px;font-size:11px;font-weight:500;line-height:17px}
|
|
552
|
+
.${prefix}-sectionDesc{color:var(--dsw-alias-label-tertiary);margin:4px 0 0;font-size:12px;line-height:1.5}
|
|
553
|
+
.${prefix}-sectionBody{flex-direction:column;min-width:0;display:flex}
|
|
554
|
+
.${prefix}-sectionFooter{align-items:center;gap:8px;padding-top:16px;display:flex;flex-wrap:wrap}
|
|
622
555
|
.${prefix}-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}
|
|
623
|
-
.${prefix}-statusBadge{white-space:nowrap;border-radius:999px;flex:none;padding:1px 8px;font-size:11px;font-weight:500;line-height:17px}
|
|
624
556
|
.${prefix}-statusOn{background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-secondary)}
|
|
625
557
|
.${prefix}-statusOff{color:var(--dsw-alias-label-tertiary)}
|
|
626
|
-
.${prefix}-body{border-top:1px solid var(--dsw-alias-border-l2);margin:0 16px;padding-bottom:8px}
|
|
627
558
|
.${prefix}-field{flex-direction:column;gap:6px;padding:12px 0;display:flex}
|
|
628
559
|
.${prefix}-field+.${prefix}-field{border-top:1px solid var(--dsw-alias-border-l2)}
|
|
629
560
|
.${prefix}-head{align-items:center;gap:8px;display:flex}
|
|
@@ -649,19 +580,9 @@ window.__ModuleLoader__.load({
|
|
|
649
580
|
.${prefix}-checkRow input:checked::after{left:16px;background:var(--dsw-alias-bg-base)}
|
|
650
581
|
.${prefix}-checkRow input:disabled{opacity:.4;cursor:default}
|
|
651
582
|
.${prefix}-checkRow input:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:2px}
|
|
652
|
-
/* 宿主内嵌分节形态(插件页 page 视图):官方设置页同构——无边框/背景,
|
|
653
|
-
横向零内边距(宽度交给宿主页面容器),小节标题 13px/600,页脚非 sticky。 */
|
|
654
|
-
.${prefix}-section{box-sizing:border-box;flex-direction:column;width:100%;min-width:0;padding:16px 0;display:flex}
|
|
655
|
-
.${prefix}-sectionHead{align-items:center;gap:8px;min-width:0;display:flex}
|
|
656
|
-
.${prefix}-sectionTitle{min-width:0;color:var(--dsw-alias-label-primary);flex:1;margin:0;font-size:13px;font-weight:600;line-height:1.5}
|
|
657
|
-
.${prefix}-sectionBadge{white-space:nowrap;border-radius:999px;flex:none;padding:1px 8px;font-size:11px;font-weight:500;line-height:17px}
|
|
658
|
-
.${prefix}-sectionDesc{color:var(--dsw-alias-label-tertiary);margin:4px 0 0;font-size:12px;line-height:1.5}
|
|
659
|
-
.${prefix}-sectionBody{flex-direction:column;min-width:0;display:flex}
|
|
660
|
-
.${prefix}-sectionFooter{align-items:center;gap:8px;padding-top:16px;display:flex;flex-wrap:wrap}
|
|
661
583
|
.${prefix}-groupLabel{color:var(--dsw-alias-label-secondary);font-size:12px;font-weight:600;padding:12px 0 2px;margin:0}
|
|
662
584
|
.${prefix}-readOnly{color:var(--dsw-alias-label-tertiary);margin:12px 0 0;font-size:12px;line-height:1.5}
|
|
663
585
|
.${prefix}-warn{color:var(--dsw-alias-label-error);margin:12px 0 0;font-size:12px;line-height:1.5}
|
|
664
|
-
.${prefix}-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;flex-wrap:wrap}
|
|
665
586
|
.${prefix}-status{min-width:0;color:var(--dsw-alias-label-secondary);flex:1;margin:0;font-size:12px;line-height:1.5}
|
|
666
587
|
.${prefix}-statusError{color:var(--dsw-alias-label-error)}
|
|
667
588
|
.${prefix}-btn{appearance:none;font:inherit;cursor:pointer;border:1px solid #0000;border-radius:8px;padding:5px 14px;font-size:13px;line-height:1.5}
|
|
@@ -671,16 +592,10 @@ window.__ModuleLoader__.load({
|
|
|
671
592
|
.${prefix}-btn:disabled{opacity:.4;cursor:default}
|
|
672
593
|
.${prefix}-btn:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:1px}
|
|
673
594
|
@media (max-width:767px){
|
|
674
|
-
.${prefix}-body{margin:0 10px}
|
|
675
|
-
.${prefix}-header{padding:12px 12px}
|
|
676
595
|
.${prefix}-input,.${prefix}-select{font-size:16px;height:40px}
|
|
677
596
|
.${prefix}-checkRow{min-height:44px;padding:8px 0}
|
|
678
|
-
.${prefix}-footer{position:sticky;bottom:0;background:var(--dsw-alias-bg-layer-2);margin:0 -10px;padding:10px 10px 6px;border-top:1px solid var(--dsw-alias-border-l2);border-bottom-left-radius:12px;border-bottom-right-radius:12px}
|
|
679
597
|
.${prefix}-status{flex-basis:100%;flex:none}
|
|
680
598
|
.${prefix}-btn{min-height:44px;flex:1;min-width:96px}
|
|
681
|
-
.${prefix}-statusBadge{display:none}
|
|
682
|
-
.${prefix}-sectionBadge{display:inline-block}
|
|
683
|
-
.${prefix}-sectionFooter{position:static}
|
|
684
599
|
}
|
|
685
600
|
@media (pointer:coarse){
|
|
686
601
|
.${prefix}-btn{min-height:44px}
|
|
@@ -711,8 +626,8 @@ ${extra}
|
|
|
711
626
|
* settings 命名空间字面量(纯常量,零依赖,浏览器半可安全引入)。
|
|
712
627
|
* 服务端直接以字面量注册(0.1.2-alpha.2 起 dsh-settings 对命名空间做编译期
|
|
713
628
|
* 语法校验,见 config.ts);浏览器半把它作为配置卡片的注册键
|
|
714
|
-
*
|
|
715
|
-
*
|
|
629
|
+
* (插件页配置卡片挂在 row/bundle config 槽位上,与命名空间解耦,
|
|
630
|
+
* 见 shared/config-slots),
|
|
716
631
|
* 同一字面量两处共用,防止漂移。
|
|
717
632
|
* @module image-studio/ns
|
|
718
633
|
*/
|
|
@@ -1514,8 +1429,8 @@ ${extra}
|
|
|
1514
1429
|
//#endregion
|
|
1515
1430
|
//#region src/client/card.tsx
|
|
1516
1431
|
/**
|
|
1517
|
-
* 配置卡片(injectPluginConfigCard
|
|
1518
|
-
*
|
|
1432
|
+
* 配置卡片(injectPluginConfigCard 两槽位 = 插件页 row/bundle config,
|
|
1433
|
+
* view 分发 summary/page):
|
|
1519
1434
|
* 三组预设(提供商/参数/提示词)+ 高级项(并发/超时/代理/画廊上限)的
|
|
1520
1435
|
* staged draft 编辑;提供商预设逐条附 API Key 管理(凭据端点,值不回显)。
|
|
1521
1436
|
* JSON 字段(extraHeaders/paramSpecs)以文本镜像编辑,保存时解析 +
|
|
@@ -1612,7 +1527,6 @@ ${extra}
|
|
|
1612
1527
|
const { t, scope, api } = props;
|
|
1613
1528
|
const snapshot = (0, react.useSyncExternalStore)((listener) => scope.subscribe(listener), () => scope.getSnapshot());
|
|
1614
1529
|
const value = snapshot.value;
|
|
1615
|
-
const [open, setOpen] = (0, react.useState)(props.view === "page");
|
|
1616
1530
|
const [draft, setDraft] = (0, react.useState)(null);
|
|
1617
1531
|
const [baseline, setBaseline] = (0, react.useState)("");
|
|
1618
1532
|
const [saving, setSaving] = (0, react.useState)(false);
|
|
@@ -1626,10 +1540,8 @@ ${extra}
|
|
|
1626
1540
|
}, [value, draft]);
|
|
1627
1541
|
const dirty = (0, react.useMemo)(() => draft !== null && JSON.stringify(draft) !== baseline, [draft, baseline]);
|
|
1628
1542
|
if (props.view === "summary") return t("card.summary");
|
|
1629
|
-
const variant = cardVariantFor(props.view);
|
|
1630
1543
|
if (value === void 0 || draft === null) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CardLoading, {
|
|
1631
1544
|
prefix: "imsc",
|
|
1632
|
-
variant,
|
|
1633
1545
|
text: t("common.loading")
|
|
1634
1546
|
});
|
|
1635
1547
|
const disabled = !snapshot.writable;
|
|
@@ -1688,9 +1600,6 @@ ${extra}
|
|
|
1688
1600
|
prefix: "imsc",
|
|
1689
1601
|
title: t("card.title"),
|
|
1690
1602
|
description: t("card.description"),
|
|
1691
|
-
open,
|
|
1692
|
-
onToggle: setOpen,
|
|
1693
|
-
variant,
|
|
1694
1603
|
statusBadge: {
|
|
1695
1604
|
text: draft.providers.length > 0 ? t("card.badgeOn").replace("{n}", String(draft.providers.length)) : t("card.badgeOff"),
|
|
1696
1605
|
on: draft.providers.length > 0
|
|
@@ -4171,10 +4080,8 @@ ${extra}
|
|
|
4171
4080
|
.imsc-loading{padding:14px 16px;margin:0;font-size:13px;color:var(--dsw-alias-label-tertiary)}
|
|
4172
4081
|
.imsc-groupTitle { margin: 14px 0 6px; font-size: 13px; font-weight: 600; }
|
|
4173
4082
|
.imsc-presetBox {
|
|
4174
|
-
border: 1px solid var(--dsw-alias-border-l3);
|
|
4175
|
-
|
|
4176
|
-
padding: 10px;
|
|
4177
|
-
margin-bottom: 10px;
|
|
4083
|
+
border-top: 1px solid var(--dsw-alias-border-l3);
|
|
4084
|
+
padding: 10px 0 2px;
|
|
4178
4085
|
display: grid;
|
|
4179
4086
|
gap: 8px;
|
|
4180
4087
|
}
|
|
@@ -4196,14 +4103,7 @@ ${extra}
|
|
|
4196
4103
|
}
|
|
4197
4104
|
.imsc-credRow { display: flex; align-items: center; gap: 8px; }
|
|
4198
4105
|
.imsc-credRow .imsc-input { flex: 1; min-width: 0; }
|
|
4199
|
-
|
|
4200
|
-
.imsc-section .imsc-presetBox {
|
|
4201
|
-
border: 0;
|
|
4202
|
-
border-top: 1px solid var(--dsw-alias-border-l2);
|
|
4203
|
-
border-radius: 0;
|
|
4204
|
-
padding: 10px 0 2px;
|
|
4205
|
-
margin-bottom: 0;
|
|
4206
|
-
}
|
|
4106
|
+
|
|
4207
4107
|
|
|
4208
4108
|
/* ── 移动端(≤767px,与 ui-mobile-fit 同断点)── */
|
|
4209
4109
|
@media (max-width: 767px) {
|
|
@@ -4237,7 +4137,6 @@ ${extra}
|
|
|
4237
4137
|
.ims-btn { min-height: 40px; }
|
|
4238
4138
|
.ims-btnSmall { min-height: 32px; }
|
|
4239
4139
|
.imsc-grid2 { grid-template-columns: 1fr; }
|
|
4240
|
-
.imsc-section .imsc-presetBox { padding: 10px 0 2px; }
|
|
4241
4140
|
}
|
|
4242
4141
|
`;
|
|
4243
4142
|
/** 注入面板 + 入口 + 卡片附加样式(重复调用幂等:已存在则跳过)。 */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dsh-plus/image-studio",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.25",
|
|
4
4
|
"description": "dsh-plus service+ui plugin: 图像工作室——OpenAI Images 协议文生图/图生图,全参数开关化,双预设体系,并发生图任务与可二次编辑画廊",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.js",
|
|
@@ -20,24 +20,24 @@
|
|
|
20
20
|
],
|
|
21
21
|
"dependencies": {
|
|
22
22
|
"https-proxy-agent": "^9.1.0",
|
|
23
|
-
"@dsh-plus/shared": "0.1.
|
|
23
|
+
"@dsh-plus/shared": "0.1.33"
|
|
24
24
|
},
|
|
25
25
|
"peerDependencies": {
|
|
26
|
-
"@deepseek-ai/cordis": "^4.0.
|
|
27
|
-
"@deepseek-ai/dsh-client-ui-primitives": "^0.2.
|
|
28
|
-
"@deepseek-ai/dsh-credentials": "^0.2.
|
|
29
|
-
"@deepseek-ai/dsh-host-webserver": "^0.2.
|
|
30
|
-
"@deepseek-ai/dsh-settings": "^0.2.
|
|
31
|
-
"@deepseek-ai/schemastery": "^3.18.
|
|
26
|
+
"@deepseek-ai/cordis": "^4.0.5-alpha.1",
|
|
27
|
+
"@deepseek-ai/dsh-client-ui-primitives": "^0.2.1-alpha.1",
|
|
28
|
+
"@deepseek-ai/dsh-credentials": "^0.2.1-alpha.1",
|
|
29
|
+
"@deepseek-ai/dsh-host-webserver": "^0.2.1-alpha.1",
|
|
30
|
+
"@deepseek-ai/dsh-settings": "^0.2.1-alpha.1",
|
|
31
|
+
"@deepseek-ai/schemastery": "^3.18.5-alpha.1"
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|
|
34
|
-
"@deepseek-ai/cordis": "4.0.
|
|
35
|
-
"@deepseek-ai/dsh-client-ui-primitives": "0.2.
|
|
36
|
-
"@deepseek-ai/dsh-credentials": "0.2.
|
|
37
|
-
"@deepseek-ai/dsh-host-webserver": "0.2.
|
|
38
|
-
"@deepseek-ai/dsh-session": "0.2.
|
|
39
|
-
"@deepseek-ai/dsh-settings": "0.2.
|
|
40
|
-
"@deepseek-ai/schemastery": "3.18.
|
|
34
|
+
"@deepseek-ai/cordis": "4.0.5-alpha.1",
|
|
35
|
+
"@deepseek-ai/dsh-client-ui-primitives": "0.2.1-alpha.1",
|
|
36
|
+
"@deepseek-ai/dsh-credentials": "0.2.1-alpha.1",
|
|
37
|
+
"@deepseek-ai/dsh-host-webserver": "0.2.1-alpha.1",
|
|
38
|
+
"@deepseek-ai/dsh-session": "0.2.1-alpha.1",
|
|
39
|
+
"@deepseek-ai/dsh-settings": "0.2.1-alpha.1",
|
|
40
|
+
"@deepseek-ai/schemastery": "3.18.5-alpha.1",
|
|
41
41
|
"@types/node": "26.4.0",
|
|
42
42
|
"@types/react": "~18.3.31",
|
|
43
43
|
"react": "^18.2.0"
|
package/src/client/card.tsx
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* 配置卡片(injectPluginConfigCard
|
|
3
|
-
*
|
|
2
|
+
* 配置卡片(injectPluginConfigCard 两槽位 = 插件页 row/bundle config,
|
|
3
|
+
* view 分发 summary/page):
|
|
4
4
|
* 三组预设(提供商/参数/提示词)+ 高级项(并发/超时/代理/画廊上限)的
|
|
5
5
|
* staged draft 编辑;提供商预设逐条附 API Key 管理(凭据端点,值不回显)。
|
|
6
6
|
* JSON 字段(extraHeaders/paramSpecs)以文本镜像编辑,保存时解析 +
|
|
@@ -13,7 +13,6 @@ import {
|
|
|
13
13
|
CardChrome,
|
|
14
14
|
CardLoading,
|
|
15
15
|
type CardStatusState,
|
|
16
|
-
cardVariantFor,
|
|
17
16
|
IDLE_STATUS,
|
|
18
17
|
type NamespaceSettingsApi,
|
|
19
18
|
type PluginConfigViewProps,
|
|
@@ -153,8 +152,6 @@ export function StudioConfigCard(props: CardProps): ReactElement | string | null
|
|
|
153
152
|
() => scope.getSnapshot(),
|
|
154
153
|
)
|
|
155
154
|
const value = snapshot.value as ImageStudioConfig | undefined
|
|
156
|
-
// 0.1.6-alpha.2 插件页 page 视图为表单落地页,默认展开;旧槽位无 view,保持折叠。
|
|
157
|
-
const [open, setOpen] = useState(props.view === 'page')
|
|
158
155
|
const [draft, setDraft] = useState<Draft | null>(null)
|
|
159
156
|
const [baseline, setBaseline] = useState('')
|
|
160
157
|
const [saving, setSaving] = useState(false)
|
|
@@ -176,11 +173,8 @@ export function StudioConfigCard(props: CardProps): ReactElement | string | null
|
|
|
176
173
|
// 插件页 summary 视图只出一行简介(hooks 已全部落定,可安全提前返回)。
|
|
177
174
|
if (props.view === 'summary') return t('card.summary')
|
|
178
175
|
|
|
179
|
-
// 插件页 page 视图内嵌宿主页面容器(已带页面级内边距与标题),用无边框分节。
|
|
180
|
-
const variant = cardVariantFor(props.view)
|
|
181
|
-
|
|
182
176
|
if (value === undefined || draft === null) {
|
|
183
|
-
return <CardLoading prefix="imsc"
|
|
177
|
+
return <CardLoading prefix="imsc" text={t('common.loading')} />
|
|
184
178
|
}
|
|
185
179
|
|
|
186
180
|
const disabled = !snapshot.writable
|
|
@@ -236,9 +230,6 @@ export function StudioConfigCard(props: CardProps): ReactElement | string | null
|
|
|
236
230
|
prefix="imsc"
|
|
237
231
|
title={t('card.title')}
|
|
238
232
|
description={t('card.description')}
|
|
239
|
-
open={open}
|
|
240
|
-
onToggle={setOpen}
|
|
241
|
-
variant={variant}
|
|
242
233
|
statusBadge={{
|
|
243
234
|
text:
|
|
244
235
|
draft.providers.length > 0
|
package/src/client/client.ts
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
* 浏览器半入口:
|
|
3
3
|
* - sidebar.footer.action:侧栏底部入口按钮(与文件/终端入口 flex 等分行宽);
|
|
4
4
|
* - shell.overlay:图像工作室面板(文生图/图生图/画廊 + 任务条);
|
|
5
|
-
* - 配置卡片:injectPluginConfigCard
|
|
6
|
-
*
|
|
5
|
+
* - 配置卡片:injectPluginConfigCard 两槽位(三组预设 + 凭据 + 高级项;
|
|
6
|
+
* 插件页 row/bundle config)。
|
|
7
7
|
* 模式与 web-files 一致:CJS factory 产物、data-plugin-css 样式
|
|
8
8
|
* 约定、slot 失配静默降级;配置读写经 ctx.remote.settings 直连(远程域名可用)。
|
|
9
9
|
* @module @dsh-plus/image-studio/client
|
package/src/client/styles.ts
CHANGED
|
@@ -561,10 +561,8 @@ export const imageStudioCss = `
|
|
|
561
561
|
.imsc-loading{padding:14px 16px;margin:0;font-size:13px;color:var(--dsw-alias-label-tertiary)}
|
|
562
562
|
.imsc-groupTitle { margin: 14px 0 6px; font-size: 13px; font-weight: 600; }
|
|
563
563
|
.imsc-presetBox {
|
|
564
|
-
border: 1px solid var(--dsw-alias-border-l3);
|
|
565
|
-
|
|
566
|
-
padding: 10px;
|
|
567
|
-
margin-bottom: 10px;
|
|
564
|
+
border-top: 1px solid var(--dsw-alias-border-l3);
|
|
565
|
+
padding: 10px 0 2px;
|
|
568
566
|
display: grid;
|
|
569
567
|
gap: 8px;
|
|
570
568
|
}
|
|
@@ -586,14 +584,7 @@ export const imageStudioCss = `
|
|
|
586
584
|
}
|
|
587
585
|
.imsc-credRow { display: flex; align-items: center; gap: 8px; }
|
|
588
586
|
.imsc-credRow .imsc-input { flex: 1; min-width: 0; }
|
|
589
|
-
|
|
590
|
-
.imsc-section .imsc-presetBox {
|
|
591
|
-
border: 0;
|
|
592
|
-
border-top: 1px solid var(--dsw-alias-border-l2);
|
|
593
|
-
border-radius: 0;
|
|
594
|
-
padding: 10px 0 2px;
|
|
595
|
-
margin-bottom: 0;
|
|
596
|
-
}
|
|
587
|
+
|
|
597
588
|
|
|
598
589
|
/* ── 移动端(≤767px,与 ui-mobile-fit 同断点)── */
|
|
599
590
|
@media (max-width: 767px) {
|
|
@@ -627,7 +618,6 @@ export const imageStudioCss = `
|
|
|
627
618
|
.ims-btn { min-height: 40px; }
|
|
628
619
|
.ims-btnSmall { min-height: 32px; }
|
|
629
620
|
.imsc-grid2 { grid-template-columns: 1fr; }
|
|
630
|
-
.imsc-section .imsc-presetBox { padding: 10px 0 2px; }
|
|
631
621
|
}
|
|
632
622
|
`
|
|
633
623
|
|
package/src/ns.ts
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
* settings 命名空间字面量(纯常量,零依赖,浏览器半可安全引入)。
|
|
3
3
|
* 服务端直接以字面量注册(0.1.2-alpha.2 起 dsh-settings 对命名空间做编译期
|
|
4
4
|
* 语法校验,见 config.ts);浏览器半把它作为配置卡片的注册键
|
|
5
|
-
*
|
|
6
|
-
*
|
|
5
|
+
* (插件页配置卡片挂在 row/bundle config 槽位上,与命名空间解耦,
|
|
6
|
+
* 见 shared/config-slots),
|
|
7
7
|
* 同一字面量两处共用,防止漂移。
|
|
8
8
|
* @module image-studio/ns
|
|
9
9
|
*/
|