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.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
- type FieldDef = TextFieldDef | NumberFieldDef | SelectFieldDef | RadioFieldDef | CheckboxFieldDef | RepeatableFieldDef | ImageUploadFieldDef | SignatureFieldDef | EditableTableFieldDef | StaticTextFieldDef | BaseFieldDef;
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
- type Computation = SumComputation | ScoreComputation;
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
- export { type BaseFieldDef, type CheckboxFieldDef, type ColumnLayout, type Computation, type Condition, type CreateUploadHandlerOptions, type DataSource, DynamicForm, EMAIL_REGEX, type EditableTableColumnDef, type EditableTableFieldDef, type EventDefinition, type FieldDef, type FieldPrefill, FieldRenderer, type FieldState, type FieldType, FormControls, type FormControlsProps, type FormDef, type FormErrors, FormProvider, type FormState, FormStore, type FormValues, type ImageUploadFieldDef, ImageUploadWidget, type LayoutNode, type NumberFieldDef, type Permission, type PresignedUploadResponse, type RadioFieldDef, ReadOnlyForm, ReadOnlyImageUpload, ReadOnlySignature, ReadOnlyTable, type RepeatableFieldDef, type Rule, type RuleAction, type RuleResult, type ScoreComputation, type ScoreRange, type Section, type SectionChild, type SelectFieldDef, type SelectOption, type SignatureFieldDef, SignatureUploadWidget, type StaticTextFieldDef, type StoreConfig, type SubmissionData, type SumComputation, type TextFieldDef, type ValidationRule, type WebhookDef, type Workflow, type WorkflowTransition, createUploadHandler, evaluateRules, useField, useForm, useFormStore, validateField, validateForm };
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 };