@huanlin/dsh-plugin-preface-context 0.1.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.
Files changed (38) hide show
  1. package/README.md +113 -0
  2. package/cordis.patch.yml +11 -0
  3. package/lib/client.js +794 -0
  4. package/lib/client.js.map +1 -0
  5. package/lib/index.js +127 -0
  6. package/lib/types/client/bind-snapshot-selector.d.ts +7 -0
  7. package/lib/types/client/bind-snapshot-selector.js +19 -0
  8. package/lib/types/client/client/bind-snapshot-selector.d.ts +7 -0
  9. package/lib/types/client/client/bind-snapshot-selector.js +19 -0
  10. package/lib/types/client/client/index.d.ts +39 -0
  11. package/lib/types/client/client/index.js +50 -0
  12. package/lib/types/client/client/locales.d.ts +7 -0
  13. package/lib/types/client/client/locales.js +41 -0
  14. package/lib/types/client/client/preface-card-controller.d.ts +94 -0
  15. package/lib/types/client/client/preface-card-controller.js +181 -0
  16. package/lib/types/client/client/preface-card.css.d.ts +53 -0
  17. package/lib/types/client/client/preface-card.css.js +327 -0
  18. package/lib/types/client/client/preface-card.d.ts +27 -0
  19. package/lib/types/client/client/preface-card.js +41 -0
  20. package/lib/types/client/config.d.ts +41 -0
  21. package/lib/types/client/config.js +42 -0
  22. package/lib/types/client/index.d.ts +39 -0
  23. package/lib/types/client/index.js +50 -0
  24. package/lib/types/client/locales.d.ts +7 -0
  25. package/lib/types/client/locales.js +41 -0
  26. package/lib/types/client/preface-card-controller.d.ts +94 -0
  27. package/lib/types/client/preface-card-controller.js +181 -0
  28. package/lib/types/client/preface-card.css.d.ts +53 -0
  29. package/lib/types/client/preface-card.css.js +327 -0
  30. package/lib/types/client/preface-card.d.ts +27 -0
  31. package/lib/types/client/preface-card.js +41 -0
  32. package/lib/types/config.d.ts +40 -0
  33. package/lib/types/config.js +42 -0
  34. package/lib/types/index.d.ts +46 -0
  35. package/lib/types/index.js +64 -0
  36. package/lib/types/settings.d.ts +50 -0
  37. package/lib/types/settings.js +85 -0
  38. package/package.json +130 -0
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Config schema for the preface-context plugin (Schemastery, strict).
3
+ *
4
+ * The plugin-row config (the `entry` passed to `apply`) is the composition
5
+ * BASE of the `preface-context` settings namespace. The settings user layer
6
+ * is layered on top (schema defaults → base → user layer) when a settings
7
+ * service is mounted; without one, the entry is the sole source.
8
+ *
9
+ * @module @huanlin/dsh-plugin-preface-context/config
10
+ */
11
+ import z from 'schemastery';
12
+ /**
13
+ * Schemastery schema for the `preface-context` settings namespace.
14
+ *
15
+ * Strict by construction: unknown keys fail validation here, even though the
16
+ * settings service itself is non-strict and would otherwise accept them.
17
+ */
18
+ export const Config = z.object({
19
+ enabled: z.boolean().default(true),
20
+ contextText: z.string().default(''),
21
+ });
22
+ /** Known config keys (for strict unknown-key rejection). */
23
+ const CONFIG_KEYS = new Set(['enabled', 'contextText']);
24
+ /**
25
+ * Resolve a raw config patch through the schema, returning a full
26
+ * {@link PrefaceConfig} with defaults applied. Unknown keys are rejected
27
+ * here (the settings service itself is non-strict and would otherwise accept
28
+ * them), matching the Loader's strict validation.
29
+ * @param input - a partial or complete config object.
30
+ * @returns the schema-resolved config.
31
+ * @throws when the input carries an unknown key or a value the schema rejects.
32
+ */
33
+ export function resolvePrefaceConfig(input) {
34
+ if (input !== null && typeof input === 'object' && !Array.isArray(input)) {
35
+ for (const key of Object.keys(input)) {
36
+ if (!CONFIG_KEYS.has(key)) {
37
+ throw new Error(`preface-context: unknown config key "${key}"`);
38
+ }
39
+ }
40
+ }
41
+ return Config(input);
42
+ }
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Preface-context settings plugin, browser half. Registers the
3
+ * `preface-context` card into the shell-declared `settings.plugin.item` slot
4
+ * (the "插件配置" settings page), keyed by the `preface-context` settings
5
+ * namespace. The card's controller binds the namespace through
6
+ * `ctx.settingsScope.bind()`, which reads/writes through the standard
7
+ * `settings.describe` / `settings.mutate` RPCs (the apiproxy accepts any
8
+ * registered namespace — no allowlist gate on current upstream dsh).
9
+ *
10
+ * Export discipline: value-imports ONLY the frozen platform module table
11
+ * (React / cordis / ui-primitives); every other `@deepseek-ai/*` import is
12
+ * type-only (erased at build) — values arrive via cordis injection
13
+ * (`ctx.settingsScope` is the read/write channel).
14
+ */
15
+ import type { Context } from '@deepseek-ai/cordis';
16
+ import { type PrefaceLocaleKey } from './locales.ts';
17
+ export type { PrefaceCardProps } from './preface-card.tsx';
18
+ export type { PrefaceLocaleKey } from './locales.ts';
19
+ declare module '@deepseek-ai/dsh-client-ui-slots' {
20
+ interface LocaleNamespaceMap {
21
+ /** The preface-context settings card copy. */
22
+ 'settings.preface-context': PrefaceLocaleKey;
23
+ }
24
+ }
25
+ /**
26
+ * Required services (cordis fiber inject). `settingsScope` is provided by the
27
+ * ui-settings base plugin; `locale` by the locale plugin; `slots` is the
28
+ * composition root. The target slot is declared by ui-settings-plugins'
29
+ * `configurable` tab, whose activation order relative to this one is
30
+ * unconstrained; registration depends on the slot through `slots.inject()`.
31
+ */
32
+ export declare const inject: string[];
33
+ /**
34
+ * Register the preface-context card once the `settings.plugin.item`
35
+ * declaration is on the ledger, wire its controller to the settings scope,
36
+ * and keep it fresh on every pushed invalidation.
37
+ * @param ctx - client root context.
38
+ */
39
+ export declare function apply(ctx: Context): void;
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Preface-context settings plugin, browser half. Registers the
3
+ * `preface-context` card into the shell-declared `settings.plugin.item` slot
4
+ * (the "插件配置" settings page), keyed by the `preface-context` settings
5
+ * namespace. The card's controller binds the namespace through
6
+ * `ctx.settingsScope.bind()`, which reads/writes through the standard
7
+ * `settings.describe` / `settings.mutate` RPCs (the apiproxy accepts any
8
+ * registered namespace — no allowlist gate on current upstream dsh).
9
+ *
10
+ * Export discipline: value-imports ONLY the frozen platform module table
11
+ * (React / cordis / ui-primitives); every other `@deepseek-ai/*` import is
12
+ * type-only (erased at build) — values arrive via cordis injection
13
+ * (`ctx.settingsScope` is the read/write channel).
14
+ */
15
+ import { PrefaceCard } from "./preface-card.js";
16
+ import { installPrefaceCardStyles } from "./preface-card.css.js";
17
+ import { PrefaceCardController } from "./preface-card-controller.js";
18
+ import { en, zh } from "./locales.js";
19
+ /** Dictionary namespace owned by this plugin. */
20
+ const NS = 'settings.preface-context';
21
+ /** Settings namespace the host half registers (must match the host constant). */
22
+ const SETTINGS_NAMESPACE = 'preface-context';
23
+ /**
24
+ * Required services (cordis fiber inject). `settingsScope` is provided by the
25
+ * ui-settings base plugin; `locale` by the locale plugin; `slots` is the
26
+ * composition root. The target slot is declared by ui-settings-plugins'
27
+ * `configurable` tab, whose activation order relative to this one is
28
+ * unconstrained; registration depends on the slot through `slots.inject()`.
29
+ */
30
+ export const inject = ['slots', 'locale', 'settingsScope'];
31
+ /**
32
+ * Register the preface-context card once the `settings.plugin.item`
33
+ * declaration is on the ledger, wire its controller to the settings scope,
34
+ * and keep it fresh on every pushed invalidation.
35
+ * @param ctx - client root context.
36
+ */
37
+ export function apply(ctx) {
38
+ ctx.effect(installPrefaceCardStyles, 'preface-context: card styles');
39
+ ctx.effect(() => ctx.locale.register(NS, { zh, en }), 'preface-context: copy dictionaries');
40
+ const settingsScope = ctx.settingsScope;
41
+ const controller = new PrefaceCardController(settingsScope.bind({ namespace: SETTINGS_NAMESPACE }));
42
+ ctx.slots.inject('settings.plugin.item', function* () {
43
+ yield ctx.slots.register({
44
+ name: 'settings.plugin.item',
45
+ key: SETTINGS_NAMESPACE,
46
+ locale: NS,
47
+ inject: () => controller.inject(),
48
+ }, PrefaceCard);
49
+ });
50
+ }
@@ -0,0 +1,7 @@
1
+ /** Locale bundles for the preface-context settings card. */
2
+ /** Locale keys the preface-context card renders. */
3
+ export type PrefaceLocaleKey = 'title' | 'description' | 'enabled' | 'enabledHint' | 'contextText' | 'contextTextHint' | 'contextTextPlaceholder' | 'overridden' | 'reset' | 'save' | 'saving' | 'discard' | 'unsaved' | 'saveFailed' | 'readOnly' | 'expand' | 'collapse';
4
+ /** English copy. */
5
+ export declare const en: Record<PrefaceLocaleKey, string>;
6
+ /** Simplified Chinese copy. */
7
+ export declare const zh: Record<PrefaceLocaleKey, string>;
@@ -0,0 +1,41 @@
1
+ /** Locale bundles for the preface-context settings card. */
2
+ /** English copy. */
3
+ export const en = {
4
+ title: 'Preface context',
5
+ description: 'Inject a text block as model-visible instructions at the start of every session.',
6
+ enabled: 'Enabled',
7
+ enabledHint: 'When off, no context is injected at session start.',
8
+ contextText: 'Context text',
9
+ contextTextHint: 'Injected once per session as instructions context, closest to the model\u2019s first answer. Empty text injects nothing.',
10
+ contextTextPlaceholder: 'Enter the text to inject at the start of every session\u2026',
11
+ overridden: 'Overridden',
12
+ reset: 'Reset to default',
13
+ save: 'Save',
14
+ saving: 'Saving\u2026',
15
+ discard: 'Discard',
16
+ unsaved: 'Unsaved',
17
+ saveFailed: 'The deployment did not accept these values; they were left for you to correct.',
18
+ readOnly: 'This deployment stores settings read-only.',
19
+ expand: 'Show settings',
20
+ collapse: 'Hide settings',
21
+ };
22
+ /** Simplified Chinese copy. */
23
+ export const zh = {
24
+ title: '前言上下文',
25
+ description: '在每次会话开头注入一段文本作为模型可见的指令上下文。',
26
+ enabled: '启用',
27
+ enabledHint: '关闭后,会话开始时不注入任何上下文。',
28
+ contextText: '上下文文本',
29
+ contextTextHint: '每次会话注入一次,作为指令上下文最贴近模型的首个回答。文本为空则不注入。',
30
+ contextTextPlaceholder: '输入要在每次会话开头注入的文本\u2026',
31
+ overridden: '已覆盖',
32
+ reset: '恢复默认',
33
+ save: '保存',
34
+ saving: '保存中\u2026',
35
+ discard: '放弃修改',
36
+ unsaved: '未保存',
37
+ saveFailed: '本部署没有接受这些值,已保留供你修改。',
38
+ readOnly: '本部署的设置为只读。',
39
+ expand: '展开设置',
40
+ collapse: '收起设置',
41
+ };
@@ -0,0 +1,94 @@
1
+ /**
2
+ * The preface-context card's staged form over the `preface-context` settings
3
+ * namespace.
4
+ *
5
+ * The upstream `ui-settings-plugins` package owns a `CardForm` helper, but it
6
+ * is an internal module (not re-exported from the package's `/client` public
7
+ * face), so an external plugin cannot reuse it. This controller is a slim
8
+ * equivalent: it stages the two fields (`enabled` boolean, `contextText`
9
+ * multiline string) and writes them through the bound {@link SettingsScope}
10
+ * on save, re-deriving its projection whenever the scope or a draft changes.
11
+ *
12
+ * Unlike the upstream `CardForm`, the `contextText` field is a multiline
13
+ * textarea: its draft preserves internal whitespace and newlines (the
14
+ * upstream `textField` helper trims, which would collapse a multi-paragraph
15
+ * preface into one line).
16
+ */
17
+ import type { SnapshotStore } from '@deepseek-ai/dsh-client-store';
18
+ import type { SettingsScope } from '@deepseek-ai/dsh-client-ui-settings/client';
19
+ import type { PrefaceConfig } from '../config.ts';
20
+ /** The two fields this card edits, as draft text. */
21
+ export interface PrefaceDraft {
22
+ /** `enabled` draft — 'true' or 'false'. */
23
+ enabled: string;
24
+ /** `contextText` draft — the raw textarea value, whitespace preserved. */
25
+ contextText: string;
26
+ }
27
+ /** One field's render state. */
28
+ export interface PrefaceFieldState {
29
+ /** Draft text the control renders. */
30
+ text: string;
31
+ /** Whether saving would leave a user-layer entry for this field. */
32
+ overridden: boolean;
33
+ }
34
+ /** Card-level state shared with the component. */
35
+ export interface PrefaceCardState {
36
+ /** False while the namespace is not served to this client. */
37
+ available: boolean;
38
+ /** Whether the Host document accepts writes. */
39
+ writable: boolean;
40
+ /** Whether the form holds edits that a save would write. */
41
+ dirty: boolean;
42
+ /** Whether a save is crossing the wire. */
43
+ saving: boolean;
44
+ /** Whether the last save did not land as staged. */
45
+ failed: boolean;
46
+ /** The `enabled` field state. */
47
+ enabled: PrefaceFieldState;
48
+ /** The `contextText` field state. */
49
+ contextText: PrefaceFieldState;
50
+ }
51
+ /** The write actions the card's slot entry injects. */
52
+ export interface PrefaceCardActions {
53
+ /** Stage draft text for one field. */
54
+ edit: (field: keyof PrefaceDraft, text: string) => void;
55
+ /** Stage a clear, so saving lets the field re-inherit the composition layer. */
56
+ resetField: (field: keyof PrefaceDraft) => void;
57
+ /** Write every staged edit, then re-seed from what the Host accepted. */
58
+ save: () => void;
59
+ /** Drop every staged edit. */
60
+ discard: () => void;
61
+ }
62
+ /** The registration-side face the card's slot entry injects. */
63
+ export interface PrefaceCardFace {
64
+ hooks: {
65
+ /** Card snapshot bound by the renderer as usePrefaceCard. */
66
+ prefaceCard: SnapshotStore<PrefaceCardState>;
67
+ };
68
+ }
69
+ /**
70
+ * Bridges the `preface-context` scope onto the card's staged form.
71
+ *
72
+ * Publishes through a snapshot store because slot components read through a
73
+ * snapshot selector, while both the scope and the local drafts change
74
+ * underneath; every projection is rebuilt from the two together.
75
+ */
76
+ export declare class PrefaceCardController {
77
+ private readonly scope;
78
+ private readonly store;
79
+ private readonly staged;
80
+ private saving;
81
+ private failed;
82
+ /** @param scope - the bound settings scope for the `preface-context` namespace. */
83
+ constructor(scope: SettingsScope<PrefaceConfig>);
84
+ /** @returns the store the card's component reads through its bound selector. */
85
+ get snapshot(): SnapshotStore<PrefaceCardState>;
86
+ private project;
87
+ private fieldState;
88
+ /** Build the face the card's slot registration injects. */
89
+ inject(): PrefaceCardFace & PrefaceCardActions;
90
+ private stage;
91
+ private publish;
92
+ /** Write every staged edit, then re-seed from what the Host accepted. */
93
+ private save;
94
+ }
@@ -0,0 +1,181 @@
1
+ /**
2
+ * The preface-context card's staged form over the `preface-context` settings
3
+ * namespace.
4
+ *
5
+ * The upstream `ui-settings-plugins` package owns a `CardForm` helper, but it
6
+ * is an internal module (not re-exported from the package's `/client` public
7
+ * face), so an external plugin cannot reuse it. This controller is a slim
8
+ * equivalent: it stages the two fields (`enabled` boolean, `contextText`
9
+ * multiline string) and writes them through the bound {@link SettingsScope}
10
+ * on save, re-deriving its projection whenever the scope or a draft changes.
11
+ *
12
+ * Unlike the upstream `CardForm`, the `contextText` field is a multiline
13
+ * textarea: its draft preserves internal whitespace and newlines (the
14
+ * upstream `textField` helper trims, which would collapse a multi-paragraph
15
+ * preface into one line).
16
+ */
17
+ /** A minimal snapshot store: a value + a listener set. Self-contained so the
18
+ * controller does not pull `createSnapshotStore` (a browser-bundle symbol)
19
+ * into its unit-test graph. */
20
+ class MiniSnapshotStore {
21
+ snapshot;
22
+ listeners = new Set();
23
+ constructor(initial) {
24
+ this.snapshot = initial;
25
+ }
26
+ getSnapshot() {
27
+ return this.snapshot;
28
+ }
29
+ set(value) {
30
+ this.snapshot = value;
31
+ for (const listener of [...this.listeners])
32
+ listener();
33
+ }
34
+ update(mutator) {
35
+ // Shallow-clone then mutate (the projections here are plain objects with
36
+ // no nested mutation, so a deep immer draft is unnecessary).
37
+ const draft = Array.isArray(this.snapshot) ? [...this.snapshot] : { ...this.snapshot };
38
+ mutator(draft);
39
+ this.set(draft);
40
+ }
41
+ subscribe(listener) {
42
+ this.listeners.add(listener);
43
+ return () => { this.listeners.delete(listener); };
44
+ }
45
+ }
46
+ /** The default value for a field when the user-layer carries none. */
47
+ function baseValue(snapshot, field) {
48
+ return snapshot.base?.[field];
49
+ }
50
+ /** The current resolved value of a field. */
51
+ function sectionValue(snapshot, field) {
52
+ return snapshot.value?.[field];
53
+ }
54
+ /** Whether the user layer carries an entry for a field. */
55
+ function stored(snapshot, field) {
56
+ const user = snapshot.user;
57
+ return user !== undefined && Object.hasOwn(user, field);
58
+ }
59
+ /** Format a stored value as draft text for a field. */
60
+ function format(field, value) {
61
+ if (field === 'enabled')
62
+ return value === true ? 'true' : 'false';
63
+ if (field === 'contextText')
64
+ return typeof value === 'string' ? value : '';
65
+ return '';
66
+ }
67
+ /** Parse draft text into a write value, or undefined when invalid. */
68
+ function parse(field, text) {
69
+ if (field === 'enabled') {
70
+ // The toggle is a boolean; the textarea is not used for this field.
71
+ return { value: text === 'true' };
72
+ }
73
+ // contextText: empty draft clears the field; otherwise the raw text is the
74
+ // value. Internal whitespace and newlines are preserved.
75
+ const trimmed = text.trim();
76
+ return trimmed === '' ? { clear: true } : { value: text };
77
+ }
78
+ /**
79
+ * Bridges the `preface-context` scope onto the card's staged form.
80
+ *
81
+ * Publishes through a snapshot store because slot components read through a
82
+ * snapshot selector, while both the scope and the local drafts change
83
+ * underneath; every projection is rebuilt from the two together.
84
+ */
85
+ export class PrefaceCardController {
86
+ scope;
87
+ store;
88
+ staged = new Map();
89
+ saving = false;
90
+ failed = false;
91
+ /** @param scope - the bound settings scope for the `preface-context` namespace. */
92
+ constructor(scope) {
93
+ this.scope = scope;
94
+ this.store = new MiniSnapshotStore(this.project());
95
+ scope.subscribe(() => { this.publish(); });
96
+ }
97
+ /** @returns the store the card's component reads through its bound selector. */
98
+ get snapshot() {
99
+ return this.store;
100
+ }
101
+ project() {
102
+ const snapshot = this.scope.getSnapshot();
103
+ const dirty = this.staged.size > 0;
104
+ return {
105
+ available: snapshot.status === 'ready',
106
+ writable: snapshot.writable,
107
+ dirty,
108
+ saving: this.saving,
109
+ failed: this.failed,
110
+ enabled: this.fieldState(snapshot, 'enabled'),
111
+ contextText: this.fieldState(snapshot, 'contextText'),
112
+ };
113
+ }
114
+ fieldState(snapshot, field) {
115
+ const staged = this.staged.get(field);
116
+ if (staged === undefined) {
117
+ return { text: format(field, sectionValue(snapshot, field)), overridden: stored(snapshot, field) };
118
+ }
119
+ const write = staged.clear ? { clear: true } : parse(field, staged.text);
120
+ return {
121
+ text: staged.text,
122
+ overridden: write !== undefined && 'value' in write,
123
+ };
124
+ }
125
+ /** Build the face the card's slot registration injects. */
126
+ inject() {
127
+ return {
128
+ hooks: { prefaceCard: this.store },
129
+ edit: (field, text) => { this.stage(field, { text, clear: false }); },
130
+ resetField: (field) => {
131
+ this.stage(field, { text: format(field, baseValue(this.scope.getSnapshot(), field)), clear: true });
132
+ },
133
+ save: () => { void this.save(); },
134
+ discard: () => {
135
+ if (this.staged.size === 0 && !this.failed)
136
+ return;
137
+ this.staged.clear();
138
+ this.failed = false;
139
+ this.publish();
140
+ },
141
+ };
142
+ }
143
+ stage(field, edit) {
144
+ this.staged.set(field, edit);
145
+ this.failed = false;
146
+ this.publish();
147
+ }
148
+ publish() {
149
+ this.store.set(this.project());
150
+ }
151
+ /** Write every staged edit, then re-seed from what the Host accepted. */
152
+ async save() {
153
+ if (this.staged.size === 0 || this.saving)
154
+ return;
155
+ this.saving = true;
156
+ this.failed = false;
157
+ this.publish();
158
+ let landed = true;
159
+ for (const [field, staged] of this.staged) {
160
+ const write = staged.clear ? { clear: true } : parse(field, staged.text);
161
+ if (write === undefined)
162
+ continue;
163
+ try {
164
+ if ('clear' in write) {
165
+ await this.scope.unset(field);
166
+ }
167
+ else {
168
+ await this.scope.set(field, write.value);
169
+ }
170
+ }
171
+ catch {
172
+ landed = false;
173
+ }
174
+ }
175
+ if (landed)
176
+ this.staged.clear();
177
+ this.saving = false;
178
+ this.failed = !landed;
179
+ this.publish();
180
+ }
181
+ }
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Card styles + runtime style injection for the preface-context settings
3
+ * card.
4
+ *
5
+ * The DSH client loader never serves `.css` artifacts — every style must be
6
+ * injected inside the bundle's factory closure (the same contract the
7
+ * upstream tsdown.client preset implements with lightningcss). A plain
8
+ * template-string stylesheet installed once at plugin activation is the slim
9
+ * equivalent for a hand-rolled bundle: static, prefixed class names
10
+ * (`dsh-pfc-*`, unique in the document) replace the hashed CSS-modules map,
11
+ * and the `<style data-plugin-css>` tag is removed when the plugin unloads.
12
+ *
13
+ * Colors resolve through `--dsw-alias-*` tokens so the card adapts to the
14
+ * light/dark theme.
15
+ *
16
+ * @module @huanlin/dsh-plugin-preface-context/client/preface-card.css
17
+ */
18
+ /** Class-name map consumed by the card component (CSS-modules replacement). */
19
+ export declare const css: {
20
+ readonly card: "dsh-pfc-card";
21
+ readonly cardOpen: "dsh-pfc-card--open";
22
+ readonly header: "dsh-pfc-header";
23
+ readonly headText: "dsh-pfc-head-text";
24
+ readonly name: "dsh-pfc-name";
25
+ readonly description: "dsh-pfc-description";
26
+ readonly pending: "dsh-pfc-pending";
27
+ readonly chevron: "dsh-pfc-chevron";
28
+ readonly chevronOpen: "dsh-pfc-chevron--open";
29
+ readonly body: "dsh-pfc-body";
30
+ readonly readOnly: "dsh-pfc-readonly";
31
+ readonly field: "dsh-pfc-field";
32
+ readonly head: "dsh-pfc-field-head";
33
+ readonly label: "dsh-pfc-label";
34
+ readonly badges: "dsh-pfc-badges";
35
+ readonly badge: "dsh-pfc-badge";
36
+ readonly reset: "dsh-pfc-reset";
37
+ readonly textarea: "dsh-pfc-textarea";
38
+ readonly toggleRow: "dsh-pfc-toggle-row";
39
+ readonly toggle: "dsh-pfc-toggle";
40
+ readonly toggleOn: "dsh-pfc-toggle--on";
41
+ readonly knob: "dsh-pfc-knob";
42
+ readonly knobOn: "dsh-pfc-knob--on";
43
+ readonly hint: "dsh-pfc-hint";
44
+ readonly footer: "dsh-pfc-footer";
45
+ readonly failed: "dsh-pfc-failed";
46
+ readonly discard: "dsh-pfc-discard";
47
+ readonly save: "dsh-pfc-save";
48
+ };
49
+ /**
50
+ * Install the card stylesheet as one tagged `<style>` element.
51
+ * @returns the disposer removing the tag (idempotent outside a document).
52
+ */
53
+ export declare function installPrefaceCardStyles(): () => void;