@encatch/schema 1.3.0-beta.6 → 1.3.0-beta.8

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/dist/esm/index.js CHANGED
@@ -4,6 +4,130 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
4
4
  // src/schemas/fields/field-schema.ts
5
5
  import { z as z4 } from "zod";
6
6
 
7
+ // src/helpers/csat-emoji-helper.ts
8
+ var CSAT_DEFAULT_EMOJIS_BY_SCALE = {
9
+ 2: ["\u{1F621}", "\u{1F604}"],
10
+ 3: ["\u{1F621}", "\u{1F610}", "\u{1F604}"],
11
+ 4: ["\u{1F621}", "\u{1F615}", "\u{1F642}", "\u{1F604}"],
12
+ 5: ["\u{1F621}", "\u{1F615}", "\u{1F610}", "\u{1F642}", "\u{1F604}"]
13
+ };
14
+ var CSAT_EMOJI_CATEGORIES = [
15
+ {
16
+ id: "unhappy",
17
+ label: "Unhappy",
18
+ emojis: ["\u{1F621}", "\u{1F620}", "\u{1F624}", "\u{1F61E}", "\u{1F615}", "\u{1F61F}", "\u{1F622}", "\u{1F62D}", "\u{1F630}", "\u{1F628}"]
19
+ },
20
+ {
21
+ id: "neutral",
22
+ label: "Neutral",
23
+ emojis: ["\u{1F610}", "\u{1F611}", "\u{1F643}", "\u{1F636}", "\u{1F972}"]
24
+ },
25
+ {
26
+ id: "happy",
27
+ label: "Happy",
28
+ emojis: ["\u{1F642}", "\u{1F60A}", "\u{1F604}", "\u{1F601}", "\u{1F606}", "\u{1F929}", "\u{1F60D}", "\u{1F970}", "\u{1F60E}"]
29
+ },
30
+ {
31
+ id: "gestures",
32
+ label: "Gestures",
33
+ emojis: ["\u{1F44D}", "\u{1F44E}", "\u{1F44F}", "\u{1F64C}", "\u{1F91D}", "\u270C\uFE0F"]
34
+ },
35
+ {
36
+ id: "hearts",
37
+ label: "Hearts",
38
+ emojis: ["\u2764\uFE0F", "\u{1F9E1}", "\u{1F49B}", "\u{1F49A}", "\u{1F499}", "\u{1F49C}", "\u{1F494}"]
39
+ },
40
+ {
41
+ id: "symbols",
42
+ label: "Symbols",
43
+ emojis: ["\u2B50", "\u{1F31F}", "\u{1F4AF}", "\u2705", "\u274C", "\u26A0\uFE0F"]
44
+ },
45
+ {
46
+ id: "celebration",
47
+ label: "Celebration",
48
+ emojis: ["\u{1F389}", "\u{1F973}", "\u{1F38A}", "\u{1F3C6}", "\u{1F525}"]
49
+ }
50
+ ];
51
+ var CSAT_EMOJI_PALETTE = [
52
+ ...new Set(CSAT_EMOJI_CATEGORIES.flatMap((category) => category.emojis))
53
+ ];
54
+ var PALETTE_SET = new Set(CSAT_EMOJI_PALETTE);
55
+ function isCsatEmojiPaletteItem(value) {
56
+ return PALETTE_SET.has(value);
57
+ }
58
+ __name(isCsatEmojiPaletteItem, "isCsatEmojiPaletteItem");
59
+ function getDefaultOverrideEmojiForScale(scale) {
60
+ const normalizedScale = [2, 3, 4, 5].includes(scale) ? scale : 5;
61
+ const defaults = CSAT_DEFAULT_EMOJIS_BY_SCALE[normalizedScale] ?? CSAT_DEFAULT_EMOJIS_BY_SCALE[5];
62
+ return defaults.map(
63
+ (emoji) => isCsatEmojiPaletteItem(emoji) ? emoji : CSAT_EMOJI_PALETTE[0] ?? "\u{1F610}"
64
+ );
65
+ }
66
+ __name(getDefaultOverrideEmojiForScale, "getDefaultOverrideEmojiForScale");
67
+ function parseOverrideEmoji(overrideEmoji) {
68
+ if (overrideEmoji == null || overrideEmoji.trim() === "") return null;
69
+ try {
70
+ const parsed = JSON.parse(overrideEmoji);
71
+ if (!Array.isArray(parsed)) return null;
72
+ if (!parsed.every((item) => typeof item === "string")) return null;
73
+ return parsed;
74
+ } catch {
75
+ return null;
76
+ }
77
+ }
78
+ __name(parseOverrideEmoji, "parseOverrideEmoji");
79
+ function serializeOverrideEmoji(emojis) {
80
+ return JSON.stringify([...emojis]);
81
+ }
82
+ __name(serializeOverrideEmoji, "serializeOverrideEmoji");
83
+ function validateOverrideEmojiForScale(overrideEmoji, scale) {
84
+ if (overrideEmoji == null || overrideEmoji.trim() === "") {
85
+ return { valid: true, emojis: null };
86
+ }
87
+ const emojis = parseOverrideEmoji(overrideEmoji);
88
+ if (!emojis) {
89
+ return { valid: false, emojis: null, error: "overrideEmoji must be a valid JSON array of strings" };
90
+ }
91
+ if (emojis.length !== scale) {
92
+ return {
93
+ valid: false,
94
+ emojis: null,
95
+ error: `overrideEmoji must contain exactly ${scale} emoji(s) for a ${scale}-point scale`
96
+ };
97
+ }
98
+ for (const emoji of emojis) {
99
+ if (!isCsatEmojiPaletteItem(emoji)) {
100
+ return {
101
+ valid: false,
102
+ emojis: null,
103
+ error: `Emoji "${emoji}" is not in the allowed CSAT palette`
104
+ };
105
+ }
106
+ }
107
+ return { valid: true, emojis };
108
+ }
109
+ __name(validateOverrideEmojiForScale, "validateOverrideEmojiForScale");
110
+ function resolveCsatEmojis(scale, overrideEmoji) {
111
+ const normalizedScale = [2, 3, 4, 5].includes(scale) ? scale : 5;
112
+ const { emojis } = validateOverrideEmojiForScale(overrideEmoji, normalizedScale);
113
+ if (emojis) return emojis;
114
+ return [...CSAT_DEFAULT_EMOJIS_BY_SCALE[normalizedScale] ?? CSAT_DEFAULT_EMOJIS_BY_SCALE[5]];
115
+ }
116
+ __name(resolveCsatEmojis, "resolveCsatEmojis");
117
+ function getCsatEmojiForPoint(point, scale, overrideEmoji) {
118
+ const emojis = resolveCsatEmojis(scale, overrideEmoji);
119
+ return emojis[point - 1] ?? emojis[emojis.length - 1] ?? "\u{1F610}";
120
+ }
121
+ __name(getCsatEmojiForPoint, "getCsatEmojiForPoint");
122
+ function trimOverrideEmojiForScale(overrideEmoji, newScale) {
123
+ const parsed = parseOverrideEmoji(overrideEmoji);
124
+ if (!parsed) return void 0;
125
+ const trimmed = parsed.slice(0, newScale);
126
+ if (trimmed.length === 0) return void 0;
127
+ return serializeOverrideEmoji(trimmed);
128
+ }
129
+ __name(trimOverrideEmojiForScale, "trimOverrideEmojiForScale");
130
+
7
131
  // src/schemas/fields/translations-schema.ts
