@welshare/questionnaire 0.1.1 → 0.2.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.
Files changed (96) hide show
  1. package/README.md +151 -0
  2. package/dist/esm/components/bmi-form.d.ts +68 -0
  3. package/dist/esm/components/bmi-form.d.ts.map +1 -0
  4. package/dist/esm/components/bmi-form.js +138 -0
  5. package/dist/esm/components/question-renderer.d.ts +6 -1
  6. package/dist/esm/components/question-renderer.d.ts.map +1 -1
  7. package/dist/esm/components/question-renderer.js +49 -14
  8. package/dist/esm/components/questions/decimal-question.d.ts +8 -1
  9. package/dist/esm/components/questions/decimal-question.d.ts.map +1 -1
  10. package/dist/esm/components/questions/decimal-question.js +19 -1
  11. package/dist/esm/components/questions/multiple-choice-question.d.ts.map +1 -1
  12. package/dist/esm/components/questions/multiple-choice-question.js +2 -2
  13. package/dist/esm/contexts/questionnaire-context.d.ts.map +1 -1
  14. package/dist/esm/contexts/questionnaire-context.js +3 -2
  15. package/dist/esm/index.d.ts +6 -2
  16. package/dist/esm/index.d.ts.map +1 -1
  17. package/dist/esm/index.js +5 -1
  18. package/dist/esm/lib/bmi-helpers.d.ts +50 -0
  19. package/dist/esm/lib/bmi-helpers.d.ts.map +1 -0
  20. package/dist/esm/lib/bmi-helpers.js +69 -0
  21. package/dist/esm/lib/constants.d.ts +94 -0
  22. package/dist/esm/lib/constants.d.ts.map +1 -0
  23. package/dist/esm/lib/constants.js +93 -0
  24. package/dist/esm/lib/questionnaire-utils.d.ts +21 -1
  25. package/dist/esm/lib/questionnaire-utils.d.ts.map +1 -1
  26. package/dist/esm/lib/questionnaire-utils.js +85 -4
  27. package/dist/esm/types/fhir.d.ts +1 -0
  28. package/dist/esm/types/fhir.d.ts.map +1 -1
  29. package/dist/esm/types/index.d.ts +25 -0
  30. package/dist/esm/types/index.d.ts.map +1 -1
  31. package/dist/styles.css +108 -0
  32. package/package.json +17 -6
  33. package/dist/node_modules/@welshare/questionnaire/.tshy/build.json +0 -8
  34. package/dist/node_modules/@welshare/questionnaire/.tshy/esm.json +0 -16
  35. package/dist/node_modules/@welshare/questionnaire/LICENSE +0 -7
  36. package/dist/node_modules/@welshare/questionnaire/README.md +0 -173
  37. package/dist/node_modules/@welshare/questionnaire/dist/esm/components/debug-section.d.ts +0 -44
  38. package/dist/node_modules/@welshare/questionnaire/dist/esm/components/debug-section.d.ts.map +0 -1
  39. package/dist/node_modules/@welshare/questionnaire/dist/esm/components/debug-section.js +0 -28
  40. package/dist/node_modules/@welshare/questionnaire/dist/esm/components/question-renderer.d.ts +0 -80
  41. package/dist/node_modules/@welshare/questionnaire/dist/esm/components/question-renderer.d.ts.map +0 -1
  42. package/dist/node_modules/@welshare/questionnaire/dist/esm/components/question-renderer.js +0 -159
  43. package/dist/node_modules/@welshare/questionnaire/dist/esm/components/questions/boolean-question.d.ts +0 -15
  44. package/dist/node_modules/@welshare/questionnaire/dist/esm/components/questions/boolean-question.d.ts.map +0 -1
  45. package/dist/node_modules/@welshare/questionnaire/dist/esm/components/questions/boolean-question.js +0 -19
  46. package/dist/node_modules/@welshare/questionnaire/dist/esm/components/questions/choice-question.d.ts +0 -19
  47. package/dist/node_modules/@welshare/questionnaire/dist/esm/components/questions/choice-question.d.ts.map +0 -1
  48. package/dist/node_modules/@welshare/questionnaire/dist/esm/components/questions/choice-question.js +0 -23
  49. package/dist/node_modules/@welshare/questionnaire/dist/esm/components/questions/decimal-question.d.ts +0 -12
  50. package/dist/node_modules/@welshare/questionnaire/dist/esm/components/questions/decimal-question.d.ts.map +0 -1
  51. package/dist/node_modules/@welshare/questionnaire/dist/esm/components/questions/decimal-question.js +0 -7
  52. package/dist/node_modules/@welshare/questionnaire/dist/esm/components/questions/integer-question.d.ts +0 -18
  53. package/dist/node_modules/@welshare/questionnaire/dist/esm/components/questions/integer-question.d.ts.map +0 -1
  54. package/dist/node_modules/@welshare/questionnaire/dist/esm/components/questions/integer-question.js +0 -24
  55. package/dist/node_modules/@welshare/questionnaire/dist/esm/components/questions/multiple-choice-question.d.ts +0 -20
  56. package/dist/node_modules/@welshare/questionnaire/dist/esm/components/questions/multiple-choice-question.d.ts.map +0 -1
  57. package/dist/node_modules/@welshare/questionnaire/dist/esm/components/questions/multiple-choice-question.js +0 -39
  58. package/dist/node_modules/@welshare/questionnaire/dist/esm/components/questions/string-question.d.ts +0 -12
  59. package/dist/node_modules/@welshare/questionnaire/dist/esm/components/questions/string-question.d.ts.map +0 -1
  60. package/dist/node_modules/@welshare/questionnaire/dist/esm/components/questions/string-question.js +0 -7
  61. package/dist/node_modules/@welshare/questionnaire/dist/esm/contexts/questionnaire-context.d.ts +0 -41
  62. package/dist/node_modules/@welshare/questionnaire/dist/esm/contexts/questionnaire-context.d.ts.map +0 -1
  63. package/dist/node_modules/@welshare/questionnaire/dist/esm/contexts/questionnaire-context.js +0 -350
  64. package/dist/node_modules/@welshare/questionnaire/dist/esm/index.d.ts +0 -7
  65. package/dist/node_modules/@welshare/questionnaire/dist/esm/index.d.ts.map +0 -1
  66. package/dist/node_modules/@welshare/questionnaire/dist/esm/index.js +0 -6
  67. package/dist/node_modules/@welshare/questionnaire/dist/esm/lib/questionnaire-utils.d.ts +0 -33
  68. package/dist/node_modules/@welshare/questionnaire/dist/esm/lib/questionnaire-utils.d.ts.map +0 -1
  69. package/dist/node_modules/@welshare/questionnaire/dist/esm/lib/questionnaire-utils.js +0 -99
  70. package/dist/node_modules/@welshare/questionnaire/dist/esm/package.json +0 -3
  71. package/dist/node_modules/@welshare/questionnaire/dist/esm/types/fhir.d.ts +0 -117
  72. package/dist/node_modules/@welshare/questionnaire/dist/esm/types/fhir.d.ts.map +0 -1
  73. package/dist/node_modules/@welshare/questionnaire/dist/esm/types/fhir.js +0 -3
  74. package/dist/node_modules/@welshare/questionnaire/dist/esm/types/index.d.ts +0 -51
  75. package/dist/node_modules/@welshare/questionnaire/dist/esm/types/index.d.ts.map +0 -1
  76. package/dist/node_modules/@welshare/questionnaire/dist/esm/types/index.js +0 -1
  77. package/dist/node_modules/@welshare/questionnaire/dist/styles.css +0 -467
  78. package/dist/node_modules/@welshare/questionnaire/dist/tokens.css +0 -130
  79. package/dist/node_modules/@welshare/questionnaire/package.json +0 -85
  80. package/dist/node_modules/@welshare/questionnaire/src/components/debug-section.tsx +0 -116
  81. package/dist/node_modules/@welshare/questionnaire/src/components/question-renderer.tsx +0 -368
  82. package/dist/node_modules/@welshare/questionnaire/src/components/questionnaire-styles.css +0 -467
  83. package/dist/node_modules/@welshare/questionnaire/src/components/questionnaire-tokens.css +0 -130
  84. package/dist/node_modules/@welshare/questionnaire/src/components/questions/boolean-question.tsx +0 -72
  85. package/dist/node_modules/@welshare/questionnaire/src/components/questions/choice-question.tsx +0 -68
  86. package/dist/node_modules/@welshare/questionnaire/src/components/questions/decimal-question.tsx +0 -32
  87. package/dist/node_modules/@welshare/questionnaire/src/components/questions/integer-question.tsx +0 -87
  88. package/dist/node_modules/@welshare/questionnaire/src/components/questions/multiple-choice-question.tsx +0 -119
  89. package/dist/node_modules/@welshare/questionnaire/src/components/questions/string-question.tsx +0 -31
  90. package/dist/node_modules/@welshare/questionnaire/src/contexts/questionnaire-context.tsx +0 -499
  91. package/dist/node_modules/@welshare/questionnaire/src/index.ts +0 -41
  92. package/dist/node_modules/@welshare/questionnaire/src/lib/__tests__/questionnaire-utils.test.ts +0 -578
  93. package/dist/node_modules/@welshare/questionnaire/src/lib/questionnaire-utils.ts +0 -122
  94. package/dist/node_modules/@welshare/questionnaire/src/types/fhir.ts +0 -126
  95. package/dist/node_modules/@welshare/questionnaire/src/types/index.ts +0 -44
  96. package/dist/node_modules/@welshare/questionnaire/tsconfig.json +0 -16
