@dsh-plus/image-studio 0.1.7 → 0.1.8
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 +43 -23
- package/package.json +1 -1
- package/src/client/panel/generator.tsx +31 -7
package/lib/client.js
CHANGED
|
@@ -2616,6 +2616,14 @@ ${extra}
|
|
|
2616
2616
|
function presetId(prefix) {
|
|
2617
2617
|
return `${prefix}-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 6)}`;
|
|
2618
2618
|
}
|
|
2619
|
+
/** 单选上传结果 → 遮罩引用(无成功条目时保持原值)。 */
|
|
2620
|
+
function uploadRef(entries) {
|
|
2621
|
+
const first = entries[0];
|
|
2622
|
+
return first === void 0 ? null : {
|
|
2623
|
+
kind: "upload",
|
|
2624
|
+
id: first.id
|
|
2625
|
+
};
|
|
2626
|
+
}
|
|
2619
2627
|
function GeneratorForm(props) {
|
|
2620
2628
|
const { t, endpoint, catalog, protocols, presets, gallery, scope, api } = props;
|
|
2621
2629
|
const [providerId, setProviderId] = (0, react.useState)("");
|
|
@@ -2980,40 +2988,52 @@ ${extra}
|
|
|
2980
2988
|
className: "ims-hint",
|
|
2981
2989
|
children: t("sources.count").replace("{n}", String(sources.length))
|
|
2982
2990
|
}),
|
|
2983
|
-
uploads.error !== null ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
|
|
2984
|
-
className: "ims-status ims-statusError",
|
|
2985
|
-
role: "alert",
|
|
2986
|
-
children: [t("upload.failed"), uploads.error]
|
|
2987
|
-
}) : null,
|
|
2988
2991
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", {
|
|
2989
2992
|
className: "ims-blockTitle",
|
|
2990
2993
|
children: t("sources.mask")
|
|
2991
2994
|
}),
|
|
2992
2995
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2993
2996
|
className: "ims-sources",
|
|
2994
|
-
children: [
|
|
2995
|
-
|
|
2996
|
-
|
|
2997
|
-
|
|
2998
|
-
|
|
2999
|
-
|
|
2997
|
+
children: [
|
|
2998
|
+
mask !== null ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
2999
|
+
className: "ims-thumb",
|
|
3000
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("img", {
|
|
3001
|
+
src: refUrl(mask),
|
|
3002
|
+
alt: ""
|
|
3003
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
3004
|
+
type: "button",
|
|
3005
|
+
className: "ims-thumbRemove",
|
|
3006
|
+
"aria-label": t("sources.maskClear"),
|
|
3007
|
+
onClick: () => setMask(null),
|
|
3008
|
+
children: "×"
|
|
3009
|
+
})]
|
|
3010
|
+
}) : null,
|
|
3011
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
3000
3012
|
type: "button",
|
|
3001
|
-
className: "ims-
|
|
3002
|
-
|
|
3003
|
-
|
|
3004
|
-
|
|
3005
|
-
|
|
3006
|
-
|
|
3007
|
-
|
|
3008
|
-
|
|
3009
|
-
|
|
3010
|
-
|
|
3011
|
-
|
|
3013
|
+
className: "ims-thumbAdd",
|
|
3014
|
+
onClick: () => setPicker("mask"),
|
|
3015
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconLayers, { size: 18 }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("sources.maskPick") })]
|
|
3016
|
+
}),
|
|
3017
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(UploadButton, {
|
|
3018
|
+
t,
|
|
3019
|
+
uploads,
|
|
3020
|
+
multiple: false,
|
|
3021
|
+
accept: "image/png",
|
|
3022
|
+
className: "ims-thumbAdd",
|
|
3023
|
+
onUploaded: (entries) => setMask(uploadRef(entries)),
|
|
3024
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconPlusOutline16, { size: 18 }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("upload.pick") })]
|
|
3025
|
+
})
|
|
3026
|
+
]
|
|
3012
3027
|
}),
|
|
3013
3028
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
3014
3029
|
className: "ims-hint",
|
|
3015
3030
|
children: t("sources.maskHint")
|
|
3016
|
-
})
|
|
3031
|
+
}),
|
|
3032
|
+
uploads.error !== null ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
|
|
3033
|
+
className: "ims-status ims-statusError",
|
|
3034
|
+
role: "alert",
|
|
3035
|
+
children: [t("upload.failed"), uploads.error]
|
|
3036
|
+
}) : null
|
|
3017
3037
|
]
|
|
3018
3038
|
}) : null
|
|
3019
3039
|
]
|
package/package.json
CHANGED
|
@@ -15,7 +15,13 @@ import {
|
|
|
15
15
|
type Scope,
|
|
16
16
|
} from '@dsh-plus/shared/client'
|
|
17
17
|
import { type ReactElement, useEffect, useMemo, useRef, useState } from 'react'
|
|
18
|
-
import type {
|
|
18
|
+
import type {
|
|
19
|
+
GenerateRequest,
|
|
20
|
+
PresetsWire,
|
|
21
|
+
ProvidersWire,
|
|
22
|
+
SourceRef,
|
|
23
|
+
UploadEntry,
|
|
24
|
+
} from '../../dto.ts'
|
|
19
25
|
import type { GalleryItem } from '../../gallery/store.ts'
|
|
20
26
|
import { MAX_SOURCE_IMAGES } from '../../limits.ts'
|
|
21
27
|
import type { ParamEntry } from '../../params/catalog.ts'
|
|
@@ -66,6 +72,12 @@ function presetId(prefix: string): string {
|
|
|
66
72
|
return `${prefix}-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 6)}`
|
|
67
73
|
}
|
|
68
74
|
|
|
75
|
+
/** 单选上传结果 → 遮罩引用(无成功条目时保持原值)。 */
|
|
76
|
+
function uploadRef(entries: UploadEntry[]): SourceRef | null {
|
|
77
|
+
const first = entries[0]
|
|
78
|
+
return first === undefined ? null : { kind: 'upload', id: first.id }
|
|
79
|
+
}
|
|
80
|
+
|
|
69
81
|
export function GeneratorForm(props: GeneratorProps): ReactElement {
|
|
70
82
|
const { t, endpoint, catalog, protocols, presets, gallery, scope, api } = props
|
|
71
83
|
const [providerId, setProviderId] = useState('')
|
|
@@ -433,12 +445,6 @@ export function GeneratorForm(props: GeneratorProps): ReactElement {
|
|
|
433
445
|
</UploadButton>
|
|
434
446
|
</div>
|
|
435
447
|
<p className="ims-hint">{t('sources.count').replace('{n}', String(sources.length))}</p>
|
|
436
|
-
{uploads.error !== null ? (
|
|
437
|
-
<p className="ims-status ims-statusError" role="alert">
|
|
438
|
-
{t('upload.failed')}
|
|
439
|
-
{uploads.error}
|
|
440
|
-
</p>
|
|
441
|
-
) : null}
|
|
442
448
|
<h3 className="ims-blockTitle">{t('sources.mask')}</h3>
|
|
443
449
|
<div className="ims-sources">
|
|
444
450
|
{mask !== null ? (
|
|
@@ -458,8 +464,26 @@ export function GeneratorForm(props: GeneratorProps): ReactElement {
|
|
|
458
464
|
<IconLayers size={18} />
|
|
459
465
|
<span>{t('sources.maskPick')}</span>
|
|
460
466
|
</button>
|
|
467
|
+
<UploadButton
|
|
468
|
+
t={t}
|
|
469
|
+
uploads={uploads}
|
|
470
|
+
multiple={false}
|
|
471
|
+
// 遮罩必须 PNG(官方要求带透明通道),文件选择器先行收窄。
|
|
472
|
+
accept="image/png"
|
|
473
|
+
className="ims-thumbAdd"
|
|
474
|
+
onUploaded={(entries) => setMask(uploadRef(entries))}
|
|
475
|
+
>
|
|
476
|
+
<IconPlusOutline16 size={18} />
|
|
477
|
+
<span>{t('upload.pick')}</span>
|
|
478
|
+
</UploadButton>
|
|
461
479
|
</div>
|
|
462
480
|
<p className="ims-hint">{t('sources.maskHint')}</p>
|
|
481
|
+
{uploads.error !== null ? (
|
|
482
|
+
<p className="ims-status ims-statusError" role="alert">
|
|
483
|
+
{t('upload.failed')}
|
|
484
|
+
{uploads.error}
|
|
485
|
+
</p>
|
|
486
|
+
) : null}
|
|
463
487
|
</section>
|
|
464
488
|
) : null}
|
|
465
489
|
</div>
|