8
132
  import { z } from "zod";
9
133
  var translationEntrySchema = z.string().min(1).describe("Translated text content");
@@ -96,7 +220,18 @@ var videoAudioQuestionTranslationSchema = baseQuestionTranslationFieldsSchema.ex
96
220
  videoIdleHint: z.string().max(200).optional().describe("Translated video idle overlay hint"),
97
221
  photoEmptyHint: z.string().max(200).optional().describe("Translated empty photo area hint"),
98
222
  photoUseCameraButtonLabel: z.string().max(80).optional().describe("Translated Use camera button"),
99
- photoUploadImageButtonLabel: z.string().max(80).optional().describe("Translated Upload image button")
223
+ photoUploadImageButtonLabel: z.string().max(80).optional().describe("Translated Upload image button"),
224
+ capturePhotoButtonLabel: z.string().max(80).optional().describe("Translated Capture photo button"),
225
+ cancelButtonLabel: z.string().max(80).optional().describe("Translated Cancel button in live photo mode"),
226
+ uploadPhotoButtonLabel: z.string().max(80).optional().describe("Translated Upload Photo button"),
227
+ replaceButtonLabel: z.string().max(80).optional().describe("Translated Replace button"),
228
+ removeButtonLabel: z.string().max(80).optional().describe("Translated Remove button"),
229
+ stopRecordingButtonLabel: z.string().max(80).optional().describe("Translated Stop recording button"),
230
+ playButtonLabel: z.string().max(80).optional().describe("Translated Play button"),
231
+ pauseButtonLabel: z.string().max(80).optional().describe("Translated Pause button"),
232
+ uploadButtonLabel: z.string().max(80).optional().describe("Translated Upload button on preview"),
233
+ rerecordButtonLabel: z.string().max(80).optional().describe("Translated Re-record button"),
234
+ dismissErrorButtonLabel: z.string().max(80).optional().describe("Translated dismiss error control label")
100
235
  }).describe("Translation schema for video/audio/photo/text questions");
