@morlay/dsh-client-ui-primitives 0.0.3 → 0.0.5

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.
Files changed (34) hide show
  1. package/README.md +18 -266
  2. package/dist/client.cjs +11 -612
  3. package/dist/client.d.cts +33 -658
  4. package/dist/client.d.mts +33 -658
  5. package/dist/index.mjs +1 -1
  6. package/dist/{reference-Dxy9uQYz.mjs → reference-Cjcn21uW.mjs} +0 -1
  7. package/locale/en.json +1 -1
  8. package/locale/zh.json +1 -1
  9. package/package.json +18 -18
  10. package/src/client/index.ts +7 -9
  11. package/src/client/schema-form/Editor.tsx +25 -38
  12. package/src/client/schema-form/SchemaForm.tsx +6 -12
  13. package/src/client/schema-form/controller.ts +65 -123
  14. package/src/client/schema-form/draft.ts +55 -138
  15. package/src/client/schema-form/fields.tsx +5 -14
  16. package/src/client/schema-form/hints.ts +31 -131
  17. package/src/client/schema-form/index.ts +15 -20
  18. package/src/client/schema-form/labels.ts +7 -9
  19. package/src/client/schema-form/lines.ts +36 -60
  20. package/src/client/schema-form/locales.ts +6 -8
  21. package/src/client/schema-form/rows.ts +22 -41
  22. package/src/client/schema-form/schema-node.ts +87 -150
  23. package/src/client/schema-form/slot-contract.ts +55 -76
  24. package/src/client/schema-form/styles.ts +39 -51
  25. package/src/client/schema-form/testing/fake-describe.ts +3 -9
  26. package/src/client/schema-form/testing/fake-scope.ts +8 -10
  27. package/src/client/schema-form/value.tsx +14 -26
  28. package/src/client/settings-form/SettingsForm.tsx +13 -17
  29. package/src/client/settings-form/fields.tsx +25 -35
  30. package/src/client/settings-form/form-model.ts +63 -145
  31. package/src/client/styling/styled.tsx +3 -5
  32. package/src/client/theme.generated.ts +18 -7
  33. package/src/reference-markdown.tsx +1 -1
  34. package/src/reference.ts +1 -1
package/dist/client.d.cts CHANGED
@@ -9409,28 +9409,17 @@ declare const sxSymbol: unique symbol;
9409
9409
  type StyledComponent<T extends ElementType> = ForwardRefExoticComponent<StyledProps<T> & RefAttributes<StyledRef<T>>> & {
9410
9410
  readonly [sxSymbol]: CSSProps;
9411
9411
  };
9412
- /**
9413
- * `styled('div')({ padding: '4px' }, { '&:hover': { … } })` → 带 `data-css-*` 的组件。
9414
- * 多个样式对象按顺序深合并(后者覆盖前者),便于把变体叠在基样式上。
9415
- */
9416
9412
  declare function styled<T extends ElementType>(Component: T, defaultProps?: Partial<ComponentProps<T>>): (...styles: CSSProps[]) => StyledComponent<T>;
9417
- /** 取回 styled 组件携带的样式对象(需要在其之上继续组合时用)。 */
9418
9413
  declare function styleOf(component: StyledComponent<ElementType>): CSSProps;
9419
9414
  //#endregion
9420
9415
  //#region src/client/theme.generated.d.ts
