case-editor-tools 1.0.0-beta.15 → 1.0.0-beta.16

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 (113) hide show
  1. package/.editorconfig +13 -0
  2. package/{index.d.ts → CHANGELOG.md} +0 -0
  3. package/LICENSE +202 -0
  4. package/package.json +3 -3
  5. package/publish.sh +9 -0
  6. package/readme.md +18 -0
  7. package/rollup.config.js +49 -0
  8. package/src/constants/key-definitions.ts +14 -0
  9. package/src/exporter/index.ts +101 -0
  10. package/{expression-utils/expressionGen.js → src/expression-utils/expressionGen.ts} +26 -29
  11. package/src/expression-utils/studyEngineExpressions.ts +359 -0
  12. package/src/index.ts +1 -0
  13. package/{logger/index.d.ts → src/logger/index.ts} +1 -1
  14. package/src/logger/logger.ts +31 -0
  15. package/{surveys/index.d.ts → src/surveys/index.ts} +3 -3
  16. package/src/surveys/survey-editor/component-editor.ts +133 -0
  17. package/{surveys/survey-editor/data-types.d.ts → src/surveys/survey-editor/data-types.ts} +18 -13
  18. package/src/surveys/survey-editor/item-editor.ts +529 -0
  19. package/src/surveys/survey-editor/survey-editor.ts +261 -0
  20. package/src/surveys/survey-engine-expressions.ts +483 -0
  21. package/src/surveys/survey-items.ts +1490 -0
  22. package/src/surveys/types/group.ts +73 -0
  23. package/{surveys/types/index.d.ts → src/surveys/types/index.ts} +4 -4
  24. package/src/surveys/types/item-properties.ts +204 -0
  25. package/{surveys/types/item.d.ts → src/surveys/types/item.ts} +42 -22
  26. package/src/surveys/types/survey-definition.ts +83 -0
  27. package/src/surveys/utils/componentGenerators.ts +76 -0
  28. package/src/surveys/utils/optionDefGenerators.ts +195 -0
  29. package/{surveys/utils/randomKeyGenerator.js → src/surveys/utils/randomKeyGenerator.ts} +9 -14
  30. package/src/surveys/utils/simple-generators.ts +106 -0
  31. package/src/surveys/utils/simple-question-editor.ts +52 -0
  32. package/{types/duration.js → src/types/duration.ts} +30 -27
  33. package/src/types/expression.ts +22 -0
  34. package/src/types/study.ts +17 -0
  35. package/src/types/studyRules.ts +39 -0
  36. package/tsconfig.json +100 -0
  37. package/constants/key-definitions.d.ts +0 -13
  38. package/constants/key-definitions.js +0 -32
  39. package/constants/key-definitions.js.map +0 -1
  40. package/exporter/index.d.ts +0 -2
  41. package/exporter/index.js +0 -99
  42. package/exporter/index.js.map +0 -1
  43. package/expression-utils/expressionGen.d.ts +0 -2
  44. package/expression-utils/expressionGen.js.map +0 -1
  45. package/expression-utils/studyEngineExpressions.d.ts +0 -114
  46. package/expression-utils/studyEngineExpressions.js +0 -283
  47. package/expression-utils/studyEngineExpressions.js.map +0 -1
  48. package/index.js +0 -3
  49. package/index.js.map +0 -1
  50. package/item-editor-7f825952.js +0 -522
  51. package/item-editor-7f825952.js.map +0 -1
  52. package/logger/index.js +0 -10
  53. package/logger/index.js.map +0 -1
  54. package/logger/logger.d.ts +0 -9
  55. package/logger/logger.js +0 -31
  56. package/logger/logger.js.map +0 -1
  57. package/surveys/index.js +0 -26
  58. package/surveys/index.js.map +0 -1
  59. package/surveys/survey-editor/component-editor.d.ts +0 -84
  60. package/surveys/survey-editor/component-editor.js +0 -112
  61. package/surveys/survey-editor/component-editor.js.map +0 -1
  62. package/surveys/survey-editor/data-types.js +0 -3
  63. package/surveys/survey-editor/data-types.js.map +0 -1
  64. package/surveys/survey-editor/item-editor.d.ts +0 -65
  65. package/surveys/survey-editor/item-editor.js +0 -13
  66. package/surveys/survey-editor/item-editor.js.map +0 -1
  67. package/surveys/survey-editor/survey-editor.d.ts +0 -43
  68. package/surveys/survey-editor/survey-editor.js +0 -231
  69. package/surveys/survey-editor/survey-editor.js.map +0 -1
  70. package/surveys/survey-engine-expressions.d.ts +0 -120
  71. package/surveys/survey-engine-expressions.js +0 -407
  72. package/surveys/survey-engine-expressions.js.map +0 -1
  73. package/surveys/survey-items.d.ts +0 -132
  74. package/surveys/survey-items.js +0 -1018
  75. package/surveys/survey-items.js.map +0 -1
  76. package/surveys/types/group.d.ts +0 -23
  77. package/surveys/types/group.js +0 -71
  78. package/surveys/types/group.js.map +0 -1
  79. package/surveys/types/index.js +0 -20
  80. package/surveys/types/index.js.map +0 -1
  81. package/surveys/types/item-properties.d.ts +0 -189
  82. package/surveys/types/item-properties.js +0 -3
  83. package/surveys/types/item-properties.js.map +0 -1
  84. package/surveys/types/item.js +0 -34
  85. package/surveys/types/item.js.map +0 -1
  86. package/surveys/types/survey-definition.d.ts +0 -19
  87. package/surveys/types/survey-definition.js +0 -60
  88. package/surveys/types/survey-definition.js.map +0 -1
  89. package/surveys/utils/componentGenerators.d.ts +0 -24
  90. package/surveys/utils/componentGenerators.js +0 -58
  91. package/surveys/utils/componentGenerators.js.map +0 -1
  92. package/surveys/utils/optionDefGenerators.d.ts +0 -68
  93. package/surveys/utils/optionDefGenerators.js +0 -162
  94. package/surveys/utils/optionDefGenerators.js.map +0 -1
  95. package/surveys/utils/randomKeyGenerator.d.ts +0 -1
  96. package/surveys/utils/randomKeyGenerator.js.map +0 -1
  97. package/surveys/utils/simple-generators.d.ts +0 -13
  98. package/surveys/utils/simple-generators.js +0 -102
  99. package/surveys/utils/simple-generators.js.map +0 -1
  100. package/surveys/utils/simple-question-editor.d.ts +0 -14
  101. package/surveys/utils/simple-question-editor.js +0 -45
  102. package/surveys/utils/simple-question-editor.js.map +0 -1
  103. package/types/duration.d.ts +0 -9
  104. package/types/duration.js.map +0 -1
  105. package/types/expression.d.ts +0 -4
  106. package/types/expression.js +0 -23
  107. package/types/expression.js.map +0 -1
  108. package/types/study.d.ts +0 -13
  109. package/types/study.js +0 -3
  110. package/types/study.js.map +0 -1
  111. package/types/studyRules.d.ts +0 -8
  112. package/types/studyRules.js +0 -32
  113. package/types/studyRules.js.map +0 -1