101
236
  var dateQuestionTranslationSchema = baseQuestionTranslationFieldsSchema.extend({
102
237
  type: z.literal("date").describe("Question type identifier"),
@@ -114,7 +249,11 @@ var signatureQuestionTranslationSchema = baseQuestionTranslationFieldsSchema.ext
114
249
  modeTabLabelUpload: z.string().max(80).optional().describe("Translated Upload tab label"),
115
250
  drawCanvasHint: z.string().max(200).optional().describe("Translated empty-canvas hint"),
116
251
  uploadZonePrimary: z.string().max(200).optional().describe("Translated idle upload prompt"),
117
- uploadZoneDrag: z.string().max(120).optional().describe("Translated drag-over upload prompt")
252
+ uploadZoneDrag: z.string().max(120).optional().describe("Translated drag-over upload prompt"),
253
+ uploadSignatureButtonLabel: z.string().max(80).optional().describe("Translated Upload Signature button"),
254
+ uploadButtonLabel: z.string().max(80).optional().describe("Translated Upload button in upload mode"),
255
+ removeButtonLabel: z.string().max(80).optional().describe("Translated Remove button"),
256
+ dismissErrorButtonLabel: z.string().max(80).optional().describe("Translated dismiss error control label")
118
257
  }).describe("Translation schema for signature questions");
