@case-framework/survey-core 0.7.0 → 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 CHANGED
@@ -49,14 +49,15 @@ pnpm add @case-framework/survey-core
49
49
  ```ts
50
50
  import {
51
51
  SurveyItemCore,
52
- ValueRefTypeLookup,
52
+ type ResponseSlotDefinition,
53
53
  ValueType,
54
54
  ItemTypeRegistry,
55
55
  } from "@case-framework/survey-core";
56
56
 
57
57
  type SingleChoiceConfig = {
58
58
  id: string;
59
- options: Array<{ id: string; key: string; type: string }>;
59
+ variableName: string;
60
+ options: Array<{ id: string; code: string; type: string }>;
60
61
  };
61
62
 
62
63
  class SingleChoiceQuestionItemCore extends SurveyItemCore<
@@ -69,6 +70,7 @@ class SingleChoiceQuestionItemCore extends SurveyItemCore<
69
70
  const cfg = (rawConfig ?? {}) as Partial<SingleChoiceConfig>;
70
71
  return {
71
72
  id: cfg.id ?? this.id,
73
+ variableName: cfg.variableName ?? "answer",
72
74
  options: cfg.options ?? [],
73
75
  };
74
76
  }
@@ -77,11 +79,23 @@ class SingleChoiceQuestionItemCore extends SurveyItemCore<
77
79
  return true;
78
80
  }
79
81
 
80
- getAvailableResponseValueSlots(): ValueRefTypeLookup {
81
- return {
82
- [`${this.id}...get...${this.config.id}`]: ValueType.reference,
83
- [`${this.id}...isDefined...${this.config.id}`]: ValueType.boolean,
84
- };
82
+ getResponseSlotDefinitions(): ResponseSlotDefinition[] {
83
+ return [
84
+ {
85
+ slotId: this.config.id,
86
+ primitiveId: this.id,
87
+ variableName: this.config.variableName,
88
+ naming: { kind: "variable", path: ["variableName"] },
89
+ valueType: ValueType.reference,
90
+ allowedValues: this.config.options.map((option) => ({
91
+ type: ValueType.reference,
92
+ value: option.id,
93
+ })),
94
+ referenceValueKeys: Object.fromEntries(
95
+ this.config.options.map((option) => [option.id, option.code]),
96
+ ),
97
+ },
98
+ ];
85
99
  }
86
100
  }
87
101
 
@@ -105,22 +119,24 @@ const survey = Survey.fromJson(
105
119
  {
106
120
  $schema:
107
121
  "https://github.com/case-framework/case-survey-toolkit/packages/survey-core/schemas/survey-schema.json",
122
+ schemaVersion: 2,
108
123
  surveyItems: [
109
124
  {
110
125
  id: "root",
111
- key: "root",
126
+ metadata: { itemLabel: "Survey" },
112
127
  itemType: ReservedSurveyItemTypes.Group,
113
128
  config: { isRoot: true, items: ["q1"] },
114
129
  },
115
130
  {
116
131
  id: "q1",
117
- key: "q1",
132
+ metadata: { itemLabel: "Example question" },
118
133
  itemType: "singleChoiceQuestion",
119
134
  config: {
120
135
  id: "q1",
136
+ variableName: "choice",
121
137
  options: [
122
- { id: "yes", key: "yes", type: "option" },
123
- { id: "no", key: "no", type: "option" },
138
+ { id: "yes", code: "yes", type: "option" },
139
+ { id: "no", code: "no", type: "option" },
124
140
  ],
125
141
  },
126
142
  },
@@ -135,30 +151,60 @@ const engine = new SurveyEngineCore(survey, { locale: "en" });
135
151
  engine.setResponse("q1", new ResponseItem([["q1", { type: ValueType.reference, value: "yes" }]]));
136
152
 
137
153
  const pages = engine.getSurveyPages("large");
138
- const responses = engine.getResponses();
154
+ const responses = engine.getSubmissionResponses();
139
155
  const events = engine.getEvents();
140
156
  ```
141
157
 
