@welshare/questionnaire 0.1.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (96) hide show
  1. package/README.md +151 -0
  2. package/dist/esm/components/bmi-form.d.ts +68 -0
  3. package/dist/esm/components/bmi-form.d.ts.map +1 -0
  4. package/dist/esm/components/bmi-form.js +138 -0
  5. package/dist/esm/components/question-renderer.d.ts +6 -1
  6. package/dist/esm/components/question-renderer.d.ts.map +1 -1
  7. package/dist/esm/components/question-renderer.js +49 -14
  8. package/dist/esm/components/questions/decimal-question.d.ts +8 -1
  9. package/dist/esm/components/questions/decimal-question.d.ts.map +1 -1
  10. package/dist/esm/components/questions/decimal-question.js +19 -1
  11. package/dist/esm/components/questions/multiple-choice-question.d.ts.map +1 -1
  12. package/dist/esm/components/questions/multiple-choice-question.js +2 -2
  13. package/dist/esm/contexts/questionnaire-context.d.ts.map +1 -1
  14. package/dist/esm/contexts/questionnaire-context.js +3 -2
  15. package/dist/esm/index.d.ts +6 -2
  16. package/dist/esm/index.d.ts.map +1 -1
  17. package/dist/esm/index.js +5 -1
  18. package/dist/esm/lib/bmi-helpers.d.ts +50 -0
  19. package/dist/esm/lib/bmi-helpers.d.ts.map +1 -0
  20. package/dist/esm/lib/bmi-helpers.js +69 -0
  21. package/dist/esm/lib/constants.d.ts +94 -0
  22. package/dist/esm/lib/constants.d.ts.map +1 -0
  23. package/dist/esm/lib/constants.js +93 -0
  24. package/dist/esm/lib/questionnaire-utils.d.ts +21 -1
  25. package/dist/esm/lib/questionnaire-utils.d.ts.map +1 -1
  26. package/dist/esm/lib/questionnaire-utils.js +85 -4
  27. package/dist/esm/types/fhir.d.ts +1 -0
  28. package/dist/esm/types/fhir.d.ts.map +1 -1
  29. package/dist/esm/types/index.d.ts +25 -0
  30. package/dist/esm/types/index.d.ts.map +1 -1
  31. package/dist/styles.css +108 -0
  32. package/package.json +17 -6
  33. package/dist/node_modules/@welshare/questionnaire/.tshy/build.json +0 -8
  34. package/dist/node_modules/@welshare/questionnaire/.tshy/esm.json +0 -16
  35. package/dist/node_modules/@welshare/questionnaire/LICENSE +0 -7
  36. package/dist/node_modules/@welshare/questionnaire/README.md +0 -173
  37. package/dist/node_modules/@welshare/questionnaire/dist/esm/components/debug-section.d.ts +0 -44
  38. package/dist/node_modules/@welshare/questionnaire/dist/esm/components/debug-section.d.ts.map +0 -1
  39. package/dist/node_modules/@welshare/questionnaire/dist/esm/components/debug-section.js +0 -28
  40. package/dist/node_modules/@welshare/questionnaire/dist/esm/components/question-renderer.d.ts +0 -80
  41. package/dist/node_modules/@welshare/questionnaire/dist/esm/components/question-renderer.d.ts.map +0 -1
  42. package/dist/node_modules/@welshare/questionnaire/dist/esm/components/question-renderer.js +0 -159
  43. package/dist/node_modules/@welshare/questionnaire/dist/esm/components/questions/boolean-question.d.ts +0 -15
  44. package/dist/node_modules/@welshare/questionnaire/dist/esm/components/questions/boolean-question.d.ts.map +0 -1
  45. package/dist/node_modules/@welshare/questionnaire/dist/esm/components/questions/boolean-question.js +0 -19
  46. package/dist/node_modules/@welshare/questionnaire/dist/esm/components/questions/choice-question.d.ts +0 -19
  47. package/dist/node_modules/@welshare/questionnaire/dist/esm/components/questions/choice-question.d.ts.map +0 -1
  48. package/dist/node_modules/@welshare/questionnaire/dist/esm/components/questions/choice-question.js +0 -23
  49. package/dist/node_modules/@welshare/questionnaire/dist/esm/components/questions/decimal-question.d.ts +0 -12
  50. package/dist/node_modules/@welshare/questionnaire/dist/esm/components/questions/decimal-question.d.ts.map +0 -1
  51. package/dist/node_modules/@welshare/questionnaire/dist/esm/components/questions/decimal-question.js +0 -7
  52. package/dist/node_modules/@welshare/questionnaire/dist/esm/components/questions/integer-question.d.ts +0 -18
  53. package/dist/node_modules/@welshare/questionnaire/dist/esm/components/questions/integer-question.d.ts.map +0 -1
  54. package/dist/node_modules/@welshare/questionnaire/dist/esm/components/questions/integer-question.js +0 -24
  55. package/dist/node_modules/@welshare/questionnaire/dist/esm/components/questions/multiple-choice-question.d.ts +0 -20
  56. package/dist/node_modules/@welshare/questionnaire/dist/esm/components/questions/multiple-choice-question.d.ts.map +0 -1
  57. package/dist/node_modules/@welshare/questionnaire/dist/esm/components/questions/multiple-choice-question.js +0 -39
  58. package/dist/node_modules/@welshare/questionnaire/dist/esm/components/questions/string-question.d.ts +0 -12
  59. package/dist/node_modules/@welshare/questionnaire/dist/esm/components/questions/string-question.d.ts.map +0 -1
  60. package/dist/node_modules/@welshare/questionnaire/dist/esm/components/questions/string-question.js +0 -7
  61. package/dist/node_modules/@welshare/questionnaire/dist/esm/contexts/questionnaire-context.d.ts +0 -41
  62. package/dist/node_modules/@welshare/questionnaire/dist/esm/contexts/questionnaire-context.d.ts.map +0 -1
  63. package/dist/node_modules/@welshare/questionnaire/dist/esm/contexts/questionnaire-context.js +0 -350
  64. package/dist/node_modules/@welshare/questionnaire/dist/esm/index.d.ts +0 -7
  65. package/dist/node_modules/@welshare/questionnaire/dist/esm/index.d.ts.map +0 -1
  66. package/dist/node_modules/@welshare/questionnaire/dist/esm/index.js +0 -6
  67. package/dist/node_modules/@welshare/questionnaire/dist/esm/lib/questionnaire-utils.d.ts +0 -33
  68. package/dist/node_modules/@welshare/questionnaire/dist/esm/lib/questionnaire-utils.d.ts.map +0 -1
  69. package/dist/node_modules/@welshare/questionnaire/dist/esm/lib/questionnaire-utils.js +0 -99
  70. package/dist/node_modules/@welshare/questionnaire/dist/esm/package.json +0 -3
  71. package/dist/node_modules/@welshare/questionnaire/dist/esm/types/fhir.d.ts +0 -117
  72. package/dist/node_modules/@welshare/questionnaire/dist/esm/types/fhir.d.ts.map +0 -1
  73. package/dist/node_modules/@welshare/questionnaire/dist/esm/types/fhir.js +0 -3
  74. package/dist/node_modules/@welshare/questionnaire/dist/esm/types/index.d.ts +0 -51
  75. package/dist/node_modules/@welshare/questionnaire/dist/esm/types/index.d.ts.map +0 -1
  76. package/dist/node_modules/@welshare/questionnaire/dist/esm/types/index.js +0 -1
  77. package/dist/node_modules/@welshare/questionnaire/dist/styles.css +0 -467
  78. package/dist/node_modules/@welshare/questionnaire/dist/tokens.css +0 -130
  79. package/dist/node_modules/@welshare/questionnaire/package.json +0 -85
  80. package/dist/node_modules/@welshare/questionnaire/src/components/debug-section.tsx +0 -116
  81. package/dist/node_modules/@welshare/questionnaire/src/components/question-renderer.tsx +0 -368
  82. package/dist/node_modules/@welshare/questionnaire/src/components/questionnaire-styles.css +0 -467
  83. package/dist/node_modules/@welshare/questionnaire/src/components/questionnaire-tokens.css +0 -130
  84. package/dist/node_modules/@welshare/questionnaire/src/components/questions/boolean-question.tsx +0 -72
  85. package/dist/node_modules/@welshare/questionnaire/src/components/questions/choice-question.tsx +0 -68
  86. package/dist/node_modules/@welshare/questionnaire/src/components/questions/decimal-question.tsx +0 -32
  87. package/dist/node_modules/@welshare/questionnaire/src/components/questions/integer-question.tsx +0 -87
  88. package/dist/node_modules/@welshare/questionnaire/src/components/questions/multiple-choice-question.tsx +0 -119
  89. package/dist/node_modules/@welshare/questionnaire/src/components/questions/string-question.tsx +0 -31
  90. package/dist/node_modules/@welshare/questionnaire/src/contexts/questionnaire-context.tsx +0 -499
  91. package/dist/node_modules/@welshare/questionnaire/src/index.ts +0 -41
  92. package/dist/node_modules/@welshare/questionnaire/src/lib/__tests__/questionnaire-utils.test.ts +0 -578
  93. package/dist/node_modules/@welshare/questionnaire/src/lib/questionnaire-utils.ts +0 -122
  94. package/dist/node_modules/@welshare/questionnaire/src/types/fhir.ts +0 -126
  95. package/dist/node_modules/@welshare/questionnaire/src/types/index.ts +0 -44
  96. package/dist/node_modules/@welshare/questionnaire/tsconfig.json +0 -16
