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.cjs CHANGED
@@ -58,6 +58,13 @@ var DialogPrimitive__namespace = /*#__PURE__*/_interopNamespace(DialogPrimitive)
58
58
  var nlp__default = /*#__PURE__*/_interopDefault(nlp);
59
59
  var SliderPrimitive__namespace = /*#__PURE__*/_interopNamespace(SliderPrimitive);
60
60
 
61
+ // src/core/marMedicationOrdersMeta.ts
62
+ var MAR_MEDICATION_ORDERS_META_KEY = "mar_medication_orders";
63
+ function fieldMetaRequestsMarMedicationOrdersButton(meta) {
64
+ if (!meta || typeof meta !== "object") return false;
65
+ return meta[MAR_MEDICATION_ORDERS_META_KEY] === true;
66
+ }
67
+
61
68
  // src/core/validate.ts
62
69
  var EMAIL_REGEX = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
63
70
  function validateField(value, field) {
@@ -458,7 +465,7 @@ var FormStore = class {
458
465
  result[field.id] = parts.length > 0 ? parts.join("\n\n") : null;
459
466
  return;
460
467
  }
461
- if (field.type === "image_upload" || field.type === "signature") {
468
+ if (field.type === "image_upload" || field.type === "media_upload" || field.type === "signature") {
462
469
  const raw = values[field.id];
463
470
  if (raw !== void 0 && raw !== null && raw !== "") {
464
471
  const key = typeof raw === "string" ? raw : raw.s3_key || raw.value || null;
@@ -2186,6 +2193,162 @@ var ImageUploadWidget = ({ fieldId }) => {
2186
2193
  showError && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-red-500", children: error })
2187
2194
  ] });
2188
2195
  };
2196
+ function urlLooksLikePdf(url) {
2197
+ return /\.pdf($|\?)/i.test(url) || url.toLowerCase().includes("application/pdf");
2198
+ }
2199
+ function isAcceptedMediaFile(file) {
2200
+ if (file.type.startsWith("image/")) return true;
2201
+ if (file.type === "application/pdf") return true;
2202
+ if (file.name.toLowerCase().endsWith(".pdf")) return true;
2203
+ return false;
2204
+ }
2205
+ var MediaUploadWidget = ({ fieldId }) => {
2206
+ const { fieldDef, value, setValue, setTouched, error, disabled, touched } = useField(fieldId);
2207
+ const store = useFormStore();
2208
+ const { state } = useForm();
2209
+ const [isUploading, setIsUploading] = React15.useState(false);
2210
+ const [preview, setPreview] = React15.useState(null);
2211
+ const [previewIsPdf, setPreviewIsPdf] = React15.useState(false);
2212
+ const fileInputRef = React15.useRef(null);
2213
+ const pendingPreviewKindRef = React15.useRef(null);
2214
+ const showError = !!error && (touched || state.submitAttempted);
2215
+ if (!fieldDef) return null;
2216
+ const uploadHandler = store.getUploadHandler();
2217
+ if (!uploadHandler) {
2218
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
2219
+ /* @__PURE__ */ jsxRuntime.jsxs(Label, { htmlFor: fieldId, children: [
2220
+ fieldDef.label,
2221
+ fieldDef.required && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-red-500", children: "*" })
2222
+ ] }),
2223
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-2 border-red-300 rounded-lg p-4 bg-red-50", children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-red-600", children: "Upload handler not configured. Please provide an onUpload function in FormProvider config." }) })
2224
+ ] });
2225
+ }
2226
+ React15__namespace.default.useEffect(() => {
2227
+ if (value && typeof value === "string") {
2228
+ setPreview(value);
2229
+ if (pendingPreviewKindRef.current) {
2230
+ setPreviewIsPdf(pendingPreviewKindRef.current === "pdf");
2231
+ pendingPreviewKindRef.current = null;
2232
+ } else {
2233
+ setPreviewIsPdf(urlLooksLikePdf(value));
2234
+ }
2235
+ } else {
2236
+ setPreview(null);
2237
+ setPreviewIsPdf(false);
2238
+ }
2239
+ }, [value]);
2240
+ const handleFileSelect = async (event) => {
2241
+ const file = event.target.files?.[0];
2242
+ if (!file) return;
2243
+ if (!isAcceptedMediaFile(file)) {
2244
+ alert("Please select an image or PDF file");
2245
+ return;
2246
+ }
2247
+ const maxSize = 10 * 1024 * 1024;
2248
+ if (file.size > maxSize) {
2249
+ alert("File size must be less than 10MB");
2250
+ return;
2251
+ }
2252
+ const isPdf = file.type === "application/pdf" || file.name.toLowerCase().endsWith(".pdf");
2253
+ setIsUploading(true);
2254
+ setTouched();
2255
+ store.incrementPendingUploads();
2256
+ try {
2257
+ const previewUrl = URL.createObjectURL(file);
2258
+ setPreview(previewUrl);
2259
+ setPreviewIsPdf(isPdf);
2260
+ const s3Key = await uploadHandler(file, file.name);
2261
+ pendingPreviewKindRef.current = isPdf ? "pdf" : "image";
2262
+ setValue(s3Key);
2263
+ } catch (error2) {
2264
+ console.error("Upload failed:", error2);
2265
+ const errorMessage = error2 instanceof Error ? error2.message : "Upload failed. Please try again.";
2266
+ alert(errorMessage);
2267
+ setPreview(null);
2268
+ setPreviewIsPdf(false);
2269
+ } finally {
2270
+ setIsUploading(false);
2271
+ store.decrementPendingUploads();
2272
+ }
2273
+ };
2274
+ const handleRemove = () => {
2275
+ pendingPreviewKindRef.current = null;
2276
+ setValue(null);
2277
+ setPreview(null);
2278
+ setPreviewIsPdf(false);
2279
+ if (fileInputRef.current) {
2280
+ fileInputRef.current.value = "";
2281
+ }
2282
+ setTouched();
2283
+ };
2284
+ const handleUploadClick = () => {
2285
+ fileInputRef.current?.click();
2286
+ };
2287
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
2288
+ /* @__PURE__ */ jsxRuntime.jsxs(Label, { htmlFor: fieldId, children: [
2289
+ fieldDef.label,
2290
+ fieldDef.required && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-red-500", children: "*" })
2291
+ ] }),
2292
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-2 border-dashed border-gray-300 rounded-lg p-4", children: preview ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
2293
+ previewIsPdf ? /* @__PURE__ */ jsxRuntime.jsx(
2294
+ "iframe",
2295
+ {
2296
+ src: preview,
2297
+ title: "Uploaded PDF",
2298
+ className: "w-full max-h-48 min-h-36 rounded-lg border border-gray-200 bg-white"
2299
+ }
2300
+ ) : /* @__PURE__ */ jsxRuntime.jsx(
2301
+ "img",
2302
+ {
2303
+ src: preview,
2304
+ alt: "Uploaded image",
2305
+ className: "max-w-full max-h-48 mx-auto rounded-lg"
2306
+ }
2307
+ ),
2308
+ /* @__PURE__ */ jsxRuntime.jsx(
2309
+ Button,
2310
+ {
2311
+ type: "button",
2312
+ variant: "destructive",
2313
+ size: "sm",
2314
+ className: "absolute top-2 right-2",
2315
+ onClick: handleRemove,
2316
+ disabled: disabled || isUploading,
2317
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "h-4 w-4" })
2318
+ }
2319
+ )
2320
+ ] }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center py-8", children: [
2321
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Image, { className: "h-12 w-12 mx-auto text-gray-400 mb-4" }),
2322
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-gray-600 mb-4", children: "Click to upload an image or PDF, or drag and drop" }),
2323
+ /* @__PURE__ */ jsxRuntime.jsxs(
2324
+ Button,
2325
+ {
2326
+ type: "button",
2327
+ variant: "outline",
2328
+ onClick: handleUploadClick,
2329
+ disabled: disabled || isUploading,
2330
+ children: [
2331
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Upload, { className: "h-4 w-4 mr-2" }),
2332
+ isUploading ? "Uploading..." : "Choose Image"
2333
+ ]
2334
+ }
2335
+ )
2336
+ ] }) }),
2337
+ /* @__PURE__ */ jsxRuntime.jsx(
2338
+ "input",
2339
+ {
2340
+ ref: fileInputRef,
2341
+ type: "file",
2342
+ accept: "image/*,application/pdf",
2343
+ onChange: handleFileSelect,
2344
+ className: "hidden",
2345
+ disabled: disabled || isUploading
2346
+ }
2347
+ ),
2348
+ fieldDef.description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-gray-500", children: fieldDef.description }),
2349
+ showError && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-red-500", children: error })
2350
+ ] });
2351
+ };
2189
2352
  var distance = (a, b) => Math.hypot(a.x - b.x, a.y - b.y);
