formanitor 0.0.31 → 0.0.33

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.mjs CHANGED
@@ -23,6 +23,13 @@ import * as DialogPrimitive from '@radix-ui/react-dialog';
23
23
  import nlp from 'compromise';
24
24
  import * as SliderPrimitive from '@radix-ui/react-slider';
25
25
 
26
+ // src/core/marMedicationOrdersMeta.ts
27
+ var MAR_MEDICATION_ORDERS_META_KEY = "mar_medication_orders";
28
+ function fieldMetaRequestsMarMedicationOrdersButton(meta) {
29
+ if (!meta || typeof meta !== "object") return false;
30
+ return meta[MAR_MEDICATION_ORDERS_META_KEY] === true;
31
+ }
32
+
26
33
  // src/core/validate.ts
27
34
  var EMAIL_REGEX = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
28
35
  function validateField(value, field) {
@@ -423,7 +430,7 @@ var FormStore = class {
423
430
  result[field.id] = parts.length > 0 ? parts.join("\n\n") : null;
424
431
  return;
425
432
  }
426
- if (field.type === "image_upload" || field.type === "signature") {
433
+ if (field.type === "image_upload" || field.type === "media_upload" || field.type === "signature") {
427
434
  const raw = values[field.id];
428
435
  if (raw !== void 0 && raw !== null && raw !== "") {
429
436
  const key = typeof raw === "string" ? raw : raw.s3_key || raw.value || null;
@@ -2151,6 +2158,162 @@ var ImageUploadWidget = ({ fieldId }) => {
2151
2158
  showError && /* @__PURE__ */ jsx("p", { className: "text-xs text-red-500", children: error })
2152
2159
  ] });
2153
2160
  };
2161
+ function urlLooksLikePdf(url) {
2162
+ return /\.pdf($|\?)/i.test(url) || url.toLowerCase().includes("application/pdf");
2163
+ }
2164
+ function isAcceptedMediaFile(file) {
2165
+ if (file.type.startsWith("image/")) return true;
2166
+ if (file.type === "application/pdf") return true;
2167
+ if (file.name.toLowerCase().endsWith(".pdf")) return true;
2168
+ return false;
2169
+ }
2170
+ var MediaUploadWidget = ({ fieldId }) => {
2171
+ const { fieldDef, value, setValue, setTouched, error, disabled, touched } = useField(fieldId);
2172
+ const store = useFormStore();
2173
+ const { state } = useForm();
2174
+ const [isUploading, setIsUploading] = useState(false);
2175
+ const [preview, setPreview] = useState(null);
2176
+ const [previewIsPdf, setPreviewIsPdf] = useState(false);
2177
+ const fileInputRef = useRef(null);
2178
+ const pendingPreviewKindRef = useRef(null);
2179
+ const showError = !!error && (touched || state.submitAttempted);
2180
+ if (!fieldDef) return null;
2181
+ const uploadHandler = store.getUploadHandler();
2182
+ if (!uploadHandler) {
2183
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
2184
+ /* @__PURE__ */ jsxs(Label, { htmlFor: fieldId, children: [
2185
+ fieldDef.label,
2186
+ fieldDef.required && /* @__PURE__ */ jsx("span", { className: "text-red-500", children: "*" })
2187
+ ] }),
2188
+ /* @__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." }) })
2189
+ ] });
2190
+ }
2191
+ React15__default.useEffect(() => {
2192
+ if (value && typeof value === "string") {
2193
+ setPreview(value);
2194
+ if (pendingPreviewKindRef.current) {
2195
+ setPreviewIsPdf(pendingPreviewKindRef.current === "pdf");
2196
+ pendingPreviewKindRef.current = null;
2197
+ } else {
2198
+ setPreviewIsPdf(urlLooksLikePdf(value));
2199
+ }
2200
+ } else {
2201
+ setPreview(null);
2202
+ setPreviewIsPdf(false);
2203
+ }
2204
+ }, [value]);
2205
+ const handleFileSelect = async (event) => {
2206
+ const file = event.target.files?.[0];
2207
+ if (!file) return;
2208
+ if (!isAcceptedMediaFile(file)) {
2209
+ alert("Please select an image or PDF file");
2210
+ return;
2211
+ }
2212
+ const maxSize = 10 * 1024 * 1024;
2213
+ if (file.size > maxSize) {
2214
+ alert("File size must be less than 10MB");
2215
+ return;
2216
+ }
2217
+ const isPdf = file.type === "application/pdf" || file.name.toLowerCase().endsWith(".pdf");
2218
+ setIsUploading(true);
2219
+ setTouched();
2220
+ store.incrementPendingUploads();
2221
+ try {
2222
+ const previewUrl = URL.createObjectURL(file);
2223
+ setPreview(previewUrl);
2224
+ setPreviewIsPdf(isPdf);
2225
+ const s3Key = await uploadHandler(file, file.name);
2226
+ pendingPreviewKindRef.current = isPdf ? "pdf" : "image";
2227
+ setValue(s3Key);
2228
+ } catch (error2) {
2229
+ console.error("Upload failed:", error2);
2230
+ const errorMessage = error2 instanceof Error ? error2.message : "Upload failed. Please try again.";
2231
+ alert(errorMessage);
2232
+ setPreview(null);
2233
+ setPreviewIsPdf(false);
2234
+ } finally {
2235
+ setIsUploading(false);
2236
+ store.decrementPendingUploads();
2237
+ }
2238
+ };
2239
+ const handleRemove = () => {
2240
+ pendingPreviewKindRef.current = null;
2241
+ setValue(null);
2242
+ setPreview(null);
2243
+ setPreviewIsPdf(false);
2244
+ if (fileInputRef.current) {
2245
+ fileInputRef.current.value = "";
2246
+ }
2247
+ setTouched();
2248
+ };
2249
+ const handleUploadClick = () => {
2250
+ fileInputRef.current?.click();
2251
+ };
2252
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
2253
+ /* @__PURE__ */ jsxs(Label, { htmlFor: fieldId, children: [
2254
+ fieldDef.label,
2255
+ fieldDef.required && /* @__PURE__ */ jsx("span", { className: "text-red-500", children: "*" })
2256
+ ] }),
2257
+ /* @__PURE__ */ jsx("div", { className: "border-2 border-dashed border-gray-300 rounded-lg p-4", children: preview ? /* @__PURE__ */ jsxs("div", { className: "relative", children: [
2258
+ previewIsPdf ? /* @__PURE__ */ jsx(
2259
+ "iframe",
2260
+ {
2261
+ src: preview,
2262
+ title: "Uploaded PDF",
2263
+ className: "w-full max-h-48 min-h-36 rounded-lg border border-gray-200 bg-white"
2264
+ }
2265
+ ) : /* @__PURE__ */ jsx(
2266
+ "img",
2267
+ {
2268
+ src: preview,
2269
+ alt: "Uploaded image",
2270
+ className: "max-w-full max-h-48 mx-auto rounded-lg"
2271
+ }
2272
+ ),
2273
+ /* @__PURE__ */ jsx(
2274
+ Button,
2275
+ {
2276
+ type: "button",
2277
+ variant: "destructive",
2278
+ size: "sm",
2279
+ className: "absolute top-2 right-2",
2280
+ onClick: handleRemove,
2281
+ disabled: disabled || isUploading,
2282
+ children: /* @__PURE__ */ jsx(X, { className: "h-4 w-4" })
2283
+ }
2284
+ )
2285
+ ] }) : /* @__PURE__ */ jsxs("div", { className: "text-center py-8", children: [
2286
+ /* @__PURE__ */ jsx(Image, { className: "h-12 w-12 mx-auto text-gray-400 mb-4" }),
2287
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-gray-600 mb-4", children: "Click to upload an image or PDF, or drag and drop" }),
2288
+ /* @__PURE__ */ jsxs(
2289
+ Button,
2290
+ {
2291
+ type: "button",
2292
+ variant: "outline",
2293
+ onClick: handleUploadClick,
2294
+ disabled: disabled || isUploading,
2295
+ children: [
2296
+ /* @__PURE__ */ jsx(Upload, { className: "h-4 w-4 mr-2" }),
2297
+ isUploading ? "Uploading..." : "Choose Image"
2298
+ ]
2299
+ }
2300
+ )
2301
+ ] }) }),
2302
+ /* @__PURE__ */ jsx(
2303
+ "input",
2304
+ {
2305
+ ref: fileInputRef,
2306
+ type: "file",
2307
+ accept: "image/*,application/pdf",
2308
+ onChange: handleFileSelect,
2309
+ className: "hidden",
2310
+ disabled: disabled || isUploading
2311
+ }
2312
+ ),
2313
+ fieldDef.description && /* @__PURE__ */ jsx("p", { className: "text-xs text-gray-500", children: fieldDef.description }),
2314
+ showError && /* @__PURE__ */ jsx("p", { className: "text-xs text-red-500", children: error })
2315
+ ] });
2316
+ };
2154
2317
  var distance = (a, b) => Math.hypot(a.x - b.x, a.y - b.y);
