@welshare/questionnaire 0.1.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 (109) hide show
  1. package/LICENSE +7 -0
  2. package/README.md +173 -0
  3. package/dist/esm/components/debug-section.d.ts +44 -0
  4. package/dist/esm/components/debug-section.d.ts.map +1 -0
  5. package/dist/esm/components/debug-section.js +28 -0
  6. package/dist/esm/components/question-renderer.d.ts +80 -0
  7. package/dist/esm/components/question-renderer.d.ts.map +1 -0
  8. package/dist/esm/components/question-renderer.js +159 -0
  9. package/dist/esm/components/questions/boolean-question.d.ts +15 -0
  10. package/dist/esm/components/questions/boolean-question.d.ts.map +1 -0
  11. package/dist/esm/components/questions/boolean-question.js +19 -0
  12. package/dist/esm/components/questions/choice-question.d.ts +19 -0
  13. package/dist/esm/components/questions/choice-question.d.ts.map +1 -0
  14. package/dist/esm/components/questions/choice-question.js +23 -0
  15. package/dist/esm/components/questions/decimal-question.d.ts +12 -0
  16. package/dist/esm/components/questions/decimal-question.d.ts.map +1 -0
  17. package/dist/esm/components/questions/decimal-question.js +7 -0
  18. package/dist/esm/components/questions/integer-question.d.ts +18 -0
  19. package/dist/esm/components/questions/integer-question.d.ts.map +1 -0
  20. package/dist/esm/components/questions/integer-question.js +24 -0
  21. package/dist/esm/components/questions/multiple-choice-question.d.ts +20 -0
  22. package/dist/esm/components/questions/multiple-choice-question.d.ts.map +1 -0
  23. package/dist/esm/components/questions/multiple-choice-question.js +39 -0
  24. package/dist/esm/components/questions/string-question.d.ts +12 -0
  25. package/dist/esm/components/questions/string-question.d.ts.map +1 -0
  26. package/dist/esm/components/questions/string-question.js +7 -0
  27. package/dist/esm/contexts/questionnaire-context.d.ts +41 -0
  28. package/dist/esm/contexts/questionnaire-context.d.ts.map +1 -0
  29. package/dist/esm/contexts/questionnaire-context.js +350 -0
  30. package/dist/esm/index.d.ts +7 -0
  31. package/dist/esm/index.d.ts.map +1 -0
  32. package/dist/esm/index.js +6 -0
  33. package/dist/esm/lib/questionnaire-utils.d.ts +29 -0
  34. package/dist/esm/lib/questionnaire-utils.d.ts.map +1 -0
  35. package/dist/esm/lib/questionnaire-utils.js +80 -0
  36. package/dist/esm/package.json +3 -0
  37. package/dist/esm/types/fhir.d.ts +117 -0
  38. package/dist/esm/types/fhir.d.ts.map +1 -0
  39. package/dist/esm/types/fhir.js +3 -0
  40. package/dist/esm/types/index.d.ts +51 -0
  41. package/dist/esm/types/index.d.ts.map +1 -0
  42. package/dist/esm/types/index.js +1 -0
  43. package/dist/node_modules/@welshare/questionnaire/.tshy/build.json +8 -0
  44. package/dist/node_modules/@welshare/questionnaire/.tshy/esm.json +16 -0
  45. package/dist/node_modules/@welshare/questionnaire/LICENSE +7 -0
  46. package/dist/node_modules/@welshare/questionnaire/README.md +173 -0
  47. package/dist/node_modules/@welshare/questionnaire/dist/esm/components/debug-section.d.ts +44 -0
  48. package/dist/node_modules/@welshare/questionnaire/dist/esm/components/debug-section.d.ts.map +1 -0
  49. package/dist/node_modules/@welshare/questionnaire/dist/esm/components/debug-section.js +28 -0
  50. package/dist/node_modules/@welshare/questionnaire/dist/esm/components/question-renderer.d.ts +80 -0
  51. package/dist/node_modules/@welshare/questionnaire/dist/esm/components/question-renderer.d.ts.map +1 -0
  52. package/dist/node_modules/@welshare/questionnaire/dist/esm/components/question-renderer.js +159 -0
  53. package/dist/node_modules/@welshare/questionnaire/dist/esm/components/questions/boolean-question.d.ts +15 -0
  54. package/dist/node_modules/@welshare/questionnaire/dist/esm/components/questions/boolean-question.d.ts.map +1 -0
  55. package/dist/node_modules/@welshare/questionnaire/dist/esm/components/questions/boolean-question.js +19 -0
  56. package/dist/node_modules/@welshare/questionnaire/dist/esm/components/questions/choice-question.d.ts +19 -0
  57. package/dist/node_modules/@welshare/questionnaire/dist/esm/components/questions/choice-question.d.ts.map +1 -0
  58. package/dist/node_modules/@welshare/questionnaire/dist/esm/components/questions/choice-question.js +23 -0
  59. package/dist/node_modules/@welshare/questionnaire/dist/esm/components/questions/decimal-question.d.ts +12 -0
  60. package/dist/node_modules/@welshare/questionnaire/dist/esm/components/questions/decimal-question.d.ts.map +1 -0
  61. package/dist/node_modules/@welshare/questionnaire/dist/esm/components/questions/decimal-question.js +7 -0
  62. package/dist/node_modules/@welshare/questionnaire/dist/esm/components/questions/integer-question.d.ts +18 -0
  63. package/dist/node_modules/@welshare/questionnaire/dist/esm/components/questions/integer-question.d.ts.map +1 -0
  64. package/dist/node_modules/@welshare/questionnaire/dist/esm/components/questions/integer-question.js +24 -0
  65. package/dist/node_modules/@welshare/questionnaire/dist/esm/components/questions/multiple-choice-question.d.ts +20 -0
  66. package/dist/node_modules/@welshare/questionnaire/dist/esm/components/questions/multiple-choice-question.d.ts.map +1 -0
  67. package/dist/node_modules/@welshare/questionnaire/dist/esm/components/questions/multiple-choice-question.js +39 -0
  68. package/dist/node_modules/@welshare/questionnaire/dist/esm/components/questions/string-question.d.ts +12 -0
  69. package/dist/node_modules/@welshare/questionnaire/dist/esm/components/questions/string-question.d.ts.map +1 -0
  70. package/dist/node_modules/@welshare/questionnaire/dist/esm/components/questions/string-question.js +7 -0
  71. package/dist/node_modules/@welshare/questionnaire/dist/esm/contexts/questionnaire-context.d.ts +41 -0
  72. package/dist/node_modules/@welshare/questionnaire/dist/esm/contexts/questionnaire-context.d.ts.map +1 -0
  73. package/dist/node_modules/@welshare/questionnaire/dist/esm/contexts/questionnaire-context.js +350 -0
  74. package/dist/node_modules/@welshare/questionnaire/dist/esm/index.d.ts +7 -0
  75. package/dist/node_modules/@welshare/questionnaire/dist/esm/index.d.ts.map +1 -0
  76. package/dist/node_modules/@welshare/questionnaire/dist/esm/index.js +6 -0
  77. package/dist/node_modules/@welshare/questionnaire/dist/esm/lib/questionnaire-utils.d.ts +29 -0
  78. package/dist/node_modules/@welshare/questionnaire/dist/esm/lib/questionnaire-utils.d.ts.map +1 -0
  79. package/dist/node_modules/@welshare/questionnaire/dist/esm/lib/questionnaire-utils.js +80 -0
  80. package/dist/node_modules/@welshare/questionnaire/dist/esm/package.json +3 -0
  81. package/dist/node_modules/@welshare/questionnaire/dist/esm/types/fhir.d.ts +117 -0
  82. package/dist/node_modules/@welshare/questionnaire/dist/esm/types/fhir.d.ts.map +1 -0
  83. package/dist/node_modules/@welshare/questionnaire/dist/esm/types/fhir.js +3 -0
  84. package/dist/node_modules/@welshare/questionnaire/dist/esm/types/index.d.ts +51 -0
  85. package/dist/node_modules/@welshare/questionnaire/dist/esm/types/index.d.ts.map +1 -0
  86. package/dist/node_modules/@welshare/questionnaire/dist/esm/types/index.js +1 -0
  87. package/dist/node_modules/@welshare/questionnaire/dist/styles.css +467 -0
  88. package/dist/node_modules/@welshare/questionnaire/dist/tokens.css +130 -0
  89. package/dist/node_modules/@welshare/questionnaire/package.json +85 -0
  90. package/dist/node_modules/@welshare/questionnaire/src/components/debug-section.tsx +116 -0
  91. package/dist/node_modules/@welshare/questionnaire/src/components/question-renderer.tsx +368 -0
  92. package/dist/node_modules/@welshare/questionnaire/src/components/questionnaire-styles.css +467 -0
  93. package/dist/node_modules/@welshare/questionnaire/src/components/questionnaire-tokens.css +130 -0
  94. package/dist/node_modules/@welshare/questionnaire/src/components/questions/boolean-question.tsx +72 -0
  95. package/dist/node_modules/@welshare/questionnaire/src/components/questions/choice-question.tsx +68 -0
  96. package/dist/node_modules/@welshare/questionnaire/src/components/questions/decimal-question.tsx +32 -0
  97. package/dist/node_modules/@welshare/questionnaire/src/components/questions/integer-question.tsx +87 -0
  98. package/dist/node_modules/@welshare/questionnaire/src/components/questions/multiple-choice-question.tsx +119 -0
  99. package/dist/node_modules/@welshare/questionnaire/src/components/questions/string-question.tsx +31 -0
  100. package/dist/node_modules/@welshare/questionnaire/src/contexts/questionnaire-context.tsx +499 -0
  101. package/dist/node_modules/@welshare/questionnaire/src/index.ts +40 -0
  102. package/dist/node_modules/@welshare/questionnaire/src/lib/__tests__/questionnaire-utils.test.ts +578 -0
  103. package/dist/node_modules/@welshare/questionnaire/src/lib/questionnaire-utils.ts +99 -0
  104. package/dist/node_modules/@welshare/questionnaire/src/types/fhir.ts +126 -0
  105. package/dist/node_modules/@welshare/questionnaire/src/types/index.ts +44 -0
  106. package/dist/node_modules/@welshare/questionnaire/tsconfig.json +16 -0
  107. package/dist/styles.css +467 -0
  108. package/dist/tokens.css +130 -0
  109. package/package.json +84 -0
