@welshare/questionnaire 0.2.0 → 0.2.1

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 (32) hide show
  1. package/README.md +187 -60
  2. package/dist/esm/components/bmi-form.d.ts.map +1 -1
  3. package/dist/esm/components/media-attachment.d.ts +21 -0
  4. package/dist/esm/components/media-attachment.d.ts.map +1 -0
  5. package/dist/esm/components/media-attachment.js +22 -0
  6. package/dist/esm/components/question-renderer.d.ts.map +1 -1
  7. package/dist/esm/components/question-renderer.js +9 -4
  8. package/dist/esm/components/questions/boolean-question.d.ts +4 -4
  9. package/dist/esm/components/questions/boolean-question.d.ts.map +1 -1
  10. package/dist/esm/components/questions/boolean-question.js +6 -6
  11. package/dist/esm/components/questions/choice-question.d.ts +4 -4
  12. package/dist/esm/components/questions/choice-question.d.ts.map +1 -1
  13. package/dist/esm/components/questions/choice-question.js +19 -11
  14. package/dist/esm/components/questions/multiple-choice-question.d.ts.map +1 -1
  15. package/dist/esm/components/questions/multiple-choice-question.js +19 -11
  16. package/dist/esm/contexts/questionnaire-context.d.ts.map +1 -1
  17. package/dist/esm/contexts/questionnaire-context.js +4 -22
  18. package/dist/esm/index.d.ts +2 -2
  19. package/dist/esm/index.d.ts.map +1 -1
  20. package/dist/esm/index.js +1 -1
  21. package/dist/esm/lib/bmi-helpers.d.ts.map +1 -1
  22. package/dist/esm/lib/constants.d.ts +12 -0
  23. package/dist/esm/lib/constants.d.ts.map +1 -1
  24. package/dist/esm/lib/constants.js +12 -0
  25. package/dist/esm/lib/questionnaire-utils.d.ts +15 -1
  26. package/dist/esm/lib/questionnaire-utils.d.ts.map +1 -1
  27. package/dist/esm/lib/questionnaire-utils.js +26 -0
  28. package/dist/esm/types/fhir.d.ts +25 -5
  29. package/dist/esm/types/fhir.d.ts.map +1 -1
  30. package/dist/esm/types/fhir.js +3 -1
  31. package/dist/esm/types/index.d.ts.map +1 -1
  32. package/package.json +2 -2
package/README.md CHANGED
@@ -11,16 +11,16 @@ npm install @welshare/questionnaire
11
11
  ## Quick Start
12
12
 
13
13
  ```tsx
14
- import { useState, useEffect } from 'react';
14
+ import { useState, useEffect } from "react";
15
15
  import {
16
16
  QuestionnaireProvider,
17
17
  useQuestionnaire,
18
18
  QuestionRenderer,
19
19
  getVisiblePages,
20
20
  type Questionnaire,
21
- } from '@welshare/questionnaire';
22
- import '@welshare/questionnaire/tokens.css';
23
- import '@welshare/questionnaire/styles.css';
21
+ } from "@welshare/questionnaire";
22
+ import "@welshare/questionnaire/tokens.css";
23
+ import "@welshare/questionnaire/styles.css";
24
24
 
25
25
  function QuestionnairePage() {
26
26
  const { questionnaire, isPageValid } = useQuestionnaire();
@@ -45,11 +45,13 @@ function QuestionnairePage() {
45
45
  }
46
46
 
47
47
  function App() {
48
- const [questionnaire, setQuestionnaire] = useState<Questionnaire | null>(null);
48
+ const [questionnaire, setQuestionnaire] = useState<Questionnaire | null>(
49
+ null
50
+ );
49
51
 
50
52
  useEffect(() => {
51
- fetch('/api/questionnaire/your-id')
52
- .then(res => res.json())
53
+ fetch("/api/questionnaire/your-id")
54
+ .then((res) => res.json())
53
55
  .then(setQuestionnaire);
54
56
  }, []);
55
57
 
@@ -68,6 +70,7 @@ function App() {
68
70
  ### QuestionnaireProvider
69
71
 
70
72
  **Props:**
73
+
71
74
  - `questionnaire: Questionnaire` - FHIR Questionnaire object
72
75
  - `questionnaireId?: string` - Optional ID override (defaults to `questionnaire.id`)
73
76
  - `useNestedStructure?: boolean` - Nested or flat response structure (default: `true`)
@@ -76,18 +79,27 @@ function App() {
76
79
 
77
80
  ```tsx
78
81
  const {
79
- questionnaire, response,
80
- updateAnswer, updateMultipleAnswers,
81
- getAnswer, getAnswers,
82
- isPageValid, getRequiredQuestions, getUnansweredRequiredQuestions,
83
- markValidationErrors, clearValidationErrors, hasValidationError,
84
- debugMode, toggleDebugMode,
82
+ questionnaire,
83
+ response,
84
+ updateAnswer,
85
+ updateMultipleAnswers,
86
+ getAnswer,
87
+ getAnswers,
88
+ isPageValid,
89
+ getRequiredQuestions,
90
+ getUnansweredRequiredQuestions,
91
+ markValidationErrors,
92
+ clearValidationErrors,
93
+ hasValidationError,
94
+ debugMode,
95
+ toggleDebugMode,
85
96
  } = useQuestionnaire();
86
97
  ```
87
98
 
88
99
  ### QuestionRenderer
89
100
 
90
101
  **Props:**
102
+
91
103
  - `item: QuestionnaireItem` - Questionnaire item to render
92
104
  - `className?: string` - Container CSS classes
93
105
  - `inputClassName?: string` - Input CSS classes
@@ -102,6 +114,7 @@ const {
102
114
  A controlled component for collecting height, weight, and calculating BMI. The component acts as an input helper that manages BMI calculation internally and reports changes to the parent via callbacks. Unit system (metric/imperial) is managed internally and automatically clears all fields when switched.
103
115
 
104
116
  **Props:**
117
+
105
118
  - `height: number` - Current height value (0 when empty)
106
119
  - `weight: number` - Current weight value (0 when empty)
107
120
  - `bmi: number` - Current BMI value (calculated and set by the component, 0 when not calculated)
@@ -111,6 +124,7 @@ A controlled component for collecting height, weight, and calculating BMI. The c
111
124
  - `className?: string` - Optional CSS classes
112
125
 
113
126
  **Features:**
127
+
114
128
  - Controlled numeric values (height, weight, bmi) managed by parent
115
129
  - BMI calculation handled internally by the component
116
130
  - Unit system managed internally (defaults to metric)
@@ -121,10 +135,10 @@ A controlled component for collecting height, weight, and calculating BMI. The c
121
135
  **Example:**
122
136
 
123
137
  ```tsx
124
- import { useState } from 'react';
125
- import { BmiForm, getBmiCategory } from '@welshare/questionnaire';
126
- import '@welshare/questionnaire/tokens.css';
127
- import '@welshare/questionnaire/styles.css';
138
+ import { useState } from "react";
139
+ import { BmiForm, getBmiCategory } from "@welshare/questionnaire";
140
+ import "@welshare/questionnaire/tokens.css";
141
+ import "@welshare/questionnaire/styles.css";
128
142
 
