@case-framework/survey-core 0.1.0 → 0.3.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 +181 -0
- package/build/editor.d.mts +169 -5
- package/build/editor.d.mts.map +1 -1
- package/build/editor.mjs +429 -12
- package/build/editor.mjs.map +1 -1
- package/build/index.d.mts +197 -6
- package/build/index.d.mts.map +1 -1
- package/build/index.mjs +365 -42
- package/build/index.mjs.map +1 -1
- package/build/{package.json/package.json → package.json} +6 -6
- package/build/{survey-C3ZHI-5z.mjs → survey-DJbgFVPz.mjs} +298 -198
- package/build/survey-DJbgFVPz.mjs.map +1 -0
- package/build/{survey-TUPUXiXl.d.mts → survey-wnGyIY66.d.mts} +81 -6
- package/build/survey-wnGyIY66.d.mts.map +1 -0
- package/package.json +6 -6
- package/build/survey-C3ZHI-5z.mjs.map +0 -1
- package/build/survey-TUPUXiXl.d.mts.map +0 -1
package/build/editor.mjs
CHANGED
|
@@ -1,5 +1,305 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import { I as generateId, R as structuredCloneMethod, l as GroupItemCore, m as ReservedSurveyItemTypes, n as SurveyItemTranslations, t as Survey } from "./survey-DJbgFVPz.mjs";
|
|
2
|
+
//#region src/editor/ai-context.ts
|
|
3
|
+
const DEFAULT_SCOPE_LIMITS = {
|
|
4
|
+
tiny: 40,
|
|
5
|
+
focused: 150,
|
|
6
|
+
full: 500
|
|
7
|
+
};
|
|
8
|
+
const DEFAULT_FOCUS_TREE_LIMIT = 120;
|
|
9
|
+
const DEFAULT_TRANSLATION_SNIPPETS_PER_ITEM = 8;
|
|
10
|
+
const DEFAULT_TRANSLATION_SNIPPET_TEXT_LIMIT = 120;
|
|
11
|
+
const PURPOSE_DEFAULTS = {
|
|
12
|
+
generic: {
|
|
13
|
+
scope: "tiny",
|
|
14
|
+
includeRawSurvey: false,
|
|
15
|
+
includeIndexes: false,
|
|
16
|
+
includeFocusItemTree: false
|
|
17
|
+
},
|
|
18
|
+
"key-suggestion": {
|
|
19
|
+
scope: "tiny",
|
|
20
|
+
includeRawSurvey: false,
|
|
21
|
+
includeIndexes: false,
|
|
22
|
+
includeFocusItemTree: true
|
|
23
|
+
},
|
|
24
|
+
"label-suggestion": {
|
|
25
|
+
scope: "tiny",
|
|
26
|
+
includeRawSurvey: false,
|
|
27
|
+
includeIndexes: false,
|
|
28
|
+
includeFocusItemTree: true
|
|
29
|
+
},
|
|
30
|
+
"item-generation": {
|
|
31
|
+
scope: "focused",
|
|
32
|
+
includeRawSurvey: false,
|
|
33
|
+
includeIndexes: true,
|
|
34
|
+
includeFocusItemTree: true
|
|
35
|
+
},
|
|
36
|
+
translation: {
|
|
37
|
+
scope: "focused",
|
|
38
|
+
includeRawSurvey: false,
|
|
39
|
+
includeIndexes: true,
|
|
40
|
+
includeFocusItemTree: true
|
|
41
|
+
},
|
|
42
|
+
"condition-management": {
|
|
43
|
+
scope: "full",
|
|
44
|
+
includeRawSurvey: true,
|
|
45
|
+
includeIndexes: true,
|
|
46
|
+
includeFocusItemTree: true
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
const sortByItemId = (items) => [...items].sort((a, b) => a.itemId.localeCompare(b.itemId));
|
|
50
|
+
function getChildIds(survey, itemId) {
|
|
51
|
+
const item = survey.surveyItems.get(itemId);
|
|
52
|
+
if (!(item instanceof GroupItemCore)) return [];
|
|
53
|
+
return [...item.items ?? []];
|
|
54
|
+
}
|
|
55
|
+
function buildParentLookup(survey) {
|
|
56
|
+
const lookup = /* @__PURE__ */ new Map();
|
|
57
|
+
for (const item of survey.surveyItems.values()) {
|
|
58
|
+
if (!(item instanceof GroupItemCore)) continue;
|
|
59
|
+
for (const childId of item.items ?? []) lookup.set(childId, item.id);
|
|
60
|
+
}
|
|
61
|
+
return lookup;
|
|
62
|
+
}
|
|
63
|
+
function createFullKeyGetter(survey, parentLookup) {
|
|
64
|
+
const fullKeyCache = /* @__PURE__ */ new Map();
|
|
65
|
+
const getFullKey = (itemId, stack = /* @__PURE__ */ new Set()) => {
|
|
66
|
+
const cached = fullKeyCache.get(itemId);
|
|
67
|
+
if (cached) return cached;
|
|
68
|
+
const item = survey.surveyItems.get(itemId);
|
|
69
|
+
if (!item) return itemId;
|
|
70
|
+
if (stack.has(itemId)) return item.key;
|
|
71
|
+
const parentId = parentLookup.get(itemId);
|
|
72
|
+
if (!parentId) {
|
|
73
|
+
fullKeyCache.set(itemId, item.key);
|
|
74
|
+
return item.key;
|
|
75
|
+
}
|
|
76
|
+
stack.add(itemId);
|
|
77
|
+
const parentFullKey = getFullKey(parentId, stack);
|
|
78
|
+
stack.delete(itemId);
|
|
79
|
+
const fullKey = `${parentFullKey}.${item.key}`;
|
|
80
|
+
fullKeyCache.set(itemId, fullKey);
|
|
81
|
+
return fullKey;
|
|
82
|
+
};
|
|
83
|
+
return getFullKey;
|
|
84
|
+
}
|
|
85
|
+
function buildFullOutline(survey, parentLookup, getFullKey) {
|
|
86
|
+
const outline = [];
|
|
87
|
+
const visited = /* @__PURE__ */ new Set();
|
|
88
|
+
const toNode = (itemId, depth) => {
|
|
89
|
+
const item = survey.surveyItems.get(itemId);
|
|
90
|
+
if (!item) return;
|
|
91
|
+
const childCount = item instanceof GroupItemCore ? item.items.length : 0;
|
|
92
|
+
return {
|
|
93
|
+
itemId,
|
|
94
|
+
parentId: parentLookup.get(itemId),
|
|
95
|
+
depth,
|
|
96
|
+
itemType: item.type,
|
|
97
|
+
key: item.key,
|
|
98
|
+
fullKey: getFullKey(itemId),
|
|
99
|
+
itemLabel: item.metadata?.itemLabel,
|
|
100
|
+
childCount
|
|
101
|
+
};
|
|
102
|
+
};
|
|
103
|
+
const visit = (itemId, depth) => {
|
|
104
|
+
if (visited.has(itemId)) return;
|
|
105
|
+
visited.add(itemId);
|
|
106
|
+
const node = toNode(itemId, depth);
|
|
107
|
+
if (node) outline.push(node);
|
|
108
|
+
for (const childId of getChildIds(survey, itemId)) visit(childId, depth + 1);
|
|
109
|
+
};
|
|
110
|
+
const root = survey.rootItem;
|
|
111
|
+
if (root) visit(root.id, 0);
|
|
112
|
+
const remaining = sortByItemId(Array.from(survey.surveyItems.values()).filter((item) => !visited.has(item.id)).map((item) => ({ itemId: item.id })));
|
|
113
|
+
for (const item of remaining) visit(item.itemId, 0);
|
|
114
|
+
return outline;
|
|
115
|
+
}
|
|
116
|
+
function collectTinyScopeIds(survey, focusItemId) {
|
|
117
|
+
const ids = /* @__PURE__ */ new Set();
|
|
118
|
+
const rootItem = survey.rootItem;
|
|
119
|
+
if (rootItem) ids.add(rootItem.id);
|
|
120
|
+
ids.add(focusItemId);
|
|
121
|
+
for (const id of survey.getItemPath(focusItemId)) ids.add(id);
|
|
122
|
+
for (const sibling of survey.getSiblings(focusItemId)) ids.add(sibling.id);
|
|
123
|
+
for (const childId of getChildIds(survey, focusItemId)) ids.add(childId);
|
|
124
|
+
return ids;
|
|
125
|
+
}
|
|
126
|
+
function addDescendants(survey, itemId, set, maxDepth) {
|
|
127
|
+
const queue = [{
|
|
128
|
+
id: itemId,
|
|
129
|
+
depth: 0
|
|
130
|
+
}];
|
|
131
|
+
while (queue.length > 0) {
|
|
132
|
+
const current = queue.shift();
|
|
133
|
+
if (!current) continue;
|
|
134
|
+
if (current.depth >= maxDepth) continue;
|
|
135
|
+
for (const childId of getChildIds(survey, current.id)) {
|
|
136
|
+
set.add(childId);
|
|
137
|
+
queue.push({
|
|
138
|
+
id: childId,
|
|
139
|
+
depth: current.depth + 1
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
function collectFocusedScopeIds(survey, focusItemId) {
|
|
145
|
+
const ids = collectTinyScopeIds(survey, focusItemId);
|
|
146
|
+
const ancestors = survey.getItemPath(focusItemId);
|
|
147
|
+
addDescendants(survey, focusItemId, ids, 2);
|
|
148
|
+
for (const sibling of survey.getSiblings(focusItemId)) {
|
|
149
|
+
if (sibling.id === focusItemId) continue;
|
|
150
|
+
ids.add(sibling.id);
|
|
151
|
+
addDescendants(survey, sibling.id, ids, 1);
|
|
152
|
+
}
|
|
153
|
+
for (const ancestorId of ancestors) {
|
|
154
|
+
const siblingIds = (survey.getParentItem(ancestorId)?.items ?? []).filter((id) => id !== ancestorId);
|
|
155
|
+
for (const siblingId of siblingIds) {
|
|
156
|
+
ids.add(siblingId);
|
|
157
|
+
addDescendants(survey, siblingId, ids, 1);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
return ids;
|
|
161
|
+
}
|
|
162
|
+
function buildFocusInfo(survey, focusItemId) {
|
|
163
|
+
if (!survey.surveyItems.has(focusItemId)) return;
|
|
164
|
+
const pathItemIds = [...survey.getItemPath(focusItemId), focusItemId];
|
|
165
|
+
return {
|
|
166
|
+
focusItemId,
|
|
167
|
+
parentItemId: survey.getParentItem(focusItemId)?.id,
|
|
168
|
+
pathItemIds,
|
|
169
|
+
siblingItemIds: survey.getSiblings(focusItemId).filter((item) => item.id !== focusItemId).map((item) => item.id),
|
|
170
|
+
childItemIds: getChildIds(survey, focusItemId)
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
const normalizeSnippetText = (text, maxChars) => {
|
|
174
|
+
return text.trim().replace(/\s+/g, " ").slice(0, maxChars);
|
|
175
|
+
};
|
|
176
|
+
const getContentText = (content, maxChars) => {
|
|
177
|
+
if (!content) return null;
|
|
178
|
+
const maybeText = content.content;
|
|
179
|
+
if (typeof maybeText !== "string") return null;
|
|
180
|
+
const normalized = normalizeSnippetText(maybeText, maxChars);
|
|
181
|
+
return normalized.length > 0 ? normalized : null;
|
|
182
|
+
};
|
|
183
|
+
function getItemTranslationSnippets(survey, itemId, maxSnippets, textLimit) {
|
|
184
|
+
const snippets = [];
|
|
185
|
+
const translations = survey.getItemTranslations(itemId);
|
|
186
|
+
if (!translations) return snippets;
|
|
187
|
+
for (const locale of translations.locales) {
|
|
188
|
+
const localeContent = translations.getAllForLocale(locale);
|
|
189
|
+
if (!localeContent) continue;
|
|
190
|
+
for (const [contentKey, content] of Object.entries(localeContent)) {
|
|
191
|
+
const text = getContentText(content, textLimit);
|
|
192
|
+
if (!text) continue;
|
|
193
|
+
snippets.push({
|
|
194
|
+
locale,
|
|
195
|
+
contentKey,
|
|
196
|
+
text
|
|
197
|
+
});
|
|
198
|
+
if (snippets.length >= maxSnippets) return snippets;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
return snippets;
|
|
202
|
+
}
|
|
203
|
+
function buildFocusItemTree(survey, focusItemId, getFullKey, options) {
|
|
204
|
+
if (!survey.surveyItems.has(focusItemId)) return { truncated: false };
|
|
205
|
+
let remainingBudget = options.treeLimit;
|
|
206
|
+
let truncated = false;
|
|
207
|
+
const visit = (itemId) => {
|
|
208
|
+
if (remainingBudget <= 0) {
|
|
209
|
+
truncated = true;
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
const item = survey.surveyItems.get(itemId);
|
|
213
|
+
if (!item) return;
|
|
214
|
+
remainingBudget -= 1;
|
|
215
|
+
const siblingKeys = survey.getSiblings(itemId).filter((sibling) => sibling.id !== itemId).map((sibling) => sibling.key);
|
|
216
|
+
const descendants = [];
|
|
217
|
+
if (item instanceof GroupItemCore) for (const childId of item.items) {
|
|
218
|
+
const childNode = visit(childId);
|
|
219
|
+
if (childNode) descendants.push(childNode);
|
|
220
|
+
}
|
|
221
|
+
return {
|
|
222
|
+
itemId: item.id,
|
|
223
|
+
itemType: item.type,
|
|
224
|
+
itemKey: item.key,
|
|
225
|
+
fullKey: getFullKey(item.id),
|
|
226
|
+
itemLabel: item.metadata?.itemLabel,
|
|
227
|
+
siblingKeys,
|
|
228
|
+
translations: getItemTranslationSnippets(survey, item.id, options.snippetsPerItem, options.snippetTextLimit),
|
|
229
|
+
descendants
|
|
230
|
+
};
|
|
231
|
+
};
|
|
232
|
+
return {
|
|
233
|
+
focusItem: visit(focusItemId),
|
|
234
|
+
truncated
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
function buildContextIndexes(survey, fullOutline, purpose) {
|
|
238
|
+
const indexes = { keyIndex: fullOutline.map((node) => ({
|
|
239
|
+
itemId: node.itemId,
|
|
240
|
+
itemType: node.itemType,
|
|
241
|
+
key: node.key,
|
|
242
|
+
fullKey: node.fullKey,
|
|
243
|
+
itemLabel: node.itemLabel,
|
|
244
|
+
path: node.fullKey.split(".").slice(0, -1)
|
|
245
|
+
})) };
|
|
246
|
+
if (purpose === "condition-management") indexes.responseSlots = Object.keys(survey.getAvailableResponseValueSlots());
|
|
247
|
+
return indexes;
|
|
248
|
+
}
|
|
249
|
+
function buildSurveyAIContextPack(survey, options = {}) {
|
|
250
|
+
const purpose = options.purpose ?? "generic";
|
|
251
|
+
const purposeDefaults = PURPOSE_DEFAULTS[purpose];
|
|
252
|
+
const scope = options.scope ?? purposeDefaults.scope;
|
|
253
|
+
const defaultLimit = DEFAULT_SCOPE_LIMITS[scope];
|
|
254
|
+
const outlineLimit = Math.max(1, options.outlineLimit ?? defaultLimit);
|
|
255
|
+
const includeRawSurvey = options.includeRawSurvey ?? purposeDefaults.includeRawSurvey;
|
|
256
|
+
const includeIndexes = options.includeIndexes ?? purposeDefaults.includeIndexes;
|
|
257
|
+
const includeFocusItemTree = options.includeFocusItemTree ?? purposeDefaults.includeFocusItemTree;
|
|
258
|
+
const focusItemId = options.focusItemId;
|
|
259
|
+
const focusExists = Boolean(focusItemId && survey.surveyItems.has(focusItemId));
|
|
260
|
+
const parentLookup = buildParentLookup(survey);
|
|
261
|
+
const getFullKey = createFullKeyGetter(survey, parentLookup);
|
|
262
|
+
const fullOutline = buildFullOutline(survey, parentLookup, getFullKey);
|
|
263
|
+
let scopedOutline = fullOutline;
|
|
264
|
+
if (scope === "tiny" && focusItemId && focusExists) {
|
|
265
|
+
const includedIds = collectTinyScopeIds(survey, focusItemId);
|
|
266
|
+
scopedOutline = fullOutline.filter((node) => includedIds.has(node.itemId));
|
|
267
|
+
} else if (scope === "focused" && focusItemId && focusExists) {
|
|
268
|
+
const includedIds = collectFocusedScopeIds(survey, focusItemId);
|
|
269
|
+
scopedOutline = fullOutline.filter((node) => includedIds.has(node.itemId));
|
|
270
|
+
}
|
|
271
|
+
const outlineTruncated = scopedOutline.length > outlineLimit;
|
|
272
|
+
const outline = outlineTruncated ? scopedOutline.slice(0, outlineLimit) : scopedOutline;
|
|
273
|
+
let focusItemTreeTruncated = false;
|
|
274
|
+
let focusItem;
|
|
275
|
+
if (includeFocusItemTree && focusItemId && focusExists) {
|
|
276
|
+
const focusTreeResult = buildFocusItemTree(survey, focusItemId, getFullKey, {
|
|
277
|
+
treeLimit: Math.max(1, options.focusItemTreeLimit ?? DEFAULT_FOCUS_TREE_LIMIT),
|
|
278
|
+
snippetsPerItem: Math.max(1, options.translationSnippetsPerItemLimit ?? DEFAULT_TRANSLATION_SNIPPETS_PER_ITEM),
|
|
279
|
+
snippetTextLimit: Math.max(1, options.translationSnippetTextLimit ?? DEFAULT_TRANSLATION_SNIPPET_TEXT_LIMIT)
|
|
280
|
+
});
|
|
281
|
+
focusItemTreeTruncated = focusTreeResult.truncated;
|
|
282
|
+
focusItem = focusTreeResult.focusItem;
|
|
283
|
+
}
|
|
284
|
+
return {
|
|
285
|
+
purpose,
|
|
286
|
+
scope,
|
|
287
|
+
surveyKey: survey.surveyKey,
|
|
288
|
+
locales: [...survey.locales],
|
|
289
|
+
itemCount: survey.surveyItems.size,
|
|
290
|
+
outline,
|
|
291
|
+
focus: focusItemId ? buildFocusInfo(survey, focusItemId) : void 0,
|
|
292
|
+
focusItem,
|
|
293
|
+
indexes: includeIndexes ? buildContextIndexes(survey, fullOutline, purpose) : void 0,
|
|
294
|
+
flags: {
|
|
295
|
+
outlineTruncated,
|
|
296
|
+
rawSurveyIncluded: includeRawSurvey,
|
|
297
|
+
focusItemTreeTruncated
|
|
298
|
+
},
|
|
299
|
+
rawSurvey: includeRawSurvey ? survey.serialize() : void 0
|
|
300
|
+
};
|
|
301
|
+
}
|
|
302
|
+
//#endregion
|
|
3
303
|
//#region src/editor/item-copy-paste.ts
|
|
4
304
|
var ItemCopyPaste = class ItemCopyPaste {
|
|
5
305
|
survey;
|
|
@@ -200,7 +500,6 @@ var ItemCopyPaste = class ItemCopyPaste {
|
|
|
200
500
|
return clipboardData.type === "survey-item" && clipboardData.version === "1.0.0" && clipboardData.rootItemId !== void 0;
|
|
201
501
|
}
|
|
202
502
|
};
|
|
203
|
-
|
|
204
503
|
//#endregion
|
|
205
504
|
//#region src/editor/undo-redo.ts
|
|
206
505
|
const CommitSource = {
|
|
@@ -385,7 +684,6 @@ var SurveyEditorUndoRedo = class SurveyEditorUndoRedo {
|
|
|
385
684
|
return instance;
|
|
386
685
|
}
|
|
387
686
|
};
|
|
388
|
-
|
|
389
687
|
//#endregion
|
|
390
688
|
//#region src/editor/survey-editor.ts
|
|
391
689
|
var SurveyEditor = class SurveyEditor {
|
|
@@ -399,8 +697,11 @@ var SurveyEditor = class SurveyEditor {
|
|
|
399
697
|
this._pluginRegistry = pluginRegistry;
|
|
400
698
|
this._undoRedo = new SurveyEditorUndoRedo(survey.serialize(), undoRedoConfig, meta);
|
|
401
699
|
}
|
|
700
|
+
/** Returns an immutable copy of the current survey state. */
|
|
402
701
|
get survey() {
|
|
403
|
-
|
|
702
|
+
const serialized = this._survey.serialize();
|
|
703
|
+
const registry = this._pluginRegistry ?? this._survey.getPluginRegistry();
|
|
704
|
+
return Survey.fromJson(serialized, registry);
|
|
404
705
|
}
|
|
405
706
|
get hasUncommittedChanges() {
|
|
406
707
|
return this._hasUncommittedChanges;
|
|
@@ -535,7 +836,7 @@ var SurveyEditor = class SurveyEditor {
|
|
|
535
836
|
if (target?.index !== void 0) insertIndex = Math.min(target.index, parentGroup.items.length);
|
|
536
837
|
else insertIndex = parentGroup.items.length;
|
|
537
838
|
this._survey.surveyItems.set(item.id, item);
|
|
538
|
-
parentGroup.
|
|
839
|
+
parentGroup.addChild(item.id, insertIndex);
|
|
539
840
|
if (content) this._survey.translations.setItemTranslations(item.id, content);
|
|
540
841
|
}
|
|
541
842
|
removeItem(itemId, nested = false) {
|
|
@@ -572,6 +873,51 @@ var SurveyEditor = class SurveyEditor {
|
|
|
572
873
|
targetGroup.items.splice(insertIndex, 0, itemId);
|
|
573
874
|
return true;
|
|
574
875
|
}
|
|
876
|
+
/**
|
|
877
|
+
* Get a deep copy of an item's raw data.
|
|
878
|
+
* The returned object is independent of the survey—mutating it will not affect the survey.
|
|
879
|
+
* Use this when you need to edit an item in a form or pass it to updateItem after modifications.
|
|
880
|
+
*
|
|
881
|
+
* @param itemId - The ID of the item to copy
|
|
882
|
+
* @returns A deep copy of the item's RawSurveyItem data
|
|
883
|
+
* @throws Error if the item is not found
|
|
884
|
+
*/
|
|
885
|
+
getItemDataCopy(itemId) {
|
|
886
|
+
const item = this._survey.surveyItems.get(itemId);
|
|
887
|
+
if (!item) throw new Error(`Item with id '${itemId}' not found`);
|
|
888
|
+
return JSON.parse(JSON.stringify(item.rawItem));
|
|
889
|
+
}
|
|
890
|
+
/**
|
|
891
|
+
* Update an item's data in the survey.
|
|
892
|
+
* Can update common attributes (displayConditions, disabledConditions, validations, etc.)
|
|
893
|
+
* as well as type-specific config.
|
|
894
|
+
*
|
|
895
|
+
* Use getItemDataCopy to obtain an editable copy, modify it, then pass it here.
|
|
896
|
+
* Alternatively, pass a Partial to merge specific fields (top-level keys only;
|
|
897
|
+
* e.g. config replaces the entire config object).
|
|
898
|
+
*
|
|
899
|
+
* @param itemId - The ID of the item to update (must match data.id if provided)
|
|
900
|
+
* @param rawItemData - Full RawSurveyItem or Partial to merge. The id cannot be changed.
|
|
901
|
+
*/
|
|
902
|
+
updateItem(itemId, rawItemData) {
|
|
903
|
+
const existingItem = this._survey.surveyItems.get(itemId);
|
|
904
|
+
if (!existingItem) throw new Error(`Item with id '${itemId}' not found`);
|
|
905
|
+
if ("id" in rawItemData && rawItemData.id !== void 0 && rawItemData.id !== itemId) throw new Error(`Cannot change item id from '${itemId}' to '${rawItemData.id}'`);
|
|
906
|
+
const merged = {
|
|
907
|
+
...existingItem.rawItem,
|
|
908
|
+
...rawItemData,
|
|
909
|
+
id: itemId
|
|
910
|
+
};
|
|
911
|
+
const newKey = merged.key ?? existingItem.key;
|
|
912
|
+
const parentGroup = this._survey.getParentItem(itemId);
|
|
913
|
+
if (parentGroup) {
|
|
914
|
+
const siblingWithSameKey = (parentGroup.items ?? []).filter((id) => id !== itemId).map((id) => this._survey.surveyItems.get(id)).find((s) => s !== void 0 && s.key === newKey);
|
|
915
|
+
if (siblingWithSameKey) throw new Error(`Key '${newKey}' is already in use by sibling item '${siblingWithSameKey.id}'`);
|
|
916
|
+
}
|
|
917
|
+
const newItem = this._survey.createItemFromRaw(merged);
|
|
918
|
+
this._survey.surveyItems.set(itemId, newItem);
|
|
919
|
+
this.markAsModified();
|
|
920
|
+
}
|
|
575
921
|
updateItemTranslations(itemId, updatedContent) {
|
|
576
922
|
this.markAsModified();
|
|
577
923
|
if (!this._survey.surveyItems.get(itemId)) throw new Error(`Item with id '${itemId}' not found`);
|
|
@@ -579,25 +925,96 @@ var SurveyEditor = class SurveyEditor {
|
|
|
579
925
|
return true;
|
|
580
926
|
}
|
|
581
927
|
/**
|
|
928
|
+
* Update survey-level translations that are not tied to specific items.
|
|
929
|
+
* Use these for survey card, navigation, validation messages, etc.
|
|
930
|
+
*/
|
|
931
|
+
updateSurveyTranslations(updates) {
|
|
932
|
+
this.markAsModified();
|
|
933
|
+
if (updates.surveyCard) this._survey.translations.setSurveyCardContent(updates.surveyCard.locale, updates.surveyCard.content);
|
|
934
|
+
if (updates.navigation) this._survey.translations.setNavigationContent(updates.navigation.locale, updates.navigation.content);
|
|
935
|
+
if (updates.validationMessages) this._survey.translations.setValidationMessages(updates.validationMessages.locale, updates.validationMessages.content);
|
|
936
|
+
}
|
|
937
|
+
/**
|
|
938
|
+
* Get maxItemsPerPage immutably (returns a copy).
|
|
939
|
+
*/
|
|
940
|
+
getMaxItemsPerPage() {
|
|
941
|
+
const val = this._survey.maxItemsPerPage;
|
|
942
|
+
return val ? { ...val } : void 0;
|
|
943
|
+
}
|
|
944
|
+
/**
|
|
945
|
+
* Update maxItemsPerPage.
|
|
946
|
+
*/
|
|
947
|
+
updateMaxItemsPerPage(value) {
|
|
948
|
+
this.markAsModified();
|
|
949
|
+
this._survey.maxItemsPerPage = value ? { ...value } : void 0;
|
|
950
|
+
}
|
|
951
|
+
/**
|
|
952
|
+
* Get metadata immutably (returns a copy).
|
|
953
|
+
*/
|
|
954
|
+
getMetadata() {
|
|
955
|
+
const val = this._survey.metadata;
|
|
956
|
+
return val ? { ...val } : void 0;
|
|
957
|
+
}
|
|
958
|
+
/**
|
|
959
|
+
* Update metadata.
|
|
960
|
+
*/
|
|
961
|
+
updateMetadata(metadata) {
|
|
962
|
+
this.markAsModified();
|
|
963
|
+
this._survey.metadata = metadata ? { ...metadata } : void 0;
|
|
964
|
+
}
|
|
965
|
+
/**
|
|
966
|
+
* Get a template value immutably (returns a deep copy).
|
|
967
|
+
*/
|
|
968
|
+
getTemplateValue(key) {
|
|
969
|
+
const val = this._survey.getTemplateValue(key);
|
|
970
|
+
return val ? structuredCloneMethod(val) : void 0;
|
|
971
|
+
}
|
|
972
|
+
/**
|
|
973
|
+
* Get all template values immutably (returns a new Map with deep-copied values).
|
|
974
|
+
*/
|
|
975
|
+
getTemplateValues() {
|
|
976
|
+
const keys = this._survey.getTemplateValueKeys();
|
|
977
|
+
const result = /* @__PURE__ */ new Map();
|
|
978
|
+
for (const key of keys) {
|
|
979
|
+
const val = this._survey.getTemplateValue(key);
|
|
980
|
+
if (val) result.set(key, structuredCloneMethod(val));
|
|
981
|
+
}
|
|
982
|
+
return result;
|
|
983
|
+
}
|
|
984
|
+
/**
|
|
985
|
+
* Add or replace a template value.
|
|
986
|
+
*/
|
|
987
|
+
setTemplateValue(key, templateValue) {
|
|
988
|
+
this.markAsModified();
|
|
989
|
+
this._survey.setTemplateValue(key, structuredCloneMethod(templateValue));
|
|
990
|
+
}
|
|
991
|
+
/**
|
|
992
|
+
* Remove a template value.
|
|
993
|
+
*/
|
|
994
|
+
removeTemplateValue(key) {
|
|
995
|
+
this.markAsModified();
|
|
996
|
+
this._survey.deleteTemplateValue(key);
|
|
997
|
+
}
|
|
998
|
+
/**
|
|
582
999
|
* Copy a survey item and all its data to clipboard format
|
|
583
|
-
* @param
|
|
1000
|
+
* @param itemId - The ID of the item to copy
|
|
584
1001
|
* @returns Clipboard data that can be serialized to JSON for clipboard
|
|
585
1002
|
*/
|
|
586
|
-
copyItem(
|
|
587
|
-
return new ItemCopyPaste(this._survey).copyItem(
|
|
1003
|
+
copyItem(itemId) {
|
|
1004
|
+
return new ItemCopyPaste(this._survey).copyItem(itemId);
|
|
588
1005
|
}
|
|
589
1006
|
/**
|
|
590
1007
|
* Paste a survey item from clipboard data to a target location
|
|
591
1008
|
* @param clipboardData - The clipboard data containing the item to paste
|
|
592
1009
|
* @param target - Target location where to paste the item
|
|
593
|
-
* @returns The
|
|
1010
|
+
* @returns The ID of the pasted item
|
|
594
1011
|
*/
|
|
595
1012
|
pasteItem(clipboardData, target) {
|
|
596
1013
|
this.markAsModified();
|
|
597
1014
|
return new ItemCopyPaste(this._survey).pasteItem(clipboardData, target);
|
|
598
1015
|
}
|
|
599
1016
|
};
|
|
600
|
-
|
|
601
1017
|
//#endregion
|
|
602
|
-
export { CommitSource, ItemCopyPaste, SurveyEditor, SurveyEditorUndoRedo };
|
|
1018
|
+
export { CommitSource, ItemCopyPaste, SurveyEditor, SurveyEditorUndoRedo, buildSurveyAIContextPack };
|
|
1019
|
+
|
|
603
1020
|
//# sourceMappingURL=editor.mjs.map
|