9421
- /**
9422
- * 官方主题的 `--dsw-*` token 全集(395 个),由 packages/client/ui-primitives/scripts/gen-design-tokens.mts 生成,勿手改。
9423
- *
9424
- * 叶子是该变量的**默认值**(官方 light 主题里首次出现的定义):既是类型推导的来源,也可作 fallback。
9425
- * `"$"` 键出现在「自身也是 token 的分支」上(命名体系里有 40 个短名同时是长名前缀的 token)。
9426
- * 消费时只需树形状——`Token.vars()` 生成 `var(--dsw-…)`,不重新定义变量。
9427
- * 漂移、往返与默认值完整性由 src/__tests__/design-tokens.spec.ts 守卫。 */
9428
9416
  declare const designTokens: {
9429
9417
  readonly alias: {
9430
9418
  readonly bg: {
9431
9419
  readonly base: "var(--dsw-static-neutral-bluish-00)";
9432
9420
  readonly document: {
9433
9421
  readonly preview: "var(--dsw-static-neutral-bluish-100)";
9422
+ readonly selection: "color-mix(in srgb, var(--dsw-static-blue-500) 40%, transparent)";
9434
9423
  };
9435
9424
  readonly layer: {
9436
9425
  readonly "1": "var(--dsw-static-neutral-bluish-00)";
@@ -9550,6 +9539,12 @@ declare const designTokens: {
9550
9539
  };
9551
9540
  readonly label: {
9552
9541
  readonly caption: "var(--dsw-static-neutral-bluish-400)";
9542
+ readonly deep: {
9543
+ readonly diving: {
9544
+ readonly $: "color-mix(in srgb, var(--dsw-static-deepseek-500) 70%, var(--dsw-static-blue-950))";
9545
+ readonly shimmer: "color-mix(in srgb, var(--dsw-static-deepseek-500) 30%, var(--dsw-static-blue-950))";
9546
+ };
9547
+ };
9553
9548
  readonly dimmed: "var(--dsw-static-neutral-bluish-200)";
9554
9549
  readonly document: {
9555
9550
  readonly preview: "var(--dsw-static-neutral-bluish-700)";
@@ -9562,6 +9557,7 @@ declare const designTokens: {
9562
9557
  readonly inverted: "var(--dsw-static-neutral-bluish-00)";
9563
9558
  };
9564
9559
  readonly secondary: "var(--dsw-static-neutral-bluish-700)";
9560
+ readonly shimmer: "color-mix(in srgb, var(--dsw-static-neutral-1000) 30%, transparent)";
9565
9561
  readonly tertiary: "var(--dsw-static-neutral-bluish-600)";
9566
9562
  };
9567
9563
  readonly link: "var(--dsw-static-deepseek-500)";
@@ -9638,6 +9634,9 @@ declare const designTokens: {
9638
9634
  readonly tertiary: "var(--dsw-static-amber-100)";
9639
9635
  };
9640
9636
  };
9637
+ readonly switch: {
9638
+ readonly thumb: "var(--dsw-static-neutral-bluish-00)";
9639
+ };
9641
9640
  readonly toast: {
9642
9641
  readonly bg: "var(--dsw-static-neutral-bluish-800)";
9643
9642
  readonly label: "var(--dsw-static-neutral-bluish-00)";
@@ -10246,6 +10245,7 @@ declare const dsw: TokenVars<{
10246
10245
  readonly base: "var(--dsw-static-neutral-bluish-00)";
10247
10246
  readonly document: {
10248
10247
  readonly preview: "var(--dsw-static-neutral-bluish-100)";
10248
+ readonly selection: "color-mix(in srgb, var(--dsw-static-blue-500) 40%, transparent)";
10249
10249
  };
10250
10250
  readonly layer: {
10251
10251
  readonly "1": "var(--dsw-static-neutral-bluish-00)";
@@ -10365,6 +10365,12 @@ declare const dsw: TokenVars<{
10365
10365
  };
10366
10366
  readonly label: {
10367
10367
  readonly caption: "var(--dsw-static-neutral-bluish-400)";
10368
+ readonly deep: {
10369
+ readonly diving: {
10370
+ readonly $: "color-mix(in srgb, var(--dsw-static-deepseek-500) 70%, var(--dsw-static-blue-950))";
10371
+ readonly shimmer: "color-mix(in srgb, var(--dsw-static-deepseek-500) 30%, var(--dsw-static-blue-950))";
10372
+ };
10373
+ };
10368
10374
  readonly dimmed: "var(--dsw-static-neutral-bluish-200)";
10369
10375
  readonly document: {
10370
10376
  readonly preview: "var(--dsw-static-neutral-bluish-700)";
@@ -10377,6 +10383,7 @@ declare const dsw: TokenVars<{
10377
10383
  readonly inverted: "var(--dsw-static-neutral-bluish-00)";
10378
10384
  };
10379
10385
  readonly secondary: "var(--dsw-static-neutral-bluish-700)";
10386
+ readonly shimmer: "color-mix(in srgb, var(--dsw-static-neutral-1000) 30%, transparent)";
10380
10387
  readonly tertiary: "var(--dsw-static-neutral-bluish-600)";
10381
10388
  };
10382
10389
  readonly link: "var(--dsw-static-deepseek-500)";
@@ -10453,6 +10460,9 @@ declare const dsw: TokenVars<{
10453
10460
  readonly tertiary: "var(--dsw-static-amber-100)";
10454
10461
  };
10455
10462
  };
10463
+ readonly switch: {
10464
+ readonly thumb: "var(--dsw-static-neutral-bluish-00)";
10465
+ };
10456
10466
  readonly toast: {
10457
10467
  readonly bg: "var(--dsw-static-neutral-bluish-800)";
10458
10468
  readonly label: "var(--dsw-static-neutral-bluish-00)";
@@ -11059,22 +11069,14 @@ type MarkdownCopySeat = (key: "copy" | "copied" | "markdown.footnotes") => strin
11059
11069
  declare function markdownLabels(t: MarkdownCopySeat): MarkdownLabels;
11060
11070
  //#endregion
11061
11071
  //#region src/client/settings-form/form-model.d.ts
11062
- /** What the model reads of one Host entry's form. */
11063
11072
  interface SettingsFormScopeSnapshot<T> {
11064
- /** `ready` while the Host serves the entry to this client; the form renders nothing otherwise. */
11065
11073
  status: "loading" | "ready" | "unavailable";
11066
- /** Last accepted schema-resolved section; undefined before the first acceptance. */
11067
11074
  value: T | undefined;
11068
- /** Composition layer the value resolves over: what a field reverts to once cleared. */
11069
11075
  base: unknown;
11070
- /** Raw user layer as stored; a field's PRESENCE here is what marks it overridden. */
11071
11076
  user: unknown;
11072
- /** Whether the Host document accepts writes. */
11073
11077
  writable: boolean;
11074
- /** Revision the snapshot was read at; a save fences its mutation with the revision its drafts started from. */
11075
11078
  revision: number | undefined;
11076
11079
  }
11077
- /** One path edit a save sends, as the shared configuration form's `mutate` accepts it. */
11078
11080
  type SettingsFormPathOp = {
11079
11081
  op: "set";
11080
11082
  path: readonly string[];
@@ -11083,114 +11085,47 @@ type SettingsFormPathOp = {
11083
11085
  op: "unset";
11084
11086
  path: readonly string[];
11085
11087
  };
11086
- /** The entry form the model stages over: the reads and the atomic write of the form `ui-settings` shares per Host entry. */
11087
11088
  interface SettingsFormScope<T> {
11088
- /** @returns the current sync snapshot. */
11089
11089
  getSnapshot(): SettingsFormScopeSnapshot<T>;
11090
- /**
11091
- * Observe snapshot replacements.
11092
- * @param listener - invoked after each snapshot change.
11093
- * @returns the disposer removing this listener.
11094
- */
11095
11090
  subscribe(listener: () => void): () => void;
11096
- /**
11097
- * Apply ordered field edits in one revision-fenced write.
11098
- * @param ops - the edits, in staging order.
11099
- * @param expectedRevision - the revision the drafts were staged against, when known.
11100
- * @returns true for Host acceptance, false for refusal, after any recovery read.
11101
- */
11102
11091
  mutate(ops: readonly SettingsFormPathOp[], expectedRevision?: number): Promise<boolean>;
11103
11092
  }
11104
- /** The write one field's staged text performs when the card is saved. */
11105
11093
  type SettingsFieldWrite = {
11106
11094
  kind: "set";
11107
11095
  value: unknown;
11108
11096
  } | {
11109
11097
  kind: "clear";
11110
11098
  };
11111
- /** How one section field converts between its stored value and its draft text. */
11112
11099
  interface SettingsFieldSpec {
11113
- /** Field name inside the namespace section. */
11114
11100
  field: string;
11115
- /** Render a stored value as draft text; the empty string when the section carries none. */
11116
11101
  format: (value: unknown) => string;
11117
- /**
11118
- * The write this draft text stages, or undefined when the text is not a
11119
- * value this field accepts — which blocks the save rather than discarding it.
11120
- */
11121
11102
  parse: (text: string) => SettingsFieldWrite | undefined;
11122
11103
  }
11123
- /**
11124
- * A control whose value is written outside the settings section. A credential
11125
- * literal never rides a response, so its draft has nothing to seed from: it is
11126
- * blank until typed, and a blank draft writes nothing.
11127
- */
11128
11104
  interface SettingsSecretSpec {
11129
- /** Field name addressing this control inside the card's form. */
11130
11105
  field: string;
11131
- /** Write the staged text; resolves to whether the Host accepted it. */
11132
11106
  write: (text: string) => Promise<boolean>;
11133
11107
  }
11134
- /** One field as a card's control renders it. */
11135
11108
  interface SettingsFieldState {
11136
- /** Draft text the control renders. */
11137
11109
  text: string;
11138
- /**
11139
- * Whether saving would leave a user-layer entry for this field. A staged
11140
- * edit answers for itself, so the badge previews the save rather than
11141
- * reporting a state the pending edit already contradicts.
11142
- */
11143
11110
  overridden: boolean;
11144
- /** Whether the draft is not a value this field accepts, which blocks saving. */
11145
11111
  invalid: boolean;
11146
11112
  }
11147
- /** Form state every plugin card shares. */
11148
11113
  interface SettingsFormShell {
11149
- /** False while the namespace is not served to this client; the card renders nothing. */
11150
11114
  available: boolean;
11151
- /** Whether the Host document accepts writes. */
11152
11115
  writable: boolean;
11153
- /** Whether the form holds edits that a save would write. */
11154
11116
  dirty: boolean;
11155
- /** Whether any staged draft is invalid, which blocks the save. */
11156
11117
  invalid: boolean;
11157
- /** Whether a save is crossing the wire. */
11158
11118
  saving: boolean;
11159
- /** Whether the last save did not land as staged; cleared by the next edit or save. */
11160
11119
  failed: boolean;
11161
11120
  }
11162
- /** The write actions every plugin card's slot entry injects. */
11163
11121
  interface SettingsFormActions {
11164
- /** Stage draft text for one field. */
11165
11122
  edit: (field: string, text: string) => void;
11166
- /** Stage a clear, so saving lets the field re-inherit the composition layer. */
11167
11123
  resetField: (field: string) => void;
11168
- /** Write every staged edit, then re-seed from what the Host accepted. */
11169
11124
  save: () => void;
11170
- /** Drop every staged edit. */
11171
11125
  discard: () => void;
11172
11126
  }
11173
- /**
11174
- * A whole-number field. An empty draft clears the field; any other draft that
11175
- * is not a finite number blocks the save.
11176
- * @param field - field name inside the namespace section.
11177
- * @returns the field's conversion spec.
11178
- */
11179
11127
  declare function settingsNumberField(field: string): SettingsFieldSpec;
11180
- /**
11181
- * A free-text field. An empty draft clears the field, so emptying the control
11182
- * and saving is the same gesture as resetting it.
11183
- * @param field - field name inside the namespace section.
11184
- * @returns the field's conversion spec.
11185
- */
11186
11128
  declare function settingsTextField(field: string): SettingsFieldSpec;
11187
- /**
11188
- * Stages one card's edits over one settings namespace and writes them on save.
11189
- *
11190
- * The form publishes through a snapshot store because slot components read
11191
- * through a snapshot selector, while both the scope and the local drafts
11192
- * change underneath; every projection is rebuilt from the two together.
11193
- */
11194
11129
  declare class SettingsFormModel<T> {
11195
11130
  private readonly scope;
11196
11131
  private readonly specs;
@@ -11201,52 +11136,13 @@ declare class SettingsFormModel<T> {
11201
11136
  private readonly unsubscribe;
11202
11137
  private saving;
11203
11138
  private failed;
11204
- /**
11205
- * @param scope - the shared configuration form for this card's namespace.
11206
- * @param specs - the section fields this card edits.
11207
- * @param secrets - the card's write-only controls, written outside the section.
11208
- */
11209
11139
  constructor(scope: SettingsFormScope<T>, specs: SettingsFieldSpec[], secrets?: SettingsSecretSpec[]);
11210
- /**
11211
- * Publish a projection of this form, rebuilt whenever the scope or a draft changes.
11212
- * @param project - build the card's state from the form's current reads.
11213
- * @returns the store the card's component reads through its bound selector.
11214
- */
11215
11140
  bind<S>(project: () => S): SnapshotStore<S>;
11216
- /**
11217
- * Read the card-level state: what the Host serves, and what a save would do.
11218
- * @returns the form state every card shares.
11219
- */
11220
11141
  shell(): SettingsFormShell;
11221
- /**
11222
- * Read one control's state.
11223
- * @param field - field name of a section field or of a write-only control.
11224
- * @returns the draft text, whether a save would leave an override, and whether it is invalid.
11225
- */
11226
11142
  field(field: string): SettingsFieldState;
11227
- /**
11228
- * Build the edit, reset, save, and discard actions bound to this form.
11229
- * @returns the actions a card's slot entry injects.
11230
- */
11231
11143
  actions(): SettingsFormActions;
11232
- /**
11233
- * Write every staged edit, then re-seed from what the Host accepted.
11234
- *
11235
- * The Host is the only authority on whether a value was accepted — its
11236
- * validators own the constraints no schema can express — so the outcome is
11237
- * read back from the section rather than predicted here. A save that did not
11238
- * land keeps its drafts, so the user can correct them instead of retyping.
11239
- * @returns settlement after every write and the read-back.
11240
- */
11241
11144
  save(): Promise<void>;
11242
- /** Release the form's accepted-value subscription. */
11243
11145
  dispose(): void;
11244
- /**
11245
- * Every staged edit a save would write. An entry whose draft is not a value
11246
- * its field accepts carries no write: the form is still dirty, and the save
11247
- * refuses rather than dropping the edit.
11248
- * @returns the planned writes, in the order the fields were staged.
11249
- */
11250
11146
  private plan;
11251
11147
  private stage;
11252
11148
  private spec;
@@ -11259,162 +11155,82 @@ declare class SettingsFormModel<T> {
11259
11155
  }
11260
11156
  //#endregion
11261
11157
  //#region src/client/settings-form/fields.d.ts
11262
- /** What every settings field control needs regardless of its value type. */
11263
11158
  interface SettingsFieldProps {
11264
- /** Stable id associating the label with its control. */
11265
11159
  id: string;
11266
- /** Visible label. */
11267
11160
  label: string;
11268
- /** One-line explanation rendered under the control. */
11269
11161
  hint: string;
11270
- /** Draft text this control renders. */
11271
11162
  text: string;
11272
- /** True when saving would leave a user-layer entry for this field. */
11273
11163
  overridden: boolean;
11274
- /** True when the draft is not a value this field accepts. */
11275
11164
  invalid: boolean;
11276
- /** Copy for the overridden badge. */
11277
11165
  overriddenLabel: string;
11278
- /** Copy for the reset control. */
11279
11166
  resetLabel: string;
11280
- /** Copy shown in place of the hint while the draft is invalid. */
11281
11167
  invalidLabel: string;
11282
- /** Disables every control (read-only document, or an unavailable namespace). */
11283
11168
  disabled: boolean;
11284
- /** Stage draft text. */
11285
11169
  onEdit: (text: string) => void;
11286
- /** Stage a clear so the field re-inherits the composition layer. */
11287
11170
  onReset: () => void;
11288
11171
  }
11289
- /**
11290
- * A staged value field. `numeric` only hints the keypad: which drafts a field
11291
- * accepts is decided by its spec, so the control never silently rewrites what
11292
- * the user typed.
11293
- * @param props - the field's copy, its staged text, and the edit actions.
11294
- * @returns the labelled control.
11295
- */
11296
11172
  declare function SettingsValueField(props: Omit<SettingsFieldProps, "hint"> & {
11297
- /** Optional explanation shown below the input. */
11298
11173
  hint?: string;
11299
- /** Rules disclosed by the information button beside the label. */
11300
11174
  help?: {
11301
11175
  label: string;
11302
11176
  content: ReactNode;
11303
11177
  };
11304
- /** Hints a numeric keypad without narrowing what the control accepts. */
11305
11178
  numeric?: boolean;
11306
- /** Placeholder shown while the draft is empty. */
11307
11179
  placeholder?: string;
11308
11180
  }): import("react/jsx-runtime").JSX.Element;
11309
- /**
11310
- * A write-only credential control. The value never rides a response, so the
11311
- * control reports only whether one is configured and starts blank; a blank
11312
- * draft writes nothing, which keeps the stored key rather than clearing it.
11313
- * 控件要求浏览器不要把已存的登录密码自动填进来(上游 11c0511271)。
11314
- * @param props - the field's copy, its staged text, and the configured state.
11315
- * @returns the labelled control.
11316
- */
11317
11181
  declare function SettingsSecretField(props: Pick<SettingsFieldProps, "id" | "label" | "hint" | "text" | "disabled" | "onEdit"> & {
11318
- /** Whether the Host reports a configured credential for this reference. */
11319
11182
  configured: boolean;
11320
- /** Copy describing the configured state. */
11321
11183
  stateLabel: string;
11322
11184
  }): import("react/jsx-runtime").JSX.Element;
11323
11185
  //#endregion
11324
11186
  //#region src/client/settings-form/SettingsForm.d.ts
11325
- /** The copy the form frame renders, from the owning plugin's dictionary. */
11326
11187
  interface SettingsFormLabels {
11327
- /** Shown in place of the controls while the namespace is not served. */
11328
11188
  unavailable: string;
11329
- /** Shown over the controls while the document is read-only. */
11330
11189
  readOnly: string;
11331
- /** Shown beside the save after a save the Host did not accept. */
11332
11190
  saveFailed: string;
11333
- /** The save control. */
11334
11191
  save: string;
11335
- /** The save control while a save is crossing the wire. */
11336
11192
  saving: string;
11337
11193
  }
11338
- /** Form chrome shared by every settings page. */
11339
11194
  interface SettingsFormProps {
11340
- /** The frame's copy. */
11341
11195
  labels: SettingsFormLabels;
11342
- /** The form state: availability, writability, and what a save would do. */
11343
11196
  state: SettingsFormShell;
11344
- /** Write every staged edit. */
11345
11197
  onSave: () => void;
11346
- /** Drop every staged edit; the form calls it when it leaves the page. */
11347
11198
  onDiscard: () => void;
11348
- /** The plugin's controls. */
11349
11199
  children: ReactNode;
11350
11200
  }
11351
- /**
11352
- * Render one plugin's settings form.
11353
- * @param props - the form's copy and state, its controls, and the save and discard actions.
11354
- * @returns the form, or the unavailable line while the namespace is not served.
11355
- */
11356
11201
  declare function SettingsForm(props: SettingsFormProps): import("react/jsx-runtime").JSX.Element;
11357
11202
  //#endregion
11358
11203
  //#region src/client/schema-form/schema-node.d.ts
11359
- /** 节点不可编辑的原因;`null` 表示可编辑。 */
11360
11204
  type ReadOnlyReason = "transform" | "function" | "constructor";
11361
- /** 归一化后的字段元数据(schemastery `meta` 的可用子集)。 */
11362
11205
  interface FieldMeta {
11363
- /** `description`(可能是本地化字典):渲染时经 locale 解析。 */
11364
11206
  description: string | Readonly<Record<string, string>> | undefined;
11365
- /** `comment`:纯文本补充说明。 */
11366
11207
  comment: string | undefined;
11367
- /** `link`:外部文档。 */
11368
11208
  link: string | undefined;
11369
- /** `role`:控件提示(`secret` / `slider` / `datetime` …)。 */
11370
11209
  role: string | undefined;
11371
- /** `role === 'secret'`:值不回传,只能写。 */
11372
11210
  secret: boolean;
11373
- /** `required()`。 */
11374
11211
  required: boolean;
11375
- /** `disabled()`:控件禁用。 */
11376
11212
  disabled: boolean;
11377
- /** `collapse()`:嵌套分组默认折叠。 */
11378
11213
  collapse: boolean;
11379
- /** `deprecated()` / `experimental()` 的徽标文本。 */
11380
11214
  badges: readonly string[];
11381
- /** `pattern()` 的正则来源。 */
11382
11215
  pattern: string | undefined;
11383
- /** `min()`。 */
11384
11216
  min: number | undefined;
11385
- /** `max()`。 */
11386
11217
  max: number | undefined;
11387
- /** `step()`:`1` 表示整数。 */
11388
11218
  step: number | undefined;
11389
- /** 是否声明了默认值(与「默认值是 undefined」区分开)。 */
11390
11219
  hasDefault: boolean;
11391
- /** 声明的默认值。 */
11392
11220
  defaultValue: unknown;
11393
- /** `extra()`:角色附带的任意数据,字段槽的自定义控件可用。 */
11394
11221
  extra: unknown;
11395
11222
  }
11396
- /** 每种节点共有的部分。 */
11397
11223
  interface FieldNodeBase {
11398
- /** 这一层的名字:对象字段名、tuple 的索引、动态子节点的占位段。 */
11399
11224
  key: string;
11400
- /** 从段根起的路径;动态段是 {@link DYNAMIC_SEGMENT}。 */
11401
11225
  path: readonly string[];
11402
- /**
11403
- * 按值展开时算好的显示名:数组成员的**项身份**(见 {@link FieldNodeBase} 所在的 array 节点)。
11404
- * 投影时没有(`undefined`),渲染层用它优先于字段名。
11405
- */
11406
11226
  label: string | undefined;
11407
- /** 归一化后的元数据。 */
11408
11227
  meta: FieldMeta;
11409
- /** 不可编辑的原因;`null` 表示可编辑。 */
11410
11228
  readOnly: ReadOnlyReason | null;
11411
11229
  }
11412
- /** 位集的一位。 */
11413
11230
  interface BitsEntry {
11414
11231
  name: string;
11415
11232
  bit: number;
11416
11233
  }
11417
- /** 渲染层要的一个字段节点。 */
11418
11234
  type FieldNode = (FieldNodeBase & {
11419
11235
  type: "object";
11420
11236
  fields: readonly FieldNode[];
@@ -11425,25 +11241,14 @@ type FieldNode = (FieldNodeBase & {
11425
11241
  }) | (FieldNodeBase & {
11426
11242
  type: "array";
11427
11243
  item: FieldNode;
11428
- /**
11429
- * 项的**身份键**:这一项的「名字」取自它自己的哪个字段。显式声明优先
11430
- * (`z.array(inner).role('items', { mergeKey: 'id' })`),否则 item 上有 `id` 字段就用 `id`。
11431
- * 它只决定显示名与「同名即冲突」的判据——写盘仍按索引(host 的 path op 就是索引语义)。
11432
- */
11433
11244
  mergeKey: string | undefined;
11434
11245
  }) | (FieldNodeBase & {
11435
11246
  type: "tuple";
11436
11247
  items: readonly FieldNode[];
11437
11248
  }) | (FieldNodeBase & {
11438
11249
  type: "union";
11439
- /** 成员全是字面量时的可选项;否则 `undefined`。 */
11440
11250
  choices: readonly unknown[] | undefined;
11441
11251
  variants: readonly FieldNode[];
11442
- /**
11443
- * 判别标签:按哪个字段的值挑变体。显式声明优先
11444
- * (`z.union([...]).role('union', { tag: 'kind' })`),否则取所有对象成员共有的**唯一**常量字段。
11445
- * schemastery 本身没有 tag 机制(union 按声明顺序逐个试),所以这只是渲染与校验的选支依据。
11446
- */
11447
11252
  tagKey: string | undefined;
11448
11253
  }) | (FieldNodeBase & {
11449
11254
  type: "intersect";
@@ -11459,441 +11264,166 @@ type FieldNode = (FieldNodeBase & {
11459
11264
  inner: FieldNode;
11460
11265
  }) | (FieldNodeBase & {
11461
11266
  type: "string" | "number" | "boolean" | "any" | "never" | "function";
11462
- }) |
11463
- /** 自引用 schema 回到祖先处:值这一层以下不再描述,由渲染层展开或只读呈现。 */
11464
- (FieldNodeBase & {
11267
+ }) | (FieldNodeBase & {
11465
11268
  type: "recursive";
11466
11269
  origin: string;
11467
11270
  });
11468
- /**
11469
- * 投影一个 schema 节点。
11470
- * @param schema - rehydrate 之后的 volatile 表单 schema(或它的子节点)。
11471
- * @param path - 该节点相对段根的路径;动态子节点由调用方给占位段。
11472
- * @returns 渲染层要的字段树。
11473
- */
11474
11271
  declare function projectNode(schema: SchemaNode, path?: readonly string[]): FieldNode;
11475
- /** 按当前值展开出的一个字段:路径与名字已按真实键与索引替换。 */
11476
11272
  interface WalkedField {
11477
11273
  path: readonly string[];
11478
11274
  node: FieldNode;
11479
- /**
11480
- * 这一行是某个动态容器的**成员本身**(dict 的键 / array 的项)时给出它的身份:容器路径、键、以及数组
11481
- * 项的位置。渲染层用它画成员行(名字 + 移除);成员的子字段不带这个标记。
11482
- */
11483
11275
  member?: {
11484
11276
  parent: readonly string[];
11485
11277
  key: string;
11486
11278
  index: number | undefined;
11487
11279
  };
11488
11280
  }
11489
- /** 候选键的来源(业务注册;见 `hints.ts`):dict 的「可以加哪些键」。 */
11490
11281
  interface SuggestedKeys {
11491
- /**
11492
- * 读某个 dict 字段的候选键。
11493
- * @param path - 该字段的具体路径。
11494
- * @returns 候选键;没有就是空数组。
11495
- */
11496
11282
  keysFor(path: readonly string[]): readonly string[];
11497
11283
  }
11498
- /**
11499
- * 按当前值把字段树展开成渲染顺序的扁平列表(前序):容器在前、子项紧随其后。
11500
- *
11501
- * 出现的**只有值里有的东西,加上必填的**:对象的必填字段始终占行(值是空的也要让用户看见"必须填"),非必填的
11502
- * 按值出现——值里没有就不占行,它在这一层的「添加属性」候选里,选中才加。数组按索引、字典按键展开;字面量
11503
- * union 是叶子控件,对象 union 只展开与当前值匹配的那个变体,intersect 的各成员在同一层展开。
11504
- * @param root - 段根的字段树。
11505
- * @param value - 生效值(或草稿后的值)。
11506
- * @returns 渲染顺序的字段列表。
11507
- */
11508
11284
  declare function walkFields(root: FieldNode, value: unknown): WalkedField[];
11509
- /** union 的变体切换:一个选项要写的值。 */
11510
11285
  interface VariantChoice {
11511
- /** 页面上显示的名字:判别标签的值,或变体的形状。 */
11512
11286
  label: string;
11513
- /** 写这个值就等于选中这一支。 */
11514
11287
  value: unknown;
11515
11288
  }
11516
11289
  //#endregion
11517
11290
  //#region src/client/schema-form/draft.d.ts
11518
- /** 命名空间段(一段配置)的值。 */
11519
11291
  type Section = Record<string, unknown>;
11520
- /** 文本草稿的解析结果:控件把用户输入交给保存那一刻解析。 */
11521
- type TextParseResult =
11522
- /** 得到一个值。 */
11523
- {
11292
+ type TextParseResult = {
11524
11293
  kind: "value";
11525
11294
  value: unknown;
11526
- } |
11527
- /** 这段文本不产生写(例如 secret 留空=保留已存的值)。 */
11528
- {
11295
+ } | {
11529
11296
  kind: "skip";
11530
- } |
11531
- /** 不是这个字段接受的值:留在屏幕上并挡住保存。 */
11532
- {
11297
+ } | {
11533
11298
  kind: "invalid";
11534
11299
  message: string;
11535
11300
  };
11536
- /** 控件给文本草稿的解析规则。 */
11537
11301
  type TextParse = (text: string) => TextParseResult;
11538
- /** 整段校验失败:消息 + 它落在哪一层(页面把消息画在**出错的那一行**上)。 */
11539
11302
  interface ValidationFailure {
11540
- /** 面向用户的消息(已去掉 schemastery 拼的 `$…` 位置前缀)。 */
11541
11303
  message: string;
11542
- /** 具体路径(段根起);空数组表示错误在整段上。 */
11543
11304
  path: readonly string[];
11544
11305
  }
11545
- /**
11546
- * 把校验器抛出的错误收成一条失败。
11547
- *
11548
- * schemastery 的 `ValidationError` 把路径留在 `options.path` 上(消息里的 `$…` 前缀是给命令行看的),所以这里
11549
- * 取路径、去前缀——行内报错据此知道挂在哪一行。
11550
- * @param error - 校验器抛出的错误。
11551
- * @returns 消息与路径。
11552
- */
11553
11306
  declare function failureOf(error: unknown): ValidationFailure;
11554
- /** 一字段渲染时要读的状态。 */
11555
11307
  interface DraftFieldState {
11556
- /** 控件要显示的值:草稿优先,否则生效层。 */
11557
11308
  value: unknown;
11558
- /** 文本草稿(文本控件显示它而不是重新格式化值)。 */
11559
11309
  text: string | undefined;
11560
- /** 草稿不合法时的消息(控件显示,同时挡住保存)。 */
11561
11310
  invalid: string | undefined;
11562
- /** 保存后这一字段是否会留下用户层条目。 */
11563
11311
  overridden: boolean;
11564
- /** 这一字段在本页有还没保存的编辑(页面上给它一处高亮与一个「撤回」)。 */
11565
11312
  staged: boolean;
11566
11313
  }
11567
- /** 模型要读要写的那个命名空间。 */
11568
11314
  type DraftScope = ConfigForm<Section>;
11569
11315
  //#endregion
11570
11316
  //#region src/client/schema-form/hints.d.ts
11571
- /** 一个 dict 字段的候选键读数。 */
11572
11317
  type SuggestedKeysReader = () => readonly string[];
11573
- /** 一个字段的文案(业务知道的说法;schema 上没有 title 这种位)。 */
11574
11318
  interface FieldText {
11575
- /** 短名字(行式视图里当注释的抬头)。 */
11576
11319
  label?: string | undefined;
11577
- /** 一句话说明。 */
11578
11320
  hint?: string | undefined;
11579
11321
  }
11580
- /** 一个字段的文案读数。 */
11581
11322
  type FieldTextReader = () => FieldText;
11582
- /** 一个可选项:要写进去的值,以及页面上显示的名字。 */
11583
11323
  interface SelectOption {
11584
- /** 选中时写进配置的值。 */
11585
11324
  value: unknown;
11586
- /** 显示名;省略就用值本身。 */
11587
11325
  label?: string | undefined;
11588
11326
  }
11589
- /** 一个字段的候选值读数。 */
11590
11327
  interface SelectSpec {
11591
- /**
11592
- * 候选依赖哪些**兄弟字段**(相对该字段所在对象的路径)。
11593
- *
11594
- * 依赖只声明"什么时候要重算":读侧在投影时按当前读数(草稿优先)求一次候选,所以声明了依赖的字段会随着
11595
- * 兄弟字段的编辑立刻换候选——「选完服务商才列它有哪些模型」就是这么来的。
11596
- */
11597
11328
  dependsOn?: readonly (readonly string[])[] | undefined;
11598
- /**
11599
- * 求候选。
11600
- * @param read - 按依赖路径(相对该字段所在对象)读当前值:草稿优先。
11601
- * @returns 可选项,顺序即页面上的顺序。
11602
- */
11603
11329
  options: (read: (path: readonly string[]) => unknown) => readonly SelectOption[];
11604
11330
  }
11605
- /** 一个命名空间里各字段的候选键、文案与候选值。 */
11606
11331
  interface SchemaFormHintsFace {
11607
- /**
11608
- * 注册一个 dict 字段的候选键读数(重复注册同一处会覆盖,并通知一次)。
11609
- * @param ns - settings 命名空间(行 id)。
11610
- * @param path - 该 dict 字段的具体路径(顶层字段就是 `['models']`)。
11611
- * @param read - 同步读数:当前候选键(顺序即页面上的顺序)。
11612
- * @returns 注销函数。
11613
- */
11614
11332
  suggestKeys(ns: string, path: readonly string[], read: SuggestedKeysReader): () => void;
11615
- /**
11616
- * 读某处当前声明的候选键。
11617
- * @param ns - settings 命名空间。
11618
- * @param path - 该字段的路径。
11619
- * @returns 候选键;没注册过就是空数组。
11620
- */
11621
11333
  keysFor(ns: string, path: readonly string[]): readonly string[];
11622
- /**
11623
- * 注册一个字段的文案(短名 + 一句话说明)。行式视图把它画成注释行;schema 的 `description` 是兜底。
11624
- * @param ns - settings 命名空间。
11625
- * @param path - 该字段的路径。
11626
- * @param read - 同步读数。
11627
- * @returns 注销函数。
11628
- */
11629
11334
  describe(ns: string, path: readonly string[], read: FieldTextReader): () => void;
11630
- /**
11631
- * 读某处当前注册的文案。
11632
- * @param ns - settings 命名空间。
11633
- * @param path - 该字段的路径。
11634
- * @returns 文案;没注册过就是空对象。
11635
- */
11636
11335
  textFor(ns: string, path: readonly string[]): FieldText;
11637
- /**
11638
- * 注册一个字段的候选值读数(页面据此把字段画成选择器,并随依赖字段变化重算)。
11639
- * @param ns - settings 命名空间。
11640
- * @param path - 该字段的路径。
11641
- * @param spec - 候选取法与它依赖的兄弟字段。
11642
- * @returns 注销函数。
11643
- */
11644
11336
  select(ns: string, path: readonly string[], spec: SelectSpec): () => void;
11645
- /**
11646
- * 注册一个**具名候选源**:schema 上用 `role('select', { source })` 认领它,字段因此不必在客户端按 ns/path
11647
- * 登记——同一个源可以被多行、多个字段复用(「服务商」「模型」就是这种)。
11648
- * @param name - 源的名字(schema 的 `role` extra 里写的那一个)。
11649
- * @param spec - 候选取法与它依赖的兄弟字段。
11650
- * @returns 注销函数。
11651
- */
11652
11337
  source(name: string, spec: SelectSpec): () => void;
11653
- /**
11654
- * 读一个具名候选源。
11655
- * @param name - 源的名字。
11656
- * @returns 该源的读数;没注册过就是 `undefined`。
11657
- */
11658
11338
  sourceFor(name: string): SelectSpec | undefined;
11659
- /**
11660
- * 读某处当前声明的候选值读数。
11661
- * @param ns - settings 命名空间。
11662
- * @param path - 该字段的路径。
11663
- * @returns 候选读数;没注册过就是 `undefined`。
11664
- */
11665
11339
  selectFor(ns: string, path: readonly string[]): SelectSpec | undefined;
11666
11340
  }
11667
- /** 提示面的完整服务(业务用注册侧,表单一侧用读侧)。 */
11668
11341
  declare class SchemaFormHints extends Service implements SchemaFormHintsFace {
11669
11342
  #private;
11670
- /** @param ctx - 提供本服务的插件上下文。 */
11671
11343
  constructor(ctx: Context);
11672
- /** @param ns - settings 命名空间。 @param path - 字段路径。 @returns 该处的键。 */
11673
11344
  keysFor(ns: string, path: readonly string[]): readonly string[];
11674
- /** @param ns - settings 命名空间。 @param path - 字段路径。 @returns 该处注册的文案。 */
11675
11345
  textFor(ns: string, path: readonly string[]): FieldText;
11676
- /**
11677
- * @param ns - settings 命名空间。
11678
- * @param path - 字段路径。
11679
- * @param spec - 候选取法与依赖。
11680
- * @returns 注销函数。
11681
- */
11682
11346
  select(ns: string, path: readonly string[], spec: SelectSpec): () => void;
11683
- /** @param ns - settings 命名空间。 @param path - 字段路径。 @returns 该处注册的候选读数。 */
11684
11347
  selectFor(ns: string, path: readonly string[]): SelectSpec | undefined;
11685
- /**
11686
- * @param name - 源的名字。
11687
- * @param spec - 候选取法与依赖。
11688
- * @returns 注销函数。
11689
- */
11690
11348
  source(name: string, spec: SelectSpec): () => void;
11691
- /** @param name - 源的名字。 @returns 该源注册的候选读数。 */
11692
11349
  sourceFor(name: string): SelectSpec | undefined;
11693
- /**
11694
- * @param ns - settings 命名空间。
11695
- * @param path - 字段路径。
11696
- * @param read - 同步读数。
11697
- * @returns 注销函数。
11698
- */
11699
11350
  describe(ns: string, path: readonly string[], read: FieldTextReader): () => void;
11700
- /**
11701
- * @param ns - settings 命名空间。
11702
- * @param path - 字段路径。
11703
- * @param read - 同步读数。
11704
- * @returns 注销函数。
11705
- */
11706
11351
  suggestKeys(ns: string, path: readonly string[], read: SuggestedKeysReader): () => void;
11707
- /**
11708
- * 观察候选键的变化(注册与注销)。
11709
- * @param listener - 变更回调。
11710
- * @returns 取消订阅。
11711
- */
11712
11352
  subscribe(listener: () => void): () => void;
11713
- /**
11714
- * 重新通知一次:读数背后的数据变了(业务自己知道),页面据此重算候选行。
11715
- */
11716
11353
  refresh(): void;
11717
11354
  }
11718
11355
  declare module "@deepseek-ai/cordis" {
11719
11356
  interface Context {
11720
- /** 通用表单的提示面(dict 的候选键)。 */
11721
11357
  schemaFormHints: SchemaFormHints;
11722
11358
  }
11723
11359
  }
11724
11360
  //#endregion
11725
11361
  //#region src/client/schema-form/controller.d.ts
11726
- /**
11727
- * rehydrate 一段配置 schema,并判它能不能当页面的根。
11728
- *
11729
- * 能当根的形状有三种:对象段、**相交段**(共享判别字段 + 各分支的 `const` 标记,段值仍是对象)、以及带判别
11730
- * 标签的 `union`(成员都是对象)。字面量 `union`(整段就是一个标量)不行:那一行的写盘会变成整段替换。
11731
- * @param serialized - host 发来的 `schema.toJSON()`。
11732
- * @param rehydrate - host schema 的 rehydrate。
11733
- * @returns schema 与它的字段树,或 `undefined`(不能当页面根)。
11734
- */
11735
11362
  declare function projectRoot(serialized: unknown, rehydrate: (serialized: unknown) => SchemaNode): {
11736
11363
  schema: SchemaNode;
11737
11364
  root: FieldNode;
11738
11365
  } | undefined;
11739
- /**
11740
- * 一行能否自动生成配置页:它的 schema 能 rehydrate 且根是 {@link projectRoot} 认的形状。
11741
- * @param view - host 发来的命名空间视图。
11742
- * @param rehydrate - host schema 的 rehydrate。
11743
- * @returns 是否可以渲染。
11744
- */
11745
11366
  declare function canRender(view: SettingsNamespaceView | undefined, rehydrate: (serialized: unknown) => SchemaNode): boolean;
11746
- /** 提示面在控制器里的读法:候选键 + 字段文案 + 候选值。 */
11747
11367
  interface HintSources extends SuggestedKeys {
11748
- /**
11749
- * 读某个字段的文案。
11750
- * @param path - 该字段的具体路径。
11751
- * @returns 业务注册的文案;没有就是空对象。
11752
- */
11753
11368
  textFor: (path: readonly string[]) => FieldText;
11754
- /**
11755
- * 读某个字段的候选值读数;不接提示面的装配可以不给(字段就还是文本编辑)。
11756
- * @param path - 该字段的具体路径。
11757
- * @returns 业务注册的候选读数;没有就是 `undefined`。
11758
- */
11759
11369
  selectFor?: ((path: readonly string[]) => SelectSpec | undefined) | undefined;
11760
- /**
11761
- * 读一个**具名候选源**(schema 的 `role('select', { source })` 认领它)。
11762
- * @param name - 源的名字。
11763
- * @returns 该源的读数;没注册过就是 `undefined`。
11764
- */
11765
11370
  sourceFor?: ((name: string) => SelectSpec | undefined) | undefined;
11766
11371
  }
11767
- /** 控制器要的外部面(`apply` 里从 cordis ctx 组装;测试直接给替身)。 */
11768
11372
  interface SchemaFormDeps {
11769
- /** 本命名空间的共享配置表单(读 + 带栅栏的写)。 */
11770
11373
  form: DraftScope;
11771
- /** describe mirror 的读面:本行的 schema、autoGenerate 与 secret 槽。 */
11772
11374
  describe: SettingsDescribeFace;
11773
- /** rehydrate host 发来的 `schema.toJSON()`。 */
11774
11375
  rehydrate: (serialized: unknown) => SchemaNode;
11775
- /** 整段校验;失败时连路径一起给(页面把消息画在那一行)。 */
11776
11376
  validate: (schema: SchemaNode, value: unknown) => ValidationFailure | undefined;
11777
- /** 本包字典(项身份冲突这类本地校验的消息)。 */
11778
11377
  t: SchemaFormTranslate;
11779
- /**
11780
- * dict 字段的候选键(业务注册,见 `hints.ts`):候选里有、值里没有的键会补成一行「未配置」,
11781
- * 用户填了才算写。
11782
- */
11783
11378
  hints?: HintSources | undefined;
11784
11379
  }
11785
- /**
11786
- * 这一层「能加进来」的一项:schema 里声明、值里还没有的字段,或业务注册的候选键。
11787
- *
11788
- * 页面上不占行——它们出现在容器的闭合行那个「添加属性 / 添加键」输入框的候选里,选中才加。
11789
- */
11790
11380
  interface AddableProperty {
11791
- /** 加进来的键名。 */
11792
11381
  key: string;
11793
- /** 说明(schema 的 `description` / `comment`,可能是本地化字典):渲染层解析后当候选的副标题。 */
11794
11382
  description: string | Readonly<Record<string, string>> | undefined;
11795
11383
  }
11796
- /** 页面级状态:表单壳 + 字段树 + 每字段草稿状态。 */
11797
11384
  interface SchemaFormState extends SettingsFormShell$1 {
11798
- /** 这一行的 schema 是否可渲染(否则页面只显示一行说明)。 */
11799
11385
  configured: boolean;
11800
- /** 字段树;未 configured 时是空对象树。 */
11801
11386
  root: FieldNode;
11802
- /** 按草稿后的值展开的字段列表(渲染顺序):追加的数组项与新增的字典键立刻出现。 */
11803
11387
  walked: readonly WalkedField[];
11804
- /** 每个具体路径的草稿状态,键见 {@link fieldKey}。 */
11805
11388
  fields: ReadonlyMap<string, DraftFieldState>;
11806
- /** secret 槽是否已配置,键见 {@link fieldKey}。 */
11807
11389
  secrets: ReadonlyMap<string, boolean>;
11808
- /** 每个字段的文案(提示面注册的),键见 {@link fieldKey};渲染层把它画成注释行。 */
11809
11390
  texts: ReadonlyMap<string, FieldText>;
11810
- /**
11811
- * 每个字段的可选项,键见 {@link fieldKey}:字面量集合的 union 自带候选,其余来自提示面。
11812
- * 候选依赖的兄弟字段一改,这里就跟着变(投影时按草稿后的值求一次)。
11813
- */
11814
11391
  options: ReadonlyMap<string, readonly SelectOption[]>;
11815
- /**
11816
- * 每个容器能加进来的项,键见 {@link fieldKey}(容器自己的路径)。没有条目就是加不了东西——对象层的输入框
11817
- * 因此只在还有声明字段没配时出现。
11818
- */
11819
11392
  addable: ReadonlyMap<string, readonly AddableProperty[]>;
11820
- /** 保存被 schema 挡下时的消息与它的位置。 */
11821
11393
  violation: ValidationFailure | undefined;
11822
- /** 每行的校验消息(键见 {@link fieldKey}):行内报错,与底部的整段提示同源。 */
11823
11394
  invalidAt: ReadonlyMap<string, string>;
11824
11395
  }
11825
- /** 控件的写动作:全部落在草稿上,`save` 是唯一的写盘点。 */
11826
11396
  interface SchemaFormActions {
11827
- /** 暂存一个合法值。 */
11828
11397
  set: (path: readonly string[], value: unknown) => void;
11829
- /** 暂存一段文本(保存时解析)。 */
11830
11398
  setText: (path: readonly string[], text: string, parse: TextParse) => void;
11831
- /** 暂存「恢复默认」。 */
11832
11399
  clear: (path: readonly string[]) => void;
11833
- /** 追加一个数组项。 */
11834
11400
  appendItem: (path: readonly string[]) => void;
11835
- /** 移除一个数组项。 */
11836
11401
  removeItem: (path: readonly string[], index: number) => void;
11837
- /** 加一个字典键。 */
11838
11402
  addKey: (path: readonly string[], key: string) => void;
11839
- /** 删一个字典键。 */
11840
11403
  removeKey: (path: readonly string[], key: string) => void;
11841
- /** 写盘。 */
11842
11404
  save: () => void;
11843
- /** 撤销一个字段的草稿(行内编辑取消)。 */
11844
11405
  revert: (path: readonly string[]) => void;
11845
- /** 丢弃草稿。 */
11846
11406
  discard: () => void;
11847
11407
  }
11848
- /** 槽位渲染器绑定的动作与可观察状态。 */
11849
11408
  interface SchemaFormFace extends SchemaFormActions {
11850
11409
  hooks: {
11851
11410
  schemaForm: SnapshotStore<SchemaFormState>;
11852
11411
  };
11853
11412
  }
11854
- /**
11855
- * 一个字段的可选项。
11856
- *
11857
- * 字面量集合的 union(`z.union(["wal", "delete"])`)自己就带着候选;其余看提示面注册的读数——读的时候把依赖的
11858
- * 兄弟字段值喂进去,所以「选完服务商才列它有哪些模型」是投影的一部分,不是额外的一次订阅。
11859
- * @param node - 字段节点。
11860
- * @param path - 该字段的具体路径。
11861
- * @param value - 段值(草稿后的)。
11862
- * @param hints - 提示面。
11863
- * @returns 可选项;没有候选就是 `undefined`。
11864
- */
11865
11413
  declare function optionsFor(node: FieldNode, path: readonly string[], value: unknown, hints: HintSources | undefined): readonly SelectOption[] | undefined;
11866
- /**
11867
- * 一行配置页的控制器。
11868
- */
11869
11414
  declare class SchemaFormController {
11870
11415
  #private;
11871
- /**
11872
- * @param ns - settings 命名空间(行 id)。
11873
- * @param deps - 该行的共享表单与 schema 面。
11874
- */
11875
11416
  constructor(ns: string, deps: SchemaFormDeps);
11876
- /** 槽位渲染器要的动作与状态。 */
11877
11417
  face(): SchemaFormFace;
11878
- /** 本行的 settings 命名空间。 */
11879
11418
  namespace(): string;
11880
- /** 外部提示(候选键这类)变了:重新投影一次,字段树与草稿都不动。 */
11881
11419
  refresh(): void;
11882
- /** 释放订阅。 */
11883
11420
  dispose(): void;
11884
11421
  }
11885
11422
  //#endregion
11886
11423
  //#region src/client/schema-form/labels.d.ts
11887
- /** 把 schema 里的本地化文本解析成当前语言;由 locale 服务提供。 */
11888
11424
  type ResolveText = (text: string | Readonly<Record<string, string>>) => string;
11889
11425
  //#endregion
11890
11426
  //#region src/client/schema-form/locales.d.ts
11891
- /**
11892
- * 本包字典(命名空间 `settings.schema-form`):表单壳、字段控件与只读呈现的文案。
11893
- *
11894
- * 字段自身的人话标签不在这里(那是业务方经字段槽或 schema `description` 给的),这里只放**机制**文案。
11895
- */
11896
- /** 中文文案(部署语言偏好是 zh)。 */
11897
11427
  declare const zh: {
11898
11428
  readonly unavailable: "该插件当前未加载,暂时无法配置。";
11899
11429
  readonly readOnly: "本部署的设置为只读。";
@@ -11948,116 +11478,58 @@ declare const zh: {
11948
11478
  readonly duplicateItem: "重复的 {key}:{value}";
11949
11479
  readonly missingItem: "每一项都需要一个 {key}";
11950
11480
  };
11951
- /** 本命名空间的字典键。 */
11952
11481
  type SchemaFormLocaleKey = keyof typeof zh;
11953
11482
  //#endregion
11954
11483
  //#region src/client/schema-form/slot-contract.d.ts
11955
- /** 字段槽的 owner props:路由输入 + 显示状态 + 受控动作(默认控件要的一切都在这里)。 */
11956
11484
  interface SchemaFieldOwnerProps {
11957
- /** settings 命名空间(行 id)。 */
11958
11485
  ns: string;
11959
- /** 字段的具体路径(动态段已按真实键或索引替换)。 */
11960
11486
  path: readonly string[];
11961
- /** 字段节点(类型、`role`、`extra`、界限、只读原因)。 */
11962
11487
  node: FieldNode;
11963
- /** 显示标签:默认是字段名拆词,业务方经槽给时会覆盖。 */
11964
11488
  label: string;
11965
- /** 显示说明(`description` 本地化 + `comment`)。 */
11966
11489
  hint: string | undefined;
11967
- /** 当前生效值(草稿优先)。 */
11968
11490
  value: unknown;
11969
- /**
11970
- * 这个字段的可选项:给了就是选择器(点值不再进文本编辑)。来源是字面量集合的 union,或业务经提示面注册的
11971
- * 候选——候选依赖的兄弟字段一变,这里就换一批。
11972
- */
11973
11491
  options: readonly SelectOption[] | undefined;
11974
- /** 文本草稿:文本控件显示它,而不是重新格式化生效值。 */
11975
11492
  text: string | undefined;
11976
- /** secret 槽是否已配置(值本身不回传)。 */
11977
11493
  secretConfigured: boolean;
11978
- /** 嵌套深度:默认控件按它缩进。 */
11979
11494
  depth: number;
11980
- /** 保存后这一字段是否会留下用户层条目。 */
11981
11495
  overridden: boolean;
11982
- /** 草稿不合法时的消息。 */
11983
11496
  invalid: string | undefined;
11984
- /** 只读部署或不可用命名空间时为 true。 */
11985
11497
  disabled: boolean;
11986
- /** 本包字典(复刻或包装默认控件时用)。 */
11987
11498
  t: SchemaFormTranslate;
11988
- /** 容器动作(增删数组项、字典键、丢弃、保存)。 */
11989
11499
  actions: SchemaFormActions;
11990
- /**
11991
- * 分组节点的折叠交互(object / dict / array / tuple);叶子节点是 `undefined`。
11992
- * 默认折叠与否由 schema 的 `collapse()` 决定,用户点一下就是反转。
11993
- */
11994
11500
  group: {
11995
11501
  collapsed: boolean;
11996
11502
  toggle: () => void;
11997
11503
  } | undefined;
11998
- /**
11999
- * 这一行是动态容器的成员本身(dict 的键 / array 的项)时的身份:容器路径、键、数组项的位置。容器成员把它画进
12000
- * 标题行(名字 + 移除),叶子成员由渲染层另起一行——所以「哪个字段属于哪个键/哪一项」在页面上一眼可见。
12001
- */
12002
11504
  member: {
12003
11505
  parent: readonly string[];
12004
11506
  key: string;
12005
11507
  index: number | undefined;
12006
11508
  pending?: boolean;
12007
11509
  } | undefined;
12008
- /** 暂存一个合法值。 */
12009
11510
  onChange: (value: unknown) => void;
12010
- /**
12011
- * 暂存一段文本:按字段类型的默认规则解析;给了 `parse` 就用它(例如 secret 留空=不写)。
12012
- * @param text - 用户输入。
12013
- * @param parse - 覆盖默认解析规则。
12014
- */
12015
11511
  onEditText: (text: string, parse?: TextParse) => void;
12016
- /** 暂存「恢复默认」。 */
12017
11512
  onReset: () => void;
12018
11513
  }
12019
- /**
12020
- * 字段槽注册项的完整 props:框架注入的 owner props({@link SchemaFieldOwnerProps})+它的 `select` 结果。
12021
- *
12022
- * 注册方的组件按这个类型声明参数(**不要**自己重写 owner props 的类型:注册时框架会把它读成 inject 面)。
12023
- */
12024
11514
  type SchemaFieldComponentProps<M extends SchemaFieldMatch = SchemaFieldMatch> = PropsRuntime<"settings.schema-form.field"> & {
12025
11515
  matched: M;
12026
11516
  };
12027
- /**
12028
- * 字段槽注册项的 `select`:返回认领结果,或 `null` 表示不认领(chain 槽的约定是 `null` 放行给下一项,
12029
- * `undefined` 不会被当成"不认领")。
12030
- */
12031
11517
  type SchemaFieldSelect = (field: SchemaFieldOwnerProps) => SchemaFieldMatch | null;
12032
- /** 字段槽 `select` 可以只给文案:控件仍由注册方渲染(拿本包的默认控件包一层即可)。 */
12033
11518
  interface SchemaFieldMatch {
12034
- /** 覆盖显示标签。 */
12035
11519
  label?: string;
12036
- /** 覆盖显示说明。 */
12037
11520
  hint?: string;
12038
11521
  }
12039
- /** Factory 的输入 props:一行的配置页。 */
12040
11522
  interface SchemaFormProps {
12041
- /** settings 命名空间(行 id)。 */
12042
11523
  ns: string;
12043
- /** 该行的控制器动作与状态。 */
12044
11524
  face: SchemaFormFace;
12045
- /** schema 里的本地化文本(`description`)按当前语言解析。 */
12046
11525
  resolveText: ResolveText;
12047
11526
  }
12048
- /** 本包字典的翻译函数(默认控件与表单壳使用)。 */
12049
11527
  type SchemaFormTranslate = TranslateNS<"settings.schema-form">;
12050
11528
  declare module "@deepseek-ai/dsh-client-ui-slots" {
12051
11529
  interface LocaleNamespaceMap {
12052
- /** 表单壳、字段控件与只读呈现的文案。 */
12053
11530
  "settings.schema-form": SchemaFormLocaleKey;
12054
11531
  }
12055
11532
  interface SlotMap {
12056
- /**
12057
- * 字段级自定义输入与文案:按 `role` 或 `ns + path` 认领一个字段,命中即渲染注册方的组件(未命中落到默认
12058
- * 控件)。注册项由业务插件用 `ctx.slots.inject('settings.schema-form.field', …)` 注册,声明由本包的
12059
- * Factory 给出。
12060
- */
12061
11533
  "settings.schema-form.field": {
12062
11534
  kind: "chain";
12063
11535
  scope: "root";
@@ -12065,10 +11537,6 @@ declare module "@deepseek-ai/dsh-client-ui-slots" {
12065
11537
  };
12066
11538
  }
12067
11539
  interface SlotFactoryMap {
12068
- /**
12069
- * 一行配置页的渲染体:每个可渲染的行注册项经 `renderFactorySlot` 渲染同一个 Factory,字段槽因此只需声明
12070
- * 一次(slots 的 children 声明 per key 唯一)。
12071
- */
12072
11540
  "settings.schema-form.form": {
12073
11541
  scope: "root";
12074
11542
  props: SchemaFormProps;
@@ -12084,87 +11552,42 @@ declare module "@deepseek-ai/dsh-client-ui-slots" {
12084
11552
  }
12085
11553
  //#endregion
12086
11554
  //#region src/client/schema-form/rows.d.ts
12087
- /** 一个该自动长出配置页的行。 */
12088
11555
  interface RowRegistrationPlan {
12089
- /** `plugins.row.config` 的 key:`<bundle 包名>#<行 id>`。 */
12090
11556
  key: string;
12091
- /** settings 命名空间(行 id)。 */
12092
11557
  ns: string;
12093
11558
  }
12094
- /**
12095
- * 配对命名空间与 bundle 行清单。
12096
- * @param namespaces - host 发来的命名空间视图。
12097
- * @param bundles - host 的 bundle 清单(含各 bundle 声明的行 id)。
12098
- * @returns 该自动注册的行,按命名空间视图的顺序。
12099
- */
12100
11559
  declare function rowRegistrations(namespaces: readonly SettingsNamespaceView[], bundles: readonly BundleInfo[]): RowRegistrationPlan[];
12101
11560
  //#endregion
12102
11561
  //#region src/client/schema-form/value.d.ts
12103
- /** 编辑态文本:字符串就是原文(换行照旧),其余按 JSON 写。 */
12104
11562
  declare function valueText(value: unknown): string;
12105
- /** 显示态文本:字符串带引号;多行与特殊字符都按 JSON 的写法收在一行里。 */
12106
11563
  declare function tokenText(value: unknown): string;
12107
- /** 值的语法色分组。 */
12108
11564
  declare function tokenTone(value: unknown): "string" | "number" | "boolean" | "empty";
12109
- /**
12110
- * 行内值的默认呈现(显示态 token)。
12111
- * @param props.owner - 字段上下文(值、是否 secret、只读原因)。
12112
- * @returns 一行里的值节点。
12113
- */
12114
11565
  declare function InlineValue({ owner }: {
12115
11566
  owner: SchemaFieldOwnerProps;
12116
11567
  }): ReactNode;
12117
- /**
12118
- * 字段槽注册方复用的默认值:只改文案时拿它包一层即可(`owner` 上覆盖 `label`/`hint`)。
12119
- *
12120
- * 注意行式视图里键名来自配置键本身、注释来自 `hint`,所以 `label` 只在业务自写控件时才需要。
12121
- */
12122
11568
  declare function SchemaFieldDefault({ owner }: {
12123
11569
  owner: SchemaFieldOwnerProps;
12124
11570
  }): ReactNode;
12125
11571
  //#endregion
12126
11572
  //#region src/client/schema-form/fields.d.ts
12127
- /**
12128
- * 各类型的文本解析规则(消息来自本包字典)。
12129
- *
12130
- * 解析不只看类型:schema 上声明的界限(`pattern` / `min` / `max` / `step`)与字面量集合都在这里说话——
12131
- * 用户敲完当场就知道对不对,而不是等保存时被整段校验退回。
12132
- * @param node - 字段节点(`meta` 是约束的来源)。
12133
- * @param t - 本包字典。
12134
- * @returns 这段文本的解析规则。
12135
- */
12136
11573
  declare function parseFor(node: FieldNode, t: SchemaFormTranslate): TextParse;
12137
11574
  //#endregion
12138
11575
  //#region src/client/schema-form/lines.d.ts
12139
- /** 一个容器的闭合行后面能加什么。 */
12140
- type AddLineSpec =
12141
- /** 数组:追加一个空项。 */
12142
- {
11576
+ type AddLineSpec = {
12143
11577
  kind: "item";
12144
- } |
12145
- /** 字典:敲键名,或从候选键里选(业务注册的读数)。 */
12146
- {
11578
+ } | {
12147
11579
  kind: "key";
12148
11580
  options: readonly AddableProperty[];
12149
- } |
12150
- /** 对象:从「schema 声明了、值里还没有」的字段里选(没有候选项时不给输入框)。 */
12151
- {
11581
+ } | {
12152
11582
  kind: "prop";
12153
11583
  options: readonly AddableProperty[];
12154
11584
  };
12155
- /** 一行上的变体切换控件。 */
12156
11585
  interface VariantControl {
12157
- /** 可以切到哪几支;顺序即声明顺序。 */
12158
11586
  choices: readonly VariantChoice[];
12159
- /** 当前落在第几支。 */
12160
11587
  selected: number;
12161
11588
  }
12162
- /** 容器类型:结构行用 `{` 还是 `[`。 */
12163
11589
  type ContainerShape = "object" | "array";
12164
- /** 一行。 */
12165
- type EditorLine =
12166
- /** 容器的开启行:`key: {` 或 `[`。 */
12167
- {
11590
+ type EditorLine = {
12168
11591
  kind: "open";
12169
11592
  path: readonly string[];
12170
11593
  node: FieldNode;
@@ -12172,82 +11595,43 @@ type EditorLine =
12172
11595
  depth: number;
12173
11596
  collapsed: boolean;
12174
11597
  member: WalkedField["member"];
12175
- /** 这一层是 union 时,可以在哪几支之间切(写哪个值)。 */
12176
11598
  variants: VariantControl | undefined;
12177
- } |
12178
- /** 容器的关闭行:`}` / `]`(添加行挂在它后面同一行)。 */
12179
- {
11599
+ } | {
12180
11600
  kind: "close";
12181
11601
  path: readonly string[];
12182
11602
  node: FieldNode;
12183
11603
  shape: ContainerShape;
12184
11604
  depth: number;
12185
- /** 这一层能加什么;`undefined` 表示加不了(对象的声明字段都配齐了)。 */
12186
11605
  add: AddLineSpec | undefined;
12187
11606
  member: WalkedField["member"];
12188
- } |
12189
- /** 字段行:`key: value`。 */
12190
- {
11607
+ } | {
12191
11608
  kind: "field";
12192
11609
  path: readonly string[];
12193
11610
  node: FieldNode;
12194
11611
  depth: number;
12195
11612
  field: DraftFieldState;
12196
11613
  member: WalkedField["member"];
12197
- /** 这个字段是 union 时,可以在哪几支之间切。 */
12198
11614
  variants: VariantControl | undefined;
12199
- /**
12200
- * 变体触发**代替这一行的值**:判别式 union 的标签行就是这样——`type: "sqlite" ▾` 里的值就是那个触发,
12201
- * 不再另画一份值。
12202
- */
12203
11615
  variantsStandIn: boolean;
12204
- } |
12205
- /** 注释行:schema 的说明与业务给的文案,画在字段行上方;这一行有问题时它装的是那条消息。 */
12206
- {
11616
+ } | {
12207
11617
  kind: "comment";
12208
11618
  path: readonly string[];
12209
11619
  depth: number;
12210
11620
  text: string;
12211
- /** 这一行有校验消息(草稿解析失败或整段校验落下来):画成错误,而不是普通说明。 */
12212
11621
  invalid: boolean;
12213
11622
  };
12214
- /**
12215
- * 容器的形状:对象类用 `{}`,序列类用 `[]`。
12216
- *
12217
- * union 没有自己的形状——它跟着**当前选中那一支**走(`access` 是数组就在页面上画 `[`),这也是
12218
- * `access: string | string[]` 这类字段以前被画成对象容器的原因。
12219
- * @param node - 字段节点。
12220
- * @param value - 这一层的值(选支判据)。
12221
- * @returns 形状;叶子节点是 `undefined`。
12222
- */
12223
11623
  declare function containerShape(node: FieldNode, value?: unknown): ContainerShape | undefined;
12224
- /** 折叠状态与可见性:记「用户切换过的路径」,开合 = 切换过就反转 schema 的默认值。 */
12225
11624
  interface FoldState {
12226
11625
  collapsed(path: readonly string[]): boolean;
12227
11626
  toggle(path: readonly string[]): void;
12228
11627
  }
12229
- /** 渲染顺序里可见的字段:折叠的容器把整棵子树滤掉,只留它自己的开启行。 */
12230
11628
  declare function visibleFields(state: SchemaFormState, fold: FoldState): readonly WalkedField[];
12231
- /**
12232
- * 排成行序列。
12233
- * @param state - 页面读数。
12234
- * @param fold - 折叠状态。
12235
- * @param resolveText - `description` 的本地化。
12236
- * @param t - 本包字典。
12237
- * @returns 行序列(行号即下标)。
12238
- */
12239
11629
  declare function editorLines(state: SchemaFormState, fold: FoldState, resolveText: ResolveText, t: SchemaFormTranslate): EditorLine[];
12240
11630
  declare namespace index_d_exports {
12241
11631
  export { EditorLine, FieldMeta, FieldNode, FieldText, FoldState, InlineValue, NS, RowRegistrationPlan, SchemaFieldComponentProps, SchemaFieldDefault, SchemaFieldMatch, SchemaFieldOwnerProps, SchemaFieldSelect, SchemaFormActions, SchemaFormController, SchemaFormFace, SchemaFormHints, SchemaFormHintsFace, SchemaFormLocaleKey, SchemaFormProps, SchemaFormState, SelectOption, SelectSpec, SuggestedKeys, SuggestedKeysReader, ValidationFailure, WalkedField, apply$1 as apply, canRender, containerShape, editorLines, failureOf, inject$1 as inject, optionsFor, parseFor, projectNode, projectRoot, rowRegistrations, tokenText, tokenTone, valueText, visibleFields, walkFields };
12242
11632
  }
12243
- /** 本包字典与槽位文案的命名空间。 */
12244
11633
  declare const NS = "settings.schema-form";
12245
- /** 需要的服务:槽位、字典、共享配置表单、schema 服务与插件管理(bundle 行清单)。 */
12246
11634
  declare const inject$1: string[];
12247
- /**
12248
- * 装上本包:字典、Factory(字段槽的声明者)与按行自动注册。
12249
- * @param ctx - 浏览器插件上下文。
12250
- */
12251
11635
  declare function apply$1(ctx: Context): void;
12252
11636
  //#endregion
12253
11637
  //#region src/reference-markdown.d.ts
@@ -12266,15 +11650,6 @@ declare function referenceMentions(actions?: ReferenceActions, tokens?: Readonly
12266
11650
  declare const ReferenceMarkdown: import("react").MemoExoticComponent<({ text, labels, actions, streaming, pathImages }: ReferenceMarkdownProps) => import("react/jsx-runtime").JSX.Element>;
12267
11651
  //#endregion
12268
11652
  //#region src/client/index.d.ts
12269
- /**
12270
- * 需要的**服务名**:样式与引用那半不要服务,schema 表单那半要槽位、字典与配置表单。
12271
- *
12272
- * 与包清单里的 `dsh.client.inject` 不是一回事:那份是**装配行 id**(谁先到),交给模块系统排 arrival 顺序;
12273
- * 这里读的是 cordis 服务名(谁已 provide),Loader 拿它决定这一行何时才算 active。写错成包名,这一行就永远
12274
- * pending(`web boot: ... waiting for services`)。
12275
- *
12276
- * 值直接取自 schema 表单那一面,不另抄一份清单。
12277
- */
12278
11653
  declare const inject: readonly string[];
12279
11654
  declare function apply(ctx: Context): void;
12280
11655
  //#endregion