129
143
  function MyComponent() {
130
144
  const [height, setHeight] = useState(0);
@@ -133,7 +147,7 @@ function MyComponent() {
133
147
 
134
148
  const handleBmiChange = (value: number) => {
135
149
  setBmi(value);
136
-
150
+
137
151
  // Optional: Get BMI category
138
152
  if (value) {
139
153
  const category = getBmiCategory(value);
@@ -157,11 +171,13 @@ function MyComponent() {
157
171
  ### Utilities
158
172
 
159
173
  **Questionnaire Utilities:**
174
+
160
175
  - `getVisiblePages(questionnaire)` - Get visible page groups
161
176
  - `calculateProgress(currentIndex, total)` - Calculate progress percentage
162
177
  - `getAllQuestionsFromPage(pageItem)` - Get all questions from a page
163
178
 
164
179
  **BMI Helper Functions:**
180
+
165
181
  - `calculateBmi(height, weight, unitSystem)` - Calculate BMI from height and weight
166
182
  - `getBmiCategory(bmi)` - Get WHO BMI category (Underweight, Normal weight, Overweight, Obese)
167
183
 
@@ -196,37 +212,139 @@ Override CSS custom properties:
196
212
  ## FHIR Extensions
197
213
 
198
214
  ### Hidden Questions
215
+
216
+ ```json
217
+ {
218
+ "extension": [
219
+ {
220
+ "url": "http://hl7.org/fhir/StructureDefinition/questionnaire-hidden",
221
+ "valueBoolean": true
222
+ }
223
+ ]
224
+ }
225
+ ```
226
+
227
+ ### Media Attachments (Images)
228
+
229
+ Display images or other media content with question items using the FHIR SDC (Structured Data Capture) extensions.
230
+
231
+ **Item Media (images on questions):**
232
+
233
+ ```json
234
+ {
235
+ "linkId": "body-diagram",
236
+ "text": "Where is the pain located?",
237
+ "type": "choice",
238
+ "extension": [
239
+ {
240
+ "url": "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-itemMedia",
241
+ "valueAttachment": {
242
+ "contentType": "image/png",
243
+ "url": "https://example.com/images/body-diagram.png",
244
+ "title": "Body diagram"
245
+ }
246
+ }
247
+ ]
248
+ }
249
+ ```
250
+
251
+ **Answer Option Media (images on answer options):**
252
+
199
253
  ```json
200
254
  {
201
- "extension": [{
202
- "url": "http://hl7.org/fhir/StructureDefinition/questionnaire-hidden",
203
- "valueBoolean": true
204
- }]
255
+ "linkId": "skin-condition",
256
+ "text": "Which image best matches your condition?",
257
+ "type": "choice",
258
+ "answerOption": [
259
+ {
260
+ "valueCoding": {
261
+ "code": "mild",
262
+ "display": "Mild"
263
+ },
264
+ "extension": [
265
+ {
266
+ "url": "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-itemAnswerMedia",
267
+ "valueAttachment": {
268
+ "contentType": "image/jpeg",
269
+ "url": "https://example.com/images/mild.jpg",
270
+ "title": "Mild condition"
271
+ }
272
+ }
273
+ ]
274
+ },
275
+ {
276
+ "valueCoding": {
277
+ "code": "severe",
278
+ "display": "Severe"
279
+ },
280
+ "extension": [
281
+ {
282
+ "url": "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-itemAnswerMedia",
283
+ "valueAttachment": {
284
+ "contentType": "image/jpeg",
285
+ "url": "https://example.com/images/severe.jpg",
286
+ "title": "Severe condition"
287
+ }
288
+ }
289
+ ]
290
+ }
291
+ ]
292
+ }
293
+ ```
294
+
295
+ **CSS Classes for Styling:**
296
+
297
+ - `.wq-question-media` - Container for question-level images
298
+ - `.wq-question-image` - Individual question image
299
+ - `.wq-choice-option-wrapper` - Wrapper around answer option with image
300
+ - `.wq-choice-option-image` - Individual answer option image
301
+
302
+ **Example Styling:**
303
+
304
+ ```css
305
+ .wq-question-image {
306
+ max-width: 100%;
307
+ height: auto;
308
+ margin-bottom: 1rem;
309
+ border-radius: 0.5rem;
310
+ }
311
+
312
+ .wq-choice-option-image {
313
+ max-width: 200px;
314
+ height: auto;
315
+ margin-bottom: 0.5rem;
316
+ border-radius: 0.25rem;
205
317
  }
206
318
  ```
207
319
 
208
320
  ### Slider Controls
321
+
209
322
  ```json
210
323
  {
211
- "extension": [{
212
- "url": "http://codes.welshare.app/StructureDefinition/questionnaire-slider-control",
213
- "extension": [
214
- { "url": "minValue", "valueInteger": 0 },
215
- { "url": "maxValue", "valueInteger": 100 },
216
- { "url": "step", "valueInteger": 1 },
217
- { "url": "unit", "valueString": "minutes" }
218
- ]
219
- }]
324
+ "extension": [
325
+ {
326
+ "url": "http://codes.welshare.app/StructureDefinition/questionnaire-slider-control",
327
+ "extension": [
328
+ { "url": "minValue", "valueInteger": 0 },
329
+ { "url": "maxValue", "valueInteger": 100 },
330
+ { "url": "step", "valueInteger": 1 },
331
+ { "url": "unit", "valueString": "minutes" }
332
+ ]
333
+ }
334
+ ]
220
335
  }
221
336
  ```
222
337
 
223
338
  ### Exclusive Options
339
+
224
340
  ```json
225
341
  {
226
- "extension": [{
227
- "url": "http://codes.welshare.app/StructureDefinition/questionnaire-exclusive-option",
228
- "valueString": "none-of-the-above-code"
229
- }]
342
+ "extension": [
343
+ {
344
+ "url": "http://codes.welshare.app/StructureDefinition/questionnaire-exclusive-option",
345
+ "valueString": "none-of-the-above-code"
346
+ }
347
+ ]
230
348
  }
231
349
  ```
232
350
 
@@ -235,37 +353,51 @@ Override CSS custom properties:
235
353
  Input helpers allow you to provide auxiliary UI (like calculators or lookup dialogs) to assist users in filling out form fields. The library detects the extension and calls your `renderHelperTrigger` function, but you control the dialog/modal implementation.
236
354
 
237
355
  **FHIR Extension:**
356
+
238
357
  ```json
239
358
  {
240
359
  "linkId": "bmi",
241
360
  "text": "Body Mass Index",
242
361
  "type": "decimal",
243
- "extension": [{
244
- "url": "http://codes.welshare.app/StructureDefinition/questionnaire-inputHelper",
245
- "valueCodeableConcept": {
246
- "coding": [{
247
- "system": "http://codes.welshare.app/input-helper-type",
248
- "code": "bmi-calculator",
249
- "display": "BMI Calculator"
250
- }],
251
- "text": "Calculate BMI from height and weight"
362
+ "extension": [
363
+ {
364
+ "url": "http://codes.welshare.app/StructureDefinition/questionnaire-inputHelper",
365
+ "valueCodeableConcept": {
366
+ "coding": [
367
+ {
368
+ "system": "http://codes.welshare.app/input-helper-type",
369
+ "code": "bmi-calculator",
370
+ "display": "BMI Calculator"
371
+ }
372
+ ],
373
+ "text": "Calculate BMI from height and weight"
374
+ }
252
375
  }
253
- }]
376
+ ]
254
377
  }
255
378
  ```
256
379
 
257
380
  **Implementation:**
258
381
 
259
382
  ```tsx
260
- import { useState } from 'react';
261
- import { QuestionRenderer, BmiForm, type HelperTriggerProps } from '@welshare/questionnaire';
383
+ import { useState } from "react";
384
+ import {
385
+ QuestionRenderer,
386
+ BmiForm,
387
+ type HelperTriggerProps,
388
+ } from "@welshare/questionnaire";
262
389
 
263
390
  function MyQuestionnaireRenderer({ item }) {
264
391
  const [showBmiDialog, setShowBmiDialog] = useState(false);
265
- const [helperCallback, setHelperCallback] = useState<((v: string | number) => void) | null>(null);
266
-
267
- const handleHelperTrigger = ({ helper, onValueSelected }: HelperTriggerProps) => {
268
- if (helper.type === 'bmi-calculator') {
392
+ const [helperCallback, setHelperCallback] = useState<
393
+ ((v: string | number) => void) | null
394
+ >(null);
395
+
396
+ const handleHelperTrigger = ({
397
+ helper,
398
+ onValueSelected,
399
+ }: HelperTriggerProps) => {
400
+ if (helper.type === "bmi-calculator") {
269
401
  return (
270
402
  <button
271
403
  type="button"
@@ -274,7 +406,7 @@ function MyQuestionnaireRenderer({ item }) {
274
406
  setShowBmiDialog(true);
275
407
  }}
276
408
  >
277
- {helper.display || 'Calculate'}
409
+ {helper.display || "Calculate"}
278
410
  </button>
279
411
  );
280
412
  }
@@ -283,11 +415,8 @@ function MyQuestionnaireRenderer({ item }) {
283
415
 
284
416
  return (
285
417
  <>
286
- <QuestionRenderer
287
- item={item}
288
- renderHelperTrigger={handleHelperTrigger}
289
- />
290
-
418
+ <QuestionRenderer item={item} renderHelperTrigger={handleHelperTrigger} />
419
+
291
420
  {showBmiDialog && (
292
421
  <Dialog onClose={() => setShowBmiDialog(false)}>
293
422
  <BmiForm
@@ -304,6 +433,7 @@ function MyQuestionnaireRenderer({ item }) {
304
433
  ```
305
434
 
306
435
  **Helper Trigger Props:**
436
+
307
437
  - `helper: InputHelperConfig` - Configuration from the extension
308
438
  - `type: string` - Helper identifier (e.g., "bmi-calculator")
309
439
  - `display?: string` - Display name from the extension
@@ -316,9 +446,6 @@ function MyQuestionnaireRenderer({ item }) {
316
446
 
317
447
  **Note:** The library only renders the trigger element you provide. You are responsible for implementing the dialog/modal UI, as this allows you to use your preferred dialog system (e.g., shadcn/ui, Radix UI, MUI, etc.).
318
448
 
319
-
320
-
321
-
322
449
  ## License
323
450
 
324
451
  MIT © Welshare UG (haftungsbeschränkt)
@@ -1 +1 @@
1
- {"version":3,"file":"bmi-form.d.ts","sourceRoot":"","sources":["../../../src/components/bmi-form.tsx"],"names":[],"mappings":"AASA;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,4BAA4B;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,0BAA0B;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,6BAA6B;IAC7B,GAAG,EAAE,MAAM,CAAC;CACb;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,4BAA4B;IAC5B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,0BAA0B;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,YAAY;IAC3B;;;;OAIG;IACH,aAAa,CAAC,EAAE,gBAAgB,CAAC;IAEjC;;;;OAIG;IACH,cAAc,CAAC,EAAE,QAAQ,GAAG,UAAU,CAAC;IAEvC;;;OAGG;IACH,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,mBAAmB,KAAK,IAAI,CAAC;IAEjD;;;;OAIG;IACH,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,mBAAmB,KAAK,IAAI,CAAC;IAEjD;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,OAAO,GAAI,mEAMrB,YAAY,4CAmSd,CAAC"}
1
+ {"version":3,"file":"bmi-form.d.ts","sourceRoot":"","sources":["../../../src/components/bmi-form.tsx"],"names":[],"mappings":"AASA;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,4BAA4B;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,0BAA0B;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,6BAA6B;IAC7B,GAAG,EAAE,MAAM,CAAC;CACb;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,4BAA4B;IAC5B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,0BAA0B;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,YAAY;IAC3B;;;;OAIG;IACH,aAAa,CAAC,EAAE,gBAAgB,CAAC;IAEjC;;;;OAIG;IACH,cAAc,CAAC,EAAE,QAAQ,GAAG,UAAU,CAAC;IAEvC;;;OAGG;IACH,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,mBAAmB,KAAK,IAAI,CAAC;IAEjD;;;;OAIG;IACH,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,mBAAmB,KAAK,IAAI,CAAC;IAEjD;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,OAAO,GAAI,mEAMrB,YAAY,4CA8Sd,CAAC"}
@@ -0,0 +1,21 @@
1
+ import type { Attachment } from "../types/fhir.js";
2
+ export interface MediaAttachmentProps {
3
+ attachment: Attachment;
4
+ alt: string;
5
+ className?: string;
6
+ }
7
+ /**
8
+ * Renders a single media attachment (image) if it has a URL and is an image type
9
+ */
10
+ export declare const MediaAttachment: ({ attachment, alt, className, }: MediaAttachmentProps) => import("react/jsx-runtime").JSX.Element | null;
11
+ export interface MediaAttachmentsProps {
12
+ attachments: Attachment[];
13
+ baseAlt?: string;
14
+ className?: string;
15
+ containerClassName?: string;
16
+ }
17
+ /**
18
+ * Renders multiple media attachments in a container
19
+ */
20
+ export declare const MediaAttachments: ({ attachments, baseAlt, className, containerClassName, }: MediaAttachmentsProps) => import("react/jsx-runtime").JSX.Element | null;
21
+ //# sourceMappingURL=media-attachment.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"media-attachment.d.ts","sourceRoot":"","sources":["../../../src/components/media-attachment.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEnD,MAAM,WAAW,oBAAoB;IACnC,UAAU,EAAE,UAAU,CAAC;IACvB,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,eAAO,MAAM,eAAe,GAAI,iCAI7B,oBAAoB,mDAkBtB,CAAC;AAEF,MAAM,WAAW,qBAAqB;IACpC,WAAW,EAAE,UAAU,EAAE,CAAC;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED;;GAEG;AACH,eAAO,MAAM,gBAAgB,GAAI,0DAK9B,qBAAqB,mDAevB,CAAC"}
@@ -0,0 +1,22 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ /**
3
+ * Renders a single media attachment (image) if it has a URL and is an image type
4
+ */
5
+ export const MediaAttachment = ({ attachment, alt, className = "", }) => {
6
+ // Only render if URL exists
7
+ if (!attachment.url)
8
+ return null;
9
+ // Check if it's an image (or assume image if no contentType)
10
+ const isImage = !attachment.contentType || attachment.contentType.startsWith("image/");
11
+ if (!isImage)
12
+ return null;
13
+ return (_jsx("img", { src: attachment.url, alt: alt, className: className, title: attachment.title }));
14
+ };
15
+ /**
16
+ * Renders multiple media attachments in a container
17
+ */
18
+ export const MediaAttachments = ({ attachments, baseAlt = "Image", className = "", containerClassName = "", }) => {
19
+ if (attachments.length === 0)
20
+ return null;
21
+ return (_jsx("div", { className: containerClassName, children: attachments.map((attachment, index) => (_jsx(MediaAttachment, { attachment: attachment, alt: attachment.title || `${baseAlt} ${index + 1}`, className: className }, index))) }));
22
+ };
@@ -1 +1 @@
1
- {"version":3,"file":"question-renderer.d.ts","sourceRoot":"","sources":["../../../src/components/question-renderer.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAU1D,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAE5F,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,iBAAiB,CAAC;IACxB;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;OAGG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,gBAAgB,CAAC,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,SAAS,CAAC;IACzD;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,mBAAmB,CAAC,EAAE,CAAC,KAAK,EAAE,kBAAkB,KAAK,SAAS,CAAC;IAC/D;;;OAGG;IACH,mBAAmB,CAAC,EAAE,CAAC,KAAK,EAAE,kBAAkB,KAAK,SAAS,CAAC;CAChE;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,gBAAgB,GAAI,eAAe,qBAAqB,4CAyBpE,CAAC"}
1
+ {"version":3,"file":"question-renderer.d.ts","sourceRoot":"","sources":["../../../src/components/question-renderer.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAkB1D,OAAO,EACL,eAAe,EACf,kBAAkB,EAClB,kBAAkB,EACnB,MAAM,mBAAmB,CAAC;AAE3B,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,iBAAiB,CAAC;IACxB;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;OAGG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,gBAAgB,CAAC,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,SAAS,CAAC;IACzD;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,mBAAmB,CAAC,EAAE,CAAC,KAAK,EAAE,kBAAkB,KAAK,SAAS,CAAC;IAC/D;;;OAGG;IACH,mBAAmB,CAAC,EAAE,CAAC,KAAK,EAAE,kBAAkB,KAAK,SAAS,CAAC;CAChE;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,gBAAgB,GAAI,eAAe,qBAAqB,4CAyBpE,CAAC"}
@@ -1,12 +1,13 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useQuestionnaire } from "../contexts/questionnaire-context.js";
3
- import { isQuestionEnabled } from "../lib/questionnaire-utils.js";
4
- import { FHIR_EXTENSIONS, WELSHARE_EXTENSIONS, FHIR_CODE_SYSTEMS } from "../lib/constants.js";
3
+ import { isQuestionEnabled, getItemMedia } from "../lib/questionnaire-utils.js";
4
+ import { FHIR_EXTENSIONS, WELSHARE_EXTENSIONS, FHIR_CODE_SYSTEMS, } from "../lib/constants.js";
5
5
  import { DebugSection } from "./debug-section.js";
6
+ import { MediaAttachments } from "./media-attachment.js";
6
7
  import { ChoiceQuestion } from "./questions/choice-question.js";
7
8
  import { MultipleChoiceQuestion } from "./questions/multiple-choice-question.js";
8
9
  import { IntegerQuestion } from "./questions/integer-question.js";
9
- import { DecimalQuestion, getDecimalHelperTriggerProps } from "./questions/decimal-question.js";
10
+ import { DecimalQuestion, getDecimalHelperTriggerProps, } from "./questions/decimal-question.js";
10
11
  import { StringQuestion } from "./questions/string-question.js";
11
12
  import { BooleanQuestion } from "./questions/boolean-question.js";
12
13
  /**
@@ -166,7 +167,9 @@ const QuestionRendererInternal = ({ item, className = "", inputClassName = "", c
166
167
  const sliderConfig = getSliderConfig();
167
168
  const renderQuestion = () => {
168
169
  switch (item.type) {
170
+ // FHIR R4 uses 'choice', R5 uses 'coding' - both render the same way
169
171
  case "choice":
172
+ case "coding":
170
173
  // Multi-select with checkboxes when repeats is true
171
174
  if (item.repeats) {
172
175
  return (_jsx(MultipleChoiceQuestion, { item: item, currentAnswers: currentAnswers, onMultipleChoiceToggle: handleMultipleChoiceToggle, choiceClassName: choiceClassName, renderCheckboxInput: renderCheckboxInput }));
@@ -190,5 +193,7 @@ const QuestionRendererInternal = ({ item, className = "", inputClassName = "", c
190
193
  const helperTriggerProps = item.type === "decimal"
191
194
  ? getDecimalHelperTriggerProps(item, currentAnswer, handleDecimalChange)
192
195
  : null;
193
- return (_jsxs("div", { className: `wq-question-container ${hasError ? "wq-has-error" : ""} ${className}`, children: [_jsxs("div", { className: "wq-question-label-row", children: [_jsxs("div", { className: "wq-question-text", children: [item.text, item.required && _jsx("span", { className: "wq-required-indicator", children: "*" })] }), helperTriggerProps && renderHelperTrigger && (_jsx("div", { className: "wq-question-helper-trigger", children: renderHelperTrigger(helperTriggerProps) }))] }), renderQuestion()] }));
196
+ // Get media attachments for this question
197
+ const mediaAttachments = getItemMedia(item);
198
+ return (_jsxs("div", { className: `wq-question-container ${hasError ? "wq-has-error" : ""} ${className}`, children: [_jsx(MediaAttachments, { attachments: mediaAttachments, baseAlt: "Question image", className: "wq-question-image", containerClassName: "wq-question-media" }), _jsxs("div", { className: "wq-question-label-row", children: [_jsxs("div", { className: "wq-question-text", children: [item.text, item.required && _jsx("span", { className: "wq-required-indicator", children: "*" })] }), helperTriggerProps && renderHelperTrigger && (_jsx("div", { className: "wq-question-helper-trigger", children: renderHelperTrigger(helperTriggerProps) }))] }), renderQuestion()] }));
194
199
  };
@@ -1,6 +1,6 @@
1
- import { type ReactNode } from 'react';
2
- import type { QuestionnaireItem, QuestionnaireResponseAnswer } from '../../types/fhir.js';
3
- import { RadioInputProps } from '@/types/index.js';
1
+ import { type ReactNode } from "react";
2
+ import type { QuestionnaireItem, QuestionnaireResponseAnswer } from "../../types/fhir.js";
3
+ import { RadioInputProps } from "@/types/index.js";
4
4
  export interface BooleanQuestionProps {
5
5
  item: QuestionnaireItem;
6
6
  currentAnswer?: QuestionnaireResponseAnswer;
@@ -11,5 +11,5 @@ export interface BooleanQuestionProps {
11
11
  /**
12
12
  * Renders a boolean question with Yes/No radio buttons
13
13
  */
14
- export declare const BooleanQuestion: ({ item, currentAnswer, onBooleanChange, choiceClassName, renderRadioInput }: BooleanQuestionProps) => import("react/jsx-runtime").JSX.Element;
14
+ export declare const BooleanQuestion: ({ item, currentAnswer, onBooleanChange, choiceClassName, renderRadioInput, }: BooleanQuestionProps) => import("react/jsx-runtime").JSX.Element;
15
15
  //# sourceMappingURL=boolean-question.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"boolean-question.d.ts","sourceRoot":"","sources":["../../../../src/components/questions/boolean-question.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,EAAE,iBAAiB,EAAE,2BAA2B,EAAE,MAAM,qBAAqB,CAAC;AAC1F,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAGnD,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,iBAAiB,CAAC;IACxB,aAAa,CAAC,EAAE,2BAA2B,CAAC;IAC5C,eAAe,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IAC1C,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,gBAAgB,CAAC,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,SAAS,CAAC;CAC1D;AAED;;GAEG;AACH,eAAO,MAAM,eAAe,GAAI,6EAM7B,oBAAoB,4CAgDtB,CAAC"}
1
+ {"version":3,"file":"boolean-question.d.ts","sourceRoot":"","sources":["../../../../src/components/questions/boolean-question.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,EACV,iBAAiB,EACjB,2BAA2B,EAC5B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAEnD,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,iBAAiB,CAAC;IACxB,aAAa,CAAC,EAAE,2BAA2B,CAAC;IAC5C,eAAe,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IAC1C,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,gBAAgB,CAAC,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,SAAS,CAAC;CAC1D;AAED;;GAEG;AACH,eAAO,MAAM,eAAe,GAAI,8EAM7B,oBAAoB,4CAoDtB,CAAC"}
@@ -2,18 +2,18 @@ import { Fragment as _Fragment, jsxs as _jsxs, jsx as _jsx } from "react/jsx-run
2
2
  /**
3
3
  * Renders a boolean question with Yes/No radio buttons
4
4
  */
5
- export const BooleanQuestion = ({ item, currentAnswer, onBooleanChange, choiceClassName = '', renderRadioInput }) => {
5
+ export const BooleanQuestion = ({ item, currentAnswer, onBooleanChange, choiceClassName = "", renderRadioInput, }) => {
6
6
  return (_jsx("div", { className: `wq-question-choice ${choiceClassName}`, children: renderRadioInput ? (_jsxs(_Fragment, { children: [renderRadioInput({
7
7
  linkId: item.linkId,
8
8
  checked: currentAnswer?.valueBoolean === true,
9
9
  onChange: () => onBooleanChange(true),
10
- label: 'Yes',
11
- index: 0
10
+ label: "Yes",
11
+ index: 0,
12
12
  }), renderRadioInput({
13
13
  linkId: item.linkId,
14
14
  checked: currentAnswer?.valueBoolean === false,
15
15
  onChange: () => onBooleanChange(false),
16
- label: 'No',
17
- index: 1
18
- })] })) : (_jsxs(_Fragment, { children: [_jsxs("label", { className: `wq-choice-option ${currentAnswer?.valueBoolean === true ? 'wq-selected' : ''}`, children: [_jsx("input", { type: "radio", name: item.linkId, checked: currentAnswer?.valueBoolean === true, onChange: () => onBooleanChange(true), "data-wq-input": "radio", "data-wq-selected": currentAnswer?.valueBoolean === true }), _jsx("span", { className: "wq-choice-label", children: "Yes" })] }), _jsxs("label", { className: `wq-choice-option ${currentAnswer?.valueBoolean === false ? 'wq-selected' : ''}`, children: [_jsx("input", { type: "radio", name: item.linkId, checked: currentAnswer?.valueBoolean === false, onChange: () => onBooleanChange(false), "data-wq-input": "radio", "data-wq-selected": currentAnswer?.valueBoolean === false }), _jsx("span", { className: "wq-choice-label", children: "No" })] })] })) }));
16
+ label: "No",
17
+ index: 1,
18
+ })] })) : (_jsxs(_Fragment, { children: [_jsxs("label", { className: `wq-choice-option ${currentAnswer?.valueBoolean === true ? "wq-selected" : ""}`, children: [_jsx("input", { type: "radio", name: item.linkId, checked: currentAnswer?.valueBoolean === true, onChange: () => onBooleanChange(true), "data-wq-input": "radio", "data-wq-selected": currentAnswer?.valueBoolean === true }), _jsx("span", { className: "wq-choice-label", children: "Yes" })] }), _jsxs("label", { className: `wq-choice-option ${currentAnswer?.valueBoolean === false ? "wq-selected" : ""}`, children: [_jsx("input", { type: "radio", name: item.linkId, checked: currentAnswer?.valueBoolean === false, onChange: () => onBooleanChange(false), "data-wq-input": "radio", "data-wq-selected": currentAnswer?.valueBoolean === false }), _jsx("span", { className: "wq-choice-label", children: "No" })] })] })) }));
19
19
  };