@@ -0,0 +1,73 @@
1
+ import { Expression, SurveyGroupItem, SurveyItem } from "survey-engine/lib/data_types";
2
+ import { Logger } from "../../logger/logger";
3
+ import { ItemEditor } from "../survey-editor/item-editor";
4
+ import { generatePageBreak } from "../utils/simple-generators";
5
+
6
+ export abstract class Group {
7
+ groupEditor: ItemEditor;
8
+ key: string;
9
+ private parentKey: string;
10
+
11
+ constructor(parentKey: string, groupKey: string, selectionMethod?: Expression) {
12
+ this.parentKey = parentKey;
13
+ this.key = [this.parentKey, groupKey].join('.');
14
+ this.groupEditor = new ItemEditor(undefined, {
15
+ itemKey: this.key,
16
+ isGroup: true
17
+ });
18
+ if (!selectionMethod) {
19
+ this.groupEditor.setSelectionMethod({ name: 'sequential' });
20
+ } else {
21
+ this.groupEditor.setSelectionMethod(selectionMethod);
22
+ }
23
+ }
24
+
25
+ abstract buildGroup(): void;
26
+
27
+ /**
28
+ * Check if this group is currently part of a path, by checking if the key attribute exists in the path of the group.
29
+ * @param partialKey Is this key segment included somewhere in the parent key of this item.
30
+ * @returns
31
+ */
32
+ isPartOf(partialKey: string): boolean {
33
+ return this.parentKey.includes(partialKey)
34
+ }
35
+
36
+ /**
37
+ * Use this method to retrieve the generated survey item
38
+ * @returns
39
+ */
40
+ get() {
41
+ this.buildGroup();
42
+ this.checkDuplicateChildKeys();
43
+ return this.groupEditor.getItem();
44
+ }
45
+
46
+ addPageBreak() {
47
+ this.groupEditor.addSurveyItem(generatePageBreak(this.key));
48
+ }
49
+
50
+ addItem(item: SurveyItem, pageBreakAfter?: boolean) {
51
+ this.groupEditor.addSurveyItem(item);
52
+ if (pageBreakAfter) {
53
+ this.addPageBreak();
54
+ }
55
+ }
56
+
57
+ private checkDuplicateChildKeys() {
58
+ const group = this.groupEditor.getItem() as SurveyGroupItem;
59
+ const keys = group.items.map(item => item.key);
60
+ const hasDuplicates = keys.some((key, index) => {
61
+ const isDuplicateKey = keys.indexOf(key) !== index;
62
+ if (isDuplicateKey) {
63
+ Logger.error('Duplicate key:');
64
+ Logger.criticalError(`${key} is used twice (at index ${keys.indexOf(key)} and at index ${index})`);
65
+ }
66
+ return isDuplicateKey;
67
+ });
68
+ if (hasDuplicates) {
69
+ Logger.error('\nSurvey contains duplicate keys.\nPlease check the lines above for more infos.\nProcess stopped prematurely.')
70
+ process.exit(1)
71
+ }
72
+ }
73
+ }
@@ -1,4 +1,4 @@
1
- export * from './group';
2
- export * from './item';
3
- export * from './item-properties';
4
- export * from './survey-definition';
1
+ export * from './group';
2
+ export * from './item';
3
+ export * from './item-properties';
4
+ export * from './survey-definition';
@@ -0,0 +1,204 @@
1
+ import { ComponentProperties, Expression, ItemComponent, Validation } from "survey-engine/lib/data_types";
2
+ import { Duration } from "../../types/duration";
3
+
4
+ export interface StyledTextComponentProp {
5
+ content: Map<string, string>;
6
+ className?: string;
7
+ }
8
+
9
+ export interface OptionDef {
10
+ key: string;
11
+ role: string;
12
+ content?: Map<string, string>;
13
+ items?: Array<StyledTextComponentProp> | Array<OptionDef>;
14
+ description?: Map<string, string>;
15
+ displayCondition?: Expression;
16
+ disabled?: Expression;
17
+ style?: Array<{ key: string, value: string }>;
18
+ optionProps?: ComponentProperties;
19
+ }
20
+
21
+ export interface GenericQuestionProps {
22
+ parentKey: string;
23
+ itemKey: string;
24
+ version?: number;
25
+ questionText: Map<string, string> | Array<StyledTextComponentProp>;
26
+ questionSubText?: Map<string, string>;
27
+ titleClassName?: string;
28
+ helpGroupContent?: Array<{
29
+ content: Map<string, string>,
30
+ style?: Array<{ key: string, value: string }>,
31
+ }>;
32
+ condition?: Expression;
33
+ topDisplayCompoments?: Array<ItemComponent>;
34
+ bottomDisplayCompoments?: Array<ItemComponent>;
35
+ isRequired?: boolean;
36
+ footnoteText?: Map<string, string>;
37
+ customValidations?: Array<Validation>;
38
+ }
39
+
40
+
41
+ /**
42
+ * Numeric Input
43
+ */
44
+ export interface NumericInputProps {
45
+ inputLabel: Map<string, string>;
46
+ labelBehindInput?: boolean;
47
+ componentProperties?: ComponentProperties;
48
+ inputMaxWidth?: string;
49
+ disabled?: Expression;
50
+ }
51
+
52
+ export type NumericInputQuestionProps = GenericQuestionProps & NumericInputProps;
53
+
54
+
55
+ /**
56
+ * Date Input
57
+ */
58
+ export interface DateInputProps {
59
+ dateInputMode: 'YMD' | 'YM' | 'Y';
60
+ inputLabelText?: Map<string, string>;
61
+ placeholderText?: Map<string, string>;
62
+ minRelativeDate?: {
63
+ reference?: number | Expression;
64
+ delta: Duration;
65
+ };
66
+ maxRelativeDate?: {
67
+ reference?: number | Expression;
68
+ delta: Duration;
69
+ };
70
+ }
71
+
72
+ export type DateInputQuestionProps = DateInputProps & GenericQuestionProps;
73
+
74
+
75
+ /**
76
+ * Text Input
77
+ */
78
+ export interface TextInputProps {
79
+ placeholderText?: Map<string, string>;
80
+ inputLabel?: Map<string, string>;
81
+ inputMaxWidth?: string;
82
+ className?: string;
83
+ maxLength?: number; // number of charachters allowed
84
+ disabled?: Expression;
85
+ }
86
+
87
+ export type TextInputQuestionProps = TextInputProps & GenericQuestionProps;
88
+
89
+ export interface MultiLineTextInput extends GenericQuestionProps {
90
+ inputLabelText?: Map<string, string>;
91
+ placeholderText?: Map<string, string>;
92
+ maxLength?: number;
93
+ }
94
+
95
+
96
+ /**
97
+ * Cloze Question
98
+ */
99
+ export interface ClozeProps {
100
+ items: Array<OptionDef>;
101
+ }
102
+
103
+ export type ClozeQuestionProps = ClozeProps & GenericQuestionProps;
104
+
105
+
106
+ /**
107
+ * Response Single Choice Likert Array
108
+ */
109
+ export type ResponsiveSingleChoiceArrayVariant = 'horizontal' | 'vertical' | 'table';
110
+
111
+ export interface ResponsiveSingleChoiceArrayProps {
112
+ scaleOptions: Array<{
113
+ key: string;
114
+ className?: string;
115
+ content: Map<string, string> | StyledTextComponentProp[];
116
+ }>,
117
+ rows: Array<{
118
+ key: string;
119
+ content: Map<string, string> | StyledTextComponentProp[];
120
+ horizontalModeProps?: {
121
+ labelPlacement?: 'none' | 'top' | 'bottom';
122
+ className?: string;
123
+ },
124
+ verticalModeProps?: {
125
+ className?: string;
126
+ }
127
+ tableModeProps?: {
128
+ className?: string;
129
+ }
130
+ }>,
131
+ defaultMode: ResponsiveSingleChoiceArrayVariant;
132
+ responsiveModes?: {
133
+ sm?: ResponsiveSingleChoiceArrayVariant;
134
+ md?: ResponsiveSingleChoiceArrayVariant;
135
+ lg?: ResponsiveSingleChoiceArrayVariant;
136
+ xl?: ResponsiveSingleChoiceArrayVariant;
137
+ xxl?: ResponsiveSingleChoiceArrayVariant;
138
+ },
139
+ rgClassName?: string;
140
+ tableModeProps?: {
141
+ className?: string;
142
+ layout?: "fixed";
143
+ firstColWidth?: string;
144
+ optionHeaderClassName?: string;
145
+ hideRowBorder?: boolean;
146
+ },
147
+ horizontalModeProps?: {
148
+ hideRowBorder?: boolean;
149
+ },
150
+ verticalModeProps?: {
151
+ hideRowBorder?: boolean;
152
+ useReverseOptionOrder?: boolean;
153
+ }
154
+ }
155
+ export type ResponsiveSingleChoiceArrayQuestionProps = GenericQuestionProps & ResponsiveSingleChoiceArrayProps;
156
+
157
+ /**
158
+ * Response Bipolar Likert Array
159
+ */
160
+ export type ResponsiveBipolarLikertArrayVariant = 'withLabelRow' | 'vertical' | 'table';
161
+ export interface ResponsiveBipolarLikertArrayProps {
162
+ scaleOptions: Array<{
163
+ key: string;
164
+ }>,
165
+ rows: Array<{
166
+ key: string;
167
+ startLabel: Map<string, string> | StyledTextComponentProp[];
168
+ endLabel: Map<string, string> | StyledTextComponentProp[];
169
+ withLabelRowModeProps?: {
170
+ className?: string;
171
+ },
172
+ verticalModeProps?: {
173
+ className?: string;
174
+ }
175
+ tableModeProps?: {
176
+ className?: string;
177
+ }
178
+ }>,
179
+ defaultMode: ResponsiveBipolarLikertArrayVariant;
180
+ responsiveModes?: {
181
+ sm?: ResponsiveBipolarLikertArrayVariant;
182
+ md?: ResponsiveBipolarLikertArrayVariant;
183
+ lg?: ResponsiveBipolarLikertArrayVariant;
184
+ xl?: ResponsiveBipolarLikertArrayVariant;
185
+ xxl?: ResponsiveBipolarLikertArrayVariant;
186
+ },
187
+ rgClassName?: string;
188
+ tableModeProps?: {
189
+ className?: string;
190
+ layout?: "fixed";
191
+ labelColWidth?: string;
192
+ hideRowBorder?: boolean;
193
+ },
194
+ withLabelRowModeProps?: {
195
+ hideRowBorder?: boolean;
196
+ maxLabelWidth?: string;
197
+ useBottomLabel?: boolean;
198
+ },
199
+ verticalModeProps?: {
200
+ hideRowBorder?: boolean;
201
+ }
202
+ }
203
+
204
+ export type ResponsiveBipolarLikertArrayQuestionProps = GenericQuestionProps & ResponsiveBipolarLikertArrayProps;
@@ -1,22 +1,42 @@
1
- import { Expression, SurveySingleItem } from "survey-engine/lib/data_types";
2
- export declare abstract class Item {
3
- key: string;
4
- item: SurveySingleItem;
5
- protected itemKey: string;
6
- protected parentKey: string;
7
- protected condition?: Expression;
8
- protected isRequired?: boolean;
9
- constructor(parentKey: string, itemKey: string);
10
- abstract buildItem(): SurveySingleItem;
11
- /**
12
- * Check if this item is currently part of a path, by checking if the key attribute exists in the path of the group.
13
- * @param partialKey Is this key segment included somewhere in the parent key of this item.
14
- * @returns
15
- */
16
- isPartOf(partialKey: string): boolean;
17
- /**
18
- * Use this method to retrieve the generated survey item
19
- * @returns
20
- */
21
- get(): SurveySingleItem;
22
- }
1
+ import { Expression, SurveySingleItem } from "survey-engine/lib/data_types";
2
+
3
+
4
+ export abstract class Item {
5
+ key: string;
6
+ item: SurveySingleItem;
7
+ protected itemKey: string;
8
+ protected parentKey: string;
9
+
10
+ protected condition?: Expression;
11
+ protected isRequired?: boolean;
12
+
13
+ constructor(parentKey: string, itemKey: string) {
14
+ this.parentKey = parentKey;
15
+ this.itemKey = itemKey;
16
+ this.key = [this.parentKey, itemKey].join('.');
17
+ this.item = {
18
+ version: 0,
19
+ key: "not defined"
20
+ }
21
+ }
22
+
23
+ abstract buildItem(): SurveySingleItem;
24
+
25
+ /**
26
+ * Check if this item is currently part of a path, by checking if the key attribute exists in the path of the group.
27
+ * @param partialKey Is this key segment included somewhere in the parent key of this item.
28
+ * @returns
29
+ */
30
+ isPartOf(partialKey: string): boolean {
31
+ return this.parentKey.includes(partialKey)
32
+ }
33
+
34
+ /**
35
+ * Use this method to retrieve the generated survey item
36
+ * @returns
37
+ */
38
+ get() {
39
+ this.item = this.buildItem();
40
+ return this.item;
41
+ }
42
+ }
@@ -0,0 +1,83 @@
1
+ import { SurveyGroupItem, SurveyItem } from "survey-engine/lib/data_types";
2
+ import { Logger } from "../../logger/logger";
3
+ import { ItemEditor } from "../survey-editor/item-editor";
4
+ import { SurveyEditor } from "../survey-editor/survey-editor";
5
+ import { generateLocStrings } from "../utils/simple-generators";
6
+
7
+ export interface SurveyProps {
8
+ surveyKey: string;
9
+ name: Map<string, string>;
10
+ description: Map<string, string>;
11
+ durationText: Map<string, string>;
12
+ // max item per page
13
+ // set prefill rules
14
+ // set context rules
15
+ }
16
+
17
+
18
+ export abstract class SurveyDefinition {
19
+ key: string;
20
+ editor: SurveyEditor;
21
+
22
+ constructor(props: SurveyProps) {
23
+ this.editor = new SurveyEditor();
24
+ this.editor.changeItemKey('survey', props.surveyKey);
25
+ this.key = props.surveyKey;
26
+
27
+ // define name and description of the survey
28
+ this.editor.setSurveyName(generateLocStrings(
29
+ props.name
30
+ ));
31
+
32
+ this.editor.setSurveyDescription(generateLocStrings(
33
+ props.description
34
+ ));
35
+
36
+ this.editor.setSurveyDuration(generateLocStrings(
37
+ props.durationText
38
+ ));
39
+
40
+ const rootItemEditor = new ItemEditor(this.editor.findSurveyItem(props.surveyKey) as SurveyGroupItem);
41
+ rootItemEditor.setSelectionMethod({ name: 'sequential' });
42
+ this.editor.updateSurveyItem(rootItemEditor.getItem());
43
+ }
44
+
45
+ abstract buildSurvey(): void;
46
+
47
+ getSurvey() {
48
+ this.buildSurvey();
49
+ this.checkDuplicateChildKeys();
50
+ return this.editor.getSurvey();
51
+ }
52
+
53
+ getSurveyJSON(pretty?: boolean) {
54
+ this.buildSurvey();
55
+ this.checkDuplicateChildKeys();
56
+ return this.editor.getSurveyJSON(pretty);
57
+ }
58
+
59
+ addItem(item: SurveyItem) {
60
+ this.editor.addExistingSurveyItem(item, this.key);
61
+ }
62
+
63
+ addSurveyItemToPath(item: SurveyItem, parentKey: string) {
64
+ this.editor.addExistingSurveyItem(item, parentKey);
65
+ }
66
+
67
+ private checkDuplicateChildKeys() {
68
+ const group = this.editor.getSurvey().current.surveyDefinition;
69
+ const keys = group.items.map(item => item.key);
70
+ const hasDuplicates = keys.some((key, index) => {
71
+ const isDuplicateKey = keys.indexOf(key) !== index;
72
+ if (isDuplicateKey) {
73
+ Logger.error('Duplicate key:');
74
+ Logger.criticalError(`${key} is used twice (at index ${keys.indexOf(key)} and at index ${index})`);
75
+ }
76
+ return isDuplicateKey;
77
+ });
78
+ if (hasDuplicates) {
79
+ Logger.error('\nSurvey item contains duplicate keys.\nPlease check the lines above for more infos.\nProcess stopped prematurely.')
80
+ process.exit(1)
81
+ }
82
+ }
83
+ }
@@ -0,0 +1,76 @@
1
+ import { Expression, ItemComponent } from "survey-engine/lib/data_types"
2
+ import { StyledTextComponentProp } from "../types/item-properties";
3
+ import { generateRandomKey } from "./randomKeyGenerator"
4
+ import { generateLocStrings } from "./simple-generators"
5
+
6
+
7
+ interface CommonProps {
8
+ key?: string,
9
+ content?: Map<string, string> | StyledTextComponentProp[];
10
+ displayCondition?: Expression;
11
+ }
12
+
13
+ interface TextProps extends CommonProps {
14
+ content: Map<string, string>;
15
+ variant?: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'p' | 'li';
16
+ className?: string;
17
+ }
18
+
19
+ const text = (props: TextProps): ItemComponent => {
20
+ const styles = [];
21
+ if (props.className !== undefined) {
22
+ styles.push({
23
+ key: 'className', value: props.className
24
+ })
25
+ }
26
+ if (props.variant !== undefined) {
27
+ styles.push({
28
+ key: 'variant', value: props.variant
29
+ })
30
+ }
31
+ return {
32
+ key: generateRandomKey(3),
33
+ role: 'text',
34
+ style: styles.length > 0 ? styles : undefined,
35
+ content: generateLocStrings(props.content),
36
+ displayCondition: props.displayCondition,
37
+ }
38
+ }
39
+
40
+ interface MarkdownProps extends CommonProps {
41
+ content: Map<string, string>;
42
+ className?: string;
43
+ }
44
+
45
+ const markdown = (props: MarkdownProps): ItemComponent => {
46
+ const styles = [];
47
+ if (props.className !== undefined) {
48
+ styles.push({
49
+ key: 'className', value: props.className
50
+ })
51
+ }
52
+ return {
53
+ key: generateRandomKey(3),
54
+ role: 'markdown',
55
+ style: styles.length > 0 ? styles : undefined,
56
+ content: generateLocStrings(props.content),
57
+ displayCondition: props.displayCondition,
58
+ }
59
+ }
60
+
61
+ const footnote = (props: {
62
+ content: Map<string, string>;
63
+ }): ItemComponent => {
64
+ return {
65
+ role: 'footnote', content: generateLocStrings(props.content), style: [
66
+ { key: 'className', value: 'fs-small fst-italic text-center' }
67
+ ]
68
+ }
69
+ }
70
+
71
+
72
+ export const ComponentGenerators = {
73
+ footnote,
74
+ text,
75
+ markdown,
76
+ }
@@ -0,0 +1,195 @@
1
+ import { Expression } from "survey-engine/lib/data_types";
2
+ import { SurveyEngine } from "../survey-engine-expressions";
3
+ import { ClozeProps, DateInputProps, NumericInputProps, OptionDef, StyledTextComponentProp, TextInputProps } from "../types/item-properties";
4
+ import { generateRandomKey } from "./randomKeyGenerator";
5
+
6
+ interface CommonProps {
7
+ key?: string,
8
+ content?: Map<string, string> | StyledTextComponentProp[];
9
+ displayCondition?: Expression;
10
+ }
11
+
12
+ interface OptionProps {
13
+ disabled?: Expression;
14
+ className?: string;
15
+ displayCondition?: Expression;
16
+ }
17
+
18
+ interface OptionTextProps extends CommonProps {
19
+ className?: string;
20
+ }
21
+
22
+ const option = (key: string, content: Map<string, string> | StyledTextComponentProp[], extraProps?: OptionProps): OptionDef => {
23
+ const styles = [];
24
+ if (extraProps?.className !== undefined) {
25
+ styles.push({
26
+ key: 'className', value: extraProps.className
27
+ })
28
+ }
29
+
30
+ return {
31
+ key: key,
32
+ role: 'option',
33
+ content: !Array.isArray(content) ? content : undefined,
34
+ items: Array.isArray(content) ? content : undefined,
35
+ displayCondition: extraProps?.displayCondition,
36
+ disabled: extraProps?.disabled,
37
+ style: styles,
38
+ }
39
+ }
40
+
41
+ const multipleChoiceOptionSubtitle = (props: OptionTextProps): OptionDef => {
42
+ const styles = [];
43
+ if (props.className !== undefined) {
44
+ styles.push({
45
+ key: 'className', value: props.className
46
+ })
47
+ }
48
+ return {
49
+ key: props.key ? props.key : generateRandomKey(6),
50
+ role: 'text',
51
+ content: !Array.isArray(props.content) ? props.content : undefined,
52
+ displayCondition: props.displayCondition,
53
+ style: styles,
54
+ }
55
+ }
56
+
57
+ const markdown = (props: OptionTextProps): OptionDef => {
58
+ const styles = [];
59
+ if (props.className !== undefined) {
60
+ styles.push({
61
+ key: 'className', value: props.className
62
+ })
63
+ }
64
+ return {
65
+ key: props.key ? props.key : generateRandomKey(6),
66
+ role: 'markdown',
67
+ content: !Array.isArray(props.content) ? props.content : undefined,
68
+ displayCondition: props.displayCondition,
69
+ style: styles,
70
+ }
71
+ }
72
+
73
+ const textInput = (props: TextInputProps & { key: string, displayCondition?: Expression }): OptionDef => {
74
+ const style: Array<{ key: string; value: string }> = [];
75
+ if (props.maxLength !== undefined) {
76
+ style.push({ key: 'maxLength', value: props.maxLength.toFixed(0) })
77
+ }
78
+ if (props.className !== undefined) {
79
+ style.push({ key: 'className', value: props.className })
80
+ }
81
+ if (props.inputMaxWidth !== undefined) {
82
+ style.push({ key: 'inputMaxWidth', value: props.inputMaxWidth })
83
+ }
84
+
85
+ return {
86
+ key: props.key,
87
+ role: 'input',
88
+ content: props.inputLabel,
89
+ description: props.placeholderText,
90
+ displayCondition: props.displayCondition,
91
+ disabled: props.disabled,
92
+ style: style.length > 0 ? style : undefined,
93
+ }
94
+ }
95
+
96
+ const numberInput = (props: NumericInputProps & { key: string, displayCondition?: Expression }): OptionDef => {
97
+ const style: Array<{ key: string; value: string }> = [];
98
+ if (props.inputMaxWidth !== undefined) {
99
+ style.push({ key: 'inputMaxWidth', value: props.inputMaxWidth })
100
+ }
101
+ if (props.labelBehindInput) {
102
+ style.push({ key: 'labelPlacement', value: 'after' });
103
+ }
104
+
105
+ return {
106
+ key: props.key,
107
+ role: 'numberInput',
108
+ content: props.inputLabel,
109
+ displayCondition: props.displayCondition,
110
+ disabled: props.disabled,
111
+ optionProps: {
112
+ min: props.componentProperties?.min !== undefined ? (typeof (props.componentProperties.min) === 'number' ? { dtype: 'num', num: props.componentProperties.min } : props.componentProperties.min) : undefined,
113
+ max: props.componentProperties?.max !== undefined ? (typeof (props.componentProperties?.max) === 'number' ? { dtype: 'num', num: props.componentProperties.max } : props.componentProperties.max) : undefined,
114
+ stepSize: props.componentProperties?.stepSize ? (typeof (props.componentProperties.stepSize) === 'number' ? { dtype: 'num', num: props.componentProperties.stepSize } : props.componentProperties.stepSize) : undefined,
115
+ },
116
+ style: style.length > 0 ? style : undefined,
117
+ }
118
+ }
119
+
120
+ const dateInput = (props: DateInputProps & { key: string, displayCondition?: Expression }): OptionDef => {
121
+ return {
122
+ key: props.key,
123
+ role: 'dateInput',
124
+ optionProps: {
125
+ dateInputMode: { str: props.dateInputMode },
126
+ min: props.minRelativeDate ? {
127
+ dtype: 'exp', exp: SurveyEngine.timestampWithOffset(
128
+ props.minRelativeDate.delta,
129
+ props.minRelativeDate.reference
130
+ )
131
+ } : undefined,
132
+ max: props.maxRelativeDate ? {
133
+ dtype: 'exp', exp: SurveyEngine.timestampWithOffset(
134
+ props.maxRelativeDate.delta,
135
+ props.maxRelativeDate.reference ? props.maxRelativeDate.reference : undefined
136
+ )
137
+ } : undefined,
138
+ },
139
+ content: props.inputLabelText,
140
+ displayCondition: props.displayCondition,
141
+ }
142
+ }
143
+
144
+ const dropDown = (props: { key: string, displayCondition?: Expression, options: Array<OptionDef> }): OptionDef => {
145
+ return {
146
+ key: props.key,
147
+ role: 'dropDownGroup',
148
+ displayCondition: props.displayCondition,
149
+ items: props.options,
150
+ }
151
+ }
152
+
153
+
154
+ const cloze = (props: ClozeProps & { key: string, displayCondition?: Expression }): OptionDef => {
155
+ return {
156
+ key: props.key,
157
+ role: 'cloze',
158
+ items: props.items,
159
+ displayCondition: props.displayCondition,
160
+ }
161
+ }
162
+
163
+ const clozeLineBreak = (): OptionDef => {
164
+ return {
165
+ key: generateRandomKey(5),
166
+ role: 'lineBreak',
167
+ }
168
+ }
169
+
170
+ export const SingleChoiceOptionTypes = {
171
+ option,
172
+ textInput,
173
+ //dateInput,
174
+ numberInput,
175
+ cloze,
176
+ }
177
+
178
+ export const MultipleChoiceOptionTypes = {
179
+ option,
180
+ subtitle: multipleChoiceOptionSubtitle,
181
+ textInput,
182
+ // dateInput,
183
+ numberInput,
184
+ cloze,
185
+ }
186
+
187
+ export const ClozeItemTypes = {
188
+ text: multipleChoiceOptionSubtitle,
189
+ markdown,
190
+ textInput,
191
+ dateInput,
192
+ clozeLineBreak,
193
+ numberInput,
194
+ dropDown,
195
+ }