2155
2318
  var smoothPoint = (prev, curr, smoothing = 0.75) => {
2156
2319
  if (!prev) return curr;
@@ -7383,6 +7546,206 @@ var OrthopedicExamWidget = ({ fieldId }) => {
7383
7546
  ) : null
7384
7547
  ] });
7385
7548
  };
7549
+ var MarMedicationOrdersWidget = ({ fieldId }) => {
7550
+ const { fieldDef, value, setTouched, error, disabled, touched } = useField(fieldId);
7551
+ const { state } = useForm();
7552
+ const handlers = useFieldHandlers(fieldId);
7553
+ const showError = !!error && (touched || state.submitAttempted);
7554
+ const onOpen = useCallback(async () => {
7555
+ await handlers.onOpenMedicationOrders?.();
7556
+ setTouched();
7557
+ }, [handlers, setTouched]);
7558
+ if (!fieldDef || fieldDef.type !== "textarea") return null;
7559
+ const textDef = fieldDef;
7560
+ const height = textDef.height;
7561
+ const theme = getThemeConfig("textarea", fieldDef.theme);
7562
+ const wrapperClass = theme?.wrapperClassName ?? "space-y-2";
7563
+ const labelClass = theme?.labelClassName;
7564
+ const labelContent = /* @__PURE__ */ jsxs(Fragment, { children: [
7565
+ fieldDef.label,
7566
+ " ",
7567
+ fieldDef.required && /* @__PURE__ */ jsx("span", { className: "text-red-500", children: "*" })
7568
+ ] });
7569
+ const labelEl = theme ? /* @__PURE__ */ jsx(Label, { htmlFor: fieldId, className: labelClass, children: labelContent }) : /* @__PURE__ */ jsx(Label, { htmlFor: fieldId, children: labelContent });
7570
+ const text = typeof value === "string" ? value : value == null ? "" : String(value);
7571
+ const hasHandler = typeof handlers.onOpenMedicationOrders === "function";
7572
+ return /* @__PURE__ */ jsxs("div", { className: wrapperClass, children: [
7573
+ labelEl,
7574
+ fieldDef.description && /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: fieldDef.description }),
7575
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2 sm:flex-row sm:items-start sm:justify-between sm:gap-3", children: [
7576
+ /* @__PURE__ */ jsx(
7577
+ "div",
7578
+ {
7579
+ id: fieldId,
7580
+ className: cn(
7581
+ "min-h-[80px] flex-1 rounded-md border border-input bg-background px-3 py-2 text-sm whitespace-pre-wrap",
7582
+ showError && "border-red-500",
7583
+ !text && "text-muted-foreground"
7584
+ ),
7585
+ style: height != null ? { minHeight: height } : void 0,
7586
+ "aria-readonly": "true",
7587
+ children: text || fieldDef.placeholder || "No medication orders added."
7588
+ }
7589
+ ),
7590
+ /* @__PURE__ */ jsx(
7591
+ Button,
7592
+ {
7593
+ type: "button",
7594
+ variant: "default",
7595
+ disabled: disabled || !hasHandler,
7596
+ onClick: onOpen,
7597
+ className: "shrink-0 sm:mt-0",
7598
+ children: "Add medication orders"
7599
+ }
7600
+ )
7601
+ ] }),
7602
+ showError && /* @__PURE__ */ jsx("p", { className: "text-xs text-red-500", children: error })
7603
+ ] });
7604
+ };
7605
+ function parseFieldValue(value) {
7606
+ if (value == null) return { orders: [], display_lines: [] };
7607
+ if (Array.isArray(value)) {
7608
+ return {
7609
+ orders: value,
7610
+ display_lines: value.map(() => null)
7611
+ };
7612
+ }
7613
+ if (typeof value === "object") {
7614
+ const v = value;
7615
+ const orders = Array.isArray(v.orders) ? v.orders : [];
7616
+ const rawLines = Array.isArray(v.display_lines) ? v.display_lines : Array.isArray(v.displayLines) ? v.displayLines : [];
7617
+ const display_lines = orders.map((_, i) => rawLines[i] ?? null);
7618
+ return { orders, display_lines };
7619
+ }
7620
+ return { orders: [], display_lines: [] };
7621
+ }
7622
+ function normalizePrescription(res) {
7623
+ const pharmacyOrderId = res.pharmacy_order_id ?? void 0;
7624
+ const orders = Array.isArray(res.orders) ? res.orders : [];
7625
+ const linesRaw = Array.isArray(res.display_lines) ? res.display_lines : [];
7626
+ const mapped = orders.filter((o) => o && typeof o.id === "string").map((o) => ({
7627
+ id: o.id,
7628
+ item_id: o.item_id == null ? void 0 : String(o.item_id),
7629
+ item_name: o.item_name ?? void 0,
7630
+ generic_name: o.generic_name ?? void 0,
7631
+ dose: o.dose == null ? void 0 : String(o.dose),
7632
+ route: o.route ?? void 0,
7633
+ frequency: o.frequency ?? void 0,
7634
+ admin_times: Array.isArray(o.admin_times) ? o.admin_times : void 0,
7635
+ meal_sleep_timing: o.meal_sleep_timing ?? void 0,
7636
+ start_date: o.start_date ?? void 0,
7637
+ end_date: o.end_date ?? void 0,
7638
+ order_type: o.order_type ?? void 0,
7639
+ status: o.status ?? void 0,
7640
+ notes: o.notes ?? null,
7641
+ pharmacy_order_id: pharmacyOrderId
7642
+ }));
7643
+ const display_lines = mapped.map((_, i) => linesRaw[i] ?? null);
7644
+ return { orders: mapped, display_lines };
7645
+ }
7646
+ function formatDuration(start, end) {
7647
+ if (!start && !end) return null;
7648
+ if (start && end) return `${start} \u2192 ${end}`;
7649
+ return start ? `Start: ${start}` : `End: ${end}`;
7650
+ }
7651
+ var DischargeMedicationOrdersWidget = ({ fieldId }) => {
7652
+ const { fieldDef, value, setValue, setTouched, error, disabled, touched, visible } = useField(fieldId);
7653
+ const { state } = useForm();
7654
+ const handlers = useFieldHandlers(fieldId);
7655
+ const showError = !!error && (touched || state.submitAttempted);
7656
+ const { orders, display_lines } = useMemo(() => parseFieldValue(value), [value]);
7657
+ const onAdd = useCallback(async () => {
7658
+ setTouched();
7659
+ const fn = handlers.onOpenDischargeMedicationOrders;
7660
+ if (!fn) return;
7661
+ const res = await fn();
7662
+ if (!res || typeof res !== "object") return;
7663
+ const normalized = normalizePrescription(res);
7664
+ setValue({
7665
+ orders: normalized.orders,
7666
+ display_lines: normalized.display_lines
7667
+ });
7668
+ }, [handlers.onOpenDischargeMedicationOrders, setTouched, setValue]);
7669
+ const onDelete = useCallback(
7670
+ (id) => {
7671
+ setTouched();
7672
+ const idx = orders.findIndex((o) => o.id === id);
7673
+ if (idx === -1) return;
7674
+ setValue({
7675
+ orders: orders.filter((o) => o.id !== id),
7676
+ display_lines: display_lines.filter((_, i) => i !== idx)
7677
+ });
7678
+ },
7679
+ [orders, display_lines, setTouched, setValue]
7680
+ );
7681
+ if (!visible || !fieldDef) return null;
7682
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
7683
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2", children: [
7684
+ /* @__PURE__ */ jsxs(Label, { className: "text-sm font-medium", children: [
7685
+ fieldDef.label,
7686
+ " ",
7687
+ fieldDef.required && /* @__PURE__ */ jsx("span", { className: "text-red-500", children: "*" })
7688
+ ] }),
7689
+ /* @__PURE__ */ jsx(Button, { type: "button", onClick: onAdd, disabled: disabled || !handlers.onOpenDischargeMedicationOrders, children: "Add medicine" })
7690
+ ] }),
7691
+ fieldDef.description && /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: fieldDef.description }),
7692
+ orders.length === 0 ? /* @__PURE__ */ jsx(
7693
+ "div",
7694
+ {
7695
+ className: cn(
7696
+ "rounded-md border border-input bg-background px-3 py-3 text-sm text-muted-foreground",
7697
+ showError && "border-red-500"
7698
+ ),
7699
+ children: "No medicines added."
7700
+ }
7701
+ ) : /* @__PURE__ */ jsx("div", { className: "space-y-2", children: orders.map((o, rowIdx) => {
7702
+ const line = display_lines[rowIdx];
7703
+ const duration = formatDuration(o.start_date, o.end_date);
7704
+ const header = typeof line?.name === "string" && line.name.trim() || o.item_name || "Medicine";
7705
+ const sub = o.generic_name ? o.generic_name : null;
7706
+ const line1 = [o.dose && `Dose: ${o.dose}`, o.route && `Route: ${o.route}`].filter(Boolean).join(" \u2022 ");
7707
+ const line2 = [
7708
+ o.frequency && `Freq: ${o.frequency}`,
7709
+ o.meal_sleep_timing && `Meal/Sleep: ${o.meal_sleep_timing}`,
7710
+ o.admin_times?.length ? `Times: ${o.admin_times.join(", ")}` : null
7711
+ ].filter(Boolean).join(" \u2022 ");
7712
+ const line3 = [
7713
+ duration ? `Duration: ${duration}` : null,
7714
+ o.order_type ? `Type: ${o.order_type}` : null,
7715
+ o.status ? `Status: ${o.status}` : null
7716
+ ].filter(Boolean).join(" \u2022 ");
7717
+ return /* @__PURE__ */ jsxs("div", { className: "rounded-md border border-input bg-background p-3", children: [
7718
+ /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-3", children: [
7719
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
7720
+ /* @__PURE__ */ jsx("div", { className: "font-semibold text-sm truncate", children: header }),
7721
+ sub && /* @__PURE__ */ jsx("div", { className: "text-xs text-muted-foreground mt-0.5 truncate", children: sub })
7722
+ ] }),
7723
+ /* @__PURE__ */ jsx(
7724
+ Button,
7725
+ {
7726
+ type: "button",
7727
+ variant: "ghost",
7728
+ className: "h-8 w-8 p-0 text-destructive",
7729
+ onClick: () => onDelete(o.id),
7730
+ "aria-label": "Delete medicine",
7731
+ children: /* @__PURE__ */ jsx(Trash2, { className: "h-4 w-4" })
7732
+ }
7733
+ )
7734
+ ] }),
7735
+ /* @__PURE__ */ jsxs("div", { className: "mt-2 space-y-1 text-xs text-muted-foreground", children: [
7736
+ line1 && /* @__PURE__ */ jsx("div", { children: line1 }),
7737
+ line2 && /* @__PURE__ */ jsx("div", { children: line2 }),
7738
+ line3 && /* @__PURE__ */ jsx("div", { children: line3 }),
7739
+ o.notes && /* @__PURE__ */ jsxs("div", { className: "text-foreground/80", children: [
7740
+ "Notes: ",
7741
+ o.notes
7742
+ ] })
7743
+ ] })
7744
+ ] }, o.id);
7745
+ }) }),
7746
+ showError && /* @__PURE__ */ jsx("p", { className: "text-xs text-red-500", children: error })
7747
+ ] });
7748
+ };
7386
7749
  var FieldRenderer = ({ fieldId }) => {
7387
7750
  const { fieldDef, visible } = useField(fieldId);
7388
7751
  if (!visible || !fieldDef) {
@@ -7396,6 +7759,9 @@ function renderWidget(fieldId, fieldDef) {
7396
7759
  case "number":
7397
7760
  return /* @__PURE__ */ jsx(TextWidget, { fieldId });
7398
7761
  case "textarea":
7762
+ if (fieldMetaRequestsMarMedicationOrdersButton(fieldDef.meta)) {
7763
+ return /* @__PURE__ */ jsx(MarMedicationOrdersWidget, { fieldId });
7764
+ }
7399
7765
  return /* @__PURE__ */ jsx(TextWidget, { fieldId });
7400
7766
  case "richtext":
7401
7767
  return /* @__PURE__ */ jsx(RichTextWidget, { fieldId });
@@ -7415,12 +7781,16 @@ function renderWidget(fieldId, fieldDef) {
7415
7781
  return /* @__PURE__ */ jsx(RepeatableWidget, { fieldId });
7416
7782
  case "image_upload":
7417
7783
  return /* @__PURE__ */ jsx(ImageUploadWidget, { fieldId });
7784
+ case "media_upload":
7785
+ return /* @__PURE__ */ jsx(MediaUploadWidget, { fieldId });
7418
7786
  case "signature":
7419
7787
  return /* @__PURE__ */ jsx(SignatureUploadWidget, { fieldId });
7420
7788
  case "editable_table":
7421
7789
  return /* @__PURE__ */ jsx(EditableTableWidget, { fieldId });
7422
7790
  case "medications":
7423
7791
  return /* @__PURE__ */ jsx(AddMedicationWidget, { fieldId });
7792
+ case "discharge_medication_orders":
7793
+ return /* @__PURE__ */ jsx(DischargeMedicationOrdersWidget, { fieldId });
7424
7794
  case "investigations":
7425
7795
  return /* @__PURE__ */ jsx(AddInvestigationWidget, { fieldId });
7426
7796
  case "procedures":
@@ -7822,6 +8192,55 @@ var ReadOnlyImageUpload = ({
7822
8192
  fieldDef.description && /* @__PURE__ */ jsx("p", { className: "text-xs text-gray-500", children: fieldDef.description })
7823
8193
  ] });
7824
8194
  };
8195
+ function urlLooksLikePdf2(url) {
8196
+ return /\.pdf($|\?)/i.test(url) || url.toLowerCase().includes("application/pdf");
8197
+ }
8198
+ var ReadOnlyMediaUpload = ({
8199
+ fieldDef,
8200
+ value
8201
+ }) => {
8202
+ const [useIframe, setUseIframe] = useState(false);
8203
+ let url = null;
8204
+ if (typeof value === "string") {
8205
+ url = value;
8206
+ } else if (value && typeof value === "object") {
8207
+ const typed = value;
8208
+ url = typed.presigned_url || typed.value || typed.s3_key || null;
8209
+ }
8210
+ useEffect(() => {
8211
+ setUseIframe(false);
8212
+ }, [url]);
8213
+ const showAsPdf = url && (urlLooksLikePdf2(url) || useIframe);
8214
+ if (!url) {
8215
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
8216
+ /* @__PURE__ */ jsx(Label, { children: fieldDef.label }),
8217
+ /* @__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: [
8218
+ /* @__PURE__ */ jsx(Image, { className: "h-8 w-8 mx-auto text-gray-400 mb-2" }),
8219
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-gray-500", children: "No file uploaded" })
8220
+ ] }) })
8221
+ ] });
8222
+ }
8223
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
8224
+ /* @__PURE__ */ jsx(Label, { children: fieldDef.label }),
8225
+ /* @__PURE__ */ jsx("div", { className: "border border-gray-200 rounded-lg p-4 bg-white", children: showAsPdf ? /* @__PURE__ */ jsx(
8226
+ "iframe",
8227
+ {
8228
+ src: url,
8229
+ title: `${fieldDef.label} PDF`,
8230
+ className: "w-full max-h-48 min-h-36 rounded-lg border border-gray-200 bg-white"
8231
+ }
8232
+ ) : /* @__PURE__ */ jsx(
8233
+ "img",
8234
+ {
8235
+ src: url,
8236
+ alt: `${fieldDef.label} upload`,
8237
+ className: "max-w-full max-h-48 mx-auto rounded-lg",
8238
+ onError: () => setUseIframe(true)
8239
+ }
8240
+ ) }),
8241
+ fieldDef.description && /* @__PURE__ */ jsx("p", { className: "text-xs text-gray-500", children: fieldDef.description })
8242
+ ] });
8243
+ };
7825
8244
  var ReadOnlySignature = ({
7826
8245
  fieldDef,
7827
8246
  value
@@ -7999,6 +8418,53 @@ var ReadOnlyReferral = ({ fieldDef, value }) => {
7999
8418
  }) })
