formanitor 0.0.30 → 0.0.32

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' | 'diagnosis_textarea' | 'richtext' | 'select' | 'multiselect' | 'radio' | 'repeatable' | 'checkbox' | 'image_upload' | 'signature' | 'date' | 'datetime' | 'editable_table' | 'static_text' | 'medications' | 'investigations' | 'procedures' | 'vitals' | 'hidden_vitals' | 'referral' | 'followup' | string;
3
+ type FieldType = 'text' | 'number' | 'textarea' | 'diagnosis_textarea' | 'richtext' | 'select' | 'multiselect' | 'radio' | 'repeatable' | 'checkbox' | 'image_upload' | 'media_upload' | 'signature' | 'date' | 'datetime' | 'editable_table' | 'static_text' | 'medications' | 'investigations' | 'procedures' | 'vitals' | 'hidden_vitals' | 'referral' | 'followup' | string;
4
4
  interface ValidationRule {
5
5
  min?: number;
6
6
  max?: number;
@@ -112,6 +112,12 @@ interface ImageUploadFieldDef extends BaseFieldDef {
112
112
  maxSize?: number;
113
113
  acceptedTypes?: string[];
114
114
  }
115
+ interface MediaUploadFieldDef extends BaseFieldDef {
116
+ type: 'media_upload';
117
+ maxSize?: number;
118
+ /** Default: images (image/*) and application/pdf */
119
+ acceptedTypes?: string[];
120
+ }
115
121
  interface SignatureFieldDef extends BaseFieldDef {
116
122
  type: 'signature';
117
123
  canvasWidth?: number;
@@ -302,7 +308,7 @@ interface DoctorFrequentItems {
302
308
  investigations?: InvestigationFrequentItem[];
303
309
  procedures?: ProcedureFrequentItem[];
304
310
  }
305
- type FieldDef = TextFieldDef | RichTextFieldDef | NumberFieldDef | SelectFieldDef | RadioFieldDef | CheckboxFieldDef | RepeatableFieldDef | ImageUploadFieldDef | SignatureFieldDef | EditableTableFieldDef | StaticTextFieldDef | MedicationsFieldDef | InvestigationsFieldDef | ProceduresFieldDef | DifferentialDiagnosisFieldDef | VitalsFieldDef | ReferralFieldDef | FollowupFieldDef | SmartTextareaFieldDef | DiagnosisTextareaFieldDef | BaseFieldDef;
311
+ type FieldDef = TextFieldDef | RichTextFieldDef | NumberFieldDef | SelectFieldDef | RadioFieldDef | CheckboxFieldDef | RepeatableFieldDef | ImageUploadFieldDef | MediaUploadFieldDef | SignatureFieldDef | EditableTableFieldDef | StaticTextFieldDef | MedicationsFieldDef | InvestigationsFieldDef | ProceduresFieldDef | DifferentialDiagnosisFieldDef | VitalsFieldDef | ReferralFieldDef | FollowupFieldDef | SmartTextareaFieldDef | DiagnosisTextareaFieldDef | BaseFieldDef;
306
312
  interface Condition {
307
313
  field?: string;
308
314
  op: '==' | '!=' | '>' | '<' | '>=' | '<=' | 'in' | 'contains';
@@ -462,7 +468,7 @@ interface StoreConfig {
462
468
  * - `stopRecording` — stop capturing, transcribe, and return the transcript
463
469
  */
464
470
  voice?: {
465
- startRecording: () => Promise<void>;
471
+ startRecording: (fieldId?: string) => Promise<void>;
466
472
  stopRecording: () => Promise<string>;
467
473
  };
468
474
  }
@@ -720,6 +726,10 @@ declare const ImageUploadWidget: React.FC<{
720
726
  fieldId: string;
721
727
  }>;
722
728
 
729
+ declare const MediaUploadWidget: React.FC<{
730
+ fieldId: string;
731
+ }>;
732
+
723
733
  declare const SignatureUploadWidget: React.FC<{
724
734
  fieldId: string;
725
735
  }>;
@@ -730,6 +740,12 @@ interface ReadOnlyImageUploadProps {
730
740
  }
731
741
  declare const ReadOnlyImageUpload: React.FC<ReadOnlyImageUploadProps>;
732
742
 
743
+ interface ReadOnlyMediaUploadProps {
744
+ fieldDef: BaseFieldDef;
745
+ value: any;
746
+ }
747
+ declare const ReadOnlyMediaUpload: React.FC<ReadOnlyMediaUploadProps>;
748
+
733
749
  interface ReadOnlySignatureProps {
734
750
  fieldDef: BaseFieldDef;
735
751
  value: any;
@@ -910,4 +926,4 @@ declare const SmartTextareaWidget: React.FC<{
910
926
  fieldId: string;
911
927
  }>;
912
928
 
913
- export { type AIDifferentialDiagnosisItem, AddInvestigationField, type AddInvestigationFieldProps, AddMedicationField, type AddMedicationFieldProps, type BaseFieldDef, type CheckboxFieldDef, type ColumnLayout, type Computation, type Condition, type CreateUploadHandlerOptions, type DataSource, type DiagnosisGradeSelection, type DiagnosisTextareaFieldDef, type DiagnosisTextareaValue, DifferentialDiagnosis, type DifferentialDiagnosisFieldDef, type DifferentialDiagnosisItem, type DifferentialDiagnosisProps, type DoctorFrequentItems, 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 InvestigationFrequentItem, type InvestigationSearchResult, type InvestigationsFieldDef, type LayoutNode, type MatchedCondition, type Medication, type MedicationFrequentItem, type MedicationSearchResult, type MedicationsFieldDef, type NumberFieldDef, type Permission, type PresignedUploadResponse, type ProcedureFrequentItem, type ProceduresFieldDef, type RadioFieldDef, ReadOnlyForm, ReadOnlyImageUpload, ReadOnlySignature, ReadOnlyTable, type ReferralFieldDef, type ReferralItem, type RepeatableFieldDef, type RichTextFieldDef, RichTextWidget, 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, useFrequentItems, useSmartKeywords, validateField, validateForm };
929
+ export { type AIDifferentialDiagnosisItem, AddInvestigationField, type AddInvestigationFieldProps, AddMedicationField, type AddMedicationFieldProps, type BaseFieldDef, type CheckboxFieldDef, type ColumnLayout, type Computation, type Condition, type CreateUploadHandlerOptions, type DataSource, type DiagnosisGradeSelection, type DiagnosisTextareaFieldDef, type DiagnosisTextareaValue, DifferentialDiagnosis, type DifferentialDiagnosisFieldDef, type DifferentialDiagnosisItem, type DifferentialDiagnosisProps, type DoctorFrequentItems, 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 InvestigationFrequentItem, type InvestigationSearchResult, type InvestigationsFieldDef, type LayoutNode, type MatchedCondition, type MediaUploadFieldDef, MediaUploadWidget, type Medication, type MedicationFrequentItem, type MedicationSearchResult, type MedicationsFieldDef, type NumberFieldDef, type Permission, type PresignedUploadResponse, type ProcedureFrequentItem, type ProceduresFieldDef, type RadioFieldDef, ReadOnlyForm, ReadOnlyImageUpload, ReadOnlyMediaUpload, ReadOnlySignature, ReadOnlyTable, type ReferralFieldDef, type ReferralItem, type RepeatableFieldDef, type RichTextFieldDef, RichTextWidget, 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, useFrequentItems, useSmartKeywords, validateField, validateForm };
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
2
 
3
- type FieldType = 'text' | 'number' | 'textarea' | 'diagnosis_textarea' | 'richtext' | 'select' | 'multiselect' | 'radio' | 'repeatable' | 'checkbox' | 'image_upload' | 'signature' | 'date' | 'datetime' | 'editable_table' | 'static_text' | 'medications' | 'investigations' | 'procedures' | 'vitals' | 'hidden_vitals' | 'referral' | 'followup' | string;
3
+ type FieldType = 'text' | 'number' | 'textarea' | 'diagnosis_textarea' | 'richtext' | 'select' | 'multiselect' | 'radio' | 'repeatable' | 'checkbox' | 'image_upload' | 'media_upload' | 'signature' | 'date' | 'datetime' | 'editable_table' | 'static_text' | 'medications' | 'investigations' | 'procedures' | 'vitals' | 'hidden_vitals' | 'referral' | 'followup' | string;
4
4
  interface ValidationRule {
5
5
  min?: number;
6
6
  max?: number;
@@ -112,6 +112,12 @@ interface ImageUploadFieldDef extends BaseFieldDef {
112
112
  maxSize?: number;
113
113
  acceptedTypes?: string[];
114
114
  }
115
+ interface MediaUploadFieldDef extends BaseFieldDef {
116
+ type: 'media_upload';
117
+ maxSize?: number;
118
+ /** Default: images (image/*) and application/pdf */
119
+ acceptedTypes?: string[];
120
+ }
115
121
  interface SignatureFieldDef extends BaseFieldDef {
116
122
  type: 'signature';
117
123
  canvasWidth?: number;
@@ -302,7 +308,7 @@ interface DoctorFrequentItems {
302
308
  investigations?: InvestigationFrequentItem[];
303
309
  procedures?: ProcedureFrequentItem[];
304
310
  }
305
- type FieldDef = TextFieldDef | RichTextFieldDef | NumberFieldDef | SelectFieldDef | RadioFieldDef | CheckboxFieldDef | RepeatableFieldDef | ImageUploadFieldDef | SignatureFieldDef | EditableTableFieldDef | StaticTextFieldDef | MedicationsFieldDef | InvestigationsFieldDef | ProceduresFieldDef | DifferentialDiagnosisFieldDef | VitalsFieldDef | ReferralFieldDef | FollowupFieldDef | SmartTextareaFieldDef | DiagnosisTextareaFieldDef | BaseFieldDef;
311
+ type FieldDef = TextFieldDef | RichTextFieldDef | NumberFieldDef | SelectFieldDef | RadioFieldDef | CheckboxFieldDef | RepeatableFieldDef | ImageUploadFieldDef | MediaUploadFieldDef | SignatureFieldDef | EditableTableFieldDef | StaticTextFieldDef | MedicationsFieldDef | InvestigationsFieldDef | ProceduresFieldDef | DifferentialDiagnosisFieldDef | VitalsFieldDef | ReferralFieldDef | FollowupFieldDef | SmartTextareaFieldDef | DiagnosisTextareaFieldDef | BaseFieldDef;
306
312
  interface Condition {
307
313
  field?: string;
308
314
  op: '==' | '!=' | '>' | '<' | '>=' | '<=' | 'in' | 'contains';
@@ -462,7 +468,7 @@ interface StoreConfig {
462
468
  * - `stopRecording` — stop capturing, transcribe, and return the transcript
463
469
  */
464
470
  voice?: {
465
- startRecording: () => Promise<void>;
471
+ startRecording: (fieldId?: string) => Promise<void>;
466
472
  stopRecording: () => Promise<string>;
467
473
  };
468
474
  }
@@ -720,6 +726,10 @@ declare const ImageUploadWidget: React.FC<{
720
726
  fieldId: string;
721
727
  }>;
722
728
 
729
+ declare const MediaUploadWidget: React.FC<{
730
+ fieldId: string;
731
+ }>;
732
+
723
733
  declare const SignatureUploadWidget: React.FC<{
724
734
  fieldId: string;
725
735
  }>;
@@ -730,6 +740,12 @@ interface ReadOnlyImageUploadProps {
730
740
  }
731
741
  declare const ReadOnlyImageUpload: React.FC<ReadOnlyImageUploadProps>;
732
742
 
743
+ interface ReadOnlyMediaUploadProps {
744
+ fieldDef: BaseFieldDef;
745
+ value: any;
746
+ }
747
+ declare const ReadOnlyMediaUpload: React.FC<ReadOnlyMediaUploadProps>;
748
+
733
749
  interface ReadOnlySignatureProps {
734
750
  fieldDef: BaseFieldDef;
735
751
  value: any;
@@ -910,4 +926,4 @@ declare const SmartTextareaWidget: React.FC<{
910
926
  fieldId: string;
911
927
  }>;
912
928
 
913
- export { type AIDifferentialDiagnosisItem, AddInvestigationField, type AddInvestigationFieldProps, AddMedicationField, type AddMedicationFieldProps, type BaseFieldDef, type CheckboxFieldDef, type ColumnLayout, type Computation, type Condition, type CreateUploadHandlerOptions, type DataSource, type DiagnosisGradeSelection, type DiagnosisTextareaFieldDef, type DiagnosisTextareaValue, DifferentialDiagnosis, type DifferentialDiagnosisFieldDef, type DifferentialDiagnosisItem, type DifferentialDiagnosisProps, type DoctorFrequentItems, 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 InvestigationFrequentItem, type InvestigationSearchResult, type InvestigationsFieldDef, type LayoutNode, type MatchedCondition, type Medication, type MedicationFrequentItem, type MedicationSearchResult, type MedicationsFieldDef, type NumberFieldDef, type Permission, type PresignedUploadResponse, type ProcedureFrequentItem, type ProceduresFieldDef, type RadioFieldDef, ReadOnlyForm, ReadOnlyImageUpload, ReadOnlySignature, ReadOnlyTable, type ReferralFieldDef, type ReferralItem, type RepeatableFieldDef, type RichTextFieldDef, RichTextWidget, 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, useFrequentItems, useSmartKeywords, validateField, validateForm };
929
+ export { type AIDifferentialDiagnosisItem, AddInvestigationField, type AddInvestigationFieldProps, AddMedicationField, type AddMedicationFieldProps, type BaseFieldDef, type CheckboxFieldDef, type ColumnLayout, type Computation, type Condition, type CreateUploadHandlerOptions, type DataSource, type DiagnosisGradeSelection, type DiagnosisTextareaFieldDef, type DiagnosisTextareaValue, DifferentialDiagnosis, type DifferentialDiagnosisFieldDef, type DifferentialDiagnosisItem, type DifferentialDiagnosisProps, type DoctorFrequentItems, 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 InvestigationFrequentItem, type InvestigationSearchResult, type InvestigationsFieldDef, type LayoutNode, type MatchedCondition, type MediaUploadFieldDef, MediaUploadWidget, type Medication, type MedicationFrequentItem, type MedicationSearchResult, type MedicationsFieldDef, type NumberFieldDef, type Permission, type PresignedUploadResponse, type ProcedureFrequentItem, type ProceduresFieldDef, type RadioFieldDef, ReadOnlyForm, ReadOnlyImageUpload, ReadOnlyMediaUpload, ReadOnlySignature, ReadOnlyTable, type ReferralFieldDef, type ReferralItem, type RepeatableFieldDef, type RichTextFieldDef, RichTextWidget, 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, useFrequentItems, useSmartKeywords, validateField, validateForm };
package/dist/index.mjs CHANGED
@@ -423,7 +423,7 @@ var FormStore = class {
423
423
  result[field.id] = parts.length > 0 ? parts.join("\n\n") : null;
424
424
  return;
425
425
  }
426
- if (field.type === "image_upload" || field.type === "signature") {
426
+ if (field.type === "image_upload" || field.type === "media_upload" || field.type === "signature") {
427
427
  const raw = values[field.id];
428
428
  if (raw !== void 0 && raw !== null && raw !== "") {
429
429
  const key = typeof raw === "string" ? raw : raw.s3_key || raw.value || null;
@@ -812,7 +812,7 @@ function VoiceMicButton({ fieldId, onTranscriptReady }) {
812
812
  setActiveFieldId(fieldId);
813
813
  setStatus("recording");
814
814
  try {
815
- await voice.startRecording();
815
+ await voice.startRecording(fieldId);
816
816
  } catch {
817
817
  setStatus("idle");
818
818
  setActiveFieldId(null);
@@ -1194,6 +1194,19 @@ var RichTextWidget = ({ fieldId }) => {
1194
1194
  const el = editor.view.dom;
1195
1195
  el.style.minHeight = `${minHeight}px`;
1196
1196
  }, [editor, minHeight]);
1197
+ useEffect(() => {
1198
+ if (!editor || editor.isDestroyed) return;
1199
+ const el = editor.view.dom;
1200
+ const handler = (e) => {
1201
+ const { text } = e.detail;
1202
+ if (!text) return;
1203
+ const currentText = editor.getText();
1204
+ const prefix = currentText.length > 0 && !/\s$/.test(currentText) ? " " : "";
1205
+ editor.chain().focus().insertContent(prefix + text).run();
1206
+ };
1207
+ el.addEventListener("insertTranscript", handler);
1208
+ return () => el.removeEventListener("insertTranscript", handler);
1209
+ }, [editor]);
1197
1210
  useEffect(() => {
1198
1211
  if (!editor || editor.isDestroyed) return;
1199
1212
  const fromForm = stringValue;
@@ -2138,6 +2151,162 @@ var ImageUploadWidget = ({ fieldId }) => {
2138
2151
  showError && /* @__PURE__ */ jsx("p", { className: "text-xs text-red-500", children: error })
2139
2152
  ] });
2140
2153
  };
2154
+ function urlLooksLikePdf(url) {
2155
+ return /\.pdf($|\?)/i.test(url) || url.toLowerCase().includes("application/pdf");
2156
+ }
2157
+ function isAcceptedMediaFile(file) {
2158
+ if (file.type.startsWith("image/")) return true;
2159
+ if (file.type === "application/pdf") return true;
2160
+ if (file.name.toLowerCase().endsWith(".pdf")) return true;
2161
+ return false;
2162
+ }
2163
+ var MediaUploadWidget = ({ fieldId }) => {
2164
+ const { fieldDef, value, setValue, setTouched, error, disabled, touched } = useField(fieldId);
2165
+ const store = useFormStore();
2166
+ const { state } = useForm();
2167
+ const [isUploading, setIsUploading] = useState(false);
2168
+ const [preview, setPreview] = useState(null);
2169
+ const [previewIsPdf, setPreviewIsPdf] = useState(false);
2170
+ const fileInputRef = useRef(null);
2171
+ const pendingPreviewKindRef = useRef(null);
2172
+ const showError = !!error && (touched || state.submitAttempted);
2173
+ if (!fieldDef) return null;
2174
+ const uploadHandler = store.getUploadHandler();
2175
+ if (!uploadHandler) {
2176
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
2177
+ /* @__PURE__ */ jsxs(Label, { htmlFor: fieldId, children: [
2178
+ fieldDef.label,
2179
+ fieldDef.required && /* @__PURE__ */ jsx("span", { className: "text-red-500", children: "*" })
2180
+ ] }),
2181
+ /* @__PURE__ */ jsx("div", { className: "border-2 border-red-300 rounded-lg p-4 bg-red-50", children: /* @__PURE__ */ jsx("p", { className: "text-sm text-red-600", children: "Upload handler not configured. Please provide an onUpload function in FormProvider config." }) })
2182
+ ] });
2183
+ }
2184
+ React15__default.useEffect(() => {
2185
+ if (value && typeof value === "string") {
2186
+ setPreview(value);
2187
+ if (pendingPreviewKindRef.current) {
2188
+ setPreviewIsPdf(pendingPreviewKindRef.current === "pdf");
2189
+ pendingPreviewKindRef.current = null;
2190
+ } else {
2191
+ setPreviewIsPdf(urlLooksLikePdf(value));
2192
+ }
2193
+ } else {
2194
+ setPreview(null);
2195
+ setPreviewIsPdf(false);
2196
+ }
2197
+ }, [value]);
2198
+ const handleFileSelect = async (event) => {
2199
+ const file = event.target.files?.[0];
2200
+ if (!file) return;
2201
+ if (!isAcceptedMediaFile(file)) {
2202
+ alert("Please select an image or PDF file");
2203
+ return;
2204
+ }
2205
+ const maxSize = 10 * 1024 * 1024;
2206
+ if (file.size > maxSize) {
2207
+ alert("File size must be less than 10MB");
2208
+ return;
2209
+ }
2210
+ const isPdf = file.type === "application/pdf" || file.name.toLowerCase().endsWith(".pdf");
2211
+ setIsUploading(true);
2212
+ setTouched();
2213
+ store.incrementPendingUploads();
2214
+ try {
2215
+ const previewUrl = URL.createObjectURL(file);
2216
+ setPreview(previewUrl);
2217
+ setPreviewIsPdf(isPdf);
2218
+ const s3Key = await uploadHandler(file, file.name);
2219
+ pendingPreviewKindRef.current = isPdf ? "pdf" : "image";
2220
+ setValue(s3Key);
2221
+ } catch (error2) {
2222
+ console.error("Upload failed:", error2);
2223
+ const errorMessage = error2 instanceof Error ? error2.message : "Upload failed. Please try again.";
2224
+ alert(errorMessage);
2225
+ setPreview(null);
2226
+ setPreviewIsPdf(false);
2227
+ } finally {
2228
+ setIsUploading(false);
2229
+ store.decrementPendingUploads();
2230
+ }
2231
+ };
2232
+ const handleRemove = () => {
2233
+ pendingPreviewKindRef.current = null;
2234
+ setValue(null);
2235
+ setPreview(null);
2236
+ setPreviewIsPdf(false);
2237
+ if (fileInputRef.current) {
2238
+ fileInputRef.current.value = "";
2239
+ }
2240
+ setTouched();
2241
+ };
2242
+ const handleUploadClick = () => {
2243
+ fileInputRef.current?.click();
2244
+ };
2245
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
2246
+ /* @__PURE__ */ jsxs(Label, { htmlFor: fieldId, children: [
2247
+ fieldDef.label,
2248
+ fieldDef.required && /* @__PURE__ */ jsx("span", { className: "text-red-500", children: "*" })
2249
+ ] }),
2250
+ /* @__PURE__ */ jsx("div", { className: "border-2 border-dashed border-gray-300 rounded-lg p-4", children: preview ? /* @__PURE__ */ jsxs("div", { className: "relative", children: [
2251
+ previewIsPdf ? /* @__PURE__ */ jsx(
2252
+ "iframe",
2253
+ {
2254
+ src: preview,
2255
+ title: "Uploaded PDF",
2256
+ className: "w-full max-h-48 min-h-36 rounded-lg border border-gray-200 bg-white"
2257
+ }
2258
+ ) : /* @__PURE__ */ jsx(
2259
+ "img",
2260
+ {
2261
+ src: preview,
2262
+ alt: "Uploaded image",
2263
+ className: "max-w-full max-h-48 mx-auto rounded-lg"
2264
+ }
2265
+ ),
2266
+ /* @__PURE__ */ jsx(
2267
+ Button,
2268
+ {
2269
+ type: "button",
2270
+ variant: "destructive",
2271
+ size: "sm",
2272
+ className: "absolute top-2 right-2",
2273
+ onClick: handleRemove,
2274
+ disabled: disabled || isUploading,
2275
+ children: /* @__PURE__ */ jsx(X, { className: "h-4 w-4" })
2276
+ }
2277
+ )
2278
+ ] }) : /* @__PURE__ */ jsxs("div", { className: "text-center py-8", children: [
2279
+ /* @__PURE__ */ jsx(Image, { className: "h-12 w-12 mx-auto text-gray-400 mb-4" }),
2280
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-gray-600 mb-4", children: "Click to upload an image or PDF, or drag and drop" }),
2281
+ /* @__PURE__ */ jsxs(
2282
+ Button,
2283
+ {
2284
+ type: "button",
2285
+ variant: "outline",
2286
+ onClick: handleUploadClick,
2287
+ disabled: disabled || isUploading,
2288
+ children: [
2289
+ /* @__PURE__ */ jsx(Upload, { className: "h-4 w-4 mr-2" }),
2290
+ isUploading ? "Uploading..." : "Choose Image"
2291
+ ]
2292
+ }
2293
+ )
2294
+ ] }) }),
2295
+ /* @__PURE__ */ jsx(
2296
+ "input",
2297
+ {
2298
+ ref: fileInputRef,
2299
+ type: "file",
2300
+ accept: "image/*,application/pdf",
2301
+ onChange: handleFileSelect,
2302
+ className: "hidden",
2303
+ disabled: disabled || isUploading
2304
+ }
2305
+ ),
2306
+ fieldDef.description && /* @__PURE__ */ jsx("p", { className: "text-xs text-gray-500", children: fieldDef.description }),
2307
+ showError && /* @__PURE__ */ jsx("p", { className: "text-xs text-red-500", children: error })
2308
+ ] });
2309
+ };
2141
2310
  var distance = (a, b) => Math.hypot(a.x - b.x, a.y - b.y);
2142
2311
  var smoothPoint = (prev, curr, smoothing = 0.75) => {
2143
2312
  if (!prev) return curr;
@@ -7402,6 +7571,8 @@ function renderWidget(fieldId, fieldDef) {
7402
7571
  return /* @__PURE__ */ jsx(RepeatableWidget, { fieldId });
7403
7572
  case "image_upload":
7404
7573
  return /* @__PURE__ */ jsx(ImageUploadWidget, { fieldId });
7574
+ case "media_upload":
7575
+ return /* @__PURE__ */ jsx(MediaUploadWidget, { fieldId });
7405
7576
  case "signature":
7406
7577
  return /* @__PURE__ */ jsx(SignatureUploadWidget, { fieldId });
7407
7578
  case "editable_table":
@@ -7809,6 +7980,55 @@ var ReadOnlyImageUpload = ({
7809
7980
  fieldDef.description && /* @__PURE__ */ jsx("p", { className: "text-xs text-gray-500", children: fieldDef.description })
7810
7981
  ] });
7811
7982
  };
7983
+ function urlLooksLikePdf2(url) {
7984
+ return /\.pdf($|\?)/i.test(url) || url.toLowerCase().includes("application/pdf");
7985
+ }
7986
+ var ReadOnlyMediaUpload = ({
7987
+ fieldDef,
7988
+ value
7989
+ }) => {
7990
+ const [useIframe, setUseIframe] = useState(false);
7991
+ let url = null;
7992
+ if (typeof value === "string") {
7993
+ url = value;
7994
+ } else if (value && typeof value === "object") {
7995
+ const typed = value;
7996
+ url = typed.presigned_url || typed.value || typed.s3_key || null;
7997
+ }
7998
+ useEffect(() => {
7999
+ setUseIframe(false);
8000
+ }, [url]);
8001
+ const showAsPdf = url && (urlLooksLikePdf2(url) || useIframe);
8002
+ if (!url) {
8003
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
8004
+ /* @__PURE__ */ jsx(Label, { children: fieldDef.label }),
8005
+ /* @__PURE__ */ jsx("div", { className: "border border-gray-200 rounded-lg p-4 bg-gray-50", children: /* @__PURE__ */ jsxs("div", { className: "text-center py-4", children: [
8006
+ /* @__PURE__ */ jsx(Image, { className: "h-8 w-8 mx-auto text-gray-400 mb-2" }),
8007
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-gray-500", children: "No file uploaded" })
8008
+ ] }) })
8009
+ ] });
8010
+ }
8011
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
8012
+ /* @__PURE__ */ jsx(Label, { children: fieldDef.label }),
8013
+ /* @__PURE__ */ jsx("div", { className: "border border-gray-200 rounded-lg p-4 bg-white", children: showAsPdf ? /* @__PURE__ */ jsx(
8014
+ "iframe",
8015
+ {
8016
+ src: url,
8017
+ title: `${fieldDef.label} PDF`,
8018
+ className: "w-full max-h-48 min-h-36 rounded-lg border border-gray-200 bg-white"
8019
+ }
8020
+ ) : /* @__PURE__ */ jsx(
8021
+ "img",
8022
+ {
8023
+ src: url,
8024
+ alt: `${fieldDef.label} upload`,
8025
+ className: "max-w-full max-h-48 mx-auto rounded-lg",
8026
+ onError: () => setUseIframe(true)
8027
+ }
8028
+ ) }),
8029
+ fieldDef.description && /* @__PURE__ */ jsx("p", { className: "text-xs text-gray-500", children: fieldDef.description })
8030
+ ] });
8031
+ };
7812
8032
  var ReadOnlySignature = ({
7813
8033
  fieldDef,
7814
8034
  value
@@ -8010,6 +8230,8 @@ var ReadOnlyFieldRenderer = ({ fieldDef, value }) => {
8010
8230
  return /* @__PURE__ */ jsx(ReadOnlyRepeatable, { fieldDef, value });
8011
8231
  case "image_upload":
8012
8232
  return /* @__PURE__ */ jsx(ReadOnlyImageUpload, { fieldDef, value });
8233
+ case "media_upload":
8234
+ return /* @__PURE__ */ jsx(ReadOnlyMediaUpload, { fieldDef, value });
8013
8235
  case "signature":
8014
8236
  return /* @__PURE__ */ jsx(ReadOnlySignature, { fieldDef, value });
8015
8237
  case "editable_table":
@@ -8217,6 +8439,6 @@ function createUploadHandler(options) {
8217
8439
  };
8218
8440
  }
8219
8441
 
8220
- export { AddInvestigationField, AddMedicationField, DifferentialDiagnosis, DynamicForm, EMAIL_REGEX, FieldRenderer, FormControls, FormProvider, FormStore, ImageUploadWidget, ReadOnlyForm, ReadOnlyImageUpload, ReadOnlySignature, ReadOnlyTable, RichTextWidget, SignatureUploadWidget, SmartForm, SmartTextareaWidget, createUploadHandler, evaluateRules, useField, useFieldHandlers, useForm, useFormStore, useFrequentItems, useSmartKeywords, validateField, validateForm };
8442
+ export { AddInvestigationField, AddMedicationField, DifferentialDiagnosis, DynamicForm, EMAIL_REGEX, FieldRenderer, FormControls, FormProvider, FormStore, ImageUploadWidget, MediaUploadWidget, ReadOnlyForm, ReadOnlyImageUpload, ReadOnlyMediaUpload, ReadOnlySignature, ReadOnlyTable, RichTextWidget, SignatureUploadWidget, SmartForm, SmartTextareaWidget, createUploadHandler, evaluateRules, useField, useFieldHandlers, useForm, useFormStore, useFrequentItems, useSmartKeywords, validateField, validateForm };
8221
8443
  //# sourceMappingURL=index.mjs.map
8222
8444
  //# sourceMappingURL=index.mjs.map