@welshare/questionnaire 0.1.2 → 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 +25 -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 -183
  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 -391
  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,183 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useQuestionnaire } from "../contexts/questionnaire-context.js";
3
- import { DebugSection } from "./debug-section.js";
4
- import { ChoiceQuestion } from "./questions/choice-question.js";
5
- import { MultipleChoiceQuestion } from "./questions/multiple-choice-question.js";
6
- import { IntegerQuestion } from "./questions/integer-question.js";
7
- import { DecimalQuestion } from "./questions/decimal-question.js";
8
- import { StringQuestion } from "./questions/string-question.js";
9
- import { BooleanQuestion } from "./questions/boolean-question.js";
10
- /**
11
- * Wrapper component that combines the library's QuestionRenderer with debug functionality.
12
- *
13
- * This component:
14
- * - Renders the library's QuestionRenderer with custom radio/checkbox renderers
15
- * - Adds DebugSection below it when debug mode is enabled
16
- *
17
- * Uses custom input renderers to maintain the app's design system styling.
18
- */
19
- export const QuestionRenderer = (rendererProps) => {
20
- const { getAnswer, getAnswers, debugMode } = useQuestionnaire();
21
- const { item } = rendererProps;
22
- const currentAnswer = getAnswer(item.linkId);
23
- const currentAnswers = getAnswers(item.linkId);
24
- // Find LOINC code if present
25
- const loincCode = item.code?.find((coding) => coding.system === "http://loinc.org");
26
- return (_jsxs("div", { children: [_jsx(QuestionRendererInternal, { ...rendererProps }), debugMode && (_jsx(DebugSection, { item: item, currentAnswer: currentAnswer, currentAnswers: currentAnswers, loincCode: loincCode }))] }));
27
- };
28
- /**
29
- * QuestionRenderer component renders different types of questionnaire items
30
- * Supports: choice, integer, decimal, string, text, boolean
31
- * Features:
32
- * - Single and multiple choice (radio/checkbox)
33
- * - Slider controls for integer inputs
34
- * - Exclusive option support for multi-select
35
- * - Auto-populated (hidden) fields
36
- * - Validation error display
37
- */
38
- const QuestionRendererInternal = ({ item, className = "", inputClassName = "", choiceClassName = "", renderRadioInput, renderCheckboxInput, }) => {
39
- const { updateAnswer, updateMultipleAnswers, getAnswer, getAnswers, hasValidationError, } = useQuestionnaire();
40
- const currentAnswer = getAnswer(item.linkId);
41
- const currentAnswers = getAnswers(item.linkId);
42
- const hasError = hasValidationError(item.linkId);
43
- // Check if this field should be hidden (auto-populated)
44
- const isAutoPopulated = item.extension?.some((ext) => ext.url ===
45
- "http://hl7.org/fhir/StructureDefinition/questionnaire-hidden" &&
46
- ext.valueBoolean === true);
47
- // Don't render auto-populated fields
48
- if (isAutoPopulated) {
49
- return null;
50
- }
51
- const handleChoiceChange = (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
- }
59
- };
60
- const handleMultipleChoiceToggle = (valueCoding, valueInteger) => {
61
- const isSelected = currentAnswers.some((answer) => answer.valueCoding?.code === valueCoding.code);
62
- // Check if there's an exclusive option extension
63
- const exclusiveOptionExt = item.extension?.find((ext) => ext.url ===
64
- "http://codes.welshare.app/StructureDefinition/questionnaire-exclusive-option");
65
- const exclusiveOptionCode = exclusiveOptionExt?.valueString;
66
- let newAnswers;
67
- if (isSelected) {
68
- // Remove the answer
69
- newAnswers = currentAnswers.filter((answer) => answer.valueCoding?.code !== valueCoding.code);
70
- }
71
- else {
72
- // Check if we're selecting the exclusive option
73
- if (exclusiveOptionCode && valueCoding.code === exclusiveOptionCode) {
74
- // Clear all other answers and only keep this one
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];
82
- }
83
- else {
84
- // Check if exclusive option is currently selected
85
- const exclusiveSelected = currentAnswers.some((answer) => answer.valueCoding?.code === exclusiveOptionCode);
86
- if (exclusiveSelected) {
87
- // Remove exclusive option and add new selection
88
- newAnswers = currentAnswers.filter((answer) => answer.valueCoding?.code !== exclusiveOptionCode);
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];
96
- }
97
- else {
98
- // Normal behavior: Add the answer (respecting maxAnswers limit)
99
- const maxAnswers = item.maxAnswers || Number.MAX_SAFE_INTEGER;
100
- if (currentAnswers.length < maxAnswers) {
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];
108
- }
109
- else {
110
- // Already at max, don't add
111
- return;
112
- }
113
- }
114
- }
115
- }
116
- updateMultipleAnswers(item.linkId, newAnswers);
117
- };
118
- const handleIntegerChange = (value) => {
119
- // Allow clearing the controlled input
120
- if (value === "") {
121
- updateAnswer(item.linkId, {});
122
- return;
123
- }
124
- const numValue = parseInt(value);
125
- if (!isNaN(numValue)) {
126
- updateAnswer(item.linkId, { valueInteger: numValue });
127
- }
128
- };
129
- const handleDecimalChange = (value) => {
130
- // Allow clearing the controlled input
131
- if (value === "") {
132
- updateAnswer(item.linkId, {});
133
- return;
134
- }
135
- const numValue = parseFloat(value);
136
- if (!isNaN(numValue)) {
137
- updateAnswer(item.linkId, { valueDecimal: numValue });
138
- }
139
- };
140
- const handleStringChange = (value) => {
141
- updateAnswer(item.linkId, { valueString: value });
142
- };
143
- const handleBooleanChange = (value) => {
144
- updateAnswer(item.linkId, { valueBoolean: value });
145
- };
146
- // Check if this field should use a slider control
147
- const getSliderConfig = () => {
148
- const sliderExt = item.extension?.find((ext) => ext.url ===
149
- "http://codes.welshare.app/StructureDefinition/questionnaire-slider-control");
150
- if (!sliderExt?.extension)
151
- return null;
152
- const minValue = sliderExt.extension.find((e) => e.url === "minValue")?.valueInteger ?? 0;
153
- const maxValue = sliderExt.extension.find((e) => e.url === "maxValue")?.valueInteger ??
154
- 100;
155
- const step = sliderExt.extension.find((e) => e.url === "step")?.valueInteger ?? 1;
156
- const unit = sliderExt.extension.find((e) => e.url === "unit")?.valueString ?? "";
157
- return { minValue, maxValue, step, unit };
158
- };
159
- const sliderConfig = getSliderConfig();
160
- const renderQuestion = () => {
161
- switch (item.type) {
162
- case "choice":
163
- // Multi-select with checkboxes when repeats is true
164
- if (item.repeats) {
165
- return (_jsx(MultipleChoiceQuestion, { item: item, currentAnswers: currentAnswers, onMultipleChoiceToggle: handleMultipleChoiceToggle, choiceClassName: choiceClassName, renderCheckboxInput: renderCheckboxInput }));
166
- }
167
- // Single-select with radio buttons (default)
168
- return (_jsx(ChoiceQuestion, { item: item, currentAnswer: currentAnswer, onChoiceChange: handleChoiceChange, choiceClassName: choiceClassName, renderRadioInput: renderRadioInput }));
169
- case "integer":
170
- return (_jsx(IntegerQuestion, { item: item, currentAnswer: currentAnswer, onIntegerChange: handleIntegerChange, inputClassName: inputClassName, sliderConfig: sliderConfig }));
171
- case "decimal":
172
- return (_jsx(DecimalQuestion, { item: item, currentAnswer: currentAnswer, onDecimalChange: handleDecimalChange, inputClassName: inputClassName }));
173
- case "string":
174
- case "text":
175
- return (_jsx(StringQuestion, { item: item, currentAnswer: currentAnswer, onStringChange: handleStringChange, inputClassName: inputClassName }));
176
- case "boolean":
177
- return (_jsx(BooleanQuestion, { item: item, currentAnswer: currentAnswer, onBooleanChange: handleBooleanChange, choiceClassName: choiceClassName, renderRadioInput: renderRadioInput }));
178
- default:
179
- return (_jsxs("div", { className: "wq-unsupported-type", children: ["Unsupported question type: ", item.type] }));
180
- }
181
- };
182
- return (_jsxs("div", { className: `wq-question-container ${hasError ? "wq-has-error" : ""} ${className}`, children: [_jsxs("div", { className: "wq-question-text", children: [item.text, item.required && _jsx("span", { className: "wq-required-indicator", children: "*" })] }), renderQuestion()] }));
183
- };
@@ -1,15 +0,0 @@
1
- import { type ReactNode } from 'react';
2
- import type { QuestionnaireItem, QuestionnaireResponseAnswer } from '../../types/fhir.js';
3
- import { RadioInputProps } from '@/types/index.js';
4
- export interface BooleanQuestionProps {
5
- item: QuestionnaireItem;
6
- currentAnswer?: QuestionnaireResponseAnswer;
7
- onBooleanChange: (value: boolean) => void;
8
- choiceClassName?: string;
9
- renderRadioInput?: (props: RadioInputProps) => ReactNode;
10
- }
11
- /**
12
- * Renders a boolean question with Yes/No radio buttons
13
- */
14
- export declare const BooleanQuestion: ({ item, currentAnswer, onBooleanChange, choiceClassName, renderRadioInput }: BooleanQuestionProps) => import("react/jsx-runtime").JSX.Element;
15
- //# sourceMappingURL=boolean-question.d.ts.map
@@ -1 +0,0 @@
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,19 +0,0 @@
1
- import { Fragment as _Fragment, jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
2
- /**
3
- * Renders a boolean question with Yes/No radio buttons
4
- */
5
- export const BooleanQuestion = ({ item, currentAnswer, onBooleanChange, choiceClassName = '', renderRadioInput }) => {
6
- return (_jsx("div", { className: `wq-question-choice ${choiceClassName}`, children: renderRadioInput ? (_jsxs(_Fragment, { children: [renderRadioInput({
7
- linkId: item.linkId,
8
- checked: currentAnswer?.valueBoolean === true,
9
- onChange: () => onBooleanChange(true),
10
- label: 'Yes',
11
- index: 0
12
- }), renderRadioInput({
13
- linkId: item.linkId,
14
- checked: currentAnswer?.valueBoolean === false,
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" })] })] })) }));
19
- };
@@ -1,19 +0,0 @@
1
- import { type ReactNode } from 'react';
2
- import type { QuestionnaireItem, QuestionnaireResponseAnswer } from '../../types/fhir.js';
3
- import { RadioInputProps } from '@/types/index.js';
4
- export interface ChoiceQuestionProps {
5
- item: QuestionnaireItem;
6
- currentAnswer?: QuestionnaireResponseAnswer;
7
- onChoiceChange: (valueCoding: {
8
- system?: string;
9
- code?: string;
10
- display?: string;
11
- }, valueInteger?: number) => void;
12
- choiceClassName?: string;
13
- renderRadioInput?: (props: RadioInputProps) => ReactNode;
14
- }
15
- /**
16
- * Renders a single-select choice question with radio buttons
17
- */
18
- export declare const ChoiceQuestion: ({ item, currentAnswer, onChoiceChange, choiceClassName, renderRadioInput }: ChoiceQuestionProps) => import("react/jsx-runtime").JSX.Element;
19
- //# sourceMappingURL=choice-question.d.ts.map
@@ -1 +0,0 @@
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,23 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- /**
3
- * Renders a single-select choice question with radio buttons
4
- */
5
- export const ChoiceQuestion = ({ item, currentAnswer, onChoiceChange, choiceClassName = '', renderRadioInput }) => {
6
- return (_jsx("div", { className: `wq-question-choice ${choiceClassName}`, children: item.answerOption?.map((option, index) => {
7
- const isSelected = currentAnswer?.valueCoding?.code === option.valueCoding?.code;
8
- // Use custom renderer if provided
9
- 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));
19
- }
20
- // 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));
22
- }) }));
23
- };
@@ -1,12 +0,0 @@
1
- import type { QuestionnaireItem, QuestionnaireResponseAnswer } from "../../types/fhir.js";
2
- export interface DecimalQuestionProps {
3
- item: QuestionnaireItem;
4
- currentAnswer?: QuestionnaireResponseAnswer;
5
- onDecimalChange: (value: string) => void;
6
- inputClassName?: string;
7
- }
8
- /**
9
- * Renders a decimal question with number input
10
- */
11
- export declare const DecimalQuestion: ({ item, currentAnswer, onDecimalChange, inputClassName, }: DecimalQuestionProps) => import("react/jsx-runtime").JSX.Element;
12
- //# sourceMappingURL=decimal-question.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"decimal-question.d.ts","sourceRoot":"","sources":["../../../../src/components/questions/decimal-question.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,iBAAiB,EACjB,2BAA2B,EAC5B,MAAM,qBAAqB,CAAC;AAE7B,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,iBAAiB,CAAC;IACxB,aAAa,CAAC,EAAE,2BAA2B,CAAC;IAC5C,eAAe,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;GAEG;AACH,eAAO,MAAM,eAAe,GAAI,2DAK7B,oBAAoB,4CAWtB,CAAC"}
@@ -1,7 +0,0 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- /**
3
- * Renders a decimal question with number input
4
- */
5
- export const DecimalQuestion = ({ item, currentAnswer, onDecimalChange, inputClassName = "", }) => {
6
- return (_jsx("input", { type: "number", className: `wq-question-input ${inputClassName}`, value: currentAnswer?.valueDecimal ?? "", onChange: (e) => onDecimalChange(e.target.value), placeholder: "Enter a number", step: "0.1" }));
7
- };
@@ -1,18 +0,0 @@
1
- import type { QuestionnaireItem, QuestionnaireResponseAnswer } from "../../types/fhir.js";
2
- export interface IntegerQuestionProps {
3
- item: QuestionnaireItem;
4
- currentAnswer?: QuestionnaireResponseAnswer;
5
- onIntegerChange: (value: string) => void;
6
- inputClassName?: string;
7
- sliderConfig?: {
8
- minValue: number;
9
- maxValue: number;
10
- step: number;
11
- unit: string;
12
- } | null;
13
- }
14
- /**
15
- * Renders an integer question with optional slider control
16
- */
17
- export declare const IntegerQuestion: ({ item, currentAnswer, onIntegerChange, inputClassName, sliderConfig, }: IntegerQuestionProps) => import("react/jsx-runtime").JSX.Element;
18
- //# sourceMappingURL=integer-question.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"integer-question.d.ts","sourceRoot":"","sources":["../../../../src/components/questions/integer-question.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,iBAAiB,EACjB,2BAA2B,EAC5B,MAAM,qBAAqB,CAAC;AAE7B,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,iBAAiB,CAAC;IACxB,aAAa,CAAC,EAAE,2BAA2B,CAAC;IAC5C,eAAe,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,YAAY,CAAC,EAAE;QACb,QAAQ,EAAE,MAAM,CAAC;QACjB,QAAQ,EAAE,MAAM,CAAC;QACjB,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;KACd,GAAG,IAAI,CAAC;CACV;AAED;;GAEG;AACH,eAAO,MAAM,eAAe,GAAI,yEAM7B,oBAAoB,4CA2DtB,CAAC"}
@@ -1,24 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- /**
3
- * Renders an integer question with optional slider control
4
- */
5
- export const IntegerQuestion = ({ item, currentAnswer, onIntegerChange, inputClassName = "", sliderConfig, }) => {
6
- // Render slider if slider config is present
7
- if (sliderConfig) {
8
- // Use current answer, or fallback to initial value, or fallback to minValue
9
- const initialValue = item.initial?.[0]?.valueInteger;
10
- const value = currentAnswer?.valueInteger ?? initialValue ?? sliderConfig.minValue;
11
- const unit = sliderConfig.unit || "";
12
- // Create abbreviated unit for range labels
13
- const unitShort = unit === "minutes"
14
- ? "min"
15
- : unit === "hours"
16
- ? "hr"
17
- : unit === "days per week"
18
- ? "days"
19
- : unit;
20
- return (_jsxs("div", { className: "wq-question-slider", children: [_jsx("input", { type: "range", className: `wq-slider-input ${inputClassName}`, min: sliderConfig.minValue, max: sliderConfig.maxValue, step: sliderConfig.step, value: value, onChange: (e) => onIntegerChange(e.target.value) }), _jsxs("div", { className: "wq-slider-value-display", children: [_jsx("span", { className: "wq-slider-value", children: value }), unit && _jsx("span", { className: "wq-slider-unit", children: unit })] }), _jsxs("div", { className: "wq-slider-range-labels", children: [_jsxs("span", { className: "wq-slider-min", children: [sliderConfig.minValue, unitShort && ` ${unitShort}`] }), _jsxs("span", { className: "wq-slider-max", children: [sliderConfig.maxValue, unitShort && ` ${unitShort}`] })] })] }));
21
- }
22
- // Default number input
23
- return (_jsx("input", { type: "number", className: `wq-question-input ${inputClassName}`, value: currentAnswer?.valueInteger ?? "", onChange: (e) => onIntegerChange(e.target.value), placeholder: "Enter a number", step: "1" }));
24
- };
@@ -1,20 +0,0 @@
1
- import { type ReactNode } from "react";
2
- import type { QuestionnaireItem, QuestionnaireResponseAnswer } from "../../types/fhir.js";
3
- import { CheckboxInputProps } from "../../types/index.js";
4
- export interface MultipleChoiceQuestionProps {
5
- item: QuestionnaireItem;
6
- currentAnswers: QuestionnaireResponseAnswer[];
7
- onMultipleChoiceToggle: (valueCoding: {
8
- system?: string;
9
- code?: string;
10
- display?: string;
11
- }, valueInteger?: number) => void;
12
- choiceClassName?: string;
13
- renderCheckboxInput?: (props: CheckboxInputProps) => ReactNode;
14
- }
15
- /**
16
- * Renders a multi-select choice question with checkboxes
17
- * Supports exclusive options and maxAnswers limits
18
- */
19
- export declare const MultipleChoiceQuestion: ({ item, currentAnswers, onMultipleChoiceToggle, choiceClassName, renderCheckboxInput, }: MultipleChoiceQuestionProps) => import("react/jsx-runtime").JSX.Element;
20
- //# sourceMappingURL=multiple-choice-question.d.ts.map
@@ -1 +0,0 @@
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;AAC7B,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,4CA0F7B,CAAC"}
@@ -1,39 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- /**
3
- * Renders a multi-select choice question with checkboxes
4
- * Supports exclusive options and maxAnswers limits
5
- */
6
- export const MultipleChoiceQuestion = ({ item, currentAnswers, onMultipleChoiceToggle, choiceClassName = "", renderCheckboxInput, }) => {
7
- const maxAnswers = item.maxAnswers || Number.MAX_SAFE_INTEGER;
8
- const atMaxAnswers = currentAnswers.length >= maxAnswers;
9
- // Check if there's an exclusive option extension
10
- const exclusiveOptionExt = item.extension?.find((ext) => ext.url ===
11
- "http://codes.welshare.app/StructureDefinition/questionnaire-exclusive-option");
12
- const exclusiveOptionCode = exclusiveOptionExt?.valueString;
13
- // Check if the exclusive option is currently selected
14
- const exclusiveSelected = exclusiveOptionCode &&
15
- currentAnswers.some((answer) => answer.valueCoding?.code === exclusiveOptionCode);
16
- // Filter options to show: if exclusive option is selected, only show that one
17
- const optionsToShow = exclusiveSelected
18
- ? item.answerOption?.filter((opt) => opt.valueCoding?.code === exclusiveOptionCode)
19
- : item.answerOption;
20
- return (_jsxs("div", { className: `wq-question-choice ${choiceClassName}`, children: [optionsToShow?.map((option, index) => {
21
- const isSelected = currentAnswers.some((answer) => answer.valueCoding?.code === option.valueCoding?.code);
22
- const isDisabled = !isSelected && atMaxAnswers;
23
- // Use custom renderer if provided
24
- 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));
35
- }
36
- // 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));
38
- }), item.maxAnswers && (_jsxs("div", { className: "wq-max-answers-hint", children: ["Selected: ", currentAnswers.length, " / ", item.maxAnswers] }))] }));
39
- };
@@ -1,12 +0,0 @@
1
- import type { QuestionnaireItem, QuestionnaireResponseAnswer } from "../../types/fhir.js";
2
- export interface StringQuestionProps {
3
- item: QuestionnaireItem;
4
- currentAnswer?: QuestionnaireResponseAnswer;
5
- onStringChange: (value: string) => void;
6
- inputClassName?: string;
7
- }
8
- /**
9
- * Renders a string or text question with text input
10
- */
11
- export declare const StringQuestion: ({ item, currentAnswer, onStringChange, inputClassName, }: StringQuestionProps) => import("react/jsx-runtime").JSX.Element;
12
- //# sourceMappingURL=string-question.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"string-question.d.ts","sourceRoot":"","sources":["../../../../src/components/questions/string-question.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,iBAAiB,EACjB,2BAA2B,EAC5B,MAAM,qBAAqB,CAAC;AAE7B,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,iBAAiB,CAAC;IACxB,aAAa,CAAC,EAAE,2BAA2B,CAAC;IAC5C,cAAc,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;GAEG;AACH,eAAO,MAAM,cAAc,GAAI,0DAK5B,mBAAmB,4CAUrB,CAAC"}
@@ -1,7 +0,0 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- /**
3
- * Renders a string or text question with text input
4
- */
5
- export const StringQuestion = ({ item, currentAnswer, onStringChange, inputClassName = "", }) => {
6
- return (_jsx("input", { type: "text", className: `wq-question-input ${inputClassName}`, value: currentAnswer?.valueString ?? "", onChange: (e) => onStringChange(e.target.value), placeholder: "Enter your answer" }));
7
- };
@@ -1,41 +0,0 @@
1
- import { type ReactNode } from "react";
2
- import type { Questionnaire, QuestionnaireItem, QuestionnaireResponse, QuestionnaireResponseAnswer } from "../types/fhir.js";
3
- export interface QuestionnaireContextType {
4
- questionnaire: Questionnaire;
5
- response: QuestionnaireResponse;
6
- updateAnswer: (linkId: string, answer: QuestionnaireResponseAnswer) => void;
7
- updateMultipleAnswers: (linkId: string, answers: QuestionnaireResponseAnswer[]) => void;
8
- getAnswer: (linkId: string) => QuestionnaireResponseAnswer | undefined;
9
- getAnswers: (linkId: string) => QuestionnaireResponseAnswer[];
10
- isPageValid: (pageItems: QuestionnaireItem[]) => boolean;
11
- getRequiredQuestions: (pageItems: QuestionnaireItem[]) => QuestionnaireItem[];
12
- getUnansweredRequiredQuestions: (pageItems: QuestionnaireItem[]) => QuestionnaireItem[];
13
- markValidationErrors: (pageItems: QuestionnaireItem[]) => void;
14
- clearValidationErrors: () => void;
15
- hasValidationError: (linkId: string) => boolean;
16
- debugMode: boolean;
17
- toggleDebugMode: () => void;
18
- }
19
- export declare const useQuestionnaire: () => QuestionnaireContextType;
20
- export interface QuestionnaireProviderProps {
21
- children: ReactNode;
22
- /**
23
- * The FHIR Questionnaire object to render
24
- * Clients are responsible for loading/fetching this data
25
- */
26
- questionnaire: Questionnaire;
27
- /**
28
- * Optional questionnaire ID to use in the response
29
- * If not provided, will use questionnaire.id
30
- * If neither exists, an error will be thrown
31
- */
32
- questionnaireId?: string;
33
- /**
34
- * If true, initializes the response with a hierarchical structure matching the questionnaire
35
- * If false, uses a flat structure
36
- * @default true
37
- */
38
- useNestedStructure?: boolean;
39
- }
40
- export declare const QuestionnaireProvider: ({ children, questionnaire, questionnaireId, useNestedStructure, }: QuestionnaireProviderProps) => import("react/jsx-runtime").JSX.Element;
41
- //# sourceMappingURL=questionnaire-context.d.ts.map
@@ -1 +0,0 @@
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;AAG1B,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,4CAoa5B,CAAC"}