8000
8419
  ] });
8001
8420
  };
8421
+ function isOrderArray(value) {
8422
+ return Array.isArray(value) && value.every(
8423
+ (v) => v != null && typeof v === "object" && typeof v.id === "string"
8424
+ );
8425
+ }
8426
+ function formatDuration2(start, end) {
8427
+ if (!start && !end) return null;
8428
+ if (start && end) return `${start} \u2192 ${end}`;
8429
+ return start ? `Start: ${start}` : `End: ${end}`;
8430
+ }
8431
+ var ReadOnlyDischargeMedicationOrders = ({ fieldDef, value }) => {
8432
+ const orders = useMemo(() => isOrderArray(value) ? value : [], [value]);
8433
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
8434
+ /* @__PURE__ */ jsx(Label, { className: "text-sm font-medium text-gray-700", children: fieldDef.label }),
8435
+ orders.length === 0 ? /* @__PURE__ */ jsx("div", { className: "text-gray-900 border border-gray-200 rounded-md p-3 bg-gray-50 min-h-[2.5rem]", children: /* @__PURE__ */ jsx("span", { className: "text-gray-400 italic", children: "No medicines added" }) }) : /* @__PURE__ */ jsx("div", { className: "space-y-2", children: orders.map((o) => {
8436
+ const duration = formatDuration2(o.start_date, o.end_date);
8437
+ const header = o.item_name ?? "Medicine";
8438
+ const sub = o.generic_name ? o.generic_name : null;
8439
+ const line1 = [o.dose && `Dose: ${o.dose}`, o.route && `Route: ${o.route}`].filter(Boolean).join(" \u2022 ");
8440
+ const line2 = [
8441
+ o.frequency && `Freq: ${o.frequency}`,
8442
+ o.meal_sleep_timing && `Meal/Sleep: ${o.meal_sleep_timing}`,
8443
+ o.admin_times?.length ? `Times: ${o.admin_times.join(", ")}` : null
8444
+ ].filter(Boolean).join(" \u2022 ");
8445
+ const line3 = [
8446
+ duration ? `Duration: ${duration}` : null,
8447
+ o.order_type ? `Type: ${o.order_type}` : null,
8448
+ o.status ? `Status: ${o.status}` : null
8449
+ ].filter(Boolean).join(" \u2022 ");
8450
+ return /* @__PURE__ */ jsxs("div", { className: "rounded-md border border-gray-200 bg-gray-50 p-3", children: [
8451
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
8452
+ /* @__PURE__ */ jsx("div", { className: "font-semibold text-sm truncate text-gray-900", children: header }),
8453
+ sub && /* @__PURE__ */ jsx("div", { className: "text-xs text-gray-500 mt-0.5 truncate", children: sub })
8454
+ ] }),
8455
+ /* @__PURE__ */ jsxs("div", { className: "mt-2 space-y-1 text-xs text-gray-600", children: [
8456
+ line1 && /* @__PURE__ */ jsx("div", { children: line1 }),
8457
+ line2 && /* @__PURE__ */ jsx("div", { children: line2 }),
8458
+ line3 && /* @__PURE__ */ jsx("div", { children: line3 }),
8459
+ o.notes && /* @__PURE__ */ jsxs("div", { className: "text-gray-800/90", children: [
8460
+ "Notes: ",
8461
+ o.notes
8462
+ ] })
8463
+ ] })
8464
+ ] }, o.id);
8465
+ }) })
8466
+ ] });
8467
+ };
8002
8468
  var ReadOnlyFieldRenderer = ({ fieldDef, value }) => {
8003
8469
  if (!fieldDef) return null;
8004
8470
  switch (fieldDef.type) {
@@ -8023,12 +8489,16 @@ var ReadOnlyFieldRenderer = ({ fieldDef, value }) => {
8023
8489
  return /* @__PURE__ */ jsx(ReadOnlyRepeatable, { fieldDef, value });
8024
8490
  case "image_upload":
8025
8491
  return /* @__PURE__ */ jsx(ReadOnlyImageUpload, { fieldDef, value });
8492
+ case "media_upload":
8493
+ return /* @__PURE__ */ jsx(ReadOnlyMediaUpload, { fieldDef, value });
8026
8494
  case "signature":
8027
8495
  return /* @__PURE__ */ jsx(ReadOnlySignature, { fieldDef, value });
8028
8496
  case "editable_table":
8029
8497
  return /* @__PURE__ */ jsx(ReadOnlyTable, { fieldDef, value });
8030
8498
  case "referral":
8031
8499
  return /* @__PURE__ */ jsx(ReadOnlyReferral, { fieldDef, value });
8500
+ case "discharge_medication_orders":
8501
+ return /* @__PURE__ */ jsx(ReadOnlyDischargeMedicationOrders, { fieldDef, value });
8032
8502
  case "static_text": {
8033
8503
  const def = fieldDef;
8034
8504
  const size = def.size ?? "regular";
@@ -8230,6 +8700,6 @@ function createUploadHandler(options) {
8230
8700
  };
8231
8701
  }
8232
8702
 
8233
- 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 };
8703
+ export { AddInvestigationField, AddMedicationField, DifferentialDiagnosis, DynamicForm, EMAIL_REGEX, FieldRenderer, FormControls, FormProvider, FormStore, ImageUploadWidget, MAR_MEDICATION_ORDERS_META_KEY, MediaUploadWidget, ReadOnlyForm, ReadOnlyImageUpload, ReadOnlyMediaUpload, ReadOnlySignature, ReadOnlyTable, RichTextWidget, SignatureUploadWidget, SmartForm, SmartTextareaWidget, createUploadHandler, evaluateRules, fieldMetaRequestsMarMedicationOrdersButton, useField, useFieldHandlers, useForm, useFormStore, useFrequentItems, useSmartKeywords, validateField, validateForm };
8234
8704
  //# sourceMappingURL=index.mjs.map
8235
8705
  //# sourceMappingURL=index.mjs.map