2190
2353
  var smoothPoint = (prev, curr, smoothing = 0.75) => {
2191
2354
  if (!prev) return curr;
@@ -7418,6 +7581,206 @@ var OrthopedicExamWidget = ({ fieldId }) => {
7418
7581
  ) : null
7419
7582
  ] });
7420
7583
  };
7584
+ var MarMedicationOrdersWidget = ({ fieldId }) => {
7585
+ const { fieldDef, value, setTouched, error, disabled, touched } = useField(fieldId);
7586
+ const { state } = useForm();
7587
+ const handlers = useFieldHandlers(fieldId);
7588
+ const showError = !!error && (touched || state.submitAttempted);
7589
+ const onOpen = React15.useCallback(async () => {
7590
+ await handlers.onOpenMedicationOrders?.();
7591
+ setTouched();
7592
+ }, [handlers, setTouched]);
7593
+ if (!fieldDef || fieldDef.type !== "textarea") return null;
7594
+ const textDef = fieldDef;
7595
+ const height = textDef.height;
7596
+ const theme = getThemeConfig("textarea", fieldDef.theme);
7597
+ const wrapperClass = theme?.wrapperClassName ?? "space-y-2";
7598
+ const labelClass = theme?.labelClassName;
7599
+ const labelContent = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
7600
+ fieldDef.label,
7601
+ " ",
7602
+ fieldDef.required && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-red-500", children: "*" })
7603
+ ] });
7604
+ const labelEl = theme ? /* @__PURE__ */ jsxRuntime.jsx(Label, { htmlFor: fieldId, className: labelClass, children: labelContent }) : /* @__PURE__ */ jsxRuntime.jsx(Label, { htmlFor: fieldId, children: labelContent });
7605
+ const text = typeof value === "string" ? value : value == null ? "" : String(value);
7606
+ const hasHandler = typeof handlers.onOpenMedicationOrders === "function";
7607
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: wrapperClass, children: [
7608
+ labelEl,
7609
+ fieldDef.description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: fieldDef.description }),
7610
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2 sm:flex-row sm:items-start sm:justify-between sm:gap-3", children: [
7611
+ /* @__PURE__ */ jsxRuntime.jsx(
7612
+ "div",
7613
+ {
7614
+ id: fieldId,
7615
+ className: cn(
7616
+ "min-h-[80px] flex-1 rounded-md border border-input bg-background px-3 py-2 text-sm whitespace-pre-wrap",
7617
+ showError && "border-red-500",
7618
+ !text && "text-muted-foreground"
7619
+ ),
7620
+ style: height != null ? { minHeight: height } : void 0,
7621
+ "aria-readonly": "true",
7622
+ children: text || fieldDef.placeholder || "No medication orders added."
7623
+ }
7624
+ ),
7625
+ /* @__PURE__ */ jsxRuntime.jsx(
7626
+ Button,
7627
+ {
7628
+ type: "button",
7629
+ variant: "default",
7630
+ disabled: disabled || !hasHandler,
7631
+ onClick: onOpen,
7632
+ className: "shrink-0 sm:mt-0",
7633
+ children: "Add medication orders"
7634
+ }
7635
+ )
7636
+ ] }),
7637
+ showError && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-red-500", children: error })
7638
+ ] });
7639
+ };
7640
+ function parseFieldValue(value) {
7641
+ if (value == null) return { orders: [], display_lines: [] };
7642
+ if (Array.isArray(value)) {
7643
+ return {
7644
+ orders: value,
7645
+ display_lines: value.map(() => null)
7646
+ };
7647
+ }
7648
+ if (typeof value === "object") {
7649
+ const v = value;
7650
+ const orders = Array.isArray(v.orders) ? v.orders : [];
7651
+ const rawLines = Array.isArray(v.display_lines) ? v.display_lines : Array.isArray(v.displayLines) ? v.displayLines : [];
7652
+ const display_lines = orders.map((_, i) => rawLines[i] ?? null);
7653
+ return { orders, display_lines };
7654
+ }
7655
+ return { orders: [], display_lines: [] };
7656
+ }
7657
+ function normalizePrescription(res) {
7658
+ const pharmacyOrderId = res.pharmacy_order_id ?? void 0;
7659
+ const orders = Array.isArray(res.orders) ? res.orders : [];
7660
+ const linesRaw = Array.isArray(res.display_lines) ? res.display_lines : [];
7661
+ const mapped = orders.filter((o) => o && typeof o.id === "string").map((o) => ({
7662
+ id: o.id,
7663
+ item_id: o.item_id == null ? void 0 : String(o.item_id),
7664
+ item_name: o.item_name ?? void 0,
7665
+ generic_name: o.generic_name ?? void 0,
7666
+ dose: o.dose == null ? void 0 : String(o.dose),
7667
+ route: o.route ?? void 0,
7668
+ frequency: o.frequency ?? void 0,
7669
+ admin_times: Array.isArray(o.admin_times) ? o.admin_times : void 0,
7670
+ meal_sleep_timing: o.meal_sleep_timing ?? void 0,
7671
+ start_date: o.start_date ?? void 0,
7672
+ end_date: o.end_date ?? void 0,
7673
+ order_type: o.order_type ?? void 0,
7674
+ status: o.status ?? void 0,
7675
+ notes: o.notes ?? null,
7676
+ pharmacy_order_id: pharmacyOrderId
7677
+ }));
7678
+ const display_lines = mapped.map((_, i) => linesRaw[i] ?? null);
7679
+ return { orders: mapped, display_lines };
7680
+ }
7681
+ function formatDuration(start, end) {
7682
+ if (!start && !end) return null;
7683
+ if (start && end) return `${start} \u2192 ${end}`;
7684
+ return start ? `Start: ${start}` : `End: ${end}`;
7685
+ }
7686
+ var DischargeMedicationOrdersWidget = ({ fieldId }) => {
7687
+ const { fieldDef, value, setValue, setTouched, error, disabled, touched, visible } = useField(fieldId);
7688
+ const { state } = useForm();
7689
+ const handlers = useFieldHandlers(fieldId);
7690
+ const showError = !!error && (touched || state.submitAttempted);
7691
+ const { orders, display_lines } = React15.useMemo(() => parseFieldValue(value), [value]);
7692
+ const onAdd = React15.useCallback(async () => {
7693
+ setTouched();
7694
+ const fn = handlers.onOpenDischargeMedicationOrders;
7695
+ if (!fn) return;
7696
+ const res = await fn();
7697
+ if (!res || typeof res !== "object") return;
7698
+ const normalized = normalizePrescription(res);
7699
+ setValue({
7700
+ orders: normalized.orders,
7701
+ display_lines: normalized.display_lines
7702
+ });
7703
+ }, [handlers.onOpenDischargeMedicationOrders, setTouched, setValue]);
7704
+ const onDelete = React15.useCallback(
7705
+ (id) => {
7706
+ setTouched();
7707
+ const idx = orders.findIndex((o) => o.id === id);
7708
+ if (idx === -1) return;
7709
+ setValue({
7710
+ orders: orders.filter((o) => o.id !== id),
7711
+ display_lines: display_lines.filter((_, i) => i !== idx)
7712
+ });
7713
+ },
7714
+ [orders, display_lines, setTouched, setValue]
7715
+ );
7716
+ if (!visible || !fieldDef) return null;
7717
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
7718
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-2", children: [
7719
+ /* @__PURE__ */ jsxRuntime.jsxs(Label, { className: "text-sm font-medium", children: [
7720
+ fieldDef.label,
7721
+ " ",
7722
+ fieldDef.required && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-red-500", children: "*" })
7723
+ ] }),
7724
+ /* @__PURE__ */ jsxRuntime.jsx(Button, { type: "button", onClick: onAdd, disabled: disabled || !handlers.onOpenDischargeMedicationOrders, children: "Add medicine" })
7725
+ ] }),
7726
+ fieldDef.description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: fieldDef.description }),
7727
+ orders.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx(
7728
+ "div",
7729
+ {
7730
+ className: cn(
7731
+ "rounded-md border border-input bg-background px-3 py-3 text-sm text-muted-foreground",
7732
+ showError && "border-red-500"
7733
+ ),
7734
+ children: "No medicines added."
7735
+ }
7736
+ ) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-2", children: orders.map((o, rowIdx) => {
7737
+ const line = display_lines[rowIdx];
7738
+ const duration = formatDuration(o.start_date, o.end_date);
7739
+ const header = typeof line?.name === "string" && line.name.trim() || o.item_name || "Medicine";
7740
+ const sub = o.generic_name ? o.generic_name : null;
7741
+ const line1 = [o.dose && `Dose: ${o.dose}`, o.route && `Route: ${o.route}`].filter(Boolean).join(" \u2022 ");
7742
+ const line2 = [
7743
+ o.frequency && `Freq: ${o.frequency}`,
7744
+ o.meal_sleep_timing && `Meal/Sleep: ${o.meal_sleep_timing}`,
7745
+ o.admin_times?.length ? `Times: ${o.admin_times.join(", ")}` : null
7746
+ ].filter(Boolean).join(" \u2022 ");
7747
+ const line3 = [
7748
+ duration ? `Duration: ${duration}` : null,
7749
+ o.order_type ? `Type: ${o.order_type}` : null,
7750
+ o.status ? `Status: ${o.status}` : null
7751
+ ].filter(Boolean).join(" \u2022 ");
7752
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-md border border-input bg-background p-3", children: [
7753
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between gap-3", children: [
7754
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0", children: [
7755
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "font-semibold text-sm truncate", children: header }),
7756
+ sub && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xs text-muted-foreground mt-0.5 truncate", children: sub })
7757
+ ] }),
7758
+ /* @__PURE__ */ jsxRuntime.jsx(
7759
+ Button,
7760
+ {
7761
+ type: "button",
7762
+ variant: "ghost",
7763
+ className: "h-8 w-8 p-0 text-destructive",
7764
+ onClick: () => onDelete(o.id),
7765
+ "aria-label": "Delete medicine",
7766
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Trash2, { className: "h-4 w-4" })
7767
+ }
7768
+ )
7769
+ ] }),
7770
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-2 space-y-1 text-xs text-muted-foreground", children: [
7771
+ line1 && /* @__PURE__ */ jsxRuntime.jsx("div", { children: line1 }),
7772
+ line2 && /* @__PURE__ */ jsxRuntime.jsx("div", { children: line2 }),
7773
+ line3 && /* @__PURE__ */ jsxRuntime.jsx("div", { children: line3 }),
7774
+ o.notes && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-foreground/80", children: [
7775
+ "Notes: ",
7776
+ o.notes
7777
+ ] })
7778
+ ] })
7779
+ ] }, o.id);
7780
+ }) }),
7781
+ showError && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-red-500", children: error })
7782
+ ] });
7783
+ };
7421
7784
  var FieldRenderer = ({ fieldId }) => {
7422
7785
  const { fieldDef, visible } = useField(fieldId);
7423
7786
  if (!visible || !fieldDef) {
@@ -7431,6 +7794,9 @@ function renderWidget(fieldId, fieldDef) {
7431
7794
  case "number":
7432
7795
  return /* @__PURE__ */ jsxRuntime.jsx(TextWidget, { fieldId });
7433
7796
  case "textarea":
7797
+ if (fieldMetaRequestsMarMedicationOrdersButton(fieldDef.meta)) {
7798
+ return /* @__PURE__ */ jsxRuntime.jsx(MarMedicationOrdersWidget, { fieldId });
7799
+ }
7434
7800
  return /* @__PURE__ */ jsxRuntime.jsx(TextWidget, { fieldId });
7435
7801
  case "richtext":
7436
7802
  return /* @__PURE__ */ jsxRuntime.jsx(RichTextWidget, { fieldId });
@@ -7450,12 +7816,16 @@ function renderWidget(fieldId, fieldDef) {
7450
7816
  return /* @__PURE__ */ jsxRuntime.jsx(RepeatableWidget, { fieldId });
7451
7817
  case "image_upload":
7452
7818
  return /* @__PURE__ */ jsxRuntime.jsx(ImageUploadWidget, { fieldId });
7819
+ case "media_upload":
7820
+ return /* @__PURE__ */ jsxRuntime.jsx(MediaUploadWidget, { fieldId });
7453
7821
  case "signature":
7454
7822
  return /* @__PURE__ */ jsxRuntime.jsx(SignatureUploadWidget, { fieldId });
7455
7823
  case "editable_table":
7456
7824
  return /* @__PURE__ */ jsxRuntime.jsx(EditableTableWidget, { fieldId });
7457
7825
  case "medications":
7458
7826
  return /* @__PURE__ */ jsxRuntime.jsx(AddMedicationWidget, { fieldId });
7827
+ case "discharge_medication_orders":
7828
+ return /* @__PURE__ */ jsxRuntime.jsx(DischargeMedicationOrdersWidget, { fieldId });
7459
7829
  case "investigations":
7460
7830
  return /* @__PURE__ */ jsxRuntime.jsx(AddInvestigationWidget, { fieldId });
7461
7831
  case "procedures":
@@ -7857,6 +8227,55 @@ var ReadOnlyImageUpload = ({
7857
8227
  fieldDef.description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-gray-500", children: fieldDef.description })
7858
8228
  ] });
7859
8229
  };
8230
+ function urlLooksLikePdf2(url) {
8231
+ return /\.pdf($|\?)/i.test(url) || url.toLowerCase().includes("application/pdf");
8232
+ }
8233
+ var ReadOnlyMediaUpload = ({
8234
+ fieldDef,
8235
+ value
8236
+ }) => {
8237
+ const [useIframe, setUseIframe] = React15.useState(false);
8238
+ let url = null;
8239
+ if (typeof value === "string") {
8240
+ url = value;
8241
+ } else if (value && typeof value === "object") {
8242
+ const typed = value;
8243
+ url = typed.presigned_url || typed.value || typed.s3_key || null;
8244
+ }
8245
+ React15.useEffect(() => {
8246
+ setUseIframe(false);
8247
+ }, [url]);
8248
+ const showAsPdf = url && (urlLooksLikePdf2(url) || useIframe);
8249
+ if (!url) {
8250
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
8251
+ /* @__PURE__ */ jsxRuntime.jsx(Label, { children: fieldDef.label }),
8252
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border border-gray-200 rounded-lg p-4 bg-gray-50", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center py-4", children: [
8253
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Image, { className: "h-8 w-8 mx-auto text-gray-400 mb-2" }),
8254
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-gray-500", children: "No file uploaded" })
8255
+ ] }) })
8256
+ ] });
8257
+ }
8258
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
8259
+ /* @__PURE__ */ jsxRuntime.jsx(Label, { children: fieldDef.label }),
8260
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border border-gray-200 rounded-lg p-4 bg-white", children: showAsPdf ? /* @__PURE__ */ jsxRuntime.jsx(
8261
+ "iframe",
8262
+ {
8263
+ src: url,
8264
+ title: `${fieldDef.label} PDF`,
8265
+ className: "w-full max-h-48 min-h-36 rounded-lg border border-gray-200 bg-white"
8266
+ }
8267
+ ) : /* @__PURE__ */ jsxRuntime.jsx(
8268
+ "img",
8269
+ {
8270
+ src: url,
8271
+ alt: `${fieldDef.label} upload`,
8272
+ className: "max-w-full max-h-48 mx-auto rounded-lg",
8273
+ onError: () => setUseIframe(true)
8274
+ }
8275
+ ) }),
8276
+ fieldDef.description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-gray-500", children: fieldDef.description })
8277
+ ] });
8278
+ };
7860
8279
  var ReadOnlySignature = ({
7861
8280
  fieldDef,
7862
8281
  value
@@ -8034,6 +8453,53 @@ var ReadOnlyReferral = ({ fieldDef, value }) => {
8034
8453
  }) })