@@ -1,6 +1,6 @@
1
- import { type ReactNode } from 'react';
2
- import type { QuestionnaireItem, QuestionnaireResponseAnswer } from '../../types/fhir.js';
3
- import { RadioInputProps } from '@/types/index.js';
1
+ import { type ReactNode } from "react";
2
+ import type { QuestionnaireItem, QuestionnaireResponseAnswer } from "../../types/fhir.js";
3
+ import { RadioInputProps } from "@/types/index.js";
4
4
  export interface ChoiceQuestionProps {
5
5
  item: QuestionnaireItem;
6
6
  currentAnswer?: QuestionnaireResponseAnswer;
@@ -15,5 +15,5 @@ export interface ChoiceQuestionProps {
15
15
  /**
16
16
  * Renders a single-select choice question with radio buttons
17
17
  */
18
- export declare const ChoiceQuestion: ({ item, currentAnswer, onChoiceChange, choiceClassName, renderRadioInput }: ChoiceQuestionProps) => import("react/jsx-runtime").JSX.Element;
18
+ export declare const ChoiceQuestion: ({ item, currentAnswer, onChoiceChange, choiceClassName, renderRadioInput, }: ChoiceQuestionProps) => import("react/jsx-runtime").JSX.Element;
19
19
  //# sourceMappingURL=choice-question.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"choice-question.d.ts","sourceRoot":"","sources":["../../../../src/components/questions/choice-question.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,EAAE,iBAAiB,EAAE,2BAA2B,EAAE,MAAM,qBAAqB,CAAC;AAC1F,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAGnD,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,iBAAiB,CAAC;IACxB,aAAa,CAAC,EAAE,2BAA2B,CAAC;IAC5C,cAAc,EAAE,CACd,WAAW,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,EACjE,YAAY,CAAC,EAAE,MAAM,KAClB,IAAI,CAAC;IACV,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,gBAAgB,CAAC,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,SAAS,CAAC;CAC1D;AAED;;GAEG;AACH,eAAO,MAAM,cAAc,GAAI,4EAM5B,mBAAmB,4CAyCrB,CAAC"}
1
+ {"version":3,"file":"choice-question.d.ts","sourceRoot":"","sources":["../../../../src/components/questions/choice-question.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,EACV,iBAAiB,EACjB,2BAA2B,EAC5B,MAAM,qBAAqB,CAAC;AAG7B,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAEnD,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,iBAAiB,CAAC;IACxB,aAAa,CAAC,EAAE,2BAA2B,CAAC;IAC5C,cAAc,EAAE,CACd,WAAW,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,EACjE,YAAY,CAAC,EAAE,MAAM,KAClB,IAAI,CAAC;IACV,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,gBAAgB,CAAC,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,SAAS,CAAC;CAC1D;AAED;;GAEG;AACH,eAAO,MAAM,cAAc,GAAI,6EAM5B,mBAAmB,4CA4ErB,CAAC"}
@@ -1,23 +1,31 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { getAnswerOptionMedia } from "../../lib/questionnaire-utils.js";
3
+ import { MediaAttachment } from "../media-attachment.js";
2
4
  /**
3
5
  * Renders a single-select choice question with radio buttons
4
6
  */
5
- export const ChoiceQuestion = ({ item, currentAnswer, onChoiceChange, choiceClassName = '', renderRadioInput }) => {
7
+ export const ChoiceQuestion = ({ item, currentAnswer, onChoiceChange, choiceClassName = "", renderRadioInput, }) => {
6
8
  return (_jsx("div", { className: `wq-question-choice ${choiceClassName}`, children: item.answerOption?.map((option, index) => {
7
9
  const isSelected = currentAnswer?.valueCoding?.code === option.valueCoding?.code;
10
+ // Get media attachment for this answer option
11
+ const mediaAttachment = getAnswerOptionMedia(option);
8
12
  // Use custom renderer if provided
9
13
  if (renderRadioInput) {
10
- return (_jsx("div", { children: renderRadioInput({
11
- linkId: item.linkId,
12
- valueCoding: option.valueCoding,
13
- valueInteger: option.valueInteger,
14
- checked: isSelected,
15
- onChange: () => onChoiceChange(option.valueCoding || {}, option.valueInteger),
16
- label: option.valueCoding?.display || '',
17
- index
18
- }) }, index));
14
+ return (_jsxs("div", { className: "wq-choice-option-wrapper", children: [mediaAttachment && (_jsx(MediaAttachment, { attachment: mediaAttachment, alt: mediaAttachment.title ||
15
+ option.valueCoding?.display ||
16
+ `Option ${index + 1}`, className: "wq-choice-option-image" })), renderRadioInput({
17
+ linkId: item.linkId,
18
+ valueCoding: option.valueCoding,
19
+ valueInteger: option.valueInteger,
20
+ checked: isSelected,
21
+ onChange: () => onChoiceChange(option.valueCoding || {}, option.valueInteger),
22
+ label: option.valueCoding?.display || "",
23
+ index,
24
+ })] }, index));
19
25
  }
20
26
  // Default rendering
21
- return (_jsxs("label", { className: `wq-choice-option ${isSelected ? 'wq-selected' : ''}`, children: [_jsx("input", { type: "radio", name: item.linkId, value: option.valueCoding?.code, checked: isSelected, onChange: () => onChoiceChange(option.valueCoding || {}, option.valueInteger), "data-wq-input": "radio", "data-wq-selected": isSelected }), _jsx("span", { className: "wq-choice-label", children: option.valueCoding?.display })] }, index));
27
+ return (_jsxs("div", { className: "wq-choice-option-wrapper", children: [mediaAttachment && (_jsx(MediaAttachment, { attachment: mediaAttachment, alt: mediaAttachment.title ||
28
+ option.valueCoding?.display ||
29
+ `Option ${index + 1}`, className: "wq-choice-option-image" })), _jsxs("label", { className: `wq-choice-option ${isSelected ? "wq-selected" : ""}`, children: [_jsx("input", { type: "radio", name: item.linkId, value: option.valueCoding?.code, checked: isSelected, onChange: () => onChoiceChange(option.valueCoding || {}, option.valueInteger), "data-wq-input": "radio", "data-wq-selected": isSelected }), _jsx("span", { className: "wq-choice-label", children: option.valueCoding?.display })] })] }, index));
22
30
  }) }));
23
31
  };
@@ -1 +1 @@
1
- {"version":3,"file":"multiple-choice-question.d.ts","sourceRoot":"","sources":["../../../../src/components/questions/multiple-choice-question.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,EACV,iBAAiB,EACjB,2BAA2B,EAC5B,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAE1D,MAAM,WAAW,2BAA2B;IAC1C,IAAI,EAAE,iBAAiB,CAAC;IACxB,cAAc,EAAE,2BAA2B,EAAE,CAAC;IAC9C,sBAAsB,EAAE,CACtB,WAAW,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,EACjE,YAAY,CAAC,EAAE,MAAM,KAClB,IAAI,CAAC;IACV,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,mBAAmB,CAAC,EAAE,CAAC,KAAK,EAAE,kBAAkB,KAAK,SAAS,CAAC;CAChE;AAED;;;GAGG;AACH,eAAO,MAAM,sBAAsB,GAAI,yFAMpC,2BAA2B,4CAwF7B,CAAC"}
1
+ {"version":3,"file":"multiple-choice-question.d.ts","sourceRoot":"","sources":["../../../../src/components/questions/multiple-choice-question.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,EACV,iBAAiB,EACjB,2BAA2B,EAC5B,MAAM,qBAAqB,CAAC;AAI7B,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAE1D,MAAM,WAAW,2BAA2B;IAC1C,IAAI,EAAE,iBAAiB,CAAC;IACxB,cAAc,EAAE,2BAA2B,EAAE,CAAC;IAC9C,sBAAsB,EAAE,CACtB,WAAW,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,EACjE,YAAY,CAAC,EAAE,MAAM,KAClB,IAAI,CAAC;IACV,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,mBAAmB,CAAC,EAAE,CAAC,KAAK,EAAE,kBAAkB,KAAK,SAAS,CAAC;CAChE;AAED;;;GAGG;AACH,eAAO,MAAM,sBAAsB,GAAI,yFAMpC,2BAA2B,4CAkH7B,CAAC"}
@@ -1,5 +1,7 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { WELSHARE_EXTENSIONS } from "../../lib/constants.js";
3
+ import { getAnswerOptionMedia } from "../../lib/questionnaire-utils.js";
4
+ import { MediaAttachment } from "../media-attachment.js";
3
5
  /**
4
6
  * Renders a multi-select choice question with checkboxes
5
7
  * Supports exclusive options and maxAnswers limits
@@ -20,20 +22,26 @@ export const MultipleChoiceQuestion = ({ item, currentAnswers, onMultipleChoiceT
20
22
  return (_jsxs("div", { className: `wq-question-choice ${choiceClassName}`, children: [optionsToShow?.map((option, index) => {
21
23
  const isSelected = currentAnswers.some((answer) => answer.valueCoding?.code === option.valueCoding?.code);
22
24
  const isDisabled = !isSelected && atMaxAnswers;
25
+ // Get media attachment for this answer option
26
+ const mediaAttachment = getAnswerOptionMedia(option);
23
27
  // Use custom renderer if provided
24
28
  if (renderCheckboxInput) {
25
- return (_jsx("div", { children: renderCheckboxInput({
26
- linkId: item.linkId,
27
- valueCoding: option.valueCoding,
28
- valueInteger: option.valueInteger,
29
- checked: isSelected,
30
- disabled: isDisabled,
31
- onChange: () => onMultipleChoiceToggle(option.valueCoding || {}, option.valueInteger),
32
- label: option.valueCoding?.display || "",
33
- index,
34
- }) }, index));
29
+ return (_jsxs("div", { className: "wq-choice-option-wrapper", children: [mediaAttachment && (_jsx(MediaAttachment, { attachment: mediaAttachment, alt: mediaAttachment.title ||
30
+ option.valueCoding?.display ||
31
+ `Option ${index + 1}`, className: "wq-choice-option-image" })), renderCheckboxInput({
32
+ linkId: item.linkId,
33
+ valueCoding: option.valueCoding,
34
+ valueInteger: option.valueInteger,
35
+ checked: isSelected,
36
+ disabled: isDisabled,
37
+ onChange: () => onMultipleChoiceToggle(option.valueCoding || {}, option.valueInteger),
38
+ label: option.valueCoding?.display || "",
39
+ index,
40
+ })] }, index));
35
41
  }
36
42
  // Default rendering
37
- return (_jsxs("label", { className: `wq-choice-option ${isSelected ? "wq-selected" : ""} ${isDisabled ? "wq-disabled" : ""}`, children: [_jsx("input", { type: "checkbox", name: item.linkId, value: option.valueCoding?.code, checked: isSelected, disabled: isDisabled, onChange: () => onMultipleChoiceToggle(option.valueCoding || {}, option.valueInteger), "data-wq-input": "checkbox", "data-wq-selected": isSelected }), _jsx("span", { className: "wq-choice-label", children: option.valueCoding?.display })] }, index));
43
+ return (_jsxs("div", { className: "wq-choice-option-wrapper", children: [mediaAttachment && (_jsx(MediaAttachment, { attachment: mediaAttachment, alt: mediaAttachment.title ||
44
+ option.valueCoding?.display ||
45
+ `Option ${index + 1}`, className: "wq-choice-option-image" })), _jsxs("label", { className: `wq-choice-option ${isSelected ? "wq-selected" : ""} ${isDisabled ? "wq-disabled" : ""}`, children: [_jsx("input", { type: "checkbox", name: item.linkId, value: option.valueCoding?.code, checked: isSelected, disabled: isDisabled, onChange: () => onMultipleChoiceToggle(option.valueCoding || {}, option.valueInteger), "data-wq-input": "checkbox", "data-wq-selected": isSelected }), _jsx("span", { className: "wq-choice-label", children: option.valueCoding?.display })] })] }, index));
38
46
  }), item.maxAnswers && (_jsxs("div", { className: "wq-max-answers-hint", children: ["Selected: ", currentAnswers.length, " / ", item.maxAnswers] }))] }));
39
47
  };
@@ -1 +1 @@
1
- {"version":3,"file":"questionnaire-context.d.ts","sourceRoot":"","sources":["../../../src/contexts/questionnaire-context.tsx"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AACf,OAAO,KAAK,EACV,aAAa,EACb,iBAAiB,EACjB,qBAAqB,EACrB,2BAA2B,EAE5B,MAAM,kBAAkB,CAAC;AAM1B,MAAM,WAAW,wBAAwB;IACvC,aAAa,EAAE,aAAa,CAAC;IAC7B,QAAQ,EAAE,qBAAqB,CAAC;IAChC,YAAY,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,2BAA2B,KAAK,IAAI,CAAC;IAC5E,qBAAqB,EAAE,CACrB,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,2BAA2B,EAAE,KACnC,IAAI,CAAC;IACV,SAAS,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,2BAA2B,GAAG,SAAS,CAAC;IACvE,UAAU,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,2BAA2B,EAAE,CAAC;IAC9D,WAAW,EAAE,CAAC,SAAS,EAAE,iBAAiB,EAAE,KAAK,OAAO,CAAC;IACzD,oBAAoB,EAAE,CAAC,SAAS,EAAE,iBAAiB,EAAE,KAAK,iBAAiB,EAAE,CAAC;IAC9E,8BAA8B,EAAE,CAC9B,SAAS,EAAE,iBAAiB,EAAE,KAC3B,iBAAiB,EAAE,CAAC;IACzB,oBAAoB,EAAE,CAAC,SAAS,EAAE,iBAAiB,EAAE,KAAK,IAAI,CAAC;IAC/D,qBAAqB,EAAE,MAAM,IAAI,CAAC;IAClC,kBAAkB,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC;IAChD,SAAS,EAAE,OAAO,CAAC;IACnB,eAAe,EAAE,MAAM,IAAI,CAAC;CAC7B;AAMD,eAAO,MAAM,gBAAgB,gCAQ5B,CAAC;AAEF,MAAM,WAAW,0BAA0B;IACzC,QAAQ,EAAE,SAAS,CAAC;IACpB;;;OAGG;IACH,aAAa,EAAE,aAAa,CAAC;IAC7B;;;;OAIG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;;;OAIG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAED,eAAO,MAAM,qBAAqB,GAAI,mEAKnC,0BAA0B,4CAya5B,CAAC"}
1
+ {"version":3,"file":"questionnaire-context.d.ts","sourceRoot":"","sources":["../../../src/contexts/questionnaire-context.tsx"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AACf,OAAO,KAAK,EACV,aAAa,EACb,iBAAiB,EACjB,qBAAqB,EACrB,2BAA2B,EAE5B,MAAM,kBAAkB,CAAC;AAM1B,MAAM,WAAW,wBAAwB;IACvC,aAAa,EAAE,aAAa,CAAC;IAC7B,QAAQ,EAAE,qBAAqB,CAAC;IAChC,YAAY,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,2BAA2B,KAAK,IAAI,CAAC;IAC5E,qBAAqB,EAAE,CACrB,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,2BAA2B,EAAE,KACnC,IAAI,CAAC;IACV,SAAS,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,2BAA2B,GAAG,SAAS,CAAC;IACvE,UAAU,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,2BAA2B,EAAE,CAAC;IAC9D,WAAW,EAAE,CAAC,SAAS,EAAE,iBAAiB,EAAE,KAAK,OAAO,CAAC;IACzD,oBAAoB,EAAE,CAAC,SAAS,EAAE,iBAAiB,EAAE,KAAK,iBAAiB,EAAE,CAAC;IAC9E,8BAA8B,EAAE,CAC9B,SAAS,EAAE,iBAAiB,EAAE,KAC3B,iBAAiB,EAAE,CAAC;IACzB,oBAAoB,EAAE,CAAC,SAAS,EAAE,iBAAiB,EAAE,KAAK,IAAI,CAAC;IAC/D,qBAAqB,EAAE,MAAM,IAAI,CAAC;IAClC,kBAAkB,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC;IAChD,SAAS,EAAE,OAAO,CAAC;IACnB,eAAe,EAAE,MAAM,IAAI,CAAC;CAC7B;AAMD,eAAO,MAAM,gBAAgB,gCAQ5B,CAAC;AAEF,MAAM,WAAW,0BAA0B;IACzC,QAAQ,EAAE,SAAS,CAAC;IACpB;;;OAGG;IACH,aAAa,EAAE,aAAa,CAAC;IAC7B;;;;OAIG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;;;OAIG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAED,eAAO,MAAM,qBAAqB,GAAI,mEAKnC,0BAA0B,4CAuZ5B,CAAC"}
@@ -91,10 +91,7 @@ export const QuestionnaireProvider = ({ children, questionnaire, questionnaireId
91
91
  }
92
92
  // If this item has nested items, search within them
93
93
  if (item.item && item.item.length > 0) {
94
- return {
95
- ...item,
96
- item: updateNestedItem(item.item),
97
- };
94
+ return { ...item, item: updateNestedItem(item.item) };
98
95
  }
99
96
  return item;
100
97
  });
@@ -122,13 +119,7 @@ export const QuestionnaireProvider = ({ children, questionnaire, questionnaireId
122
119
  }
123
120
  else {
124
121
  // Create new item
125
- return [
126
- ...items,
127
- {
128
- linkId,
129
- answer: [answer],
130
- },
131
- ];
122
+ return [...items, { linkId, answer: [answer] }];
132
123
  }
133
124
  };
134
125
  newResponse.item = findOrCreateItem(newResponse.item);
@@ -161,10 +152,7 @@ export const QuestionnaireProvider = ({ children, questionnaire, questionnaireId
161
152
  }
162
153
  // If this item has nested items, search within them
163
154
  if (item.item && item.item.length > 0) {
164
- return {
165
- ...item,
166
- item: updateNestedItem(item.item),
167
- };
155
+ return { ...item, item: updateNestedItem(item.item) };
168
156
  }
169
157
  return item;
170
158
  });
@@ -190,13 +178,7 @@ export const QuestionnaireProvider = ({ children, questionnaire, questionnaireId
190
178
  return updated;
191
179
  }
192
180
  else {
193
- return [
194
- ...items,
195
- {
196
- linkId,
197
- answer: answers,
198
- },
199
- ];
181
+ return [...items, { linkId, answer: answers }];
200
182
  }
201
183
  };
202
184
  newResponse.item = findOrCreateItem(newResponse.item);
@@ -3,9 +3,9 @@ export type { QuestionRendererProps } from "./components/question-renderer.js";
3
3
  export { BmiForm } from "./components/bmi-form.js";
4
4
  export type { BmiFormProps } from "./components/bmi-form.js";
5
5
  export { QuestionnaireProvider, useQuestionnaire, type QuestionnaireContextType, type QuestionnaireProviderProps, } from "./contexts/questionnaire-context.js";
6
- export type { Coding, Extension, Questionnaire, QuestionnaireItem, QuestionnaireItemAnswerOption, QuestionnaireResponse, QuestionnaireResponseAnswer, QuestionnaireResponseItem, } from "./types/fhir.js";
6
+ export type { Attachment, Coding, Extension, Questionnaire, QuestionnaireItem, QuestionnaireItemAnswerOption, QuestionnaireResponse, QuestionnaireResponseAnswer, QuestionnaireResponseItem, } from "./types/fhir.js";
7
7
  export type { RadioInputProps, CheckboxInputProps, InputHelperConfig, HelperTriggerProps, } from "./types/index.js";
8
- export { calculateProgress, findQuestionnaireItem, getAllQuestionsFromPage, getExclusiveOptionCode, getInputHelper, getVisiblePages, hasAnswerValue, isQuestionHidden, } from "./lib/questionnaire-utils.js";
8
+ export { calculateProgress, findQuestionnaireItem, getAllQuestionsFromPage, getAnswerOptionMedia, getExclusiveOptionCode, getInputHelper, getItemMedia, getVisiblePages, hasAnswerValue, isQuestionHidden, } from "./lib/questionnaire-utils.js";
9
9
  export { calculateBmi } from "./lib/bmi-helpers.js";
10
10
  export { FHIR_EXTENSIONS, WELSHARE_EXTENSIONS, WELSHARE_CODE_SYSTEMS, FHIR_CODE_SYSTEMS, } from "./lib/constants.js";
11
11
  //# 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;AAE3C,OAAO,EAAE,OAAO,EAAE,MAAM,0BAA0B,CAAC;AACnD,YAAY,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAG7D,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,EAClB,iBAAiB,EACjB,kBAAkB,GACnB,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EACL,iBAAiB,EACjB,qBAAqB,EACrB,uBAAuB,EACvB,sBAAsB,EACtB,cAAc,EACd,eAAe,EACf,cAAc,EACd,gBAAgB,GACjB,MAAM,8BAA8B,CAAC;AAEtC,OAAO,EACL,YAAY,EACb,MAAM,sBAAsB,CAAC;AAG9B,OAAO,EACL,eAAe,EACf,mBAAmB,EACnB,qBAAqB,EACrB,iBAAiB,GAClB,MAAM,oBAAoB,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,EAAE,qBAAqB,EAAE,MAAM,mCAAmC,CAAC;AAE/E,OAAO,EAAE,OAAO,EAAE,MAAM,0BAA0B,CAAC;AACnD,YAAY,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAG7D,OAAO,EACL,qBAAqB,EACrB,gBAAgB,EAChB,KAAK,wBAAwB,EAC7B,KAAK,0BAA0B,GAChC,MAAM,qCAAqC,CAAC;AAG7C,YAAY,EACV,UAAU,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,EAClB,iBAAiB,EACjB,kBAAkB,GACnB,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EACL,iBAAiB,EACjB,qBAAqB,EACrB,uBAAuB,EACvB,oBAAoB,EACpB,sBAAsB,EACtB,cAAc,EACd,YAAY,EACZ,eAAe,EACf,cAAc,EACd,gBAAgB,GACjB,MAAM,8BAA8B,CAAC;AAEtC,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAGpD,OAAO,EACL,eAAe,EACf,mBAAmB,EACnB,qBAAqB,EACrB,iBAAiB,GAClB,MAAM,oBAAoB,CAAC"}
package/dist/esm/index.js CHANGED
@@ -4,7 +4,7 @@ export { BmiForm } from "./components/bmi-form.js";
4
4
  // Contexts
5
5
  export { QuestionnaireProvider, useQuestionnaire, } from "./contexts/questionnaire-context.js";
6
6
  // Utils
7
- export { calculateProgress, findQuestionnaireItem, getAllQuestionsFromPage, getExclusiveOptionCode, getInputHelper, getVisiblePages, hasAnswerValue, isQuestionHidden, } from "./lib/questionnaire-utils.js";
7
+ export { calculateProgress, findQuestionnaireItem, getAllQuestionsFromPage, getAnswerOptionMedia, getExclusiveOptionCode, getInputHelper, getItemMedia, getVisiblePages, hasAnswerValue, isQuestionHidden, } from "./lib/questionnaire-utils.js";
8
8
  export { calculateBmi } from "./lib/bmi-helpers.js";
9
9
  // Constants
10
10
  export { FHIR_EXTENSIONS, WELSHARE_EXTENSIONS, WELSHARE_CODE_SYSTEMS, FHIR_CODE_SYSTEMS, } from "./lib/constants.js";
@@ -1 +1 @@
1
- {"version":3,"file":"bmi-helpers.d.ts","sourceRoot":"","sources":["../../../src/lib/bmi-helpers.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;GAEG;AACH,eAAO,MAAM,WAAW,OAAO,CAAC;AAChC,eAAO,MAAM,eAAe,KAAK,CAAC;AAClC,eAAO,MAAM,SAAS,aAAa,CAAC;AAEpC;;GAEG;AACH,wBAAgB,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAE7C;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAEjD;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAGtE;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAK9E;AAED;;GAEG;AACH,wBAAgB,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAE1C;AAED;;GAEG;AACH,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE3C;AAED;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAOvE"}
1
+ {"version":3,"file":"bmi-helpers.d.ts","sourceRoot":"","sources":["../../../src/lib/bmi-helpers.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;GAEG;AACH,eAAO,MAAM,WAAW,OAAO,CAAC;AAChC,eAAO,MAAM,eAAe,KAAK,CAAC;AAClC,eAAO,MAAM,SAAS,aAAa,CAAC;AAEpC;;GAEG;AACH,wBAAgB,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAE7C;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAEjD;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAGtE;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,MAAM,GAAG;IAC7C,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB,CAKA;AAED;;GAEG;AACH,wBAAgB,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAE1C;AAED;;GAEG;AACH,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE3C;AAED;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAOvE"}
@@ -9,6 +9,18 @@ export declare const FHIR_EXTENSIONS: {
9
9
  * @see http://hl7.org/fhir/StructureDefinition/questionnaire-hidden
10
10
  */
11
11
  readonly QUESTIONNAIRE_HIDDEN: "http://hl7.org/fhir/StructureDefinition/questionnaire-hidden";
12
+ /**
13
+ * SDC extension for attaching media (images, audio, video) to questionnaire items
14
+ * Type: Attachment with contentType, url, title, etc.
15
+ * @see http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-itemMedia
16
+ */
17
+ readonly ITEM_MEDIA: "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-itemMedia";
18
+ /**
19
+ * SDC extension for attaching media to specific answer options
20
+ * Type: Attachment with contentType, url, title, etc.
21
+ * @see http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-itemAnswerMedia
22
+ */
23
+ readonly ITEM_ANSWER_MEDIA: "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-itemAnswerMedia";
12
24
  };
13
25
  /**
14
26
  * Welshare Custom Extension URLs
@@ -1 +1 @@
1
- {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../src/lib/constants.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,eAAO,MAAM,eAAe;IAC1B;;;;OAIG;;CAEK,CAAC;AAEX;;;;GAIG;AACH,eAAO,MAAM,mBAAmB;IAC9B;;;;;;;;;;;OAWG;;IAGH;;;;;;;;;;;;;;;;;OAiBG;;IAGH;;;;;;;;;;;;;;;;OAgBG;;CAEK,CAAC;AAEX;;;GAGG;AACH,eAAO,MAAM,qBAAqB;IAChC;;;;OAIG;;CAEK,CAAC;AAEX;;;GAGG;AACH,eAAO,MAAM,iBAAiB;IAC5B;;;;OAIG;;CAEK,CAAC"}
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../src/lib/constants.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,eAAO,MAAM,eAAe;IAC1B;;;;OAIG;;IAIH;;;;OAIG;;IAIH;;;;OAIG;;CAGK,CAAC;AAEX;;;;GAIG;AACH,eAAO,MAAM,mBAAmB;IAC9B;;;;;;;;;;;OAWG;;IAIH;;;;;;;;;;;;;;;;;OAiBG;;IAIH;;;;;;;;;;;;;;;;OAgBG;;CAGK,CAAC;AAEX;;;GAGG;AACH,eAAO,MAAM,qBAAqB;IAChC;;;;OAIG;;CAEK,CAAC;AAEX;;;GAGG;AACH,eAAO,MAAM,iBAAiB;IAC5B;;;;OAIG;;CAEK,CAAC"}
@@ -9,6 +9,18 @@ export const FHIR_EXTENSIONS = {
9
9
  * @see http://hl7.org/fhir/StructureDefinition/questionnaire-hidden
10
10
  */
11
11
  QUESTIONNAIRE_HIDDEN: "http://hl7.org/fhir/StructureDefinition/questionnaire-hidden",
12
+ /**
13
+ * SDC extension for attaching media (images, audio, video) to questionnaire items
14
+ * Type: Attachment with contentType, url, title, etc.
15
+ * @see http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-itemMedia
16
+ */
17
+ ITEM_MEDIA: "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-itemMedia",
18
+ /**
19
+ * SDC extension for attaching media to specific answer options
20
+ * Type: Attachment with contentType, url, title, etc.
21
+ * @see http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-itemAnswerMedia
22
+ */
23
+ ITEM_ANSWER_MEDIA: "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-itemAnswerMedia",
12
24
  };
13
25
  /**
14
26
  * Welshare Custom Extension URLs
@@ -1,4 +1,4 @@
1
- import type { Questionnaire, QuestionnaireItem, QuestionnaireResponseAnswer } from "../types/fhir.js";
1
+ import type { Questionnaire, QuestionnaireItem, QuestionnaireResponseAnswer, QuestionnaireItemAnswerOption, Attachment } from "../types/fhir.js";
2
2
  /**
3
3
  * Get visible pages from a questionnaire (excludes hidden groups)
4
4
  */
@@ -50,4 +50,18 @@ export declare const getInputHelper: (item: QuestionnaireItem) => InputHelperCon
50
50
  * @returns true if the question should be enabled, false otherwise
51
51
  */
52
52
  export declare const isQuestionEnabled: (item: QuestionnaireItem, getAnswer: (linkId: string) => QuestionnaireResponseAnswer | undefined) => boolean;
53
+ /**
54
+ * Extract media attachments from a questionnaire item's extensions
55
+ * Returns all itemMedia extensions as an array of Attachments
56
+ * @param item The questionnaire item to extract media from
57
+ * @returns Array of Attachment objects (can be empty if no media found)
58
+ */
59
+ export declare const getItemMedia: (item: QuestionnaireItem) => Attachment[];
60
+ /**
61
+ * Extract media attachment from an answer option's extensions
62
+ * Returns the first itemAnswerMedia extension found
63
+ * @param option The answer option to extract media from
64
+ * @returns Attachment object or undefined if no media found
65
+ */
66
+ export declare const getAnswerOptionMedia: (option: QuestionnaireItemAnswerOption) => Attachment | undefined;
53
67
  //# sourceMappingURL=questionnaire-utils.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"questionnaire-utils.d.ts","sourceRoot":"","sources":["../../../src/lib/questionnaire-utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,aAAa,EACb,iBAAiB,EACjB,2BAA2B,EAC5B,MAAM,kBAAkB,CAAC;AAG1B;;GAEG;AACH,eAAO,MAAM,eAAe,GAC1B,eAAe,aAAa,KAC3B,iBAAiB,EAcnB,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,GAC5B,kBAAkB,MAAM,EACxB,YAAY,MAAM,KACjB,MAGF,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,uBAAuB,GAClC,UAAU,iBAAiB,KAC1B,iBAAiB,EAsBnB,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,OAQ1D,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,sBAAsB,GACjC,MAAM,iBAAiB,KACtB,MAAM,GAAG,SAKX,CAAC;AAEF;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;GAGG;AACH,eAAO,MAAM,cAAc,GACzB,MAAM,iBAAiB,KACtB,iBAAiB,GAAG,IAatB,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,GAC5B,MAAM,iBAAiB,EACvB,WAAW,CAAC,MAAM,EAAE,MAAM,KAAK,2BAA2B,GAAG,SAAS,KACrE,OAkEF,CAAC"}
1
+ {"version":3,"file":"questionnaire-utils.d.ts","sourceRoot":"","sources":["../../../src/lib/questionnaire-utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,aAAa,EACb,iBAAiB,EACjB,2BAA2B,EAC3B,6BAA6B,EAC7B,UAAU,EACX,MAAM,kBAAkB,CAAC;AAG1B;;GAEG;AACH,eAAO,MAAM,eAAe,GAC1B,eAAe,aAAa,KAC3B,iBAAiB,EAcnB,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,GAC5B,kBAAkB,MAAM,EACxB,YAAY,MAAM,KACjB,MAGF,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,uBAAuB,GAClC,UAAU,iBAAiB,KAC1B,iBAAiB,EAsBnB,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,OAQ1D,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,sBAAsB,GACjC,MAAM,iBAAiB,KACtB,MAAM,GAAG,SAKX,CAAC;AAEF;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;GAGG;AACH,eAAO,MAAM,cAAc,GACzB,MAAM,iBAAiB,KACtB,iBAAiB,GAAG,IAatB,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,GAC5B,MAAM,iBAAiB,EACvB,WAAW,CAAC,MAAM,EAAE,MAAM,KAAK,2BAA2B,GAAG,SAAS,KACrE,OAkEF,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,YAAY,GAAI,MAAM,iBAAiB,KAAG,UAAU,EAOhE,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB,GAC/B,QAAQ,6BAA6B,KACpC,UAAU,GAAG,SAQf,CAAC"}
@@ -178,3 +178,29 @@ export const isQuestionEnabled = (item, getAnswer) => {
178
178
  }
179
179
  return false;
180
180
  };
181
+ /**
182
+ * Extract media attachments from a questionnaire item's extensions
183
+ * Returns all itemMedia extensions as an array of Attachments
184
+ * @param item The questionnaire item to extract media from
185
+ * @returns Array of Attachment objects (can be empty if no media found)
186
+ */
187
+ export const getItemMedia = (item) => {
188
+ if (!item.extension)
189
+ return [];
190
+ return item.extension
191
+ .filter((ext) => ext.url === FHIR_EXTENSIONS.ITEM_MEDIA)
192
+ .map((ext) => ext.valueAttachment)
193
+ .filter((attachment) => attachment !== undefined);
194
+ };
195
+ /**
196
+ * Extract media attachment from an answer option's extensions
197
+ * Returns the first itemAnswerMedia extension found
198
+ * @param option The answer option to extract media from
199
+ * @returns Attachment object or undefined if no media found
200
+ */
201
+ export const getAnswerOptionMedia = (option) => {
202
+ if (!option.extension)
203
+ return undefined;
204
+ const mediaExt = option.extension.find((ext) => ext.url === FHIR_EXTENSIONS.ITEM_ANSWER_MEDIA);
205
+ return mediaExt?.valueAttachment;
206
+ };
@@ -5,6 +5,16 @@ export type Coding = {
5
5
  display?: string;
6
6
  userSelected?: boolean;
7
7
  };
8
+ export type Attachment = {
9
+ contentType?: string;
10
+ language?: string;
11
+ data?: string;
12
+ url?: string;
13
+ size?: number;
14
+ hash?: string;
15
+ title?: string;
16
+ creation?: string;
17
+ };
8
18
  export type QuestionnaireItemAnswerOption = {
9
19
  valueCoding?: Coding;
10
20
  valueInteger?: number;
@@ -12,6 +22,7 @@ export type QuestionnaireItemAnswerOption = {
12
22
  valueTime?: string;
13
23
  valueString?: string;
14
24
  initialSelected?: boolean;
25
+ extension?: Extension[];
15
26
  };
16
27
  export type Extension = {
17
28
  url: string;
@@ -26,6 +37,7 @@ export type Extension = {
26
37
  language?: string;
27
38
  expression?: string;
28
39
  };
40
+ valueAttachment?: Attachment;
29
41
  extension?: Extension[];
30
42
  };
31
43
  export type QuestionnaireItem = {
@@ -34,7 +46,7 @@ export type QuestionnaireItem = {
34
46
  code?: Coding[];
35
47
  prefix?: string;
36
48
  text?: string;
37
- type: 'group' | 'display' | 'boolean' | 'decimal' | 'integer' | 'date' | 'dateTime' | 'time' | 'string' | 'text' | 'url' | 'choice' | 'open-choice' | 'attachment' | 'reference' | 'quantity';
49
+ type: "group" | "display" | "boolean" | "decimal" | "integer" | "date" | "dateTime" | "time" | "string" | "text" | "url" | "choice" | "open-choice" | "coding" | "attachment" | "reference" | "quantity";
38
50
  enableWhen?: Array<{
39
51
  question: string;
40
52
  operator: string;
@@ -69,13 +81,21 @@ export type QuestionnaireItem = {
69
81
  item?: QuestionnaireItem[];
70
82
  };
71
83
  export type Questionnaire = {
72
- resourceType: 'Questionnaire';
84
+ resourceType: "Questionnaire";
73
85
  id: string;
86
+ /** Metadata including profile declarations (e.g., R4 vs R5 compatibility) */
87
+ meta?: {
88
+ profile?: string[];
89
+ tag?: Array<{
90
+ system?: string;
91
+ code?: string;
92
+ }>;
93
+ };
74
94
  url?: string;
75
95
  version?: string;
76
96
  name?: string;
77
97
  title?: string;
78
- status: 'draft' | 'active' | 'retired' | 'unknown';
98
+ status: "draft" | "active" | "retired" | "unknown";
79
99
  subjectType?: string[];
80
100
  date?: string;
81
101
  publisher?: string;
@@ -108,10 +128,10 @@ export type QuestionnaireResponseItem = {
108
128
  item?: QuestionnaireResponseItem[];
109
129
  };
110
130
  export type QuestionnaireResponse = {
111
- resourceType: 'QuestionnaireResponse';
131
+ resourceType: "QuestionnaireResponse";
112
132
  id?: string;
113
133
  questionnaire?: string;
114
- status: 'in-progress' | 'completed' | 'amended' | 'entered-in-error' | 'stopped';
134
+ status: "in-progress" | "completed" | "amended" | "entered-in-error" | "stopped";
115
135
  authored?: string;
116
136
  item?: QuestionnaireResponseItem[];
117
137
  };
@@ -1 +1 @@
1
- {"version":3,"file":"fhir.d.ts","sourceRoot":"","sources":["../../../src/types/fhir.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"fhir.d.ts","sourceRoot":"","sources":["../../../src/types/fhir.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,5 @@
1
1
  // FHIR Types for Questionnaire and QuestionnaireResponse
2
- // Based on FHIR R4 Specification with extensions commonly used in Welshare surveys
2
+ // Based on FHIR R4/R5 Specifications with extensions commonly used in Welshare surveys
3
+ // Note: FHIR R4 uses 'choice' and 'open-choice', while FHIR R5 uses 'coding'.
4
+ // Both are supported for backwards compatibility.
3
5
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/types/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,sCAAsC;IACtC,MAAM,EAAE,MAAM,CAAC;IACf,gCAAgC;IAChC,WAAW,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACnE,iDAAiD;IACjD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gDAAgD;IAChD,OAAO,EAAE,OAAO,CAAC;IACjB,sCAAsC;IACtC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,2CAA2C;IAC3C,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,uCAAuC;IACvC,KAAK,EAAE,MAAM,CAAC;IACd,2CAA2C;IAC3C,KAAK,EAAE,MAAM,CAAC;CACf;AAGD;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,sCAAsC;IACtC,MAAM,EAAE,MAAM,CAAC;IACf,gCAAgC;IAChC,WAAW,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACnE,iDAAiD;IACjD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gDAAgD;IAChD,OAAO,EAAE,OAAO,CAAC;IACjB,sCAAsC;IACtC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,0CAA0C;IAC1C,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,uCAAuC;IACvC,KAAK,EAAE,MAAM,CAAC;IACd,2CAA2C;IAC3C,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,sDAAsD;IACtD,IAAI,EAAE,MAAM,CAAC;IACb,kCAAkC;IAClC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,+BAA+B;IAC/B,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;GAGG;AACH,MAAM,WAAW,kBAAkB,CAAC,CAAC,GAAG,MAAM,GAAG,MAAM;IACrD,kDAAkD;IAClD,MAAM,EAAE,iBAAiB,CAAC;IAC1B,sCAAsC;IACtC,MAAM,EAAE,MAAM,CAAC;IACf,0CAA0C;IAC1C,YAAY,CAAC,EAAE,CAAC,CAAC;IACjB,0DAA0D;IAC1D,eAAe,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,CAAC;CACrC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/types/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,sCAAsC;IACtC,MAAM,EAAE,MAAM,CAAC;IACf,gCAAgC;IAChC,WAAW,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACnE,iDAAiD;IACjD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gDAAgD;IAChD,OAAO,EAAE,OAAO,CAAC;IACjB,sCAAsC;IACtC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,2CAA2C;IAC3C,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,uCAAuC;IACvC,KAAK,EAAE,MAAM,CAAC;IACd,2CAA2C;IAC3C,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,sCAAsC;IACtC,MAAM,EAAE,MAAM,CAAC;IACf,gCAAgC;IAChC,WAAW,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACnE,iDAAiD;IACjD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gDAAgD;IAChD,OAAO,EAAE,OAAO,CAAC;IACjB,sCAAsC;IACtC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,0CAA0C;IAC1C,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,uCAAuC;IACvC,KAAK,EAAE,MAAM,CAAC;IACd,2CAA2C;IAC3C,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,sDAAsD;IACtD,IAAI,EAAE,MAAM,CAAC;IACb,kCAAkC;IAClC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,+BAA+B;IAC/B,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;GAGG;AACH,MAAM,WAAW,kBAAkB,CAAC,CAAC,GAAG,MAAM,GAAG,MAAM;IACrD,kDAAkD;IAClD,MAAM,EAAE,iBAAiB,CAAC;IAC1B,sCAAsC;IACtC,MAAM,EAAE,MAAM,CAAC;IACf,0CAA0C;IAC1C,YAAY,CAAC,EAAE,CAAC,CAAC;IACjB,0DAA0D;IAC1D,eAAe,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,CAAC;CACrC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@welshare/questionnaire",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "FHIR Questionnaire components for React with state management and validation",
5
5
  "keywords": [
6
6
  "react",
@@ -88,7 +88,7 @@
88
88
  "audit": "pnpm audit --audit-level=moderate",
89
89
  "audit:fix": "pnpm audit fix",
90
90
  "check:deps": "pnpm outdated",
91
- "verify:publish": "bash scripts/verify-publish.sh",
91
+ "verify:publish": "bash ../../scripts/verify-publish.sh",
92
92
  "storybook": "storybook dev -p 6006",
93
93
  "build-storybook": "storybook build"
94
94
  }