@welshare/questionnaire 0.1.0 → 0.1.2

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.
@@ -49,7 +49,13 @@ const QuestionRendererInternal = ({ item, className = "", inputClassName = "", c
49
49
  return null;
50
50
  }
51
51
  const handleChoiceChange = (valueCoding, valueInteger) => {
52
- updateAnswer(item.linkId, { valueCoding, valueInteger });
52
+ // For choice questions, only set one field: valueCoding takes precedence
53
+ if (valueCoding && (valueCoding.code || valueCoding.display || valueCoding.system)) {
54
+ updateAnswer(item.linkId, { valueCoding });
55
+ }
56
+ else if (valueInteger !== undefined) {
57
+ updateAnswer(item.linkId, { valueInteger });
58
+ }
53
59
  };
54
60
  const handleMultipleChoiceToggle = (valueCoding, valueInteger) => {
55
61
  const isSelected = currentAnswers.some((answer) => answer.valueCoding?.code === valueCoding.code);
@@ -66,7 +72,13 @@ const QuestionRendererInternal = ({ item, className = "", inputClassName = "", c
66
72
  // Check if we're selecting the exclusive option
67
73
  if (exclusiveOptionCode && valueCoding.code === exclusiveOptionCode) {
68
74
  // Clear all other answers and only keep this one
69
- newAnswers = [{ valueCoding, valueInteger }];
75
+ // For choice questions, only set one field: valueCoding takes precedence
76
+ const answer = valueCoding && (valueCoding.code || valueCoding.display || valueCoding.system)
77
+ ? { valueCoding }
78
+ : valueInteger !== undefined
79
+ ? { valueInteger }
80
+ : { valueCoding };
81
+ newAnswers = [answer];
70
82
  }
71
83
  else {
72
84
  // Check if exclusive option is currently selected
@@ -74,13 +86,25 @@ const QuestionRendererInternal = ({ item, className = "", inputClassName = "", c
74
86
  if (exclusiveSelected) {
75
87
  // Remove exclusive option and add new selection
76
88
  newAnswers = currentAnswers.filter((answer) => answer.valueCoding?.code !== exclusiveOptionCode);
77
- newAnswers = [...newAnswers, { valueCoding, valueInteger }];
89
+ // For choice questions, only set one field: valueCoding takes precedence
90
+ const answer = valueCoding && (valueCoding.code || valueCoding.display || valueCoding.system)
91
+ ? { valueCoding }
92
+ : valueInteger !== undefined
93
+ ? { valueInteger }
94
+ : { valueCoding };
95
+ newAnswers = [...newAnswers, answer];
78
96
  }
79
97
  else {
80
98
  // Normal behavior: Add the answer (respecting maxAnswers limit)
81
99
  const maxAnswers = item.maxAnswers || Number.MAX_SAFE_INTEGER;
82
100
  if (currentAnswers.length < maxAnswers) {
83
- newAnswers = [...currentAnswers, { valueCoding, valueInteger }];
101
+ // For choice questions, only set one field: valueCoding takes precedence
102
+ const answer = valueCoding && (valueCoding.code || valueCoding.display || valueCoding.system)
103
+ ? { valueCoding }
104
+ : valueInteger !== undefined
105
+ ? { valueInteger }
106
+ : { valueCoding };
107
+ newAnswers = [...currentAnswers, answer];
84
108
  }
85
109
  else {
86
110
  // Already at max, don't add
@@ -3,5 +3,5 @@ export type { QuestionRendererProps } from "./components/question-renderer.js";
3
3
  export { QuestionnaireProvider, useQuestionnaire, type QuestionnaireContextType, type QuestionnaireProviderProps, } from "./contexts/questionnaire-context.js";
4
4
  export type { Coding, Extension, Questionnaire, QuestionnaireItem, QuestionnaireItemAnswerOption, QuestionnaireResponse, QuestionnaireResponseAnswer, QuestionnaireResponseItem, } from "./types/fhir.js";
5
5
  export type { RadioInputProps, CheckboxInputProps, } from "./types/index.js";
6
- export { calculateProgress, getAllQuestionsFromPage, getExclusiveOptionCode, getVisiblePages, hasAnswerValue, isQuestionHidden, } from "./lib/questionnaire-utils.js";
6
+ export { calculateProgress, findQuestionnaireItem, getAllQuestionsFromPage, getExclusiveOptionCode, getVisiblePages, hasAnswerValue, isQuestionHidden, } from "./lib/questionnaire-utils.js";
7
7
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AACrE,YAAY,EACV,qBAAqB,EACtB,MAAM,mCAAmC,CAAC;AAG3C,OAAO,EACL,qBAAqB,EACrB,gBAAgB,EAChB,KAAK,wBAAwB,EAC7B,KAAK,0BAA0B,GAChC,MAAM,qCAAqC,CAAC;AAG7C,YAAY,EACV,MAAM,EACN,SAAS,EACT,aAAa,EACb,iBAAiB,EACjB,6BAA6B,EAC7B,qBAAqB,EACrB,2BAA2B,EAC3B,yBAAyB,GAC1B,MAAM,iBAAiB,CAAC;AAEzB,YAAY,EACV,eAAe,EACf,kBAAkB,GACnB,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EACL,iBAAiB,EACjB,uBAAuB,EACvB,sBAAsB,EACtB,eAAe,EACf,cAAc,EACd,gBAAgB,GACjB,MAAM,8BAA8B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AACrE,YAAY,EACV,qBAAqB,EACtB,MAAM,mCAAmC,CAAC;AAG3C,OAAO,EACL,qBAAqB,EACrB,gBAAgB,EAChB,KAAK,wBAAwB,EAC7B,KAAK,0BAA0B,GAChC,MAAM,qCAAqC,CAAC;AAG7C,YAAY,EACV,MAAM,EACN,SAAS,EACT,aAAa,EACb,iBAAiB,EACjB,6BAA6B,EAC7B,qBAAqB,EACrB,2BAA2B,EAC3B,yBAAyB,GAC1B,MAAM,iBAAiB,CAAC;AAEzB,YAAY,EACV,eAAe,EACf,kBAAkB,GACnB,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EACL,iBAAiB,EACjB,qBAAqB,EACrB,uBAAuB,EACvB,sBAAsB,EACtB,eAAe,EACf,cAAc,EACd,gBAAgB,GACjB,MAAM,8BAA8B,CAAC"}
package/dist/esm/index.js CHANGED
@@ -3,4 +3,4 @@ export { QuestionRenderer } from "./components/question-renderer.js";
3
3
  // Contexts
4
4
  export { QuestionnaireProvider, useQuestionnaire, } from "./contexts/questionnaire-context.js";
5
5
  // Utils
6
- export { calculateProgress, getAllQuestionsFromPage, getExclusiveOptionCode, getVisiblePages, hasAnswerValue, isQuestionHidden, } from "./lib/questionnaire-utils.js";
6
+ export { calculateProgress, findQuestionnaireItem, getAllQuestionsFromPage, getExclusiveOptionCode, getVisiblePages, hasAnswerValue, isQuestionHidden, } from "./lib/questionnaire-utils.js";
@@ -14,6 +14,10 @@ export declare const calculateProgress: (currentPageIndex: number, totalPages: n
14
14
  * Get all questions from a page (flattens nested groups)
15
15
  */
16
16
  export declare const getAllQuestionsFromPage: (pageItem: QuestionnaireItem) => QuestionnaireItem[];
17
+ /**
18
+ * Recursively searches for a questionnaire item by linkId
19
+ */
20
+ export declare function findQuestionnaireItem(items: QuestionnaireItem[] | undefined, linkId: string): QuestionnaireItem | null;
17
21
  /**
18
22
  * Check if a question has any answer value
19
23
  */
@@ -1 +1 @@
1
- {"version":3,"file":"questionnaire-utils.d.ts","sourceRoot":"","sources":["../../../src/lib/questionnaire-utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAEzE;;GAEG;AACH,eAAO,MAAM,eAAe,GAAI,eAAe,aAAa,KAAG,iBAAiB,EAc/E,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,GAAI,kBAAkB,MAAM,EAAE,YAAY,MAAM,KAAG,MAGhF,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,uBAAuB,GAAI,UAAU,iBAAiB,KAAG,iBAAiB,EAsBtF,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,cAAc,GAAI,QAAQ,GAAG,KAAG,OAe5C,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,gBAAgB,GAAI,MAAM,iBAAiB,KAAG,OAM1D,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,sBAAsB,GAAI,MAAM,iBAAiB,KAAG,MAAM,GAAG,SAKzE,CAAC"}
1
+ {"version":3,"file":"questionnaire-utils.d.ts","sourceRoot":"","sources":["../../../src/lib/questionnaire-utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAEzE;;GAEG;AACH,eAAO,MAAM,eAAe,GAAI,eAAe,aAAa,KAAG,iBAAiB,EAc/E,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,GAAI,kBAAkB,MAAM,EAAE,YAAY,MAAM,KAAG,MAGhF,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,uBAAuB,GAAI,UAAU,iBAAiB,KAAG,iBAAiB,EAsBtF,CAAC;AAEF;;GAEG;AACH,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,iBAAiB,EAAE,GAAG,SAAS,EACtC,MAAM,EAAE,MAAM,GACb,iBAAiB,GAAG,IAAI,CAe1B;AAED;;GAEG;AACH,eAAO,MAAM,cAAc,GAAI,QAAQ,GAAG,KAAG,OAe5C,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,gBAAgB,GAAI,MAAM,iBAAiB,KAAG,OAM1D,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,sBAAsB,GAAI,MAAM,iBAAiB,KAAG,MAAM,GAAG,SAKzE,CAAC"}
@@ -47,6 +47,25 @@ export const getAllQuestionsFromPage = (pageItem) => {
47
47
  }
48
48
  return questions;
49
49
  };
50
+ /**
51
+ * Recursively searches for a questionnaire item by linkId
52
+ */
53
+ export function findQuestionnaireItem(items, linkId) {
54
+ if (!items)
55
+ return null;
56
+ for (const item of items) {
57
+ if (item.linkId === linkId) {
58
+ return item;
59
+ }
60
+ // Recursively search nested items
61
+ if (item.item && item.item.length > 0) {
62
+ const found = findQuestionnaireItem(item.item, linkId);
63
+ if (found)
64
+ return found;
65
+ }
66
+ }
67
+ return null;
68
+ }
50
69
  /**
51
70
  * Check if a question has any answer value
52
71
  */
@@ -49,7 +49,13 @@ const QuestionRendererInternal = ({ item, className = "", inputClassName = "", c
49
49
  return null;
50
50
  }
51
51
  const handleChoiceChange = (valueCoding, valueInteger) => {
52
- updateAnswer(item.linkId, { valueCoding, valueInteger });
52
+ // For choice questions, only set one field: valueCoding takes precedence
53
+ if (valueCoding && (valueCoding.code || valueCoding.display || valueCoding.system)) {
54
+ updateAnswer(item.linkId, { valueCoding });
55
+ }
56
+ else if (valueInteger !== undefined) {
57
+ updateAnswer(item.linkId, { valueInteger });
58
+ }
53
59
  };
54
60
  const handleMultipleChoiceToggle = (valueCoding, valueInteger) => {
55
61
  const isSelected = currentAnswers.some((answer) => answer.valueCoding?.code === valueCoding.code);
@@ -66,7 +72,13 @@ const QuestionRendererInternal = ({ item, className = "", inputClassName = "", c
66
72
  // Check if we're selecting the exclusive option
67
73
  if (exclusiveOptionCode && valueCoding.code === exclusiveOptionCode) {
68
74
  // Clear all other answers and only keep this one
69
- newAnswers = [{ valueCoding, valueInteger }];
75
+ // For choice questions, only set one field: valueCoding takes precedence
76
+ const answer = valueCoding && (valueCoding.code || valueCoding.display || valueCoding.system)
77
+ ? { valueCoding }
78
+ : valueInteger !== undefined
79
+ ? { valueInteger }
80
+ : { valueCoding };
81
+ newAnswers = [answer];
70
82
  }
71
83
  else {
72
84
  // Check if exclusive option is currently selected
@@ -74,13 +86,25 @@ const QuestionRendererInternal = ({ item, className = "", inputClassName = "", c
74
86
  if (exclusiveSelected) {
75
87
  // Remove exclusive option and add new selection
76
88
  newAnswers = currentAnswers.filter((answer) => answer.valueCoding?.code !== exclusiveOptionCode);
77
- newAnswers = [...newAnswers, { valueCoding, valueInteger }];
89
+ // For choice questions, only set one field: valueCoding takes precedence
90
+ const answer = valueCoding && (valueCoding.code || valueCoding.display || valueCoding.system)
91
+ ? { valueCoding }
92
+ : valueInteger !== undefined
93
+ ? { valueInteger }
94
+ : { valueCoding };
95
+ newAnswers = [...newAnswers, answer];
78
96
  }
79
97
  else {
80
98
  // Normal behavior: Add the answer (respecting maxAnswers limit)
81
99
  const maxAnswers = item.maxAnswers || Number.MAX_SAFE_INTEGER;
82
100
  if (currentAnswers.length < maxAnswers) {
83
- newAnswers = [...currentAnswers, { valueCoding, valueInteger }];
101
+ // For choice questions, only set one field: valueCoding takes precedence
102
+ const answer = valueCoding && (valueCoding.code || valueCoding.display || valueCoding.system)
103
+ ? { valueCoding }
104
+ : valueInteger !== undefined
105
+ ? { valueInteger }
106
+ : { valueCoding };
107
+ newAnswers = [...currentAnswers, answer];
84
108
  }
85
109
  else {
86
110
  // Already at max, don't add
@@ -3,5 +3,5 @@ export type { QuestionRendererProps } from "./components/question-renderer.js";
3
3
  export { QuestionnaireProvider, useQuestionnaire, type QuestionnaireContextType, type QuestionnaireProviderProps, } from "./contexts/questionnaire-context.js";
4
4
  export type { Coding, Extension, Questionnaire, QuestionnaireItem, QuestionnaireItemAnswerOption, QuestionnaireResponse, QuestionnaireResponseAnswer, QuestionnaireResponseItem, } from "./types/fhir.js";
5
5
  export type { RadioInputProps, CheckboxInputProps, } from "./types/index.js";
6
- export { calculateProgress, getAllQuestionsFromPage, getExclusiveOptionCode, getVisiblePages, hasAnswerValue, isQuestionHidden, } from "./lib/questionnaire-utils.js";
6
+ export { calculateProgress, findQuestionnaireItem, getAllQuestionsFromPage, getExclusiveOptionCode, getVisiblePages, hasAnswerValue, isQuestionHidden, } from "./lib/questionnaire-utils.js";
7
7
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AACrE,YAAY,EACV,qBAAqB,EACtB,MAAM,mCAAmC,CAAC;AAG3C,OAAO,EACL,qBAAqB,EACrB,gBAAgB,EAChB,KAAK,wBAAwB,EAC7B,KAAK,0BAA0B,GAChC,MAAM,qCAAqC,CAAC;AAG7C,YAAY,EACV,MAAM,EACN,SAAS,EACT,aAAa,EACb,iBAAiB,EACjB,6BAA6B,EAC7B,qBAAqB,EACrB,2BAA2B,EAC3B,yBAAyB,GAC1B,MAAM,iBAAiB,CAAC;AAEzB,YAAY,EACV,eAAe,EACf,kBAAkB,GACnB,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EACL,iBAAiB,EACjB,uBAAuB,EACvB,sBAAsB,EACtB,eAAe,EACf,cAAc,EACd,gBAAgB,GACjB,MAAM,8BAA8B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AACrE,YAAY,EACV,qBAAqB,EACtB,MAAM,mCAAmC,CAAC;AAG3C,OAAO,EACL,qBAAqB,EACrB,gBAAgB,EAChB,KAAK,wBAAwB,EAC7B,KAAK,0BAA0B,GAChC,MAAM,qCAAqC,CAAC;AAG7C,YAAY,EACV,MAAM,EACN,SAAS,EACT,aAAa,EACb,iBAAiB,EACjB,6BAA6B,EAC7B,qBAAqB,EACrB,2BAA2B,EAC3B,yBAAyB,GAC1B,MAAM,iBAAiB,CAAC;AAEzB,YAAY,EACV,eAAe,EACf,kBAAkB,GACnB,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EACL,iBAAiB,EACjB,qBAAqB,EACrB,uBAAuB,EACvB,sBAAsB,EACtB,eAAe,EACf,cAAc,EACd,gBAAgB,GACjB,MAAM,8BAA8B,CAAC"}
@@ -3,4 +3,4 @@ export { QuestionRenderer } from "./components/question-renderer.js";
3
3
  // Contexts
4
4
  export { QuestionnaireProvider, useQuestionnaire, } from "./contexts/questionnaire-context.js";
5
5
  // Utils
6
- export { calculateProgress, getAllQuestionsFromPage, getExclusiveOptionCode, getVisiblePages, hasAnswerValue, isQuestionHidden, } from "./lib/questionnaire-utils.js";
6
+ export { calculateProgress, findQuestionnaireItem, getAllQuestionsFromPage, getExclusiveOptionCode, getVisiblePages, hasAnswerValue, isQuestionHidden, } from "./lib/questionnaire-utils.js";
@@ -14,6 +14,10 @@ export declare const calculateProgress: (currentPageIndex: number, totalPages: n
14
14
  * Get all questions from a page (flattens nested groups)
15
15
  */
16
16
  export declare const getAllQuestionsFromPage: (pageItem: QuestionnaireItem) => QuestionnaireItem[];
17
+ /**
18
+ * Recursively searches for a questionnaire item by linkId
19
+ */
20
+ export declare function findQuestionnaireItem(items: QuestionnaireItem[] | undefined, linkId: string): QuestionnaireItem | null;
17
21
  /**
18
22
  * Check if a question has any answer value
19
23
  */
@@ -1 +1 @@
1
- {"version":3,"file":"questionnaire-utils.d.ts","sourceRoot":"","sources":["../../../src/lib/questionnaire-utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAEzE;;GAEG;AACH,eAAO,MAAM,eAAe,GAAI,eAAe,aAAa,KAAG,iBAAiB,EAc/E,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,GAAI,kBAAkB,MAAM,EAAE,YAAY,MAAM,KAAG,MAGhF,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,uBAAuB,GAAI,UAAU,iBAAiB,KAAG,iBAAiB,EAsBtF,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,cAAc,GAAI,QAAQ,GAAG,KAAG,OAe5C,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,gBAAgB,GAAI,MAAM,iBAAiB,KAAG,OAM1D,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,sBAAsB,GAAI,MAAM,iBAAiB,KAAG,MAAM,GAAG,SAKzE,CAAC"}
1
+ {"version":3,"file":"questionnaire-utils.d.ts","sourceRoot":"","sources":["../../../src/lib/questionnaire-utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAEzE;;GAEG;AACH,eAAO,MAAM,eAAe,GAAI,eAAe,aAAa,KAAG,iBAAiB,EAc/E,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,GAAI,kBAAkB,MAAM,EAAE,YAAY,MAAM,KAAG,MAGhF,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,uBAAuB,GAAI,UAAU,iBAAiB,KAAG,iBAAiB,EAsBtF,CAAC;AAEF;;GAEG;AACH,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,iBAAiB,EAAE,GAAG,SAAS,EACtC,MAAM,EAAE,MAAM,GACb,iBAAiB,GAAG,IAAI,CAe1B;AAED;;GAEG;AACH,eAAO,MAAM,cAAc,GAAI,QAAQ,GAAG,KAAG,OAe5C,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,gBAAgB,GAAI,MAAM,iBAAiB,KAAG,OAM1D,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,sBAAsB,GAAI,MAAM,iBAAiB,KAAG,MAAM,GAAG,SAKzE,CAAC"}
@@ -47,6 +47,25 @@ export const getAllQuestionsFromPage = (pageItem) => {
47
47
  }
48
48
  return questions;
49
49
  };
50
+ /**
51
+ * Recursively searches for a questionnaire item by linkId
52
+ */
53
+ export function findQuestionnaireItem(items, linkId) {
54
+ if (!items)
55
+ return null;
56
+ for (const item of items) {
57
+ if (item.linkId === linkId) {
58
+ return item;
59
+ }
60
+ // Recursively search nested items
61
+ if (item.item && item.item.length > 0) {
62
+ const found = findQuestionnaireItem(item.item, linkId);
63
+ if (found)
64
+ return found;
65
+ }
66
+ }
67
+ return null;
68
+ }
50
69
  /**
51
70
  * Check if a question has any answer value
52
71
  */
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@welshare/questionnaire",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "FHIR Questionnaire components for React with state management and validation",
5
5
  "keywords": [
6
6
  "react",
@@ -160,7 +160,12 @@ const QuestionRendererInternal = ({
160
160
  valueCoding: { system?: string; code?: string; display?: string },
161
161
  valueInteger?: number
162
162
  ) => {
163
- updateAnswer(item.linkId, { valueCoding, valueInteger });
163
+ // For choice questions, only set one field: valueCoding takes precedence
164
+ if (valueCoding && (valueCoding.code || valueCoding.display || valueCoding.system)) {
165
+ updateAnswer(item.linkId, { valueCoding });
166
+ } else if (valueInteger !== undefined) {
167
+ updateAnswer(item.linkId, { valueInteger });
168
+ }
164
169
  };
165
170
 
166
171
  const handleMultipleChoiceToggle = (
@@ -189,7 +194,13 @@ const QuestionRendererInternal = ({
189
194
  // Check if we're selecting the exclusive option
190
195
  if (exclusiveOptionCode && valueCoding.code === exclusiveOptionCode) {
191
196
  // Clear all other answers and only keep this one
192
- newAnswers = [{ valueCoding, valueInteger }];
197
+ // For choice questions, only set one field: valueCoding takes precedence
198
+ const answer = valueCoding && (valueCoding.code || valueCoding.display || valueCoding.system)
199
+ ? { valueCoding }
200
+ : valueInteger !== undefined
201
+ ? { valueInteger }
202
+ : { valueCoding };
203
+ newAnswers = [answer];
193
204
  } else {
194
205
  // Check if exclusive option is currently selected
195
206
  const exclusiveSelected = currentAnswers.some(
@@ -201,12 +212,24 @@ const QuestionRendererInternal = ({
201
212
  newAnswers = currentAnswers.filter(
202
213
  (answer) => answer.valueCoding?.code !== exclusiveOptionCode
203
214
  );
204
- newAnswers = [...newAnswers, { valueCoding, valueInteger }];
215
+ // For choice questions, only set one field: valueCoding takes precedence
216
+ const answer = valueCoding && (valueCoding.code || valueCoding.display || valueCoding.system)
217
+ ? { valueCoding }
218
+ : valueInteger !== undefined
219
+ ? { valueInteger }
220
+ : { valueCoding };
221
+ newAnswers = [...newAnswers, answer];
205
222
  } else {
206
223
  // Normal behavior: Add the answer (respecting maxAnswers limit)
207
224
  const maxAnswers = item.maxAnswers || Number.MAX_SAFE_INTEGER;
208
225
  if (currentAnswers.length < maxAnswers) {
209
- newAnswers = [...currentAnswers, { valueCoding, valueInteger }];
226
+ // For choice questions, only set one field: valueCoding takes precedence
227
+ const answer = valueCoding && (valueCoding.code || valueCoding.display || valueCoding.system)
228
+ ? { valueCoding }
229
+ : valueInteger !== undefined
230
+ ? { valueInteger }
231
+ : { valueCoding };
232
+ newAnswers = [...currentAnswers, answer];
210
233
  } else {
211
234
  // Already at max, don't add
212
235
  return;
@@ -32,6 +32,7 @@ export type {
32
32
  // Utils
33
33
  export {
34
34
  calculateProgress,
35
+ findQuestionnaireItem,
35
36
  getAllQuestionsFromPage,
36
37
  getExclusiveOptionCode,
37
38
  getVisiblePages,
@@ -57,6 +57,29 @@ export const getAllQuestionsFromPage = (pageItem: QuestionnaireItem): Questionna
57
57
  return questions;
58
58
  };
59
59
 
60
+ /**
61
+ * Recursively searches for a questionnaire item by linkId
62
+ */
63
+ export function findQuestionnaireItem(
64
+ items: QuestionnaireItem[] | undefined,
65
+ linkId: string
66
+ ): QuestionnaireItem | null {
67
+ if (!items) return null;
68
+
69
+ for (const item of items) {
70
+ if (item.linkId === linkId) {
71
+ return item;
72
+ }
73
+ // Recursively search nested items
74
+ if (item.item && item.item.length > 0) {
75
+ const found = findQuestionnaireItem(item.item, linkId);
76
+ if (found) return found;
77
+ }
78
+ }
79
+
80
+ return null;
81
+ }
82
+
60
83
  /**
61
84
  * Check if a question has any answer value
62
85
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@welshare/questionnaire",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "FHIR Questionnaire components for React with state management and validation",
5
5
  "keywords": [
6
6
  "react",