@@ -1,68 +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
-
5
-
6
- export interface ChoiceQuestionProps {
7
- item: QuestionnaireItem;
8
- currentAnswer?: QuestionnaireResponseAnswer;
9
- onChoiceChange: (
10
- valueCoding: { system?: string; code?: string; display?: string },
11
- valueInteger?: number
12
- ) => void;
13
- choiceClassName?: string;
14
- renderRadioInput?: (props: RadioInputProps) => ReactNode;
15
- }
16
-
17
- /**
18
- * Renders a single-select choice question with radio buttons
19
- */
20
- export const ChoiceQuestion = ({
21
- item,
22
- currentAnswer,
23
- onChoiceChange,
24
- choiceClassName = '',
25
- renderRadioInput
26
- }: ChoiceQuestionProps) => {
27
- return (
28
- <div className={`wq-question-choice ${choiceClassName}`}>
29
- {item.answerOption?.map((option, index) => {
30
- const isSelected = currentAnswer?.valueCoding?.code === option.valueCoding?.code;
31
-
32
- // Use custom renderer if provided
33
- if (renderRadioInput) {
34
- return (
35
- <div key={index}>
36
- {renderRadioInput({
37
- linkId: item.linkId,
38
- valueCoding: option.valueCoding,
39
- valueInteger: option.valueInteger,
40
- checked: isSelected,
41
- onChange: () => onChoiceChange(option.valueCoding || {}, option.valueInteger),
42
- label: option.valueCoding?.display || '',
43
- index
44
- })}
45
- </div>
46
- );
47
- }
48
-
49
- // Default rendering
50
- return (
51
- <label key={index} className={`wq-choice-option ${isSelected ? 'wq-selected' : ''}`}>
52
- <input
53
- type="radio"
54
- name={item.linkId}
55
- value={option.valueCoding?.code}
56
- checked={isSelected}
57
- onChange={() => onChoiceChange(option.valueCoding || {}, option.valueInteger)}
58
- data-wq-input="radio"
59
- data-wq-selected={isSelected}
60
- />
61
- <span className="wq-choice-label">{option.valueCoding?.display}</span>
62
- </label>
63
- );
64
- })}
65
- </div>
66
- );
67
- };
68
-
@@ -1,32 +0,0 @@
1
- import type {
2
- QuestionnaireItem,
3
- QuestionnaireResponseAnswer,
4
- } from "../../types/fhir.js";
5
-
6
- export interface DecimalQuestionProps {
7
- item: QuestionnaireItem;
8
- currentAnswer?: QuestionnaireResponseAnswer;
9
- onDecimalChange: (value: string) => void;
10
- inputClassName?: string;
11
- }
12
-
13
- /**
14
- * Renders a decimal question with number input
15
- */
16
- export const DecimalQuestion = ({
17
- item,
18
- currentAnswer,
19
- onDecimalChange,
20
- inputClassName = "",
21
- }: DecimalQuestionProps) => {
22
- return (
23
- <input
24
- type="number"
25
- className={`wq-question-input ${inputClassName}`}
26
- value={currentAnswer?.valueDecimal ?? ""}
27
- onChange={(e) => onDecimalChange(e.target.value)}
28
- placeholder="Enter a number"
29
- step="0.1"
30
- />
31
- );
32
- };
@@ -1,87 +0,0 @@
1
- import type {
2
- QuestionnaireItem,
3
- QuestionnaireResponseAnswer,
4
- } from "../../types/fhir.js";
5
-
6
- export interface IntegerQuestionProps {
7
- item: QuestionnaireItem;
8
- currentAnswer?: QuestionnaireResponseAnswer;
9
- onIntegerChange: (value: string) => void;
10
- inputClassName?: string;
11
- sliderConfig?: {
12
- minValue: number;
13
- maxValue: number;
14
- step: number;
15
- unit: string;
16
- } | null;
17
- }
18
-
19
- /**
20
- * Renders an integer question with optional slider control
21
- */
22
- export const IntegerQuestion = ({
23
- item,
24
- currentAnswer,
25
- onIntegerChange,
26
- inputClassName = "",
27
- sliderConfig,
28
- }: IntegerQuestionProps) => {
29
- // Render slider if slider config is present
30
- if (sliderConfig) {
31
- // Use current answer, or fallback to initial value, or fallback to minValue
32
- const initialValue = item.initial?.[0]?.valueInteger;
33
- const value =
34
- currentAnswer?.valueInteger ?? initialValue ?? sliderConfig.minValue;
35
- const unit = sliderConfig.unit || "";
36
-
37
- // Create abbreviated unit for range labels
38
- const unitShort =
39
- unit === "minutes"
40
- ? "min"
41
- : unit === "hours"
42
- ? "hr"
43
- : unit === "days per week"
44
- ? "days"
45
- : unit;
46
-
47
- return (
48
- <div className="wq-question-slider">
49
- <input
50
- type="range"
51
- className={`wq-slider-input ${inputClassName}`}
52
- min={sliderConfig.minValue}
53
- max={sliderConfig.maxValue}
54
- step={sliderConfig.step}
55
- value={value}
56
- onChange={(e) => onIntegerChange(e.target.value)}
57
- />
58
- <div className="wq-slider-value-display">
59
- <span className="wq-slider-value">{value}</span>
60
- {unit && <span className="wq-slider-unit">{unit}</span>}
61
- </div>
62
- <div className="wq-slider-range-labels">
63
- <span className="wq-slider-min">
64
- {sliderConfig.minValue}
65
- {unitShort && ` ${unitShort}`}
66
- </span>
67
- <span className="wq-slider-max">
68
- {sliderConfig.maxValue}
69
- {unitShort && ` ${unitShort}`}
70
- </span>
71
- </div>
72
- </div>
73
- );
74
- }
75
-
76
- // Default number input
77
- return (
78
- <input
79
- type="number"
80
- className={`wq-question-input ${inputClassName}`}
81
- value={currentAnswer?.valueInteger ?? ""}
82
- onChange={(e) => onIntegerChange(e.target.value)}
83
- placeholder="Enter a number"
84
- step="1"
85
- />
86
- );
87
- };
@@ -1,119 +0,0 @@
1
- import { type ReactNode } from "react";
2
- import type {
3
- QuestionnaireItem,
4
- QuestionnaireResponseAnswer,
5
- } from "../../types/fhir.js";
6
- import { CheckboxInputProps } from "../../types/index.js";
7
-
8
- export interface MultipleChoiceQuestionProps {
9
- item: QuestionnaireItem;
10
- currentAnswers: QuestionnaireResponseAnswer[];
11
- onMultipleChoiceToggle: (
12
- valueCoding: { system?: string; code?: string; display?: string },
13
- valueInteger?: number
14
- ) => void;
15
- choiceClassName?: string;
16
- renderCheckboxInput?: (props: CheckboxInputProps) => ReactNode;
17
- }
18
-
19
- /**
20
- * Renders a multi-select choice question with checkboxes
21
- * Supports exclusive options and maxAnswers limits
22
- */
23
- export const MultipleChoiceQuestion = ({
24
- item,
25
- currentAnswers,
26
- onMultipleChoiceToggle,
27
- choiceClassName = "",
28
- renderCheckboxInput,
29
- }: MultipleChoiceQuestionProps) => {
30
- const maxAnswers = item.maxAnswers || Number.MAX_SAFE_INTEGER;
31
- const atMaxAnswers = currentAnswers.length >= maxAnswers;
32
-
33
- // Check if there's an exclusive option extension
34
- const exclusiveOptionExt = item.extension?.find(
35
- (ext) =>
36
- ext.url ===
37
- "http://codes.welshare.app/StructureDefinition/questionnaire-exclusive-option"
38
- );
39
- const exclusiveOptionCode = exclusiveOptionExt?.valueString;
40
-
41
- // Check if the exclusive option is currently selected
42
- const exclusiveSelected =
43
- exclusiveOptionCode &&
44
- currentAnswers.some(
45
- (answer) => answer.valueCoding?.code === exclusiveOptionCode
46
- );
47
-
48
- // Filter options to show: if exclusive option is selected, only show that one
49
- const optionsToShow = exclusiveSelected
50
- ? item.answerOption?.filter(
51
- (opt) => opt.valueCoding?.code === exclusiveOptionCode
52
- )
53
- : item.answerOption;
54
-
55
- return (
56
- <div className={`wq-question-choice ${choiceClassName}`}>
57
- {optionsToShow?.map((option, index) => {
58
- const isSelected = currentAnswers.some(
59
- (answer) => answer.valueCoding?.code === option.valueCoding?.code
60
- );
61
- const isDisabled = !isSelected && atMaxAnswers;
62
-
63
- // Use custom renderer if provided
64
- if (renderCheckboxInput) {
65
- return (
66
- <div key={index}>
67
- {renderCheckboxInput({
68
- linkId: item.linkId,
69
- valueCoding: option.valueCoding,
70
- valueInteger: option.valueInteger,
71
- checked: isSelected,
72
- disabled: isDisabled,
73
- onChange: () =>
74
- onMultipleChoiceToggle(
75
- option.valueCoding || {},
76
- option.valueInteger
77
- ),
78
- label: option.valueCoding?.display || "",
79
- index,
80
- })}
81
- </div>
82
- );
83
- }
84
-
85
- // Default rendering
86
- return (
87
- <label
88
- key={index}
89
- className={`wq-choice-option ${isSelected ? "wq-selected" : ""} ${isDisabled ? "wq-disabled" : ""}`}
90
- >
91
- <input
92
- type="checkbox"
93
- name={item.linkId}
94
- value={option.valueCoding?.code}
95
- checked={isSelected}
96
- disabled={isDisabled}
97
- onChange={() =>
98
- onMultipleChoiceToggle(
99
- option.valueCoding || {},
100
- option.valueInteger
101
- )
102
- }
103
- data-wq-input="checkbox"
104
- data-wq-selected={isSelected}
105
- />
106
- <span className="wq-choice-label">
107
- {option.valueCoding?.display}
108
- </span>
109
- </label>
110
- );
111
- })}
112
- {item.maxAnswers && (
113
- <div className="wq-max-answers-hint">
114
- Selected: {currentAnswers.length} / {item.maxAnswers}
115
- </div>
116
- )}
117
- </div>
118
- );
119
- };
@@ -1,31 +0,0 @@
1
- import type {
2
- QuestionnaireItem,
3
- QuestionnaireResponseAnswer,
4
- } from "../../types/fhir.js";
5
-
6
- export interface StringQuestionProps {
7
- item: QuestionnaireItem;
8
- currentAnswer?: QuestionnaireResponseAnswer;
9
- onStringChange: (value: string) => void;
10
- inputClassName?: string;
11
- }
12
-
13
- /**
14
- * Renders a string or text question with text input
15
- */
16
- export const StringQuestion = ({
17
- item,
18
- currentAnswer,
19
- onStringChange,
20
- inputClassName = "",
21
- }: StringQuestionProps) => {
22
- return (
23
- <input
24
- type="text"
25
- className={`wq-question-input ${inputClassName}`}
26
- value={currentAnswer?.valueString ?? ""}
27
- onChange={(e) => onStringChange(e.target.value)}
28
- placeholder="Enter your answer"
29
- />
30
- );
31
- };