@@ -0,0 +1,126 @@
1
+ // FHIR Types for Questionnaire and QuestionnaireResponse
2
+ // Based on FHIR R4 Specification with extensions commonly used in Welshare surveys
3
+
4
+ export type Coding = {
5
+ system?: string;
6
+ version?: string;
7
+ code?: string;
8
+ display?: string;
9
+ userSelected?: boolean;
10
+ }
11
+
12
+ export type QuestionnaireItemAnswerOption = {
13
+ valueCoding?: Coding;
14
+ valueInteger?: number;
15
+ valueDate?: string;
16
+ valueTime?: string;
17
+ valueString?: string;
18
+ initialSelected?: boolean;
19
+ }
20
+
21
+ export type Extension = {
22
+ url: string;
23
+ valueBoolean?: boolean;
24
+ valueString?: string;
25
+ valueInteger?: number;
26
+ valueCodeableConcept?: {
27
+ coding?: Coding[];
28
+ };
29
+ valueExpression?: {
30
+ language?: string;
31
+ expression?: string;
32
+ };
33
+ extension?: Extension[];
34
+ }
35
+
36
+ export type QuestionnaireItem = {
37
+ linkId: string;
38
+ definition?: string;
39
+ code?: Coding[];
40
+ prefix?: string;
41
+ text?: string;
42
+ type: 'group' | 'display' | 'boolean' | 'decimal' | 'integer' | 'date' | 'dateTime' | 'time' | 'string' | 'text' | 'url' | 'choice' | 'open-choice' | 'attachment' | 'reference' | 'quantity';
43
+ enableWhen?: Array<{
44
+ question: string;
45
+ operator: string;
46
+ answerBoolean?: boolean;
47
+ answerDecimal?: number;
48
+ answerInteger?: number;
49
+ answerDate?: string;
50
+ answerDateTime?: string;
51
+ answerTime?: string;
52
+ answerString?: string;
53
+ answerCoding?: Coding;
54
+ }>;
55
+ enableBehavior?: string;
56
+ required?: boolean;
57
+ repeats?: boolean;
58
+ readOnly?: boolean;
59
+ maxLength?: number;
60
+ maxAnswers?: number;
61
+ answerValueSet?: string;
62
+ answerOption?: QuestionnaireItemAnswerOption[];
63
+ initial?: Array<{
64
+ valueBoolean?: boolean;
65
+ valueDecimal?: number;
66
+ valueInteger?: number;
67
+ valueDate?: string;
68
+ valueDateTime?: string;
69
+ valueTime?: string;
70
+ valueString?: string;
71
+ valueCoding?: Coding;
72
+ }>;
73
+ extension?: Extension[];
74
+ item?: QuestionnaireItem[];
75
+ }
76
+
77
+ export type Questionnaire = {
78
+ resourceType: 'Questionnaire';
79
+ id: string;
80
+ url?: string;
81
+ version?: string;
82
+ name?: string;
83
+ title?: string;
84
+ status: 'draft' | 'active' | 'retired' | 'unknown';
85
+ subjectType?: string[];
86
+ date?: string;
87
+ publisher?: string;
88
+ description?: string;
89
+ item?: QuestionnaireItem[];
90
+ }
91
+
92
+ export type QuestionnaireResponseAnswer = {
93
+ valueBoolean?: boolean;
94
+ valueDecimal?: number;
95
+ valueInteger?: number;
96
+ valueDate?: string;
97
+ valueDateTime?: string;
98
+ valueTime?: string;
99
+ valueString?: string;
100
+ valueUri?: string;
101
+ valueCoding?: Coding;
102
+ valueQuantity?: {
103
+ value?: number;
104
+ unit?: string;
105
+ system?: string;
106
+ code?: string;
107
+ };
108
+ item?: QuestionnaireResponseItem[];
109
+ }
110
+
111
+ export type QuestionnaireResponseItem = {
112
+ linkId: string;
113
+ definition?: string;
114
+ text?: string;
115
+ answer?: QuestionnaireResponseAnswer[];
116
+ item?: QuestionnaireResponseItem[];
117
+ }
118
+
119
+ export type QuestionnaireResponse = {
120
+ resourceType: 'QuestionnaireResponse';
121
+ id?: string;
122
+ questionnaire?: string;
123
+ status: 'in-progress' | 'completed' | 'amended' | 'entered-in-error' | 'stopped';
124
+ authored?: string;
125
+ item?: QuestionnaireResponseItem[];
126
+ }
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Props for rendering a radio button option
3
+ */
4
+ export interface RadioInputProps {
5
+ /** The linkId of the question item */
6
+ linkId: string;
7
+ /** The option's value coding */
8
+ valueCoding?: { system?: string; code?: string; display?: string };
9
+ /** The option's integer value (if applicable) */
10
+ valueInteger?: number;
11
+ /** Whether this option is currently selected */
12
+ checked: boolean;
13
+ /** Whether this option is disabled */
14
+ disabled?: boolean;
15
+ /** Callback when the option is selected */
16
+ onChange: () => void;
17
+ /** The display text for this option */
18
+ label: string;
19
+ /** The index of this option in the list */
20
+ index: number;
21
+ }
22
+
23
+
24
+ /**
25
+ * Props for rendering a checkbox option
26
+ */
27
+ export interface CheckboxInputProps {
28
+ /** The linkId of the question item */
29
+ linkId: string;
30
+ /** The option's value coding */
31
+ valueCoding?: { system?: string; code?: string; display?: string };
32
+ /** The option's integer value (if applicable) */
33
+ valueInteger?: number;
34
+ /** Whether this option is currently selected */
35
+ checked: boolean;
36
+ /** Whether this option is disabled */
37
+ disabled?: boolean;
38
+ /** Callback when the option is toggled */
39
+ onChange: () => void;
40
+ /** The display text for this option */
41
+ label: string;
42
+ /** The index of this option in the list */
43
+ index: number;
44
+ }
@@ -0,0 +1,16 @@
1
+ {
2
+ "extends": "@workspace/typescript-config/react-library.json",
3
+ "compilerOptions": {
4
+ "baseUrl": ".",
5
+ "paths": {
6
+ "@/*": ["./src/*"]
7
+ },
8
+ "allowJs": true,
9
+ "jsx": "react-jsx"
10
+ },
11
+ "include": [
12
+ "**/*.ts",
13
+ "**/*.tsx"
14
+ ],
15
+ "exclude": ["node_modules", "dist"]
16
+ }
@@ -0,0 +1,467 @@
1
+ /**
2
+ * Welshare Questionnaire Styles
3
+ *
4
+ * Scoped styles using .wq- prefix to avoid conflicts with other CSS systems.
5
+ * Uses CSS custom properties from questionnaire-tokens.css for easy customization.
6
+ *
7
+ * Import both files in your application:
8
+ * import '@welshare/react/questionnaire-tokens.css';
9
+ * import '@welshare/react/questionnaire-styles.css';
10
+ */
11
+
12
+ /* === Question Container === */
13
+ .wq-question-container {
14
+ margin-bottom: var(--wq-question-gap);
15
+ padding: var(--wq-space-lg);
16
+ border-radius: var(--wq-radius-md);
17
+ transition: all var(--wq-transition-base);
18
+ }
19
+
20
+ .wq-question-container.wq-has-error {
21
+ border: var(--wq-border-width) solid var(--wq-color-error-border);
22
+ background-color: var(--wq-color-error-bg);
23
+ }
24
+
25
+ /* === Question Text === */
26
+ .wq-question-text {
27
+ font-size: var(--wq-font-size-lg);
28
+ font-weight: var(--wq-font-weight-medium);
29
+ margin-bottom: var(--wq-space-md);
30
+ color: var(--wq-color-text-primary);
31
+ line-height: 1.5;
32
+ }
33
+
34
+ .wq-required-indicator {
35
+ color: var(--wq-color-error);
36
+ margin-left: var(--wq-space-xs);
37
+ font-weight: var(--wq-font-weight-semibold);
38
+ }
39
+
40
+ /* === Choice Inputs (Radio/Checkbox) === */
41
+ .wq-question-choice {
42
+ display: flex;
43
+ flex-direction: column;
44
+ gap: var(--wq-space-md);
45
+ }
46
+
47
+ .wq-choice-option {
48
+ display: flex;
49
+ align-items: center;
50
+ padding: var(--wq-choice-padding-y) var(--wq-choice-padding-x);
51
+ border: var(--wq-border-width) solid var(--wq-color-border);
52
+ border-radius: var(--wq-radius-md);
53
+ cursor: pointer;
54
+ transition: all var(--wq-transition-fast);
55
+ background-color: var(--wq-color-surface);
56
+ }
57
+
58
+ .wq-choice-option:hover:not(.wq-disabled) {
59
+ border-color: var(--wq-color-border-hover);
60
+ background-color: var(--wq-color-background);
61
+ }
62
+
63
+ .wq-choice-option.wq-selected {
64
+ border-color: var(--wq-color-selected-border);
65
+ background-color: var(--wq-color-selected);
66
+ }
67
+
68
+ .wq-choice-option.wq-disabled {
69
+ opacity: 0.5;
70
+ cursor: not-allowed;
71
+ }
72
+
73
+ /* === Default Input Styling (for backward compatibility) === */
74
+ /* Note: When using custom renderers, these styles won't apply */
75
+ .wq-choice-option input[type="radio"],
76
+ .wq-choice-option input[type="checkbox"] {
77
+ margin-right: var(--wq-space-md);
78
+ width: 1.25rem;
79
+ height: 1.25rem;
80
+ cursor: pointer;
81
+ flex-shrink: 0;
82
+ }
83
+
84
+ .wq-choice-option.wq-disabled input[type="radio"],
85
+ .wq-choice-option.wq-disabled input[type="checkbox"] {
86
+ cursor: not-allowed;
87
+ opacity: 0.5;
88
+ }
89
+
90
+ .wq-choice-label {
91
+ flex: 1;
92
+ font-size: var(--wq-font-size-base);
93
+ color: var(--wq-color-text-secondary);
94
+ line-height: 1.5;
95
+ }
96
+
97
+ .wq-choice-option.wq-selected .wq-choice-label {
98
+ color: var(--wq-color-text-primary);
99
+ font-weight: var(--wq-font-weight-medium);
100
+ }
101
+
102
+ .wq-max-answers-hint {
103
+ font-size: var(--wq-font-size-sm);
104
+ color: var(--wq-color-text-tertiary);
105
+ margin-top: var(--wq-space-sm);
106
+ font-weight: var(--wq-font-weight-normal);
107
+ }
108
+
109
+ /* === Text Inputs === */
110
+ .wq-question-input {
111
+ width: 100%;
112
+ padding: var(--wq-input-padding-y) var(--wq-input-padding-x);
113
+ border: var(--wq-border-width) solid var(--wq-color-border);
114
+ border-radius: var(--wq-radius-md);
115
+ font-size: var(--wq-font-size-base);
116
+ color: var(--wq-color-text-primary);
117
+ background-color: var(--wq-color-surface);
118
+ transition: all var(--wq-transition-fast);
119
+ min-height: var(--wq-input-height);
120
+ line-height: 1.5;
121
+ }
122
+
123
+ .wq-question-input:hover {
124
+ border-color: var(--wq-color-border-hover);
125
+ }
126
+
127
+ .wq-question-input:focus {
128
+ outline: none;
129
+ border-color: var(--wq-color-border-focus);
130
+ box-shadow: var(--wq-shadow-focus);
131
+ }
132
+
133
+ .wq-question-input::placeholder {
134
+ color: var(--wq-color-text-placeholder);
135
+ }
136
+
137
+ .wq-question-input:disabled {
138
+ opacity: 0.6;
139
+ cursor: not-allowed;
140
+ background-color: var(--wq-color-background);
141
+ }
142
+
143
+ /* === Slider Inputs === */
144
+ .wq-question-slider {
145
+ padding: var(--wq-space-lg) 0;
146
+ }
147
+
148
+ .wq-slider-input {
149
+ width: 100%;
150
+ height: var(--wq-slider-height);
151
+ border-radius: var(--wq-radius-sm);
152
+ background: var(--wq-color-border);
153
+ outline: none;
154
+ -webkit-appearance: none;
155
+ appearance: none;
156
+ cursor: pointer;
157
+ margin-bottom: 1rem;
158
+
159
+ }
160
+
161
+ .wq-slider-input::-webkit-slider-thumb {
162
+ -webkit-appearance: none;
163
+ appearance: none;
164
+ width: var(--wq-slider-thumb-size);
165
+ height: var(--wq-slider-thumb-size);
166
+ border-radius: var(--wq-radius-full);
167
+ background: var(--wq-color-primary);
168
+ cursor: pointer;
169
+ transition: all var(--wq-transition-fast);
170
+ box-shadow: var(--wq-shadow-sm);
171
+ }
172
+
173
+ .wq-slider-input::-webkit-slider-thumb:hover {
174
+ background: var(--wq-color-primary-hover);
175
+ transform: scale(1.1);
176
+ }
177
+
178
+ .wq-slider-input::-webkit-slider-thumb:active {
179
+ transform: scale(0.95);
180
+ }
181
+
182
+ .wq-slider-input::-moz-range-thumb {
183
+ width: var(--wq-slider-thumb-size);
184
+ height: var(--wq-slider-thumb-size);
185
+ border-radius: var(--wq-radius-full);
186
+ background: var(--wq-color-primary);
187
+ cursor: pointer;
188
+ border: none;
189
+ transition: all var(--wq-transition-fast);
190
+ box-shadow: var(--wq-shadow-sm);
191
+ }
192
+
193
+ .wq-slider-input::-moz-range-thumb:hover {
194
+ background: var(--wq-color-primary-hover);
195
+ transform: scale(1.1);
196
+ }
197
+
198
+ .wq-slider-input::-moz-range-thumb:active {
199
+ transform: scale(0.95);
200
+ }
201
+
202
+ .wq-slider-input:focus {
203
+ outline: none;
204
+ }
205
+
206
+ .wq-slider-input:focus::-webkit-slider-thumb {
207
+ box-shadow: var(--wq-shadow-focus);
208
+ }
209
+
210
+ .wq-slider-input:focus::-moz-range-thumb {
211
+ box-shadow: var(--wq-shadow-focus);
212
+ }
213
+
214
+ .wq-slider-value-display {
215
+ text-align: center;
216
+ margin-top: var(--wq-space-lg);
217
+ font-size: var(--wq-font-size-xl);
218
+ font-weight: var(--wq-font-weight-semibold);
219
+ color: var(--wq-color-text-primary);
220
+ border: 2px solid var(--wq-color-border);
221
+ border-radius: var(--wq-radius-md);
222
+ }
223
+
224
+ .wq-slider-value {
225
+ font-size: 2rem;
226
+ font-weight: 700;
227
+ color: var(--wq-color-primary);
228
+ font-variant-numeric: tabular-nums;
229
+ }
230
+
231
+ .wq-slider-unit {
232
+ font-size: var(--wq-font-size-base);
233
+ font-weight: var(--wq-font-weight-normal);
234
+ color: var(--wq-color-text-tertiary);
235
+ margin-left: var(--wq-space-sm);
236
+ }
237
+
238
+ .wq-slider-range-labels {
239
+ display: flex;
240
+ justify-content: space-between;
241
+ margin-top: var(--wq-space-sm);
242
+ font-size: var(--wq-font-size-sm);
243
+ color: var(--wq-color-text-tertiary);
244
+ }
245
+
246
+ .wq-slider-min,
247
+ .wq-slider-max {
248
+ font-weight: var(--wq-font-weight-medium);
249
+ }
250
+
251
+ /* === Unsupported Type === */
252
+ .wq-unsupported-type {
253
+ padding: var(--wq-space-lg);
254
+ background-color: var(--wq-color-warning-50);
255
+ border: var(--wq-border-width) solid var(--wq-color-warning-500);
256
+ border-radius: var(--wq-radius-md);
257
+ color: var(--wq-color-warning-800);
258
+ font-weight: var(--wq-font-weight-medium);
259
+ font-size: var(--wq-font-size-base);
260
+ }
261
+
262
+ /* === Progress Bar === */
263
+ .wq-progress-bar {
264
+ width: 100%;
265
+ height: var(--wq-progress-height);
266
+ background-color: var(--wq-color-border);
267
+ border-radius: var(--wq-radius-sm);
268
+ overflow: hidden;
269
+ margin-bottom: var(--wq-space-lg);
270
+ }
271
+
272
+ .wq-progress-fill {
273
+ height: 100%;
274
+ background-color: var(--wq-color-primary);
275
+ transition: width var(--wq-transition-slow);
276
+ }
277
+
278
+ /* === Loading and Error States === */
279
+ .wq-loading,
280
+ .wq-error {
281
+ display: flex;
282
+ justify-content: center;
283
+ align-items: center;
284
+ min-height: 20rem;
285
+ font-size: var(--wq-font-size-lg);
286
+ color: var(--wq-color-text-tertiary);
287
+ }
288
+
289
+ .wq-error {
290
+ color: var(--wq-color-error);
291
+ font-weight: var(--wq-font-weight-medium);
292
+ }
293
+
294
+ /* === Accessibility === */
295
+ .wq-question-input:focus-visible,
296
+ .wq-choice-option:focus-within {
297
+ outline: var(--wq-border-width) solid var(--wq-color-border-focus);
298
+ outline-offset: 2px;
299
+ }
300
+
301
+ /* === Responsive Design === */
302
+ @media (max-width: 640px) {
303
+ .wq-question-container {
304
+ padding: var(--wq-space-md);
305
+ }
306
+
307
+ .wq-question-text {
308
+ font-size: var(--wq-font-size-base);
309
+ }
310
+
311
+ .wq-choice-option {
312
+ padding: var(--wq-space-sm) var(--wq-space-md);
313
+ }
314
+
315
+ .wq-slider-value-display {
316
+ font-size: var(--wq-font-size-lg);
317
+ }
318
+ }
319
+
320
+ /* === Print Styles === */
321
+ @media print {
322
+ .wq-question-container {
323
+ page-break-inside: avoid;
324
+ break-inside: avoid;
325
+ }
326
+
327
+ .wq-choice-option.wq-selected {
328
+ border-color: #000;
329
+ background-color: #f0f0f0;
330
+ }
331
+ }
332
+
333
+
334
+ /* Debug Section Styles
335
+ * These styles are designed to work with the questionnaire library's CSS variables
336
+ * and can be easily moved to the shared package.
337
+ */
338
+
339
+ .wq-debug-section {
340
+ margin-top: 1.5rem;
341
+ padding: 1rem;
342
+ background-color: var(--wq-color-background);
343
+ border: 1px solid var(--wq-color-border);
344
+ border-radius: var(--wq-radius-md);
345
+ }
346
+
347
+ .wq-loinc-link-section {
348
+ margin-bottom: 1rem;
349
+ padding: 0.75rem;
350
+ }
351
+
352
+ .wq-loinc-link {
353
+ color: var(--wq-color-primary);
354
+ text-decoration: none;
355
+ font-weight: 600;
356
+ font-size: 0.9rem;
357
+ display: inline-flex;
358
+ align-items: center;
359
+ gap: 0.5rem;
360
+ transition: all 0.2s ease;
361
+ }
362
+
363
+ .wq-loinc-link:hover {
364
+ text-decoration: underline;
365
+ }
366
+
367
+ .wq-loinc-link::after {
368
+ content: "↗";
369
+ font-size: 1rem;
370
+ }
371
+
372
+ .wq-debug-title {
373
+ font-size: 0.85rem;
374
+ font-weight: 600;
375
+ color: var(--wq-color-primary);
376
+ margin-bottom: 0.5rem;
377
+ text-transform: uppercase;
378
+ letter-spacing: 0.5px;
379
+ }
380
+
381
+ .wq-debug-json {
382
+ margin: 0;
383
+ padding: 0.75rem;
384
+ background: rgba(0, 0, 0, 0.6);
385
+ border: 1px solid rgba(255, 255, 255, 0.35);
386
+ border-radius: 4px;
387
+ font-family: 'Courier New', Courier, monospace;
388
+ font-size: 0.85rem;
389
+ color: #e0e0e0;
390
+ overflow-x: auto;
391
+ white-space: pre;
392
+ line-height: 1.5;
393
+ margin-bottom: 1rem;
394
+ }
395
+
396
+ .wq-debug-json:last-child {
397
+ margin-bottom: 0;
398
+ }
399
+
400
+ /* Collapsible Debug Section Styles */
401
+ .wq-debug-collapsible {
402
+ margin-bottom: 0.75rem;
403
+ }
404
+
405
+ .wq-debug-collapsible:last-child {
406
+ margin-bottom: 0;
407
+ }
408
+
409
+ .wq-debug-collapsible-header {
410
+ width: 100%;
411
+ display: flex;
412
+ align-items: center;
413
+ gap: 0.5rem;
414
+ padding: 0.75rem;
415
+ background: rgba(255, 165, 0, 0.15);
416
+ border: 1px solid rgba(255, 165, 0, 0.3);
417
+ border-radius: var(--wq-radius-md);
418
+ cursor: pointer;
419
+ transition: all 0.2s ease;
420
+ font-family: inherit;
421
+ font-size: 0.85rem;
422
+ color: var(--wq-color-text-primary);
423
+ text-align: left;
424
+ }
425
+
426
+ .wq-debug-collapsible-header:hover {
427
+ background: rgba(255, 165, 0, 0.25);
428
+ border-color: rgba(255, 165, 0, 0.5);
429
+ }
430
+
431
+ .wq-debug-collapsible-header:active {
432
+ transform: scale(0.98);
433
+ }
434
+
435
+ .wq-debug-collapsible-header .chevron {
436
+ font-size: 0.7rem;
437
+ color: var(--wq-color-primary);
438
+ transition: transform 0.2s ease;
439
+ display: inline-block;
440
+ }
441
+
442
+ .wq-debug-collapsible-header .chevron.open {
443
+ transform: rotate(90deg);
444
+ }
445
+
446
+ .wq-debug-collapsible-header .debug-title {
447
+ margin: 0;
448
+ flex: 1;
449
+ }
450
+
451
+ .wq-debug-collapsible .debug-json {
452
+ margin-top: 0.5rem;
453
+ margin-bottom: 0;
454
+ animation: wq-slideDown 0.2s ease-out;
455
+ }
456
+
457
+ @keyframes wq-slideDown {
458
+ from {
459
+ opacity: 0;
460
+ transform: translateY(-10px);
461
+ }
462
+ to {
463
+ opacity: 1;
464
+ transform: translateY(0);
465
+ }
466
+ }
467
+