@@ -1,499 +0,0 @@
1
- import {
2
- createContext,
3
- useContext,
4
- useEffect,
5
- useState,
6
- type ReactNode,
7
- } from "react";
8
- import type {
9
- Questionnaire,
10
- QuestionnaireItem,
11
- QuestionnaireResponse,
12
- QuestionnaireResponseAnswer,
13
- QuestionnaireResponseItem,
14
- } from "../types/fhir.js";
15
- import { getAllQuestionsFromPage } from "../lib/questionnaire-utils.js";
16
-
17
- export interface QuestionnaireContextType {
18
- questionnaire: Questionnaire;
19
- response: QuestionnaireResponse;
20
- updateAnswer: (linkId: string, answer: QuestionnaireResponseAnswer) => void;
21
- updateMultipleAnswers: (
22
- linkId: string,
23
- answers: QuestionnaireResponseAnswer[]
24
- ) => void;
25
- getAnswer: (linkId: string) => QuestionnaireResponseAnswer | undefined;
26
- getAnswers: (linkId: string) => QuestionnaireResponseAnswer[];
27
- isPageValid: (pageItems: QuestionnaireItem[]) => boolean;
28
- getRequiredQuestions: (pageItems: QuestionnaireItem[]) => QuestionnaireItem[];
29
- getUnansweredRequiredQuestions: (
30
- pageItems: QuestionnaireItem[]
31
- ) => QuestionnaireItem[];
32
- markValidationErrors: (pageItems: QuestionnaireItem[]) => void;
33
- clearValidationErrors: () => void;
34
- hasValidationError: (linkId: string) => boolean;
35
- debugMode: boolean;
36
- toggleDebugMode: () => void;
37
- }
38
-
39
- const QuestionnaireContext = createContext<
40
- QuestionnaireContextType | undefined
41
- >(undefined);
42
-
43
- export const useQuestionnaire = () => {
44
- const context = useContext(QuestionnaireContext);
45
- if (!context) {
46
- throw new Error(
47
- "useQuestionnaire must be used within QuestionnaireProvider"
48
- );
49
- }
50
- return context;
51
- };
52
-
53
- export interface QuestionnaireProviderProps {
54
- children: ReactNode;
55
- /**
56
- * The FHIR Questionnaire object to render
57
- * Clients are responsible for loading/fetching this data
58
- */
59
- questionnaire: Questionnaire;
60
- /**
61
- * Optional questionnaire ID to use in the response
62
- * If not provided, will use questionnaire.id
63
- * If neither exists, an error will be thrown
64
- */
65
- questionnaireId?: string;
66
- /**
67
- * If true, initializes the response with a hierarchical structure matching the questionnaire
68
- * If false, uses a flat structure
69
- * @default true
70
- */
71
- useNestedStructure?: boolean;
72
- }
73
-
74
- export const QuestionnaireProvider = ({
75
- children,
76
- questionnaire,
77
- questionnaireId,
78
- useNestedStructure = true,
79
- }: QuestionnaireProviderProps) => {
80
- const [response, setResponse] = useState<QuestionnaireResponse>({
81
- resourceType: "QuestionnaireResponse",
82
- status: "in-progress",
83
- item: [],
84
- });
85
- const [validationErrors, setValidationErrors] = useState<Set<string>>(
86
- new Set()
87
- );
88
-
89
- const [debugMode, setDebugMode] = useState(false);
90
-
91
- const toggleDebugMode = () => {
92
- setDebugMode((prev) => !prev);
93
- };
94
-
95
- // Determine the questionnaire ID to use
96
- const effectiveQuestionnaireId = questionnaireId || questionnaire.id;
97
-
98
- if (!effectiveQuestionnaireId) {
99
- throw new Error(
100
- "QuestionnaireProvider: questionnaireId prop or questionnaire.id must be provided"
101
- );
102
- }
103
-
104
- // Initialize response structure when questionnaire or options change
105
- useEffect(() => {
106
- if (useNestedStructure) {
107
- // Build response structure mirroring questionnaire hierarchy
108
- const buildResponseStructure = (
109
- questionnaireItems?: QuestionnaireItem[]
110
- ): QuestionnaireResponseItem[] => {
111
- if (!questionnaireItems) return [];
112
-
113
- return questionnaireItems.map((item) => {
114
- const responseItem: QuestionnaireResponseItem = {
115
- linkId: item.linkId,
116
- };
117
-
118
- // Add text if present
119
- if (item.text) {
120
- responseItem.text = item.text;
121
- }
122
-
123
- // If item has nested items (group), recursively build structure
124
- if (item.item && item.item.length > 0) {
125
- responseItem.item = buildResponseStructure(item.item);
126
- }
127
-
128
- // If item has initial values, add them as answers
129
- if (item.initial && item.initial.length > 0) {
130
- responseItem.answer = item.initial;
131
- }
132
-
133
- return responseItem;
134
- });
135
- };
136
-
137
- const initialItems = buildResponseStructure(questionnaire.item);
138
-
139
- // Initialize response structure with hierarchical structure
140
- setResponse({
141
- resourceType: "QuestionnaireResponse",
142
- questionnaire: effectiveQuestionnaireId,
143
- status: "in-progress",
144
- authored: new Date().toISOString(),
145
- item: initialItems,
146
- });
147
- } else {
148
- // Flat structure initialization
149
- setResponse({
150
- resourceType: "QuestionnaireResponse",
151
- questionnaire: effectiveQuestionnaireId,
152
- status: "in-progress",
153
- authored: new Date().toISOString(),
154
- item: [],
155
- });
156
- }
157
- }, [questionnaire, effectiveQuestionnaireId, useNestedStructure]);
158
-
159
- const updateAnswer = (
160
- linkId: string,
161
- answer: QuestionnaireResponseAnswer
162
- ) => {
163
- setResponse((prev) => {
164
- const newResponse = { ...prev };
165
-
166
- if (useNestedStructure) {
167
- // Recursively find and update the item in the nested structure
168
- const updateNestedItem = (
169
- items: QuestionnaireResponseItem[] = []
170
- ): QuestionnaireResponseItem[] => {
171
- return items.map((item) => {
172
- // If this is the item we're looking for, update it
173
- if (item.linkId === linkId) {
174
- return {
175
- linkId: item.linkId,
176
- ...(item.definition && { definition: item.definition }),
177
- ...(item.text && { text: item.text }),
178
- answer: [answer],
179
- ...(item.item && { item: item.item }),
180
- };
181
- }
182
-
183
- // If this item has nested items, search within them
184
- if (item.item && item.item.length > 0) {
185
- return {
186
- ...item,
187
- item: updateNestedItem(item.item),
188
- };
189
- }
190
-
191
- return item;
192
- });
193
- };
194
-
195
- newResponse.item = updateNestedItem(newResponse.item);
196
- } else {
197
- // Flat structure: find or create the item
198
- const findOrCreateItem = (
199
- items: QuestionnaireResponseItem[] = []
200
- ): QuestionnaireResponseItem[] => {
201
- const existingIndex = items.findIndex(
202
- (item) => item.linkId === linkId
203
- );
204
-
205
- if (existingIndex >= 0) {
206
- // Update existing item
207
- const updated = [...items];
208
- const existingItem = updated[existingIndex]!;
209
- updated[existingIndex] = {
210
- linkId: existingItem.linkId,
211
- ...(existingItem.definition && {
212
- definition: existingItem.definition,
213
- }),
214
- ...(existingItem.text && { text: existingItem.text }),
215
- answer: [answer],
216
- ...(existingItem.item && { item: existingItem.item }),
217
- };
218
- return updated;
219
- } else {
220
- // Create new item
221
- return [
222
- ...items,
223
- {
224
- linkId,
225
- answer: [answer],
226
- },
227
- ];
228
- }
229
- };
230
-
231
- newResponse.item = findOrCreateItem(newResponse.item);
232
- }
233
-
234
- return newResponse;
235
- });
236
-
237
- // Clear validation error for this question when answered
238
- setValidationErrors((prev) => {
239
- const newErrors = new Set(prev);
240
- newErrors.delete(linkId);
241
- return newErrors;
242
- });
243
- };
244
-
245
- const updateMultipleAnswers = (
246
- linkId: string,
247
- answers: QuestionnaireResponseAnswer[]
248
- ) => {
249
- setResponse((prev) => {
250
- const newResponse = { ...prev };
251
-
252
- if (useNestedStructure) {
253
- // Recursively find and update the item in the nested structure
254
- const updateNestedItem = (
255
- items: QuestionnaireResponseItem[] = []
256
- ): QuestionnaireResponseItem[] => {
257
- return items.map((item) => {
258
- // If this is the item we're looking for, update it
259
- if (item.linkId === linkId) {
260
- return {
261
- linkId: item.linkId,
262
- ...(item.definition && { definition: item.definition }),
263
- ...(item.text && { text: item.text }),
264
- answer: answers,
265
- ...(item.item && { item: item.item }),
266
- };
267
- }
268
-
269
- // If this item has nested items, search within them
270
- if (item.item && item.item.length > 0) {
271
- return {
272
- ...item,
273
- item: updateNestedItem(item.item),
274
- };
275
- }
276
-
277
- return item;
278
- });
279
- };
280
-
281
- newResponse.item = updateNestedItem(newResponse.item);
282
- } else {
283
- // Flat structure
284
- const findOrCreateItem = (
285
- items: QuestionnaireResponseItem[] = []
286
- ): QuestionnaireResponseItem[] => {
287
- const existingIndex = items.findIndex(
288
- (item) => item.linkId === linkId
289
- );
290
-
291
- if (existingIndex >= 0) {
292
- const updated = [...items];
293
- const existingItem = updated[existingIndex]!;
294
- updated[existingIndex] = {
295
- linkId: existingItem.linkId,
296
- ...(existingItem.definition && {
297
- definition: existingItem.definition,
298
- }),
299
- ...(existingItem.text && { text: existingItem.text }),
300
- answer: answers,
301
- ...(existingItem.item && { item: existingItem.item }),
302
- };
303
- return updated;
304
- } else {
305
- return [
306
- ...items,
307
- {
308
- linkId,
309
- answer: answers,
310
- },
311
- ];
312
- }
313
- };
314
-
315
- newResponse.item = findOrCreateItem(newResponse.item);
316
- }
317
-
318
- return newResponse;
319
- });
320
-
321
- // Clear validation error for this question when answered
322
- setValidationErrors((prev) => {
323
- const newErrors = new Set(prev);
324
- newErrors.delete(linkId);
325
- return newErrors;
326
- });
327
- };
328
-
329
- const getAnswer = (
330
- linkId: string
331
- ): QuestionnaireResponseAnswer | undefined => {
332
- // Recursively search for the item in nested structure or flat structure
333
- const findItem = (
334
- items?: QuestionnaireResponseItem[]
335
- ): QuestionnaireResponseItem | undefined => {
336
- if (!items) return undefined;
337
-
338
- for (const item of items) {
339
- if (item.linkId === linkId) {
340
- return item;
341
- }
342
-
343
- if (item.item && item.item.length > 0) {
344
- const found = findItem(item.item);
345
- if (found) return found;
346
- }
347
- }
348
-
349
- return undefined;
350
- };
351
-
352
- const item = findItem(response.item);
353
- return item?.answer?.[0];
354
- };
355
-
356
- const getAnswers = (linkId: string): QuestionnaireResponseAnswer[] => {
357
- // Recursively search for the item in nested structure or flat structure
358
- const findItem = (
359
- items?: QuestionnaireResponseItem[]
360
- ): QuestionnaireResponseItem | undefined => {
361
- if (!items) return undefined;
362
-
363
- for (const item of items) {
364
- if (item.linkId === linkId) {
365
- return item;
366
- }
367
-
368
- if (item.item && item.item.length > 0) {
369
- const found = findItem(item.item);
370
- if (found) return found;
371
- }
372
- }
373
-
374
- return undefined;
375
- };
376
-
377
- const item = findItem(response.item);
378
- return item?.answer || [];
379
- };
380
-
381
- const getRequiredQuestions = (
382
- pageItems: QuestionnaireItem[]
383
- ): QuestionnaireItem[] => {
384
- // Recursively flatten nested groups so required questions inside them
385
- // are included in page validation.
386
- const allQuestionsOnPage = getAllQuestionsFromPage({
387
- linkId: "__page__",
388
- type: "group",
389
- item: pageItems,
390
- });
391
-
392
- return allQuestionsOnPage.filter((item) => item.required === true);
393
- };
394
-
395
- const isNonEmptyString = (value: unknown): value is string =>
396
- typeof value === "string" && value.trim().length > 0;
397
-
398
- const hasMeaningfulAnswer = (answer?: QuestionnaireResponseAnswer): boolean => {
399
- if (!answer) return false;
400
-
401
- // Primitive numeric/boolean values are meaningful even when 0/false.
402
- if (answer.valueBoolean !== undefined) return true;
403
- if (answer.valueInteger !== undefined) return true;
404
- if (answer.valueDecimal !== undefined) return true;
405
-
406
- // String-like answers must be non-empty (trimmed) to be meaningful.
407
- if (isNonEmptyString(answer.valueString)) return true;
408
- if (isNonEmptyString(answer.valueDate)) return true;
409
- if (isNonEmptyString(answer.valueDateTime)) return true;
410
- if (isNonEmptyString(answer.valueTime)) return true;
411
- if (isNonEmptyString(answer.valueUri)) return true;
412
-
413
- // Coding answers are meaningful when they contain at least one identifier.
414
- if (
415
- answer.valueCoding &&
416
- (isNonEmptyString(answer.valueCoding.code) ||
417
- isNonEmptyString(answer.valueCoding.display) ||
418
- isNonEmptyString(answer.valueCoding.system))
419
- ) {
420
- return true;
421
- }
422
-
423
- // Quantity answers are meaningful when a value is provided.
424
- if (answer.valueQuantity?.value !== undefined) return true;
425
-
426
- return false;
427
- };
428
-
429
- const isPageValid = (pageItems: QuestionnaireItem[]): boolean => {
430
- const requiredQuestions = getRequiredQuestions(pageItems);
431
-
432
- return requiredQuestions.every((question) => {
433
- // For multi-select questions (repeats = true), check if there's at least one answer
434
- if (question.repeats) {
435
- const answers = getAnswers(question.linkId);
436
- return answers.some((a) => hasMeaningfulAnswer(a));
437
- }
438
-
439
- // For single-answer questions
440
- const answer = getAnswer(question.linkId);
441
- return hasMeaningfulAnswer(answer);
442
- });
443
- };
444
-
445
- const getUnansweredRequiredQuestions = (
446
- pageItems: QuestionnaireItem[]
447
- ): QuestionnaireItem[] => {
448
- const requiredQuestions = getRequiredQuestions(pageItems);
449
-
450
- return requiredQuestions.filter((question) => {
451
- // For multi-select questions (repeats = true), check if there's at least one answer
452
- if (question.repeats) {
453
- const answers = getAnswers(question.linkId);
454
- return !answers.some((a) => hasMeaningfulAnswer(a));
455
- }
456
-
457
- // For single-answer questions
458
- const answer = getAnswer(question.linkId);
459
- return !hasMeaningfulAnswer(answer);
460
- });
461
- };
462
-
463
- const markValidationErrors = (pageItems: QuestionnaireItem[]) => {
464
- const unansweredRequired = getUnansweredRequiredQuestions(pageItems);
465
- const errorLinkIds = unansweredRequired.map((q) => q.linkId);
466
- setValidationErrors(new Set(errorLinkIds));
467
- };
468
-
469
- const clearValidationErrors = () => {
470
- setValidationErrors(new Set());
471
- };
472
-
473
- const hasValidationError = (linkId: string): boolean => {
474
- return validationErrors.has(linkId);
475
- };
476
-
477
- return (
478
- <QuestionnaireContext.Provider
479
- value={{
480
- questionnaire,
481
- response,
482
- updateAnswer,
483
- updateMultipleAnswers,
484
- getAnswer,
485
- getAnswers,
486
- isPageValid,
487
- getRequiredQuestions,
488
- getUnansweredRequiredQuestions,
489
- markValidationErrors,
490
- clearValidationErrors,
491
- hasValidationError,
492
- debugMode,
493
- toggleDebugMode,
494
- }}
495
- >
496
- {children}
497
- </QuestionnaireContext.Provider>
498
- );
499
- };
@@ -1,41 +0,0 @@
1
- // Components
2
- export { QuestionRenderer } from "./components/question-renderer.js";
3
- export type {
4
- QuestionRendererProps
5
- } from "./components/question-renderer.js";
6
-
7
- // Contexts
8
- export {
9
- QuestionnaireProvider,
10
- useQuestionnaire,
11
- type QuestionnaireContextType,
12
- type QuestionnaireProviderProps,
13
- } from "./contexts/questionnaire-context.js";
14
-
15
- // Types
16
- export type {
17
- Coding,
18
- Extension,
19
- Questionnaire,
20
- QuestionnaireItem,
21
- QuestionnaireItemAnswerOption,
22
- QuestionnaireResponse,
23
- QuestionnaireResponseAnswer,
24
- QuestionnaireResponseItem,
25
- } from "./types/fhir.js";
26
-
27
- export type {
28
- RadioInputProps,
29
- CheckboxInputProps,
30
- } from "./types/index.js";
31
-
32
- // Utils
33
- export {
34
- calculateProgress,
35
- findQuestionnaireItem,
36
- getAllQuestionsFromPage,
37
- getExclusiveOptionCode,
38
- getVisiblePages,
39
- hasAnswerValue,
40
- isQuestionHidden,
41
- } from "./lib/questionnaire-utils.js";