119
258
  var schedulerQuestionTranslationSchema = baseQuestionTranslationFieldsSchema.extend({
120
259
  type: z.literal("scheduler").describe("Question type identifier"),
@@ -1390,7 +1529,53 @@ var csatQuestionSchema = questionSchema.extend({
1390
1529
  ),
1391
1530
  scaleLabels: z4.record(z4.string(), z4.string().max(100)).optional().describe(
1392
1531
  "Per-point label text keyed by value string ('1'\u2013'5'); keys must match the chosen scale size"
1532
+ ),
1533
+ overrideEmoji: z4.string().max(500).optional().describe(
1534
+ "JSON string array of emoji characters ordered low\u2192high (index 0 = point 1); length must match scale when set; values must be from the allowed CSAT emoji palette"
1393
1535
  )
1536
+ }).superRefine((data, ctx) => {
1537
+ if (data.overrideEmoji == null || data.overrideEmoji.trim() === "") {
1538
+ return;
1539
+ }
1540
+ const scale = data.scale ?? 5;
1541
+ let parsed;
1542
+ try {
1543
+ parsed = JSON.parse(data.overrideEmoji);
1544
+ } catch {
1545
+ ctx.addIssue({
1546
+ code: z4.ZodIssueCode.custom,
1547
+ message: "overrideEmoji must be a valid JSON array of strings",
1548
+ path: ["overrideEmoji"]
1549
+ });
1550
+ return;
1551
+ }
1552
+ if (!Array.isArray(parsed) || !parsed.every((item) => typeof item === "string")) {
1553
+ ctx.addIssue({
1554
+ code: z4.ZodIssueCode.custom,
1555
+ message: "overrideEmoji must be a JSON array of strings",
1556
+ path: ["overrideEmoji"]
1557
+ });
1558
+ return;
1559
+ }
1560
+ if (parsed.length !== scale) {
1561
+ ctx.addIssue({
1562
+ code: z4.ZodIssueCode.custom,
1563
+ message: `overrideEmoji must contain exactly ${scale} emoji(s) for a ${scale}-point scale`,
1564
+ path: ["overrideEmoji"]
1565
+ });
1566
+ return;
1567
+ }
1568
+ const allowed = new Set(CSAT_EMOJI_PALETTE);
1569
+ for (const emoji of parsed) {
1570
+ if (!allowed.has(emoji)) {
1571
+ ctx.addIssue({
1572
+ code: z4.ZodIssueCode.custom,
1573
+ message: `Emoji "${emoji}" is not in the allowed CSAT palette`,
1574
+ path: ["overrideEmoji"]
1575
+ });
1576
+ return;
1577
+ }
1578
+ }
1394
1579
  }).describe(
1395
1580
  "Schema for a CSAT (Customer Satisfaction Score) question using an industry-standard 1-to-N positive scale (N = 2\u20135)"
1396
1581
  );
@@ -1561,7 +1746,11 @@ var signatureQuestionSchema = questionSchema.extend({
1561
1746
  ),
1562
1747
  uploadZoneDrag: z4.string().max(120).optional().describe(
1563
1748
  "Short prompt when dragging a file over the upload zone; falls back to platform default"
1564
- )
1749
+ ),
1750
+ uploadSignatureButtonLabel: z4.string().max(80).optional().describe("Label for the Upload Signature button in draw mode"),
1751
+ uploadButtonLabel: z4.string().max(80).optional().describe("Label for the Upload button in upload mode preview"),
1752
+ removeButtonLabel: z4.string().max(80).optional().describe("Label for Remove controls in upload mode"),
1753
+ dismissErrorButtonLabel: z4.string().max(80).optional().describe("Accessible label for the dismiss control on upload error overlays")
1565
1754
  }).describe(
1566
1755
  "Schema for a signature question where respondents can type, draw, or upload their electronic signature"
1567
1756
  );