158
+ For submission, use `getSurveyResponse(key)` (or `getSubmissionResponses()` for item
159
+ views). Hidden questions, groups, matrix rows and declared component slots are
160
+ excluded across every page. `getResponses()` and `getSurveyResponse(key, true)`
161
+ retain hidden answers for session snapshots and resuming. `getAnswer()` reads a
162
+ retained stored answer; `getActiveAnswer()` reads the answer available to survey
163
+ logic. Hidden answers are undefined to expressions, including `isDefined`, and do
164
+ not affect validation, follow-up conditions or computed scores.
165
+
166
+ The engine compiles visibility and answer dependencies once and memoizes active
167
+ values per update. Cyclic dependencies are rejected before the session starts,
168
+ including visibility based on the same question's answer or its own computed score.
169
+ Undefined/nonboolean display conditions hide their target. Visibility callbacks
170
+ (`customExpression`) are not reproducible or statically analyzable; use serialized
171
+ custom context values instead. Submitted responses save the locale and participant
172
+ flags alongside custom values so exports reconstruct the same evaluation context.
173
+ Export reconstruction does not reapply configured prefills.
174
+
175
+ Item plugins declare component-gated slots with `getConditionalResponseSlots()`.
176
+ Several entries for one slot require all listed components to be visible. More
177
+ complex projection (such as hidden choices or unselected embedded fields) uses
178
+ `getActiveResponseValue()` and must declare its slot/component dependencies in
179
+ `getActiveResponseDependencies()`. Computed values must declare their source slots;
180
+ they receive active source answers only. Never mutate retained answers in these hooks.
181
+
182
+ Only interactive items have response objects;
183
+ `getResponseItem()` returns `undefined` for groups, page breaks, and display items,
184
+ and `setResponse()` rejects these targets.
185
+
142
186
  ### 3. Export responses to CSV
143
187
 
144
188
  ```ts
145
189
  import { SurveyResponse, SurveyResponseExporter } from "@case-framework/survey-core";
146
190
 
147
- const response = new SurveyResponse("response-1", "v1");
148
- response.responses = new Map(responses.map((r) => [r.itemId, r]));
191
+ const response = engine.getSurveyResponse("response-1");
149
192
  response.submittedAt = Math.floor(Date.now() / 1000);
150
193
 
194
+ // The host supplies the definition that collected these answers.
151
195
  const exporter = new SurveyResponseExporter([
152
- {
153
- versionId: "v1",
154
- surveyKey: survey.surveyKey ?? "survey",
155
- survey,
156
- },
196
+ { schema: survey, responses: [response], sourceId: "host-release" },
157
197
  ]);
158
-
159
- const csv = exporter.exportResponsesToCsv([response]);
198
+ const csv = exporter.exportResponsesToCsv();
160
199
  ```
161
200
 
201
+ Persist `response.serialize()` to retain the response envelope and its event log.
202
+ The CSV contains answer columns and survey-level metadata; it does not include
203
+ the event history. Events currently record survey opening, response changes, and
204
+ language changes with timestamps in Unix seconds. Rendered/displayed item
205
+ timestamps are not recorded, and hosts must call `onPageChanged()` themselves to
206
+ record page changes.
207
+
162
208
  ### 4. Edit surveys with the editor entrypoint
163
209
 
164
210
  ```ts
@@ -168,11 +214,90 @@ const editor = new SurveyEditor(survey, { pluginRegistry });
168
214
 
169
215
  const newItem = survey.createItemFromRaw({
170
216
  id: "q2",
171
- key: "q2",
217
+ metadata: { itemLabel: "Another question" },
172
218
  itemType: "singleChoiceQuestion",
173
- config: { id: "q2", options: [] },
219
+ config: { id: "q2", variableName: "second_choice", options: [] },
174
220
  });
175
221
 
176
222
  editor.addItem({ parentId: survey.rootItem!.id }, newItem);
177
223
  editor.commit({ label: "Add q2", source: CommitSource.USER });
178
224
  ```
