@lmzhen/dsh-evolution-settings-ui 0.6.1 → 0.8.0
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.md +37 -5
- package/lib/client.js +597 -91
- package/lib/types/client/ParamCard.d.ts +24 -6
- package/lib/types/client/SettingsSection.d.ts +18 -0
- package/lib/types/client/generated-params.d.ts +11 -1
- package/lib/types/client/index.d.ts +18 -8
- package/lib/types/client/messages.d.ts +42 -19
- package/lib/types/client/seam.d.ts +45 -6
- package/lib/types/client/settle.d.ts +25 -0
- package/lib/types/client/styles.d.ts +34 -0
- package/package.json +3 -2
|
@@ -4,13 +4,27 @@
|
|
|
4
4
|
* Structural local types on purpose: this package is distributed outside the
|
|
5
5
|
* platform repository and a value import of another plugin is forbidden, so the
|
|
6
6
|
* settings scope and its snapshot are declared by the shape the renderer hands
|
|
7
|
-
* over (
|
|
7
|
+
* over (\`getSnapshot\`/\`subscribe\`, status/value/user/writable).
|
|
8
|
+
*
|
|
9
|
+
* Layout and behaviour follow the platform's own settings fields: a collapsed card
|
|
10
|
+
* header (namespace title, change count, chevron), then one block per field —
|
|
11
|
+
* label with its unit and source chip, a control HOLDING THE CURRENT VALUE, the
|
|
12
|
+
* Chinese hint — and one 放弃修改/保存 pair at the card's foot. The control is
|
|
13
|
+
* typed from the registry (\`control\`), so booleans are switches, enums are
|
|
14
|
+
* selects and numbers are numeric inputs with the unit shown beside the label.
|
|
8
15
|
*/
|
|
9
16
|
import { type ReactNode } from 'react';
|
|
10
17
|
import type { ClientParamField } from './generated-params.ts';
|
|
11
|
-
import type
|
|
18
|
+
import { type MessageKey } from './messages.ts';
|
|
12
19
|
import type { ParamSectionSnapshot, ParamSectionSource } from './seam.ts';
|
|
13
|
-
/**
|
|
20
|
+
/**
|
|
21
|
+
* Injected face: plain data and callbacks, plus the hook seat.
|
|
22
|
+
*
|
|
23
|
+
* The `hooks` compartment belongs to the shell, not to the component: the
|
|
24
|
+
* renderer binds its entries to `use<Name>` props and omits `hooks` from what
|
|
25
|
+
* the component receives. A card that reads `props.hooks` therefore reads a prop
|
|
26
|
+
* that never exists.
|
|
27
|
+
*/
|
|
14
28
|
export interface ParamCardFace {
|
|
15
29
|
namespace: string;
|
|
16
30
|
fields: readonly ClientParamField[];
|
|
@@ -21,9 +35,13 @@ export interface ParamCardFace {
|
|
|
21
35
|
paramSection: ParamSectionSource;
|
|
22
36
|
};
|
|
23
37
|
}
|
|
24
|
-
/**
|
|
25
|
-
|
|
26
|
-
|
|
38
|
+
/**
|
|
39
|
+
* Props the renderer binds for one card: the inject face minus its hook compartment,
|
|
40
|
+
* plus the seats bound from it. Spelled the way the shell derives it, so reaching for
|
|
41
|
+
* `props.hooks` fails the type check instead of failing at runtime.
|
|
42
|
+
*/
|
|
43
|
+
export type ParamCardProps = Omit<ParamCardFace, 'hooks'> & {
|
|
44
|
+
/** Bound from \`hooks.paramSection\` by the renderer. */
|
|
27
45
|
readonly useParamSection: <T>(selector: (state: ParamSectionSnapshot) => T) => T;
|
|
28
46
|
};
|
|
29
47
|
/**
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The section shell: title, one-line explanation, then one card per namespace.
|
|
3
|
+
*
|
|
4
|
+
* This is the shape the platform's own settings sections use — a heading plus the
|
|
5
|
+
* child slots it declared in its registration. The cards themselves are separate
|
|
6
|
+
* registrations keyed by namespace, so a namespace the Host does not serve simply
|
|
7
|
+
* renders nothing and a deployment that drops this row loses the whole section.
|
|
8
|
+
* @module @lmzhen/dsh-evolution-settings-ui/client
|
|
9
|
+
*/
|
|
10
|
+
import { type ReactNode } from 'react';
|
|
11
|
+
import { type SectionFace } from './seam.ts';
|
|
12
|
+
/**
|
|
13
|
+
* Render the section.
|
|
14
|
+
* @param face - the shell's inject face: translator and child-slot renderer.
|
|
15
|
+
* @returns the section element.
|
|
16
|
+
*/
|
|
17
|
+
export declare function SettingsSection(face: SectionFace): ReactNode;
|
|
18
|
+
//# sourceMappingURL=SettingsSection.d.ts.map
|
|
@@ -8,8 +8,18 @@
|
|
|
8
8
|
export interface ClientParamField {
|
|
9
9
|
id: string;
|
|
10
10
|
group: string;
|
|
11
|
-
/** The registry summary,
|
|
11
|
+
/** The registry summary (English), kept for parity with PARAMETERS.md. */
|
|
12
12
|
doc: string;
|
|
13
|
+
/** Card label, from the registry UI tail (Chinese). */
|
|
14
|
+
label: string;
|
|
15
|
+
/** Card help text, from the registry UI tail (Chinese). */
|
|
16
|
+
hint: string;
|
|
17
|
+
/** Which control the card renders. */
|
|
18
|
+
control: 'number' | 'switch' | 'select' | 'text';
|
|
19
|
+
/** Unit suffix for a number field ('' when it carries none). */
|
|
20
|
+
unit: string;
|
|
21
|
+
/** Allowed values for a select field ([] otherwise). */
|
|
22
|
+
values: readonly string[];
|
|
13
23
|
}
|
|
14
24
|
/** One card: the settings namespace plus the fields it exposes. */
|
|
15
25
|
export interface ClientParamSection {
|
|
@@ -1,18 +1,28 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Browser half: one
|
|
2
|
+
* Browser half: one settings section ("自进化") hosting one card per namespace.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
4
|
+
* Until 0.7.0 the cards lived inside the platform's own 插件 section, because
|
|
5
|
+
* this bundle injected `@deepseek-ai/dsh-client-ui-settings-plugins` and claimed
|
|
6
|
+
* its keyed `settings.plugin.item` slot. The parameters are not a plugin
|
|
7
|
+
* inventory though — the other feature areas (market, skins, Web plugins, side
|
|
8
|
+
* cards) each register their OWN section, so this bundle now does the same:
|
|
9
|
+
* inject the settings shell, register `settings.section`, and host the cards in
|
|
10
|
+
* a keyed child slot of that section.
|
|
11
|
+
*
|
|
12
|
+
* The join key is still the namespace itself: the Host half of each owning plugin
|
|
13
|
+
* registers it, this half claims it in the keyed card slot, and the section pairs
|
|
14
|
+
* them. A namespace the Host does not serve renders nothing, and a deployment that
|
|
15
|
+
* drops this row shows no section at all: the pair carries no Host-side behaviour.
|
|
9
16
|
* @module @lmzhen/dsh-evolution-settings-ui/client
|
|
10
17
|
*/
|
|
11
18
|
import type { Context as ClientContext } from '@deepseek-ai/cordis';
|
|
12
|
-
/** Required client services: the slot registry
|
|
19
|
+
/** Required client services: the slot registry, the settings transport, the locale seat. */
|
|
13
20
|
export declare const inject: string[];
|
|
21
|
+
/** Section id and nav order (the platform's own sections sit at 0/10/15/20). */
|
|
22
|
+
export declare const SECTION_ID = "evolution";
|
|
23
|
+
export declare const SECTION_ORDER = 25;
|
|
14
24
|
/**
|
|
15
|
-
* Register
|
|
25
|
+
* Register the locale namespace, the section and its cards.
|
|
16
26
|
* @param ctx - client cordis context.
|
|
17
27
|
*/
|
|
18
28
|
export declare function apply(ctx: ClientContext): void;
|
|
@@ -1,29 +1,52 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Copy for the evolution parameter cards.
|
|
2
|
+
* Copy for the evolution settings section and its parameter cards.
|
|
3
3
|
*
|
|
4
|
-
* The
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
4
|
+
* The section is registered through the platform's locale seat (`ctx.locale`),
|
|
5
|
+
* which is the same route the other out-of-repo client plugins take. The earlier
|
|
6
|
+
* note in this package's README — that an outside package cannot bind the locale
|
|
7
|
+
* seat — is wrong: `locale.register(namespace, { zh, en })` is the documented
|
|
8
|
+
* call, and it is what makes the section title and its copy follow the UI
|
|
9
|
+
* language instead of shipping one hard-coded dictionary.
|
|
8
10
|
*/
|
|
9
|
-
/**
|
|
10
|
-
export declare const
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
readonly
|
|
14
|
-
readonly
|
|
15
|
-
readonly
|
|
16
|
-
readonly
|
|
17
|
-
readonly
|
|
18
|
-
readonly
|
|
19
|
-
readonly
|
|
11
|
+
/** Locale namespace this bundle registers. */
|
|
12
|
+
export declare const NS = "evolution-settings";
|
|
13
|
+
/** Chinese copy (the family's primary language). */
|
|
14
|
+
export declare const zh: {
|
|
15
|
+
readonly title: "自进化";
|
|
16
|
+
readonly subtitle: "审查/记忆/策展/技能四个命名空间的参数可在用户层覆盖;此处只列可改项,其余仍由部署面决定。";
|
|
17
|
+
readonly overridden: "用户";
|
|
18
|
+
readonly deployment: "部署";
|
|
19
|
+
readonly loading: "正在读取设置文档…";
|
|
20
|
+
readonly unavailable: "这个命名空间没有宿主提供服务(对应插件行未挂载)";
|
|
21
|
+
readonly readonly: "本次会话的设置文档是只读的(内存模式)";
|
|
22
|
+
readonly apply: "保存";
|
|
23
|
+
readonly reset: "恢复部署默认";
|
|
24
|
+
readonly empty: "这个命名空间没有可改项";
|
|
25
|
+
readonly changed: "{n} 项已改";
|
|
26
|
+
readonly discard: "放弃修改";
|
|
27
|
+
readonly saving: "保存中…";
|
|
28
|
+
readonly refused: "写入未被接受——宿主的校验拒绝了它(值保持原样)。原因见 /evolution params 或 /evolution doctor。";
|
|
29
|
+
readonly cardReview: "审查";
|
|
30
|
+
readonly cardMemory: "记忆";
|
|
31
|
+
readonly cardToolMemory: "记忆工具";
|
|
32
|
+
readonly cardCurator: "策展";
|
|
33
|
+
readonly cardSkills: "技能";
|
|
20
34
|
};
|
|
35
|
+
/** English copy, key for key with {@link zh}. */
|
|
36
|
+
export declare const en: Record<keyof typeof zh, string>;
|
|
37
|
+
/**
|
|
38
|
+
* Card titles per settings namespace. A namespace without an entry falls back to
|
|
39
|
+
* its raw name, so a Host that registers a new namespace still renders — the
|
|
40
|
+
* title is presentation, the namespace is the join key.
|
|
41
|
+
*/
|
|
42
|
+
export declare const NAMESPACE_TITLES: Readonly<Record<string, string>>;
|
|
21
43
|
/** One message key. */
|
|
22
|
-
export type MessageKey = keyof typeof
|
|
44
|
+
export type MessageKey = keyof typeof zh;
|
|
23
45
|
/**
|
|
24
|
-
* Resolve one message.
|
|
46
|
+
* Resolve one message without the locale seat (tests and the fallback path).
|
|
25
47
|
* @param key - the message key.
|
|
48
|
+
* @param language - which dictionary to read; defaults to Chinese.
|
|
26
49
|
* @returns the copy this bundle carries.
|
|
27
50
|
*/
|
|
28
|
-
export declare function message(key: MessageKey): string;
|
|
51
|
+
export declare function message(key: MessageKey, language?: 'zh' | 'en'): string;
|
|
29
52
|
//# sourceMappingURL=messages.d.ts.map
|
|
@@ -4,11 +4,15 @@
|
|
|
4
4
|
* The package is distributed OUTSIDE the platform repository, so it declares the
|
|
5
5
|
* two seams it consumes instead of importing another plugin's values (forbidden
|
|
6
6
|
* by the client bundle-purity rule) or its types (which would drag the platform
|
|
7
|
-
* sources into this project). The shapes are the
|
|
8
|
-
* `settings.
|
|
9
|
-
* per-namespace settings scope the write path fences with the
|
|
7
|
+
* sources into this project). The shapes are the shell's contract: a
|
|
8
|
+
* `settings.section` registration hosting a keyed card slot, the inject faces
|
|
9
|
+
* both hand back, the per-namespace settings scope the write path fences with the
|
|
10
|
+
* revision it read, and the locale seat the section's copy resolves through.
|
|
10
11
|
* @module @lmzhen/dsh-evolution-settings-ui/client
|
|
11
12
|
*/
|
|
13
|
+
import type { ReactNode } from 'react';
|
|
14
|
+
/** Our card slot, hosted by the section this bundle registers. */
|
|
15
|
+
export declare const CARD_SLOT = "evolution.namespace.card";
|
|
12
16
|
/** Snapshot of one settings namespace, as the client scope reports it. */
|
|
13
17
|
export interface ParamSectionSnapshot {
|
|
14
18
|
status: 'loading' | 'ready' | 'unavailable';
|
|
@@ -27,23 +31,58 @@ export interface SettingsScopeLike {
|
|
|
27
31
|
set(field: string, value: unknown): Promise<void>;
|
|
28
32
|
unset(field: string): Promise<void>;
|
|
29
33
|
}
|
|
30
|
-
/** Registration options the keyed slot takes. */
|
|
34
|
+
/** Registration options the keyed card slot under our own section takes. */
|
|
31
35
|
export interface SlotRegisterOptions {
|
|
32
|
-
name:
|
|
36
|
+
name: typeof CARD_SLOT;
|
|
33
37
|
/** The settings namespace this card edits — the slot's key. */
|
|
34
38
|
key: string;
|
|
35
39
|
inject: () => unknown;
|
|
36
40
|
}
|
|
41
|
+
/** Options a `settings.section` registration carries (the shell's own shape). */
|
|
42
|
+
export interface SectionRegisterOptions {
|
|
43
|
+
name: 'settings.section';
|
|
44
|
+
/** Section id; the shell derives the nav entry's DOM id from it. */
|
|
45
|
+
id: string;
|
|
46
|
+
/** Nav order: the platform's own sections sit at 0/10/15/20. */
|
|
47
|
+
order: number;
|
|
48
|
+
/** Lazy label: the shell re-reads it when the locale changes. */
|
|
49
|
+
label: () => string;
|
|
50
|
+
/** Locale namespace the label and the section's copy resolve through. */
|
|
51
|
+
locale: string;
|
|
52
|
+
/** Child slots this section hosts, declared for the shell's renderer. */
|
|
53
|
+
children?: Record<string, {
|
|
54
|
+
kind: 'keyed' | 'list' | 'single';
|
|
55
|
+
scope: 'root';
|
|
56
|
+
}>;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* The face the shell hands a section component: a translator bound to our locale
|
|
60
|
+
* namespace and the renderer for the child slots we declared.
|
|
61
|
+
*/
|
|
62
|
+
export interface SectionFace {
|
|
63
|
+
t: (key: string) => string;
|
|
64
|
+
/** Render one child slot; `filter` selects keyed entries (e.g. `{ entryKey }`). */
|
|
65
|
+
renderSlot: (name: string, props?: Record<string, unknown>, filter?: Record<string, unknown>) => ReactNode;
|
|
66
|
+
}
|
|
67
|
+
/** The locale seat: register this bundle's namespace, bind a translator. */
|
|
68
|
+
export interface LocaleSeat {
|
|
69
|
+
register(namespace: string, dictionaries: {
|
|
70
|
+
zh: Record<string, string>;
|
|
71
|
+
en: Record<string, string>;
|
|
72
|
+
}): () => void;
|
|
73
|
+
bind(namespace: string): (key: string) => string;
|
|
74
|
+
}
|
|
37
75
|
/** The slice of the client context this plugin consumes. */
|
|
38
76
|
export interface ClientSeam {
|
|
39
77
|
slots: {
|
|
40
78
|
inject(name: string, callback: () => Generator<unknown, void, unknown>): unknown;
|
|
41
|
-
register(options: SlotRegisterOptions, component: (props: never) => unknown): () => void;
|
|
79
|
+
register(options: SlotRegisterOptions | SectionRegisterOptions, component: (props: never) => unknown): () => void;
|
|
42
80
|
};
|
|
43
81
|
settingsScope: {
|
|
44
82
|
bind(spec: {
|
|
45
83
|
namespace: string;
|
|
46
84
|
}): SettingsScopeLike;
|
|
47
85
|
};
|
|
86
|
+
locale: LocaleSeat;
|
|
48
87
|
}
|
|
49
88
|
//# sourceMappingURL=seam.d.ts.map
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The save verdict: did the Host take the values this card asked for?
|
|
3
|
+
*
|
|
4
|
+
* A write promise that resolves is not a verdict. Both settings scopes this bundle runs
|
|
5
|
+
* on finish a recovery read before it resolves, so a value the Host refused is simply
|
|
6
|
+
* still the previous one. Presence in the user layer cannot tell refusal from acceptance
|
|
7
|
+
* on a field the operator had already overridden — the refused value's key is present
|
|
8
|
+
* too — so the verdict compares what each staged id holds now against what was requested.
|
|
9
|
+
* @module @lmzhen/dsh-evolution-settings-ui
|
|
10
|
+
*/
|
|
11
|
+
/** One staged write awaiting its verdict. */
|
|
12
|
+
export interface PendingWrite {
|
|
13
|
+
/** Parameter id the write named. */
|
|
14
|
+
readonly id: string;
|
|
15
|
+
/** The value handed to the scope's `set`. */
|
|
16
|
+
readonly want: unknown;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Whether every staged write is visible in the user layer.
|
|
20
|
+
* @param pending - the writes awaiting a verdict.
|
|
21
|
+
* @param user - the user layer of the post-write snapshot; a non-section reads as empty.
|
|
22
|
+
* @returns true when each staged id now holds the value that was requested.
|
|
23
|
+
*/
|
|
24
|
+
export declare function landedWrites(pending: readonly PendingWrite[], user: unknown): boolean;
|
|
25
|
+
//# sourceMappingURL=settle.d.ts.map
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The section's stylesheet.
|
|
3
|
+
*
|
|
4
|
+
* The platform's own client bundles compile CSS Modules into a string and inject
|
|
5
|
+
* it once behind a \`<style data-plugin-css="<pkg>/<file>">\` tag; this bundle is
|
|
6
|
+
* built outside that pipeline, so it carries its own string and injects it the
|
|
7
|
+
* same way. Every rule reads the platform's design tokens (\`--dsw-alias-*\`), so
|
|
8
|
+
* the section follows the light and dark themes without owning a colour, and the
|
|
9
|
+
* field metrics (12px/6px padding-gap, 13px label, 12px hint) match the ones the
|
|
10
|
+
* platform's own settings fields use.
|
|
11
|
+
* @module @lmzhen/dsh-evolution-settings-ui/client
|
|
12
|
+
*/
|
|
13
|
+
/** Tag id that makes the injection idempotent. */
|
|
14
|
+
export declare const CSS_TAG_ID = "@lmzhen/dsh-evolution-settings-ui/settings.css";
|
|
15
|
+
/** The stylesheet the section injects once. */
|
|
16
|
+
export declare const CSS: string;
|
|
17
|
+
/** The slice of the DOM the injection touches (this package typechecks without DOM lib). */
|
|
18
|
+
interface StyleHost {
|
|
19
|
+
querySelector(selector: string): unknown;
|
|
20
|
+
createElement(tag: string): {
|
|
21
|
+
dataset: Record<string, string>;
|
|
22
|
+
textContent: string;
|
|
23
|
+
};
|
|
24
|
+
head: {
|
|
25
|
+
appendChild(node: unknown): void;
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Inject the stylesheet once per document.
|
|
30
|
+
* @param host - the document to inject into; defaults to the global one.
|
|
31
|
+
*/
|
|
32
|
+
export declare function injectStyles(host?: StyleHost): void;
|
|
33
|
+
export {};
|
|
34
|
+
//# sourceMappingURL=styles.d.ts.map
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lmzhen/dsh-evolution-settings-ui",
|
|
3
3
|
"description": "Web settings cards for the evolution family's parameter namespaces (community build)",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.8.0",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
@@ -33,7 +33,8 @@
|
|
|
33
33
|
"client": {
|
|
34
34
|
"platform": "web",
|
|
35
35
|
"inject": [
|
|
36
|
-
"@deepseek-ai/dsh-client-ui-settings
|
|
36
|
+
"@deepseek-ai/dsh-client-ui-settings",
|
|
37
|
+
"@deepseek-ai/dsh-client-locale"
|
|
37
38
|
]
|
|
38
39
|
}
|
|
39
40
|
},
|