@@ -1723,7 +1912,18 @@ var videoAudioQuestionSchema = questionSchema.extend({
1723
1912
  "Hint in the empty photo preview area; falls back to placeholder then built-in copy"
1724
1913
  ),
1725
1914
  photoUseCameraButtonLabel: z4.string().max(80).optional().describe("Label for the Use camera button in photo mode"),
1726
- photoUploadImageButtonLabel: z4.string().max(80).optional().describe("Label for the upload image button in photo mode")
1915
+ photoUploadImageButtonLabel: z4.string().max(80).optional().describe("Label for the upload image button in photo mode"),
1916
+ capturePhotoButtonLabel: z4.string().max(80).optional().describe("Label for the Capture photo button in live photo mode"),
1917
+ cancelButtonLabel: z4.string().max(80).optional().describe("Label for the Cancel button when live photo camera is open"),
1918
+ uploadPhotoButtonLabel: z4.string().max(80).optional().describe("Label for the Upload Photo button on photo preview"),
1919
+ replaceButtonLabel: z4.string().max(80).optional().describe("Label for the Replace button on photo preview"),
1920
+ removeButtonLabel: z4.string().max(80).optional().describe("Label for Remove controls across media modes"),
1921
+ stopRecordingButtonLabel: z4.string().max(80).optional().describe("Label for the Stop recording button while recording"),
1922
+ playButtonLabel: z4.string().max(80).optional().describe("Label for the Play button on recording preview"),
1923
+ pauseButtonLabel: z4.string().max(80).optional().describe("Label for the Pause button on recording preview"),
1924
+ uploadButtonLabel: z4.string().max(80).optional().describe("Label for the Upload button on recording preview"),
1925
+ rerecordButtonLabel: z4.string().max(80).optional().describe("Label for the Re-record button on recording preview"),
1926
+ dismissErrorButtonLabel: z4.string().max(80).optional().describe("Accessible label for dismiss on media upload error overlays")
1727
1927
  }).describe(
1728
1928
  "Schema for a video, audio, and photo question where respondents can record or upload media or enter a text answer"
1729
1929
  );
@@ -2689,6 +2889,9 @@ export {
2689
2889
  AnnotationSchema,
2690
2890
  AnswerItemSchema,
2691
2891
  AnswerSchema,
2892
+ CSAT_DEFAULT_EMOJIS_BY_SCALE,
2893
+ CSAT_EMOJI_CATEGORIES,
2894
+ CSAT_EMOJI_PALETTE,
2692
2895
  ChoiceOrderOptions,
2693
2896
  CsatDisplayStyles,
2694
2897
  CsatScales,
@@ -2786,9 +2989,12 @@ export {
2786
2989
  formConfigurationResponseSchema,
2787
2990
  formDetailsSchema,
2788
2991
  formPropertiesSchema,
2992
+ getCsatEmojiForPoint,
2993
+ getDefaultOverrideEmojiForScale,
2789
2994
  gradientAttachmentSchema,
2790
2995
  imageAttachmentSchema,
2791
2996
  inAppDisplayTypeSchema,
2997
+ isCsatEmojiPaletteItem,
2792
2998
  layoutAttachmentSchema,
2793
2999
  layoutSurfaceSchema,
2794
3000
  logicJumpRuleSchema,
@@ -2821,6 +3027,7 @@ export {
2821
3027
  objectToSnake,
2822
3028
  opinionScaleQuestionSchema,
2823
3029
  otherConfigurationPropertiesSchema,
3030
+ parseOverrideEmoji,
2824
3031
  partialFeedbackSchema,
2825
3032
  paymentsUpiAmountConfigSchema,
2826
3033
  paymentsUpiQuestionSchema,
@@ -2857,6 +3064,7 @@ export {
2857
3064
  refineTextDataSchema,
2858
3065
  refineTextParamsSchema,
2859
3066
  refineTextResponseSchema,
3067
+ resolveCsatEmojis,
2860
3068
  responseSchema,
2861
3069
  schedulerProviderSchema,
2862
3070
  schedulerQuestionSchema,
@@ -2866,6 +3074,7 @@ export {
2866
3074
  sectionSchema,
2867
3075
  sectionTranslationSchema,
2868
3076
  sectionTranslationsByLanguageSchema,
3077
+ serializeOverrideEmoji,
2869
3078
  sessionInfoSchema,
2870
3079
  shareableModeSchema,
2871
3080
  shortAnswerQuestionSchema,
@@ -2890,8 +3099,10 @@ export {
2890
3099
  translationEntrySchema,
2891
3100
  translationsSchema,
2892
3101
  triggerActionSchema,
3102
+ trimOverrideEmojiForScale,
2893
3103
  userInfoSchema,
2894
3104
  userPropertiesSchema,
3105
+ validateOverrideEmojiForScale,
2895
3106
  validationRuleSchema,
2896
3107
  validationRuleTypeSchema,
2897
3108
  videoAttachmentSchema,