8035
8454
  ] });
8036
8455
  };
8456
+ function isOrderArray(value) {
8457
+ return Array.isArray(value) && value.every(
8458
+ (v) => v != null && typeof v === "object" && typeof v.id === "string"
8459
+ );
8460
+ }
8461
+ function formatDuration2(start, end) {
8462
+ if (!start && !end) return null;
8463
+ if (start && end) return `${start} \u2192 ${end}`;
8464
+ return start ? `Start: ${start}` : `End: ${end}`;
8465
+ }
8466
+ var ReadOnlyDischargeMedicationOrders = ({ fieldDef, value }) => {
8467
+ const orders = React15.useMemo(() => isOrderArray(value) ? value : [], [value]);
8468
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
8469
+ /* @__PURE__ */ jsxRuntime.jsx(Label, { className: "text-sm font-medium text-gray-700", children: fieldDef.label }),
8470
+ orders.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-gray-900 border border-gray-200 rounded-md p-3 bg-gray-50 min-h-[2.5rem]", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-gray-400 italic", children: "No medicines added" }) }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-2", children: orders.map((o) => {
8471
+ const duration = formatDuration2(o.start_date, o.end_date);
8472
+ const header = o.item_name ?? "Medicine";
8473
+ const sub = o.generic_name ? o.generic_name : null;
8474
+ const line1 = [o.dose && `Dose: ${o.dose}`, o.route && `Route: ${o.route}`].filter(Boolean).join(" \u2022 ");
8475
+ const line2 = [
8476
+ o.frequency && `Freq: ${o.frequency}`,
8477
+ o.meal_sleep_timing && `Meal/Sleep: ${o.meal_sleep_timing}`,
8478
+ o.admin_times?.length ? `Times: ${o.admin_times.join(", ")}` : null
8479
+ ].filter(Boolean).join(" \u2022 ");
8480
+ const line3 = [
8481
+ duration ? `Duration: ${duration}` : null,
8482
+ o.order_type ? `Type: ${o.order_type}` : null,
8483
+ o.status ? `Status: ${o.status}` : null
8484
+ ].filter(Boolean).join(" \u2022 ");
8485
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-md border border-gray-200 bg-gray-50 p-3", children: [
8486
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0", children: [
8487
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "font-semibold text-sm truncate text-gray-900", children: header }),
8488
+ sub && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xs text-gray-500 mt-0.5 truncate", children: sub })
8489
+ ] }),
8490
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-2 space-y-1 text-xs text-gray-600", children: [
8491
+ line1 && /* @__PURE__ */ jsxRuntime.jsx("div", { children: line1 }),
8492
+ line2 && /* @__PURE__ */ jsxRuntime.jsx("div", { children: line2 }),
8493
+ line3 && /* @__PURE__ */ jsxRuntime.jsx("div", { children: line3 }),
8494
+ o.notes && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-gray-800/90", children: [
8495
+ "Notes: ",
8496
+ o.notes
8497
+ ] })
8498
+ ] })
8499
+ ] }, o.id);
8500
+ }) })
8501
+ ] });
8502
+ };
8037
8503
  var ReadOnlyFieldRenderer = ({ fieldDef, value }) => {
8038
8504
  if (!fieldDef) return null;
8039
8505
  switch (fieldDef.type) {
@@ -8058,12 +8524,16 @@ var ReadOnlyFieldRenderer = ({ fieldDef, value }) => {
8058
8524
  return /* @__PURE__ */ jsxRuntime.jsx(ReadOnlyRepeatable, { fieldDef, value });
8059
8525
  case "image_upload":
8060
8526
  return /* @__PURE__ */ jsxRuntime.jsx(ReadOnlyImageUpload, { fieldDef, value });
8527
+ case "media_upload":
8528
+ return /* @__PURE__ */ jsxRuntime.jsx(ReadOnlyMediaUpload, { fieldDef, value });
8061
8529
  case "signature":
8062
8530
  return /* @__PURE__ */ jsxRuntime.jsx(ReadOnlySignature, { fieldDef, value });
8063
8531
  case "editable_table":
8064
8532
  return /* @__PURE__ */ jsxRuntime.jsx(ReadOnlyTable, { fieldDef, value });
8065
8533
  case "referral":
8066
8534
  return /* @__PURE__ */ jsxRuntime.jsx(ReadOnlyReferral, { fieldDef, value });
8535
+ case "discharge_medication_orders":
8536
+ return /* @__PURE__ */ jsxRuntime.jsx(ReadOnlyDischargeMedicationOrders, { fieldDef, value });
8067
8537
  case "static_text": {
8068
8538
  const def = fieldDef;
8069
8539
  const size = def.size ?? "regular";
@@ -8275,8 +8745,11 @@ exports.FormControls = FormControls;
8275
8745
  exports.FormProvider = FormProvider;
8276
8746
  exports.FormStore = FormStore;
8277
8747
  exports.ImageUploadWidget = ImageUploadWidget;
8748
+ exports.MAR_MEDICATION_ORDERS_META_KEY = MAR_MEDICATION_ORDERS_META_KEY;
8749
+ exports.MediaUploadWidget = MediaUploadWidget;
8278
8750
  exports.ReadOnlyForm = ReadOnlyForm;
8279
8751
  exports.ReadOnlyImageUpload = ReadOnlyImageUpload;
8752
+ exports.ReadOnlyMediaUpload = ReadOnlyMediaUpload;
8280
8753
  exports.ReadOnlySignature = ReadOnlySignature;
8281
8754
  exports.ReadOnlyTable = ReadOnlyTable;
8282
8755
  exports.RichTextWidget = RichTextWidget;
@@ -8285,6 +8758,7 @@ exports.SmartForm = SmartForm;
8285
8758
  exports.SmartTextareaWidget = SmartTextareaWidget;
8286
8759
  exports.createUploadHandler = createUploadHandler;
8287
8760
  exports.evaluateRules = evaluateRules;
8761
+ exports.fieldMetaRequestsMarMedicationOrdersButton = fieldMetaRequestsMarMedicationOrdersButton;
8288
8762
  exports.useField = useField;
8289
8763
  exports.useFieldHandlers = useFieldHandlers;
8290
8764
  exports.useForm = useForm;