225
+
226
+ ## Calendar dates
227
+
228
+ Date responses and expression constants store calendar strings, not Unix timestamps:
229
+ `{ type: "date", value: "2026-09-20" }`. Year (`"2026"`) and month (`"2026-09"`)
230
+ precision are preserved; `date[]` stores arrays of these strings. Numeric dates and
231
+ ISO date-time strings are rejected. This is a breaking response and expression API change;
232
+ there is no implicit conversion of old timestamp data. Actual event timestamps retain their
233
+ existing instant semantics.
234
+
235
+ Use `const_date("2026-09-20")`, `response_date(ref)`, and the `date_eq`, `date_gt`,
236
+ `date_gte`, `date_lt`, `date_lte`, `date_min`, `date_max` builders. Equality includes
237
+ precision; ordering/min/max require matching precision. `date_add_days`,
238
+ `date_add_months`, and `date_add_years` accept a date expression and signed integer
239
+ number expression. They preserve precision and clamp month-end dates. Nonzero offsets
240
+ cannot require finer precision than the input. `date_diff(a, b)` returns signed a-b in
241
+ days, months, or years according to the matching input precision. Missing values,
242
+ precision mismatches, and arithmetic outside years 0001–9999 return undefined.
243
+
244
+ Form and matrix date bounds accept `valueExpression` (date-valued CASE expression)
245
+ instead of a literal `value`. For example:
246
+
247
+ ```ts
248
+ const bound = {
249
+ id: "after-start",
250
+ type: "minDate",
251
+ valueExpression: date_add_days(response_date("visit...get...start"), const_number(2))
252
+ .getExpression()!
253
+ .serialize(),
254
+ };
255
+ ```
256
+
257
+ Bounds evaluate against current responses, including after the source answer changes.
258
+ Minimum bounds use the start of their period, maximum bounds the end; an answer's entire
259
+ period must fit. Optional unanswered fields pass; supplied answers with unresolved bounds
260
+ fail validation. Host item cores receive an optional expression evaluator as the third
261
+ argument to `getResponseValidationValues`.
262
+
263
+ Default exports preserve the calendar string. Custom formatting and date templates are
264
+ timezone-independent; partial dates retain their canonical value even if a pattern requests
265
+ missing components. Use local Date adapters only at calendar-widget boundaries.
266
+
267
+ ## Response identities, naming and export profiles
268
+
269
+ Surveys and flat response envelopes use `schemaVersion: 2`. Persist `answers[slotId]` separately from `itemMetadata`, context and events. A host-selected schema owns each slot; a submission does not require a publication/version ID. Old drafts and profiles must be recreated, not implicitly interpreted against this format.
270
+
271
+ Use `survey.getResponseSlotRegistry()` for typed ownership, variable names, categorical domains, computed dependencies, labels and export codes. Serialized expression nodes use `{type: "responseVariable", variableRef: {slotId, method: "get" | "isDefined"}}`. Names and item positions are never identities.
272
+
273
+ Names are unique lowercase snake_case, begin with a letter, and contain at most 32 characters. `previewResponseNaming(survey, edits)` and `editor.renameResponseVariables(edits)` support atomic renames, including swaps. Matrix edits target `{primitiveId, prefix?, rows?, columns?}`; cells remain derived. Copying creates fresh owned identities and suffixes names or matrix prefixes with `_2`, `_3`, etc. `editor.lastResponseNameChanges` reports the result. Plugins expose `naming` paths and owned component IDs to participate in copying and editing.
274
+
275
+ Categorical answers store option IDs, including ordinary form and form-matrix dropdowns. Expression constants compared with a categorical slot must be option IDs from that slot's declared domain. `survey.getExpressionResponseSlots()` reports each reference with its owning `itemId` and typed `allowedValues`; unknown references and out-of-domain constants are blocking diagnostics that stop runtime and export readiness rather than evaluating false and silently changing branching. Never infer an option ID from a matching display label or export code.
276
+
277
+ Previous-response prefills reference `{surveyKey?, slotId}`. The host resolver answers them from its own stored submissions; duplicating a draft keeps these references external instead of remapping them to the copy.
278
+
279
+ `metadata.itemLabel` is an optional **Editor name**. `survey.resolveItemEditorName(id, locale)` falls back to meaningful content and localized composition; `getItemDisplayPath` returns structural IDs plus display breadcrumbs. Items have no coding key.
280
+
281
+ `ExporterProfile` requires `schemaVersion: 1`. `slotOverrides` uses exact slot IDs; `columnHeaders` and ordering use `encodeExportColumnId(["response", slotId, "value"])` or `["response", slotId, "option", optionId]`. Unknown entries and matrix-cell header overrides are errors. `SlotTransformConfig` supports `include`, `categorical` (codes/labels/ids), `multiple` (json/delimited/indicators), explicit `delimiter`, `booleanValues`, date formatting, numeric `precision`, `durationUnit`, and explicit alternative mappings. Missing values are blank; answered empty selections become `[]` or zero indicators. Codes must be complete, nonempty and unambiguous. Delimited list entries are double-quoted with doubled internal quotes. Durations default to seconds; calendar months/years require an explicit matching unit because their lengths are not fixed.
282
+
283
+ Computed slots are excluded by default; `{mode:"default", include:true}` evaluates them against the supplied schema and response context. `generateCodebook(survey, {profile})` and `generateExportCodebook(batches, options)` describe the actual compiled projection and mappings. Combined exports require an explicit `codingPolicy`; incompatible types/domains are rejected, and changed codes need complete explicit harmonized mappings.
284
+
285
+ The editor's `previewResponseSettings` / `updateResponseSettings` combine naming, option-code and format edits before one ordinary commit. Authoring formats live in `RawSurveyItem.responseSettings[slotId]`; batch profiles can override them. Both the per-item controls and survey-wide **Response data** view use these APIs. Hosts may wrap the editor in the exported `ResponseSettingsSuggestionProvider` to supply FAIR suggestions as `{naming, settings}`; suggestions are previewed and validated by the same manual mutation path.
286
+
287
+ ### Persisted naming fields
288
+
289
+ All choice, consent and form responses store `variableName`. Matrices store `prefix`, row `rowName`, and (for form matrices) column `columnName`; full variable names are derived and never stored again on cells. Categorical options store `code`, including form/dropdown options. Option IDs remain the stored answer values. Former field/row/column/option `key` and dropdown option `value` fields are rejected rather than read as aliases. Item editor names remain `metadata.itemLabel`.
290
+
291
+ Response edits emit one `responseChanged` event per changed slot, with `slotId`,
292
+ `timestamp` (Unix seconds), and `operation` (`set` or `clear`). Unchanged values
293
+ emit no event. Initial restored/prefilled values do not emit change events.
294
+ The survey schema resolves slot ownership; events do not duplicate item types,
295
+ answer values, or source information.
296
+
297
+ Visibility conditions with defined, non-boolean results fail closed and are available
298
+ through `engine.getEvaluationDiagnostics()`. Each diagnostic identifies the item,
299
+ optional component, and result type without including answer values. Diagnostics
300
+ describe the current evaluation, are deduplicated by condition, and omit unanswered
301
+ conditions and conditions skipped because a parent is hidden. They are separate from
302
+ response-normalization diagnostics and participant events. Context updates always
303
+ reevaluate conditions; only an actual locale change records a language-change event.
@@ -1,12 +1,2 @@
1
- //#region src/editor/item-colors.d.ts
2
- /**
3
- * Editor-only item-color swatches persisted in `metadata.editorItemColor`.
4
- *
5
- * This is shared survey-editor configuration: hosts may render the editor
6
- * without enabling the assistant, while assistant proposals must validate
7
- * against the same values.
8
- */
9
- declare const SURVEY_EDITOR_ITEM_COLORS: readonly ["#404040", "#b91c1c", "#c2410c", "#a16207", "#4d7c0f", "#047857", "#0369a1", "#4338ca", "#7e22ce", "#86198f", "#be123c"];
10
- //#endregion
11
- export { SURVEY_EDITOR_ITEM_COLORS };
12
- //# sourceMappingURL=colors.d.mts.map
1
+ import { t as SURVEY_EDITOR_ITEM_COLORS } from "../item-colors-DgoJeSCQ.mjs";
2
+ export { SURVEY_EDITOR_ITEM_COLORS };
@@ -1 +1 @@
1
- {"version":3,"file":"colors.mjs","names":[],"sources":["../../src/editor/item-colors.ts"],"sourcesContent":["/**\n * Editor-only item-color swatches persisted in `metadata.editorItemColor`.\n *\n * This is shared survey-editor configuration: hosts may render the editor\n * without enabling the assistant, while assistant proposals must validate\n * against the same values.\n */\nexport const SURVEY_EDITOR_ITEM_COLORS = [\n \"#404040\",\n \"#b91c1c\",\n \"#c2410c\",\n \"#a16207\",\n \"#4d7c0f\",\n \"#047857\",\n \"#0369a1\",\n \"#4338ca\",\n \"#7e22ce\",\n \"#86198f\",\n \"#be123c\",\n] as const;\n"],"mappings":";;;;;;;;AAOA,MAAa,4BAA4B;CACvC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD"}
1
+ {"version":3,"file":"colors.mjs","names":[],"sources":["../../src/editor/item-colors.ts"],"sourcesContent":["/**\n * Editor-only item-color swatches persisted in `metadata.editorItemColor`.\n *\n * This is shared survey-editor configuration: hosts may render the editor\n * without enabling the assistant, while assistant proposals must validate\n * against the same values.\n */\nexport const SURVEY_EDITOR_ITEM_COLORS = [\n \"#404040\",\n \"#b91c1c\",\n \"#c2410c\",\n \"#a16207\",\n \"#4d7c0f\",\n \"#047857\",\n \"#0369a1\",\n \"#4338ca\",\n \"#7e22ce\",\n \"#86198f\",\n \"#be123c\",\n] as const;\n"],"mappings":";;;;;;;;AAOA,MAAa,4BAA4B;CACvC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF"}
@@ -1,16 +1,48 @@
1
- import { D as SurveyCardContent, E as NavigationContent, Gt as SurveyItemCore, Jt as RawSurveyItem, M as Content, S as RawSurveyAsset, k as SurveyItemTranslations, m as ItemTypeRegistry, t as Survey, vt as TemplateValueDefinition, w as JsonComponentContent, x as RawSurvey } from "./survey-DedDemSc.mjs";
2
-
1
+ import { Jn as SurveyItemCore, Lt as ItemTypeRegistry, Qt as JsonComponentContent, St as SlotTransformConfig, Wn as RawSurveyItem, Xt as RawSurveyAsset, Yt as RawSurvey, en as NavigationContent, on as Content, rn as SurveyItemTranslations, tn as SurveyCardContent, ua as TemplateValueDefinition, wt as Survey } from "./index-SDbZ5WQM.mjs";
2
+ //#region src/editor/response-naming.d.ts
3
+ export interface ResponseNameChange {
4
+ slotId: string;
5
+ itemId: string;
6
+ before: string;
7
+ after: string;
8
+ }
9
+ export type ResponseNamingEdit = {
10
+ slotId: string;
11
+ variableName: string;
12
+ } | {
13
+ primitiveId: string;
14
+ prefix?: string;
15
+ rows?: Record<string, string>;
16
+ columns?: Record<string, string>;
17
+ };
18
+ export declare function previewResponseNaming(survey: Survey, edits: readonly ResponseNamingEdit[]): {
19
+ survey: RawSurvey;
20
+ changes: ResponseNameChange[];
21
+ };
22
+ /** Allocate whole matrix prefixes and individual names in deterministic declaration order. */
23
+ export declare function allocateCopiedResponseNames(survey: Survey, items: SurveyItemCore[]): ResponseNameChange[];
24
+ export interface ResponseSettingsEdit {
25
+ slotId: string;
26
+ optionCodes?: Record<string, string>;
27
+ exportSettings?: SlotTransformConfig;
28
+ }
29
+ /** Naming, categorical codes, and formats share one detached, atomic preview. */
30
+ export declare function previewResponseSettings(survey: Survey, naming: readonly ResponseNamingEdit[], settings: readonly ResponseSettingsEdit[]): {
31
+ survey: RawSurvey;
32
+ changes: ResponseNameChange[];
33
+ };
34
+ //#endregion
3
35
  //#region src/editor/types.d.ts
