formanitor 0.0.11 → 0.0.14
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.
- package/dist/index.cjs +2214 -124
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +305 -4
- package/dist/index.d.ts +305 -4
- package/dist/index.mjs +2207 -128
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -1
package/dist/index.d.cts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
|
|
3
|
-
type FieldType = 'text' | 'number' | 'textarea' | 'select' | 'multiselect' | 'radio' | 'repeatable' | 'checkbox' | 'image_upload' | 'signature' | 'date' | 'datetime' | 'editable_table' | 'static_text' | string;
|
|
3
|
+
type FieldType = 'text' | 'number' | 'textarea' | 'select' | 'multiselect' | 'radio' | 'repeatable' | 'checkbox' | 'image_upload' | 'signature' | 'date' | 'datetime' | 'editable_table' | 'static_text' | 'medications' | 'investigations' | 'procedures' | 'vitals' | 'referral' | 'followup' | string;
|
|
4
4
|
interface ValidationRule {
|
|
5
5
|
min?: number;
|
|
6
6
|
max?: number;
|
|
@@ -42,6 +42,26 @@ interface BaseFieldDef {
|
|
|
42
42
|
disabled?: boolean;
|
|
43
43
|
hidden?: boolean;
|
|
44
44
|
prefill?: FieldPrefill;
|
|
45
|
+
/**
|
|
46
|
+
* High-level column position in SmartForm layout.
|
|
47
|
+
* - "left" and "right" are narrow side columns.
|
|
48
|
+
* - "center" is the main content column and is 2× the width of side columns.
|
|
49
|
+
* Default: "center" when omitted.
|
|
50
|
+
*/
|
|
51
|
+
position?: 'left' | 'center' | 'right';
|
|
52
|
+
/**
|
|
53
|
+
* How many layout columns this field spans horizontally.
|
|
54
|
+
* - 1 = occupies its own column (e.g. just "left", just "center", or just "right")
|
|
55
|
+
* - 2 = spans into an adjacent column (e.g. left+center or center+right)
|
|
56
|
+
* Default: 1.
|
|
57
|
+
*/
|
|
58
|
+
colSpan?: 1 | 2;
|
|
59
|
+
/**
|
|
60
|
+
* Optional theme name for component styling.
|
|
61
|
+
* Renders the field with theme-specific styles (e.g. textarea with "highlight-label"
|
|
62
|
+
* shows the label in a colored block above the input).
|
|
63
|
+
*/
|
|
64
|
+
theme?: string;
|
|
45
65
|
meta?: Record<string, unknown>;
|
|
46
66
|
}
|
|
47
67
|
interface TextFieldDef extends BaseFieldDef {
|
|
@@ -118,7 +138,86 @@ interface StaticTextFieldDef extends BaseFieldDef {
|
|
|
118
138
|
/** Display size. Default: 'regular'. */
|
|
119
139
|
size?: 'regular' | 'large';
|
|
120
140
|
}
|
|
121
|
-
|
|
141
|
+
interface MedicationsFieldDef extends BaseFieldDef {
|
|
142
|
+
type: 'medications';
|
|
143
|
+
}
|
|
144
|
+
interface InvestigationsFieldDef extends BaseFieldDef {
|
|
145
|
+
type: 'investigations';
|
|
146
|
+
}
|
|
147
|
+
interface ProceduresFieldDef extends BaseFieldDef {
|
|
148
|
+
type: 'procedures';
|
|
149
|
+
}
|
|
150
|
+
interface DifferentialDiagnosisFieldDef extends BaseFieldDef {
|
|
151
|
+
type: 'differential_diagnosis';
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* A read-only vitals panel populated by an external API fetch.
|
|
155
|
+
* The consumer provides `onFetch` in `fieldHandlers` for this field ID.
|
|
156
|
+
* The fetched value (raw vitals object) is stored in form state and included in submission.
|
|
157
|
+
*/
|
|
158
|
+
interface VitalsFieldDef extends BaseFieldDef {
|
|
159
|
+
type: 'vitals';
|
|
160
|
+
}
|
|
161
|
+
/** One selected referral. Stored in form state as an array of these. */
|
|
162
|
+
interface ReferralItem {
|
|
163
|
+
specialization: string;
|
|
164
|
+
is_urgent: boolean;
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Referral field: label "Referral to" with a multiselect dropdown and chips.
|
|
168
|
+
* Value shape: ReferralItem[] e.g. [{ specialization: "Cardiology", is_urgent: false }, ...].
|
|
169
|
+
* Options via fieldHandlers[fieldId].onFetchOptions (e.g. { specializations: string[] }).
|
|
170
|
+
*/
|
|
171
|
+
interface ReferralFieldDef extends BaseFieldDef {
|
|
172
|
+
type: 'referral';
|
|
173
|
+
options?: SelectOption[];
|
|
174
|
+
}
|
|
175
|
+
/** Stored value for followup field: false/null = no followup; object = one-time followup as number of days from current date. */
|
|
176
|
+
interface FollowupValue {
|
|
177
|
+
followupType: 'one time';
|
|
178
|
+
/** Number of days from (current) date when set; always stored as string. */
|
|
179
|
+
value: string;
|
|
180
|
+
unit: 'days';
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Follow-up field: "No Follow-up" | "One Time" with schedule by duration (e.g. 7 days) or by date.
|
|
184
|
+
* Value shape: false | FollowupValue.
|
|
185
|
+
*/
|
|
186
|
+
interface FollowupFieldDef extends BaseFieldDef {
|
|
187
|
+
type: 'followup';
|
|
188
|
+
}
|
|
189
|
+
/** A matched master record returned from a backend search API. */
|
|
190
|
+
interface MatchedCondition {
|
|
191
|
+
id: number | string;
|
|
192
|
+
name: string;
|
|
193
|
+
created_at?: string;
|
|
194
|
+
updated_at?: string;
|
|
195
|
+
}
|
|
196
|
+
/** A single keyword-to-master-record match produced by NLP extraction + search. */
|
|
197
|
+
interface ExtractedKeywordMatch {
|
|
198
|
+
extractedKeyword: string;
|
|
199
|
+
matchedCondition: MatchedCondition;
|
|
200
|
+
}
|
|
201
|
+
/** Structured value stored in form state for smart_textarea fields. */
|
|
202
|
+
interface SmartTextareaValue {
|
|
203
|
+
text: string;
|
|
204
|
+
extractedKeywords: ExtractedKeywordMatch[];
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Smart textarea that performs client-side NLP keyword extraction and searches
|
|
208
|
+
* matched terms against backend master tables via `fieldHandlers[fieldId].onSearch`.
|
|
209
|
+
*
|
|
210
|
+
* Value shape: `SmartTextareaValue` — `{ text, extractedKeywords }`.
|
|
211
|
+
*/
|
|
212
|
+
interface SmartTextareaFieldDef extends BaseFieldDef {
|
|
213
|
+
type: 'smart_textarea';
|
|
214
|
+
height?: number;
|
|
215
|
+
/** Semantic label for the kind of content (e.g. 'allergies', 'chiefComplaints', 'symptoms'). */
|
|
216
|
+
componentType: string;
|
|
217
|
+
/** Debounce delay in ms before NLP + search triggers. Default: 1000. */
|
|
218
|
+
debounceDelay?: number;
|
|
219
|
+
}
|
|
220
|
+
type FieldDef = TextFieldDef | NumberFieldDef | SelectFieldDef | RadioFieldDef | CheckboxFieldDef | RepeatableFieldDef | ImageUploadFieldDef | SignatureFieldDef | EditableTableFieldDef | StaticTextFieldDef | MedicationsFieldDef | InvestigationsFieldDef | ProceduresFieldDef | DifferentialDiagnosisFieldDef | VitalsFieldDef | ReferralFieldDef | FollowupFieldDef | SmartTextareaFieldDef | BaseFieldDef;
|
|
122
221
|
interface Condition {
|
|
123
222
|
field?: string;
|
|
124
223
|
op: '==' | '!=' | '>' | '<' | '>=' | '<=' | 'in' | 'contains';
|
|
@@ -180,7 +279,25 @@ interface SumComputation {
|
|
|
180
279
|
type: 'sum';
|
|
181
280
|
fields: string[];
|
|
182
281
|
}
|
|
183
|
-
|
|
282
|
+
/** Expression node for formula computation: field ref, number, or binary op. */
|
|
283
|
+
type FormulaExpr = {
|
|
284
|
+
type: 'field';
|
|
285
|
+
field: string;
|
|
286
|
+
} | {
|
|
287
|
+
type: 'number';
|
|
288
|
+
value: number;
|
|
289
|
+
} | {
|
|
290
|
+
type: 'op';
|
|
291
|
+
op: '+' | '-' | '*' | '/' | '**';
|
|
292
|
+
left: FormulaExpr;
|
|
293
|
+
right: FormulaExpr;
|
|
294
|
+
};
|
|
295
|
+
interface FormulaComputation {
|
|
296
|
+
target: string;
|
|
297
|
+
type: 'formula';
|
|
298
|
+
expression: FormulaExpr;
|
|
299
|
+
}
|
|
300
|
+
type Computation = SumComputation | ScoreComputation | FormulaComputation;
|
|
184
301
|
interface FormDef {
|
|
185
302
|
id: string;
|
|
186
303
|
version: number;
|
|
@@ -277,6 +394,15 @@ declare class FormStore {
|
|
|
277
394
|
getFieldDef(fieldId: string): FieldDef | undefined;
|
|
278
395
|
hasPersistence(): boolean;
|
|
279
396
|
setValue(fieldId: string, value: any): void;
|
|
397
|
+
/**
|
|
398
|
+
* Set multiple values at once (e.g. from AI analysis). Only updates keys that
|
|
399
|
+
* exist in the schema. Runs evaluate/notify/save once.
|
|
400
|
+
* @param partial Map of fieldId -> value
|
|
401
|
+
* @param options.touch If false, do not mark fields as touched (e.g. for AI-suggested values)
|
|
402
|
+
*/
|
|
403
|
+
setValues(partial: Record<string, any>, options?: {
|
|
404
|
+
touch?: boolean;
|
|
405
|
+
}): void;
|
|
280
406
|
setTouched(fieldId: string): void;
|
|
281
407
|
setRole(role: string): void;
|
|
282
408
|
load(): Promise<void>;
|
|
@@ -297,6 +423,13 @@ declare class FormStore {
|
|
|
297
423
|
* }
|
|
298
424
|
*/
|
|
299
425
|
getSerializedValuesForSubmission(): FormValues;
|
|
426
|
+
/**
|
|
427
|
+
* Raw form values as stored internally, without any serialization or
|
|
428
|
+
* transformation. Useful when consumers need access to richer structures
|
|
429
|
+
* (e.g. smart_textarea keyword metadata) alongside the flattened values
|
|
430
|
+
* returned by getSerializedValuesForSubmission.
|
|
431
|
+
*/
|
|
432
|
+
getRawValues(): FormValues;
|
|
300
433
|
private serializeValuesForSubmission;
|
|
301
434
|
private evaluate;
|
|
302
435
|
getAvailableTransitions(): WorkflowTransition[];
|
|
@@ -338,9 +471,32 @@ interface RuleResult {
|
|
|
338
471
|
}
|
|
339
472
|
declare function evaluateRules(values: FormValues, rules: Rule[], fields: Record<string, FieldDef>): RuleResult;
|
|
340
473
|
|
|
474
|
+
type FieldHandler = {
|
|
475
|
+
onSearch: (query: string) => Promise<any[]>;
|
|
476
|
+
recentlyUsed?: any[];
|
|
477
|
+
/**
|
|
478
|
+
* Called by widgets that display externally-fetched data (e.g. vitals).
|
|
479
|
+
* Invoked once on mount and again when the user hits the refresh button.
|
|
480
|
+
* The resolved value is written directly into the field's form state.
|
|
481
|
+
*/
|
|
482
|
+
onFetch?: () => Promise<any>;
|
|
483
|
+
/**
|
|
484
|
+
* Called by the referral widget to load dropdown options. May return
|
|
485
|
+
* { specializations: string[] } or { label: string; value: any }[].
|
|
486
|
+
*/
|
|
487
|
+
onFetchOptions?: () => Promise<{
|
|
488
|
+
specializations?: string[];
|
|
489
|
+
} | {
|
|
490
|
+
label: string;
|
|
491
|
+
value: any;
|
|
492
|
+
}[]>;
|
|
493
|
+
};
|
|
494
|
+
type FieldHandlersMap = Record<string, FieldHandler>;
|
|
495
|
+
declare function useFieldHandlers(fieldId: string): FieldHandler;
|
|
341
496
|
interface FormProviderProps {
|
|
342
497
|
schema: FormDef;
|
|
343
498
|
config?: StoreConfig;
|
|
499
|
+
fieldHandlers?: FieldHandlersMap;
|
|
344
500
|
children: React.ReactNode;
|
|
345
501
|
}
|
|
346
502
|
declare const FormProvider: React.FC<FormProviderProps>;
|
|
@@ -354,6 +510,7 @@ declare function useForm(): {
|
|
|
354
510
|
availableTransitions: WorkflowTransition[];
|
|
355
511
|
hasPersistence: boolean;
|
|
356
512
|
getSerializedValues: () => FormValues;
|
|
513
|
+
getRawValues: () => FormValues;
|
|
357
514
|
markSubmitAttempted: () => void;
|
|
358
515
|
flushPendingUploads: () => Promise<void>;
|
|
359
516
|
};
|
|
@@ -376,6 +533,35 @@ declare function useField(fieldId: string): {
|
|
|
376
533
|
|
|
377
534
|
declare const DynamicForm: React.FC;
|
|
378
535
|
|
|
536
|
+
/** Shape of one differential diagnosis item from AI (must match form field value) */
|
|
537
|
+
type AIDifferentialDiagnosisItem = {
|
|
538
|
+
category: string;
|
|
539
|
+
condition: string;
|
|
540
|
+
likelihood: string;
|
|
541
|
+
severity: string;
|
|
542
|
+
treatability: string;
|
|
543
|
+
keyFeatures?: string[];
|
|
544
|
+
nextSteps?: string[];
|
|
545
|
+
};
|
|
546
|
+
interface SmartFormProps {
|
|
547
|
+
/**
|
|
548
|
+
* Structured result from AI analysis (e.g. patient-doctor conversation).
|
|
549
|
+
* When this is set or updated, values are applied to the form by field ID.
|
|
550
|
+
* Only keys that exist in the form schema are applied; unknown keys are ignored.
|
|
551
|
+
* Fields are not marked as "touched" so you can distinguish AI-suggested vs user-edited if needed.
|
|
552
|
+
* Listens to both reference and content changes (e.g. streaming updates to the same object).
|
|
553
|
+
*/
|
|
554
|
+
aiAnalysisResult?: Record<string, any> | null;
|
|
555
|
+
}
|
|
556
|
+
/**
|
|
557
|
+
* Form view that supports applying AI analysis results after load. Use inside
|
|
558
|
+
* FormProvider like DynamicForm. When aiAnalysisResult is provided (e.g. when
|
|
559
|
+
* AI finishes analyzing conversation), its values are applied to the form in
|
|
560
|
+
* one batch without marking fields as touched. Re-applies when the result
|
|
561
|
+
* reference or content changes (e.g. streaming or incremental AI updates).
|
|
562
|
+
*/
|
|
563
|
+
declare const SmartForm: React.FC<SmartFormProps>;
|
|
564
|
+
|
|
379
565
|
interface FieldRendererProps {
|
|
380
566
|
fieldId: string;
|
|
381
567
|
}
|
|
@@ -461,4 +647,119 @@ interface CreateUploadHandlerOptions {
|
|
|
461
647
|
*/
|
|
462
648
|
declare function createUploadHandler(options: CreateUploadHandlerOptions): (file: File | Blob, filename: string) => Promise<string>;
|
|
463
649
|
|
|
464
|
-
|
|
650
|
+
/** Shape of a medication as returned by AI analysis */
|
|
651
|
+
type AIMedication = {
|
|
652
|
+
id: string | number;
|
|
653
|
+
brand_name: string;
|
|
654
|
+
generic_name: string;
|
|
655
|
+
form?: string;
|
|
656
|
+
strength?: string;
|
|
657
|
+
reason?: string;
|
|
658
|
+
};
|
|
659
|
+
|
|
660
|
+
type MedicationSearchResult = {
|
|
661
|
+
id: number;
|
|
662
|
+
name: string;
|
|
663
|
+
generic_name?: string;
|
|
664
|
+
manufacturer?: string;
|
|
665
|
+
score?: number;
|
|
666
|
+
};
|
|
667
|
+
type Medication = {
|
|
668
|
+
id: number;
|
|
669
|
+
brand_name: string;
|
|
670
|
+
generic_name: string;
|
|
671
|
+
frequency: string;
|
|
672
|
+
is_custom: boolean;
|
|
673
|
+
duration_value: string;
|
|
674
|
+
duration_unit: 'days' | 'weeks' | 'months';
|
|
675
|
+
before_after: 'AFTER FOOD' | 'BEFORE FOOD';
|
|
676
|
+
morning: string;
|
|
677
|
+
afternoon: string;
|
|
678
|
+
night: string;
|
|
679
|
+
notes: string;
|
|
680
|
+
};
|
|
681
|
+
type AddMedicationFieldProps = {
|
|
682
|
+
label?: string;
|
|
683
|
+
value: Medication[];
|
|
684
|
+
onChange: (items: Medication[]) => void;
|
|
685
|
+
onSearch: (query: string) => Promise<MedicationSearchResult[]>;
|
|
686
|
+
recentlyUsed?: MedicationSearchResult[];
|
|
687
|
+
/** AI-suggested medications shown as badges; clicking adds to value */
|
|
688
|
+
suggestedMedications?: AIMedication[];
|
|
689
|
+
};
|
|
690
|
+
declare const AddMedicationField: React.FC<AddMedicationFieldProps>;
|
|
691
|
+
|
|
692
|
+
type InvestigationSearchResult = {
|
|
693
|
+
id: string;
|
|
694
|
+
name: string;
|
|
695
|
+
code?: string;
|
|
696
|
+
description?: string;
|
|
697
|
+
categories?: string[];
|
|
698
|
+
synonyms?: string[];
|
|
699
|
+
sample_type?: string;
|
|
700
|
+
method?: string;
|
|
701
|
+
reference_range?: string;
|
|
702
|
+
sample_unit?: string;
|
|
703
|
+
sample_qty?: number;
|
|
704
|
+
turnaround_time?: number;
|
|
705
|
+
preparation?: string;
|
|
706
|
+
service_type?: string;
|
|
707
|
+
department?: string;
|
|
708
|
+
is_vip_enabled?: boolean;
|
|
709
|
+
is_pacs_enabled?: boolean;
|
|
710
|
+
score?: number;
|
|
711
|
+
};
|
|
712
|
+
type Investigation = InvestigationSearchResult & {
|
|
713
|
+
label: string;
|
|
714
|
+
is_custom: boolean;
|
|
715
|
+
fromAI: boolean;
|
|
716
|
+
};
|
|
717
|
+
type AddInvestigationFieldProps = {
|
|
718
|
+
label?: string;
|
|
719
|
+
value: Investigation[];
|
|
720
|
+
onChange: (items: Investigation[]) => void;
|
|
721
|
+
onSearch: (query: string) => Promise<InvestigationSearchResult[]>;
|
|
722
|
+
recentlyUsed?: InvestigationSearchResult[];
|
|
723
|
+
};
|
|
724
|
+
declare const AddInvestigationField: React.FC<AddInvestigationFieldProps>;
|
|
725
|
+
|
|
726
|
+
type DifferentialDiagnosisItem = {
|
|
727
|
+
category: string;
|
|
728
|
+
condition: string;
|
|
729
|
+
likelihood: string;
|
|
730
|
+
severity: string;
|
|
731
|
+
treatability: string;
|
|
732
|
+
keyFeatures?: string[];
|
|
733
|
+
nextSteps?: string[];
|
|
734
|
+
};
|
|
735
|
+
type DifferentialDiagnosisProps = {
|
|
736
|
+
differentialDiagnosis: DifferentialDiagnosisItem[];
|
|
737
|
+
className?: string;
|
|
738
|
+
height?: string;
|
|
739
|
+
};
|
|
740
|
+
/**
|
|
741
|
+
* - Outer: rounded border [#D0D0D0], highlight label strip (#FEE8EC)
|
|
742
|
+
* - Body: scrollable list of diagnosis cards with accordion expand/collapse
|
|
743
|
+
*/
|
|
744
|
+
declare const DifferentialDiagnosis: React.FC<DifferentialDiagnosisProps>;
|
|
745
|
+
|
|
746
|
+
interface SmartKeywordsResult {
|
|
747
|
+
extractedNouns: string[];
|
|
748
|
+
matchedConditions: ExtractedKeywordMatch[];
|
|
749
|
+
isProcessing: boolean;
|
|
750
|
+
error: string | null;
|
|
751
|
+
}
|
|
752
|
+
/**
|
|
753
|
+
* Extracts noun phrases from `text` using compromise, deduplicates, then
|
|
754
|
+
* searches each noun against a backend master table via `onSearch`. Returns
|
|
755
|
+
* the flattened list of keyword-to-master-record matches.
|
|
756
|
+
*
|
|
757
|
+
* All NLP runs client-side; the backend only receives simple query strings.
|
|
758
|
+
*/
|
|
759
|
+
declare function useSmartKeywords(text: string, onSearch: (query: string) => Promise<any[]>, debounceDelay?: number): SmartKeywordsResult;
|
|
760
|
+
|
|
761
|
+
declare const SmartTextareaWidget: React.FC<{
|
|
762
|
+
fieldId: string;
|
|
763
|
+
}>;
|
|
764
|
+
|
|
765
|
+
export { type AIDifferentialDiagnosisItem, AddInvestigationField, type AddInvestigationFieldProps, AddMedicationField, type AddMedicationFieldProps, type BaseFieldDef, type CheckboxFieldDef, type ColumnLayout, type Computation, type Condition, type CreateUploadHandlerOptions, type DataSource, DifferentialDiagnosis, type DifferentialDiagnosisFieldDef, type DifferentialDiagnosisItem, type DifferentialDiagnosisProps, DynamicForm, EMAIL_REGEX, type EditableTableColumnDef, type EditableTableFieldDef, type EventDefinition, type ExtractedKeywordMatch, type FieldDef, type FieldHandler, type FieldHandlersMap, type FieldPrefill, FieldRenderer, type FieldState, type FieldType, type FollowupFieldDef, type FollowupValue, FormControls, type FormControlsProps, type FormDef, type FormErrors, FormProvider, type FormState, FormStore, type FormValues, type FormulaComputation, type FormulaExpr, type ImageUploadFieldDef, ImageUploadWidget, type Investigation, type InvestigationSearchResult, type InvestigationsFieldDef, type LayoutNode, type MatchedCondition, type Medication, type MedicationSearchResult, type MedicationsFieldDef, type NumberFieldDef, type Permission, type PresignedUploadResponse, type ProceduresFieldDef, type RadioFieldDef, ReadOnlyForm, ReadOnlyImageUpload, ReadOnlySignature, ReadOnlyTable, type ReferralFieldDef, type ReferralItem, type RepeatableFieldDef, type Rule, type RuleAction, type RuleResult, type ScoreComputation, type ScoreRange, type Section, type SectionChild, type SelectFieldDef, type SelectOption, type SignatureFieldDef, SignatureUploadWidget, SmartForm, type SmartFormProps, type SmartKeywordsResult, type SmartTextareaFieldDef, type SmartTextareaValue, SmartTextareaWidget, type StaticTextFieldDef, type StoreConfig, type SubmissionData, type SumComputation, type TextFieldDef, type ValidationRule, type VitalsFieldDef, type WebhookDef, type Workflow, type WorkflowTransition, createUploadHandler, evaluateRules, useField, useFieldHandlers, useForm, useFormStore, useSmartKeywords, validateField, validateForm };
|