4
- interface Target {
36
+ export interface Target {
5
37
  parentId: string;
6
38
  index?: number;
7
39
  }
8
40
  //#endregion
9
41
  //#region src/editor/item-copy-paste.d.ts
10
- type SerializedTranslations = {
42
+ export type SerializedTranslations = {
11
43
  [locale: string]: JsonComponentContent;
12
44
  };
13
- interface SurveyItemClipboardData {
45
+ export interface SurveyItemClipboardData {
14
46
  type: "survey-item";
15
47
  version: string;
16
48
  items: Array<{
@@ -23,7 +55,8 @@ interface SurveyItemClipboardData {
23
55
  rootItemId: string;
24
56
  timestamp: number;
25
57
  }
26
- declare class ItemCopyPaste {
58
+ export declare class ItemCopyPaste {
59
+ lastResponseNameChanges: ResponseNameChange[];
27
60
  private survey;
28
61
  constructor(survey: Survey);
29
62
  /**
@@ -77,27 +110,28 @@ declare class ItemCopyPaste {
77
110
  }
78
111
  //#endregion
79
112
  //#region src/editor/undo-redo.d.ts
80
- interface UndoRedoConfig {
113
+ export interface UndoRedoConfig {
81
114
  maxTotalMemoryMB: number;
82
115
  minHistorySize: number;
83
116
  maxHistorySize: number;
84
117
  }
85
- declare const CommitSource: {
118
+ export declare const CommitSource: {
86
119
  readonly USER: "user";
87
120
  readonly SYSTEM: "system";
88
121
  readonly ASSISTANT: "assistant";
89
122
  };
90
- type CommitSource = (typeof CommitSource)[keyof typeof CommitSource];
91
- interface CommitMeta {
123
+ export type CommitSource = (typeof CommitSource)[keyof typeof CommitSource];
124
+ export interface CommitMeta {
92
125
  label: string;
93
126
  source?: CommitSource;
94
127
  }
95
- interface AssetPatch {
128
+ export interface AssetPatch {
96
129
  assetId: string;
97
130
  prev?: RawSurveyAsset;
98
131
  next?: RawSurveyAsset;
99
132
  }
100
133
  interface BaseHistoryEntry {
134
+ id?: string;
101
135
  timestamp: number;
102
136
  meta: CommitMeta;
103
137
  memorySize: number;
@@ -111,7 +145,7 @@ interface AssetChangeHistoryEntry extends BaseHistoryEntry {
111
145
  changes: AssetPatch[];
112
146
  }
113
147
  type HistoryEntry = SurveySnapshotHistoryEntry | AssetChangeHistoryEntry;
114
- interface SurveyEditorHistoryCommit {
148
+ export interface SurveyEditorHistoryCommit {
115
149
  index: number;
116
150
  kind: HistoryEntry["kind"];
117
151
  meta: CommitMeta;
@@ -122,10 +156,11 @@ interface SurveyEditorHistoryCommit {
122
156
  type SerializedHistoryEntry = SurveySnapshotHistoryEntry | AssetChangeHistoryEntry | (BaseHistoryEntry & {
123
157
  survey: RawSurvey;
124
158
  });
125
- declare class SurveyEditorUndoRedo {
159
+ export declare class SurveyEditorUndoRedo {
126
160
  private history;
127
161
  private currentIndex;
128
162
  private _config;
163
+ private baseAssetSize?;
129
164
  private _initialAssets?;
130
165
  constructor(initialSurvey: RawSurvey, config?: Partial<UndoRedoConfig>, meta?: CommitMeta, initialAssets?: Record<string, RawSurveyAsset>);
131
166
  private saveEntry;
@@ -137,6 +172,8 @@ declare class SurveyEditorUndoRedo {
137
172
  private getStateAtIndex;
138
173
  private applyAssetPatch;
139
174
  private getAssetsAtIndex;
175
+ getEntryId(index: number): string | undefined;
176
+ findEntryIndex(id: string): number;
140
177
  commit(survey: RawSurvey, meta: CommitMeta): void;
141
178
  commitAssetChange(changes: AssetPatch[], meta: CommitMeta): void;
142
179
  getCurrentState(): RawSurvey;
@@ -212,22 +249,37 @@ declare class SurveyEditorUndoRedo {
212
249
  }
213
250
  //#endregion
214
251
  //#region src/editor/survey-editor.d.ts
215
- interface SerializedSurveyEditor {
252
+ export interface SerializedSurveyEditor {
216
253
  version: string;
217
254
  survey: RawSurvey;
218
255
  undoRedo: ReturnType<SurveyEditorUndoRedo["serialize"]>;
219
256
  hasUncommittedChanges: boolean;
220
257
  }
221
- interface SurveyEditorConfig extends Partial<UndoRedoConfig> {
258
+ export interface SurveyEditorConfig extends Partial<UndoRedoConfig> {
222
259
  /** Plugin registry for deserializing survey state during undo/redo. Required when survey contains custom item types. */
223
260
  pluginRegistry?: ItemTypeRegistry;
224
261
  }
225
- declare class SurveyEditor {
262
+ export declare class SurveyEditor {
263
+ lastResponseNameChanges: ResponseNameChange[];
264
+ renameResponseVariables(edits: readonly ResponseNamingEdit[]): ResponseNameChange[];
265
+ updateResponseSettings(naming: readonly ResponseNamingEdit[], settings: readonly ResponseSettingsEdit[]): ResponseNameChange[];
226
266
  private _survey;
227
267
  private _undoRedo;
228
268
  private _hasUncommittedChanges;
269
+ private mutationEpoch;
270
+ private pendingAssets;
229
271
  private _pluginRegistry?;
230
272
  constructor(survey: Survey, config?: SurveyEditorConfig, meta?: CommitMeta);
273
+ /**
274
+ * An isolated field edit owns only its field value (held by the caller) and
275
+ * affected item metadata. Any intervening core action invalidates this handle.
276
+ * The caller must finish pre-existing work before opening a handle.
277
+ */
278
+ beginFieldEdit(itemId?: string): {
279
+ run: <T>(write: () => T) => T;
280
+ reconcile: (restoreValue?: () => void) => boolean;
281
+ };
282
+ get hasCommittedChanges(): boolean;
231
283
  /** Returns an immutable copy of the current survey state. */
232
284
  get survey(): Survey;
233
285
  get hasUncommittedChanges(): boolean;
@@ -297,6 +349,10 @@ declare class SurveyEditor {
297
349
  * @param rawItemData - Full RawSurveyItem or Partial to merge. The id cannot be changed.
298
350
  */
299
351
  updateItem(itemId: string, rawItemData: RawSurveyItem | Partial<RawSurveyItem>): void;
352
+ /** Detached field read; does not construct a Survey or visit other locales. */
353
+ getItemTranslationContent(itemId: string, locale: string, contentKey: string, fallbackLocale?: string): Content | undefined;
354
+ /** Publish accepted content without committing history. Equivalent writes are no-ops. */
355
+ setItemTranslationContent(itemId: string, locale: string, contentKey: string, content?: Content): boolean;
300
356
  updateItemTranslations(itemId: string, updatedContent?: SurveyItemTranslations): boolean;
301
357
  /**
302
358
  * Update survey-level translations that are not tied to specific items.
@@ -375,6 +431,8 @@ declare class SurveyEditor {
375
431
  /**
376
432
  * Add or replace a survey asset.
377
433
  */
434
+ /** Stage one live asset delta. Default setAsset/removeAsset remain immediate. */
435
+ stageAsset(assetId: string, asset?: RawSurveyAsset): void;
378
436
  setAsset(assetId: string, asset: RawSurveyAsset): void;
379
437
  /**
380
438
  * Remove a survey asset.
@@ -395,5 +453,4 @@ declare class SurveyEditor {
395
453
  pasteItem(clipboardData: SurveyItemClipboardData, target: Target): string;
396
454
  }
397
455
  //#endregion
398
- export { AssetPatch, CommitMeta, CommitSource, ItemCopyPaste, SerializedSurveyEditor, SerializedTranslations, SurveyEditor, SurveyEditorConfig, SurveyEditorHistoryCommit, SurveyEditorUndoRedo, SurveyItemClipboardData, Target, UndoRedoConfig };
399
456
  //# sourceMappingURL=editor.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"editor.d.mts","names":[],"sources":["../src/editor/types.ts","../src/editor/item-copy-paste.ts","../src/editor/undo-redo.ts","../src/editor/survey-editor.ts"],"mappings":"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"}
1
+ {"version":3,"file":"editor.d.mts","names":[],"sources":["../src/editor/response-naming.ts","../src/editor/types.ts","../src/editor/item-copy-paste.ts","../src/editor/undo-redo.ts","../src/editor/survey-editor.ts"],"mappings":"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"}