formanitor 0.0.40 → 0.0.42

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
@@ -225,8 +225,21 @@ var defaultGeneralSurgerySmartHistory = () => ({
225
225
  gi: { appetite: "", weightLoss: "", bowelHabits: "", checks: [] },
226
226
  breast: { lumpDuration: "", nippleDischarge: "", checks: [] },
227
227
  ano: { checks: [] },
228
- thyroid: { swellingDuration: "", checks: [] },
229
- systemic: ""
228
+ thyroid: { swellingDuration: "", checks: [] }
229
+ });
230
+ var defaultBreastExamSide = () => ({
231
+ size: "",
232
+ quadrant: "",
233
+ tenderness: "",
234
+ fixity: "",
235
+ skinInvolvement: "",
236
+ consistency: "",
237
+ axillaryNodes: false,
238
+ nippleAreolarComplex: false
239
+ });
240
+ var defaultBreastExaminationBlock = () => ({
241
+ left: defaultBreastExamSide(),
242
+ right: defaultBreastExamSide()
230
243
  });
231
244
  var defaultGeneralSurgeryExamination = () => ({
232
245
  general: [],
@@ -239,7 +252,7 @@ var defaultGeneralSurgeryExamination = () => ({
239
252
  bowelSounds: "none"
240
253
  },
241
254
  hernia: { site: "", reducible: false, coughImpulse: false, tenderness: false },
242
- breast: { lumpSizeCm: "", mobile: false, skinInvolvement: false, axillaryNodes: false },
255
+ breast: defaultBreastExaminationBlock(),
243
256
  thyroid: { size: "", mobileDeglutition: false, nodules: false, cervicalNodes: false },
244
257
  anorectal: { inspection: "", dreDone: false, proctoscopyDone: false, notes: "" },
245
258
  limb: { dilatedVeins: false, ulcer: false, oedema: false }
@@ -335,8 +348,32 @@ function normalizeGeneralSurgerySmartHistory(raw) {
335
348
  thyroid: {
336
349
  swellingDuration: str2(thy.swellingDuration),
337
350
  checks: strArr(thy.checks)
338
- },
339
- systemic: typeof v.systemic === "string" ? v.systemic : d.systemic
351
+ }
352
+ };
353
+ }
354
+ function normalizeBreastExamSide(partial) {
355
+ const e = defaultBreastExamSide();
356
+ const str2 = (x) => typeof x === "string" ? x : "";
357
+ const bool = (x) => x === true;
358
+ if (!partial || typeof partial !== "object") return e;
359
+ const p = partial;
360
+ return {
361
+ size: str2(p.size),
362
+ quadrant: str2(p.quadrant),
363
+ tenderness: str2(p.tenderness),
364
+ fixity: str2(p.fixity),
365
+ skinInvolvement: str2(p.skinInvolvement),
366
+ consistency: str2(p.consistency),
367
+ axillaryNodes: bool(p.axillaryNodes),
368
+ nippleAreolarComplex: bool(p.nippleAreolarComplex)
369
+ };
370
+ }
371
+ function normalizeBreastExaminationBlock(raw) {
372
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) return defaultBreastExaminationBlock();
373
+ const br = raw;
374
+ return {
375
+ left: normalizeBreastExamSide(br.left),
376
+ right: normalizeBreastExamSide(br.right)
340
377
  };
341
378
  }
342
379
  function normalizeGeneralSurgeryExamination(raw) {
@@ -369,12 +406,7 @@ function normalizeGeneralSurgeryExamination(raw) {
369
406
  coughImpulse: bool(hb.coughImpulse),
370
407
  tenderness: bool(hb.tenderness)
371
408
  },
372
- breast: {
373
- lumpSizeCm: typeof br.lumpSizeCm === "string" ? br.lumpSizeCm : "",
374
- mobile: bool(br.mobile),
375
- skinInvolvement: bool(br.skinInvolvement),
376
- axillaryNodes: bool(br.axillaryNodes)
377
- },
409
+ breast: normalizeBreastExaminationBlock(br),
378
410
  thyroid: {
379
411
  size: typeof th.size === "string" ? th.size : "",
380
412
  mobileDeglutition: bool(th.mobileDeglutition),
@@ -412,6 +444,259 @@ function gsGradingRowVisible(cond, chips, regions, grade) {
412
444
  if (t.regions.some((r) => regions.includes(r))) return true;
413
445
  return false;
414
446
  }
447
+ var SWELLING_OPT_LABELS = {
448
+ reducible_hernia: "Reducible (hernia)",
449
+ cough_impulse: "Cough impulse",
450
+ skin_changes: "Skin changes"
451
+ };
452
+ var GI_OPT_LABELS = {
453
+ bleeding_pr: "Bleeding PR",
454
+ vomiting: "Vomiting",
455
+ haematemesis: "Haematemesis"
456
+ };
457
+ var BREAST_OPT_LABELS = {
458
+ pain: "Pain",
459
+ fh_ca_breast: "Family history of Ca breast"
460
+ };
461
+ var ANO_OPT_LABELS = {
462
+ pain_defecation: "Pain during defecation",
463
+ bleeding: "Bleeding",
464
+ constipation: "Constipation",
465
+ discharge: "Discharge"
466
+ };
467
+ var THYROID_OPT_LABELS = {
468
+ dysphagia: "Dysphagia",
469
+ voice_change: "Voice change",
470
+ thyrotoxicosis: "Thyrotoxicosis symptoms"
471
+ };
472
+ var SOCRATES_LABELS = {
473
+ site: "Site",
474
+ onset: "Onset",
475
+ character: "Character",
476
+ radiation: "Radiation",
477
+ associated: "Associated",
478
+ timing: "Timing",
479
+ exacerbating: "Exacerbating / relieving"
480
+ };
481
+ var GENERAL_EXAM_LABELS = {
482
+ pallor: "Pallor",
483
+ icterus: "Icterus",
484
+ cyanosis: "Cyanosis",
485
+ clubbing: "Clubbing",
486
+ lymphadenopathy: "Lymphadenopathy",
487
+ oedema: "Oedema"
488
+ };
489
+ var REGION_EXAM_LABELS = {
490
+ abdomen: "Abdomen",
491
+ hernia: "Hernia",
492
+ breast: "Breast",
493
+ thyroid: "Thyroid",
494
+ anorectal: "Anorectal",
495
+ limb: "Limb / varicose"
496
+ };
497
+ var ABD_INSP_LABELS = {
498
+ distension: "Distension",
499
+ scars: "Scars",
500
+ visible_peristalsis: "Visible peristalsis"
501
+ };
502
+ var ABD_PALP_LABELS = {
503
+ tenderness: "Tenderness",
504
+ guarding: "Guarding",
505
+ rigidity: "Rigidity",
506
+ mass: "Palpable mass"
507
+ };
508
+ var ABD_PERC_LABELS = {
509
+ tympany: "Tympany",
510
+ shifting_dullness: "Shifting dullness"
511
+ };
512
+ function trimLine(s) {
513
+ return s.replace(/\s+/g, " ").trim();
514
+ }
515
+ var SK_ORDER = ["site", "onset", "character", "radiation", "associated", "timing", "exacerbating"];
516
+ function formatGeneralSurgerySmartHistoryToNarrative(v, chips) {
517
+ const blocks = [];
518
+ const showPain = chips.includes("pain");
519
+ const showSwelling = chips.includes("swelling_lump");
520
+ const showGI = chips.includes("bleeding") || chips.includes("obstruction");
521
+ const showBreast = chips.includes("breast");
522
+ const showAno = chips.includes("anorectal");
523
+ const showThyroid = chips.includes("thyroid");
524
+ if (showPain) {
525
+ const painLines = [];
526
+ for (const key of SK_ORDER) {
527
+ const raw = v.pain[key];
528
+ if (typeof raw === "string" && raw.trim()) {
529
+ painLines.push(`${SOCRATES_LABELS[key]}: ${trimLine(raw)}`);
530
+ }
531
+ }
532
+ if (v.pain.severity > 0) {
533
+ painLines.push(`Severity (0\u201310): ${v.pain.severity}`);
534
+ }
535
+ if (painLines.length > 0) {
536
+ blocks.push(["SOCRATES \u2014 pain", ...painLines.map((l) => `\u2022 ${l}`)].join("\n"));
537
+ }
538
+ }
539
+ if (showSwelling) {
540
+ const parts = [];
541
+ if (v.swelling.duration.trim()) parts.push(`Duration: ${trimLine(v.swelling.duration)}`);
542
+ if (v.swelling.sizeProgression.trim())
543
+ parts.push(`Size progression: ${trimLine(v.swelling.sizeProgression)}`);
544
+ if (v.swelling.painfulPainless.trim())
545
+ parts.push(`Painful / painless: ${trimLine(v.swelling.painfulPainless)}`);
546
+ for (const c of v.swelling.checks) {
547
+ const lb = SWELLING_OPT_LABELS[c] ?? c;
548
+ parts.push(lb);
549
+ }
550
+ if (parts.length > 0) {
551
+ blocks.push(["Swelling history", ...parts.map((p) => `\u2022 ${p}`)].join("\n"));
552
+ }
553
+ }
554
+ if (showGI) {
555
+ const parts = [];
556
+ if (v.gi.appetite.trim()) parts.push(`Appetite: ${trimLine(v.gi.appetite)}`);
557
+ if (v.gi.weightLoss.trim()) parts.push(`Weight loss: ${trimLine(v.gi.weightLoss)}`);
558
+ if (v.gi.bowelHabits.trim()) parts.push(`Bowel habits: ${trimLine(v.gi.bowelHabits)}`);
559
+ for (const c of v.gi.checks) {
560
+ parts.push(GI_OPT_LABELS[c] ?? c);
561
+ }
562
+ if (parts.length > 0) {
563
+ blocks.push(["GI history", ...parts.map((p) => `\u2022 ${p}`)].join("\n"));
564
+ }
565
+ }
566
+ if (showBreast) {
567
+ const parts = [];
568
+ if (v.breast.lumpDuration.trim()) parts.push(`Lump duration: ${trimLine(v.breast.lumpDuration)}`);
569
+ if (v.breast.nippleDischarge.trim())
570
+ parts.push(`Nipple discharge: ${trimLine(v.breast.nippleDischarge)}`);
571
+ for (const c of v.breast.checks) {
572
+ parts.push(BREAST_OPT_LABELS[c] ?? c);
573
+ }
574
+ if (parts.length > 0) {
575
+ blocks.push(["Breast history", ...parts.map((p) => `\u2022 ${p}`)].join("\n"));
576
+ }
577
+ }
578
+ if (showAno) {
579
+ const parts = [];
580
+ for (const c of v.ano.checks) {
581
+ parts.push(ANO_OPT_LABELS[c] ?? c);
582
+ }
583
+ if (parts.length > 0) {
584
+ blocks.push(["Anorectal history", ...parts.map((p) => `\u2022 ${p}`)].join("\n"));
585
+ }
586
+ }
587
+ if (showThyroid) {
588
+ const parts = [];
589
+ if (v.thyroid.swellingDuration.trim())
590
+ parts.push(`Swelling duration: ${trimLine(v.thyroid.swellingDuration)}`);
591
+ for (const c of v.thyroid.checks) {
592
+ parts.push(THYROID_OPT_LABELS[c] ?? c);
593
+ }
594
+ if (parts.length > 0) {
595
+ blocks.push(["Thyroid history", ...parts.map((p) => `\u2022 ${p}`)].join("\n"));
596
+ }
597
+ }
598
+ return blocks.join("\n\n");
599
+ }
600
+ var BOWEL_SOUND_LABELS = {
601
+ none: "\u2014",
602
+ normal: "Normal",
603
+ up: "Increased (\u2191)",
604
+ down: "Decreased (\u2193)",
605
+ absent: "Absent"
606
+ };
607
+ function formatGeneralSurgeryExaminationToNarrative(v) {
608
+ const blocks = [];
609
+ const generalPositive = v.general.map((k) => GENERAL_EXAM_LABELS[k] ?? k).filter(Boolean);
610
+ if (generalPositive.length > 0) {
611
+ blocks.push(
612
+ ["General examination", ...generalPositive.map((g) => `\u2022 ${g}`)].join("\n")
613
+ );
614
+ }
615
+ if (v.regions.length > 0) {
616
+ const names = v.regions.map((r) => REGION_EXAM_LABELS[r] ?? r);
617
+ blocks.push(`Regional examination: ${names.join(", ")}`);
618
+ }
619
+ if (v.regions.includes("abdomen")) {
620
+ const sub = [];
621
+ const ins = v.abdomen.inspection.map((x) => ABD_INSP_LABELS[x] ?? x);
622
+ const pal = v.abdomen.palpation.map((x) => ABD_PALP_LABELS[x] ?? x);
623
+ const per = v.abdomen.percussion.map((x) => ABD_PERC_LABELS[x] ?? x);
624
+ if (ins.length) sub.push(`Inspection: ${ins.join(", ")}`);
625
+ if (pal.length) sub.push(`Palpation: ${pal.join(", ")}`);
626
+ if (v.abdomen.massNotes.trim()) sub.push(`Mass / mobility: ${trimLine(v.abdomen.massNotes)}`);
627
+ if (per.length) sub.push(`Percussion: ${per.join(", ")}`);
628
+ const bs = BOWEL_SOUND_LABELS[v.abdomen.bowelSounds];
629
+ if (v.abdomen.bowelSounds !== "none") {
630
+ sub.push(`Bowel sounds: ${bs}`);
631
+ }
632
+ if (sub.length > 0) {
633
+ blocks.push(["Abdomen", ...sub.map((s) => `\u2022 ${s}`)].join("\n"));
634
+ }
635
+ }
636
+ if (v.regions.includes("hernia")) {
637
+ const sub = [];
638
+ if (v.hernia.site.trim()) sub.push(`Site: ${trimLine(v.hernia.site)}`);
639
+ if (v.hernia.reducible) sub.push("Reducible");
640
+ if (v.hernia.coughImpulse) sub.push("Cough impulse positive");
641
+ if (v.hernia.tenderness) sub.push("Tenderness");
642
+ if (sub.length > 0) {
643
+ blocks.push(["Hernia", ...sub.map((s) => `\u2022 ${s}`)].join("\n"));
644
+ }
645
+ }
646
+ if (v.regions.includes("breast")) {
647
+ const sub = [];
648
+ const appendSide = (label, s) => {
649
+ const lines = [];
650
+ if (s.size.trim()) lines.push(`Size: ${trimLine(s.size)}`);
651
+ if (s.quadrant.trim()) lines.push(`Quadrant: ${trimLine(s.quadrant)}`);
652
+ if (s.tenderness.trim()) lines.push(`Tenderness: ${trimLine(s.tenderness)}`);
653
+ if (s.fixity.trim()) lines.push(`Fixity: ${trimLine(s.fixity)}`);
654
+ if (s.skinInvolvement.trim()) lines.push(`Skin involvement: ${trimLine(s.skinInvolvement)}`);
655
+ if (s.consistency.trim()) lines.push(`Consistency: ${trimLine(s.consistency)}`);
656
+ if (s.axillaryNodes) lines.push("Axillary nodes");
657
+ if (s.nippleAreolarComplex) lines.push("Nipple-areolar complex");
658
+ if (lines.length > 0) {
659
+ sub.push(`${label}: ${lines.join("; ")}`);
660
+ }
661
+ };
662
+ appendSide("Left breast", v.breast.left);
663
+ appendSide("Right breast", v.breast.right);
664
+ if (sub.length > 0) {
665
+ blocks.push(["Breast", ...sub.map((s) => `\u2022 ${s}`)].join("\n"));
666
+ }
667
+ }
668
+ if (v.regions.includes("thyroid")) {
669
+ const sub = [];
670
+ if (v.thyroid.size.trim()) sub.push(`Size: ${trimLine(v.thyroid.size)}`);
671
+ if (v.thyroid.mobileDeglutition) sub.push("Mobile with deglutition");
672
+ if (v.thyroid.nodules) sub.push("Nodules");
673
+ if (v.thyroid.cervicalNodes) sub.push("Cervical lymph nodes");
674
+ if (sub.length > 0) {
675
+ blocks.push(["Thyroid", ...sub.map((s) => `\u2022 ${s}`)].join("\n"));
676
+ }
677
+ }
678
+ if (v.regions.includes("anorectal")) {
679
+ const sub = [];
680
+ if (v.anorectal.inspection.trim())
681
+ sub.push(`Inspection: ${trimLine(v.anorectal.inspection)}`);
682
+ if (v.anorectal.dreDone) sub.push("DRE done");
683
+ if (v.anorectal.proctoscopyDone) sub.push("Proctoscopy done");
684
+ if (v.anorectal.notes.trim()) sub.push(`DRE / proctoscopy notes: ${trimLine(v.anorectal.notes)}`);
685
+ if (sub.length > 0) {
686
+ blocks.push(["Anorectal", ...sub.map((s) => `\u2022 ${s}`)].join("\n"));
687
+ }
688
+ }
689
+ if (v.regions.includes("limb")) {
690
+ const sub = [];
691
+ if (v.limb.dilatedVeins) sub.push("Dilated veins");
692
+ if (v.limb.ulcer) sub.push("Ulcer");
693
+ if (v.limb.oedema) sub.push("Oedema");
694
+ if (sub.length > 0) {
695
+ blocks.push(["Limb / varicose", ...sub.map((s) => `\u2022 ${s}`)].join("\n"));
696
+ }
697
+ }
698
+ return blocks.join("\n\n");
699
+ }
415
700
 
416
701
  // src/core/painScaleFlags.ts
417
702
  function normalizePainScaleFlags(raw, bounds) {
@@ -9236,6 +9521,7 @@ var SliderWidget = ({ fieldId }) => {
9236
9521
  ] });
9237
9522
  };
9238
9523
  var CHIEF_CHIPS_FIELD = "chief_complaints_chips";
9524
+ var GS_SYMPTOMS_FIELD = "symptoms";
9239
9525
  var SWELLING_OPTS = [
9240
9526
  { value: "reducible_hernia", label: "Reducible (hernia)" },
9241
9527
  { value: "cough_impulse", label: "Cough impulse" },
@@ -9276,16 +9562,26 @@ function Panel({ title, children }) {
9276
9562
  /* @__PURE__ */ jsx("div", { className: "p-3", children })
9277
9563
  ] });
9278
9564
  }
9279
- function chipList(state) {
9280
- const raw = state.values[CHIEF_CHIPS_FIELD];
9565
+ function chipListFromRaw(raw) {
9281
9566
  return Array.isArray(raw) ? raw.filter((x) => typeof x === "string") : [];
9282
9567
  }
9283
9568
  var GsSmartHistoryWidget = ({ fieldId }) => {
9284
9569
  const { fieldDef, value, setValue, setTouched, error, touched, disabled } = useField(fieldId);
9570
+ const hopcField = useField(GS_SYMPTOMS_FIELD);
9285
9571
  const { state } = useForm();
9286
9572
  const showError = !!error && (touched || state.submitAttempted);
9287
9573
  const safe = useMemo(() => normalizeGeneralSurgerySmartHistory(value), [value]);
9288
- const chips = useMemo(() => chipList(state), [state]);
9574
+ const chiefChipsRaw = state.values[CHIEF_CHIPS_FIELD];
9575
+ const chips = useMemo(() => chipListFromRaw(chiefChipsRaw), [chiefChipsRaw]);
9576
+ const [hopcNarrativeLocked, setHopcNarrativeLocked] = useState(false);
9577
+ useEffect(() => {
9578
+ if (hopcNarrativeLocked) return;
9579
+ const next = formatGeneralSurgerySmartHistoryToNarrative(
9580
+ normalizeGeneralSurgerySmartHistory(value),
9581
+ chips
9582
+ );
9583
+ hopcField.setValue(next);
9584
+ }, [value, chips, hopcNarrativeLocked]);
9289
9585
  const showPain = chips.includes("pain");
9290
9586
  const showSwelling = chips.includes("swelling_lump");
9291
9587
  const showGI = chips.includes("bleeding") || chips.includes("obstruction");
@@ -9551,15 +9847,51 @@ var GsSmartHistoryWidget = ({ fieldId }) => {
9551
9847
  ] }, o.value)) })
9552
9848
  ] }) : null,
9553
9849
  /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
9554
- /* @__PURE__ */ jsx(Label, { className: "text-xs font-medium text-slate-700", children: "Systemic surgical screening" }),
9850
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center justify-between gap-2", children: [
9851
+ /* @__PURE__ */ jsx(Label, { className: "text-xs font-semibold text-slate-700", children: hopcField.fieldDef?.label ?? "History of presenting complaint" }),
9852
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
9853
+ hopcNarrativeLocked ? /* @__PURE__ */ jsxs("span", { className: "rounded bg-amber-50 px-1.5 py-0.5 text-[10px] font-medium text-amber-900 ring-1 ring-amber-200/80", children: [
9854
+ "You edited this summary. Use",
9855
+ " ",
9856
+ /* @__PURE__ */ jsx("span", { className: "italic", children: "'Regenerate'" }),
9857
+ " ",
9858
+ "to update it from the form."
9859
+ ] }) : null,
9860
+ hopcNarrativeLocked ? /* @__PURE__ */ jsx(
9861
+ Button,
9862
+ {
9863
+ type: "button",
9864
+ variant: "outline",
9865
+ size: "sm",
9866
+ className: "h-7 shrink-0 px-2 text-xs",
9867
+ disabled: disabled || hopcField.disabled,
9868
+ onClick: () => {
9869
+ setHopcNarrativeLocked(false);
9870
+ hopcField.setValue(
9871
+ formatGeneralSurgerySmartHistoryToNarrative(
9872
+ normalizeGeneralSurgerySmartHistory(value),
9873
+ chips
9874
+ )
9875
+ );
9876
+ },
9877
+ children: "Regenerate"
9878
+ }
9879
+ ) : null
9880
+ ] })
9881
+ ] }),
9882
+ hopcNarrativeLocked ? /* @__PURE__ */ jsx("p", { className: "text-[10px] text-muted-foreground", children: "Edit this box anytime. Use Regenerate to replace with fresh text from the structured fields." }) : null,
9555
9883
  /* @__PURE__ */ jsx(
9556
9884
  Textarea,
9557
9885
  {
9558
- className: "min-h-[72px] rounded-md border border-input bg-white text-sm",
9559
- placeholder: "Fever, weight loss, appetite loss, fatigue, malignancy red flags\u2026",
9560
- value: safe.systemic,
9561
- onChange: (e) => update({ ...safe, systemic: e.target.value }),
9562
- disabled
9886
+ className: "min-h-[88px] rounded-md border border-input bg-white text-sm",
9887
+ placeholder: "Onset, progression, associated symptoms, relevant negatives\u2026",
9888
+ value: typeof hopcField.value === "string" ? hopcField.value : hopcField.value == null ? "" : String(hopcField.value),
9889
+ onChange: (e) => {
9890
+ setHopcNarrativeLocked(true);
9891
+ hopcField.setValue(e.target.value);
9892
+ hopcField.setTouched();
9893
+ },
9894
+ disabled: disabled || hopcField.disabled
9563
9895
  }
9564
9896
  )
9565
9897
  ] })
@@ -9611,12 +9943,72 @@ function RegionCard({ title, children }) {
9611
9943
  /* @__PURE__ */ jsx("div", { className: "p-3", children })
9612
9944
  ] });
9613
9945
  }
9946
+ var BREAST_TEXT_KEYS = [
9947
+ { key: "size", label: "Size" },
9948
+ { key: "quadrant", label: "Quadrant" },
9949
+ { key: "tenderness", label: "Tenderness" },
9950
+ { key: "fixity", label: "Fixity" },
9951
+ { key: "skinInvolvement", label: "Skin involvement" },
9952
+ { key: "consistency", label: "Consistency" }
9953
+ ];
9954
+ function BreastLumpColumn({
9955
+ title,
9956
+ data,
9957
+ onChange,
9958
+ disabled
9959
+ }) {
9960
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-2 rounded-md border border-[#D0D0D0] bg-slate-50/50 p-3", children: [
9961
+ /* @__PURE__ */ jsx("p", { className: "text-[11px] font-semibold uppercase tracking-wide text-muted-foreground", children: title }),
9962
+ /* @__PURE__ */ jsx("div", { className: "grid grid-cols-1 gap-2 sm:grid-cols-2", children: BREAST_TEXT_KEYS.map(({ key, label }) => /* @__PURE__ */ jsxs("label", { className: "block", children: [
9963
+ /* @__PURE__ */ jsx("span", { className: "mb-1 block font-medium", children: label }),
9964
+ /* @__PURE__ */ jsx(
9965
+ Input,
9966
+ {
9967
+ className: "h-8 text-xs",
9968
+ value: data[key],
9969
+ onChange: (e) => onChange({ [key]: e.target.value }),
9970
+ disabled
9971
+ }
9972
+ )
9973
+ ] }, key)) }),
9974
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap gap-x-4 gap-y-2 pt-1", children: [
9975
+ /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2", children: [
9976
+ /* @__PURE__ */ jsx(
9977
+ Checkbox,
9978
+ {
9979
+ checked: data.axillaryNodes,
9980
+ onCheckedChange: (c) => onChange({ axillaryNodes: c === true }),
9981
+ disabled
9982
+ }
9983
+ ),
9984
+ "Axillary nodes"
9985
+ ] }),
9986
+ /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2", children: [
9987
+ /* @__PURE__ */ jsx(
9988
+ Checkbox,
9989
+ {
9990
+ checked: data.nippleAreolarComplex,
9991
+ onCheckedChange: (c) => onChange({ nippleAreolarComplex: c === true }),
9992
+ disabled
9993
+ }
9994
+ ),
9995
+ "Nipple-areolar complex"
9996
+ ] })
9997
+ ] })
9998
+ ] });
9999
+ }
9614
10000
  var GsExaminationWidget = ({ fieldId }) => {
9615
10001
  const { fieldDef, value, setValue, setTouched, error, touched, disabled } = useField(fieldId);
9616
10002
  const clinicalField = useField(GS_CLINICAL_EXAMINATION_FIELD);
9617
10003
  const { state } = useForm();
9618
10004
  const showError = !!error && (touched || state.submitAttempted);
9619
10005
  const safe = useMemo(() => normalizeGeneralSurgeryExamination(value), [value]);
10006
+ const [clinicalNarrativeLocked, setClinicalNarrativeLocked] = useState(false);
10007
+ useEffect(() => {
10008
+ if (clinicalNarrativeLocked) return;
10009
+ const next = formatGeneralSurgeryExaminationToNarrative(normalizeGeneralSurgeryExamination(value));
10010
+ clinicalField.setValue(next);
10011
+ }, [value, clinicalNarrativeLocked]);
9620
10012
  const update = (next) => {
9621
10013
  setValue(next);
9622
10014
  setTouched();
@@ -9808,52 +10200,31 @@ var GsExaminationWidget = ({ fieldId }) => {
9808
10200
  "Tenderness"
9809
10201
  ] })
9810
10202
  ] }) }) : null,
9811
- has("breast") ? /* @__PURE__ */ jsx(RegionCard, { title: "Breast exam", children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 gap-3 text-xs md:grid-cols-4", children: [
9812
- /* @__PURE__ */ jsxs("label", { className: "block", children: [
9813
- /* @__PURE__ */ jsx("span", { className: "mb-1 block font-medium", children: "Lump size (cm)" }),
9814
- /* @__PURE__ */ jsx(
9815
- Input,
9816
- {
9817
- className: "h-8 text-xs",
9818
- value: safe.breast.lumpSizeCm,
9819
- onChange: (e) => update({ ...safe, breast: { ...safe.breast, lumpSizeCm: e.target.value } }),
9820
- disabled
9821
- }
9822
- )
9823
- ] }),
9824
- /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2", children: [
9825
- /* @__PURE__ */ jsx(
9826
- Checkbox,
9827
- {
9828
- checked: safe.breast.mobile,
9829
- onCheckedChange: (c) => update({ ...safe, breast: { ...safe.breast, mobile: c === true } }),
9830
- disabled
9831
- }
9832
- ),
9833
- "Mobile"
9834
- ] }),
9835
- /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2", children: [
9836
- /* @__PURE__ */ jsx(
9837
- Checkbox,
9838
- {
9839
- checked: safe.breast.skinInvolvement,
9840
- onCheckedChange: (c) => update({ ...safe, breast: { ...safe.breast, skinInvolvement: c === true } }),
9841
- disabled
9842
- }
9843
- ),
9844
- "Skin involvement"
9845
- ] }),
9846
- /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2", children: [
9847
- /* @__PURE__ */ jsx(
9848
- Checkbox,
9849
- {
9850
- checked: safe.breast.axillaryNodes,
9851
- onCheckedChange: (c) => update({ ...safe, breast: { ...safe.breast, axillaryNodes: c === true } }),
9852
- disabled
9853
- }
9854
- ),
9855
- "Axillary nodes"
9856
- ] })
10203
+ has("breast") ? /* @__PURE__ */ jsx(RegionCard, { title: "Breast exam", children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 gap-4 text-xs md:grid-cols-2", children: [
10204
+ /* @__PURE__ */ jsx(
10205
+ BreastLumpColumn,
10206
+ {
10207
+ title: "Left breast",
10208
+ data: safe.breast.left,
10209
+ onChange: (p) => update({
10210
+ ...safe,
10211
+ breast: { ...safe.breast, left: { ...safe.breast.left, ...p } }
10212
+ }),
10213
+ disabled
10214
+ }
10215
+ ),
10216
+ /* @__PURE__ */ jsx(
10217
+ BreastLumpColumn,
10218
+ {
10219
+ title: "Right breast",
10220
+ data: safe.breast.right,
10221
+ onChange: (p) => update({
10222
+ ...safe,
10223
+ breast: { ...safe.breast, right: { ...safe.breast.right, ...p } }
10224
+ }),
10225
+ disabled
10226
+ }
10227
+ )
9857
10228
  ] }) }) : null,
9858
10229
  has("thyroid") ? /* @__PURE__ */ jsx(RegionCard, { title: "Thyroid exam", children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 gap-3 text-xs md:grid-cols-4", children: [
9859
10230
  /* @__PURE__ */ jsxs("label", { className: "block", children: [
@@ -9988,13 +10359,43 @@ var GsExaminationWidget = ({ fieldId }) => {
9988
10359
  ] }) }) : null
9989
10360
  ] }),
9990
10361
  /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
9991
- /* @__PURE__ */ jsx(Label, { className: "text-xs font-semibold text-slate-700", children: clinicalField.fieldDef?.label ?? "Clinical examination" }),
10362
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center justify-between gap-2", children: [
10363
+ /* @__PURE__ */ jsx(Label, { className: "text-xs font-semibold text-slate-700", children: clinicalField.fieldDef?.label ?? "Clinical examination" }),
10364
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
10365
+ clinicalNarrativeLocked ? /* @__PURE__ */ jsxs("span", { className: "rounded bg-amber-50 px-1.5 py-0.5 text-[10px] font-medium text-amber-900 ring-1 ring-amber-200/80", children: [
10366
+ "You edited this summary. Use",
10367
+ " ",
10368
+ /* @__PURE__ */ jsx("span", { className: "italic", children: "'Regenerate'" }),
10369
+ " ",
10370
+ "to update it from the form."
10371
+ ] }) : null,
10372
+ clinicalNarrativeLocked ? /* @__PURE__ */ jsx(
10373
+ Button,
10374
+ {
10375
+ type: "button",
10376
+ variant: "outline",
10377
+ size: "sm",
10378
+ className: "h-7 shrink-0 px-2 text-xs",
10379
+ disabled: disabled || clinicalField.disabled,
10380
+ onClick: () => {
10381
+ setClinicalNarrativeLocked(false);
10382
+ clinicalField.setValue(
10383
+ formatGeneralSurgeryExaminationToNarrative(normalizeGeneralSurgeryExamination(value))
10384
+ );
10385
+ },
10386
+ children: "Regenerate"
10387
+ }
10388
+ ) : null
10389
+ ] })
10390
+ ] }),
10391
+ clinicalNarrativeLocked ? /* @__PURE__ */ jsx("p", { className: "text-[10px] text-muted-foreground", children: "Edit this box anytime. Use Regenerate to replace with fresh text from the structured examination." }) : null,
9992
10392
  /* @__PURE__ */ jsx(
9993
10393
  Textarea,
9994
10394
  {
9995
10395
  className: "min-h-[88px] rounded-md border border-input bg-white text-sm",
9996
10396
  value: typeof clinicalField.value === "string" ? clinicalField.value : clinicalField.value == null ? "" : String(clinicalField.value),
9997
10397
  onChange: (e) => {
10398
+ setClinicalNarrativeLocked(true);
9998
10399
  clinicalField.setValue(e.target.value);
9999
10400
  clinicalField.setTouched();
10000
10401
  },
@@ -10008,7 +10409,7 @@ var GsExaminationWidget = ({ fieldId }) => {
10008
10409
  };
10009
10410
  var CHIEF_CHIPS_FIELD2 = "chief_complaints_chips";
10010
10411
  var GS_EXAMINATION_FIELD = "gs_examination";
10011
- function chipList2(state) {
10412
+ function chipList(state) {
10012
10413
  const raw = state.values[CHIEF_CHIPS_FIELD2];
10013
10414
  return Array.isArray(raw) ? raw.filter((x) => typeof x === "string") : [];
10014
10415
  }
@@ -10022,7 +10423,7 @@ var GsGradingWidget = ({ fieldId }) => {
10022
10423
  const { state } = useForm();
10023
10424
  const showError = !!error && (touched || state.submitAttempted);
10024
10425
  const safe = useMemo(() => normalizeGeneralSurgeryGrading(value), [value]);
10025
- const chips = useMemo(() => chipList2(state), [state]);
10426
+ const chips = useMemo(() => chipList(state), [state]);
10026
10427
  const regions = useMemo(() => regionList(state), [state]);
10027
10428
  const visibleRows = useMemo(() => {
10028
10429
  return ALL_GS_CONDITIONS.filter(
@@ -11121,7 +11522,19 @@ var ReadOnlyFieldRenderer = ({
11121
11522
  ].join("\n");
11122
11523
  return /* @__PURE__ */ jsx(ReadOnlyText, { fieldDef, value: lines });
11123
11524
  }
11124
- case "general_surgery_smart_history":
11525
+ case "general_surgery_smart_history": {
11526
+ const structuredDisplay = value && typeof value === "object" ? JSON.stringify(normalizeGeneralSurgerySmartHistory(value), null, 2) : value == null || value === "" ? "\u2014" : String(value);
11527
+ const hopcDef = resolveFieldDef?.("symptoms");
11528
+ const hopcRaw = allValues?.["symptoms"];
11529
+ const hopcStr = typeof hopcRaw === "string" ? hopcRaw : hopcRaw != null && hopcRaw !== "" ? String(hopcRaw) : "";
11530
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
11531
+ /* @__PURE__ */ jsx(ReadOnlyText, { fieldDef, value: structuredDisplay }),
11532
+ hopcDef ? /* @__PURE__ */ jsx(ReadOnlyText, { fieldDef: hopcDef, value: hopcStr }) : hopcStr ? /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
11533
+ /* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-gray-700", children: "History of presenting complaint" }),
11534
+ /* @__PURE__ */ jsx("div", { className: "text-gray-900 border border-gray-200 rounded-md p-3 bg-gray-50 min-h-[2.5rem] whitespace-pre-wrap", children: hopcStr })
11535
+ ] }) : null
11536
+ ] });
11537
+ }
11125
11538
  case "general_surgery_grading":
11126
11539
  return /* @__PURE__ */ jsx(
11127
11540
  ReadOnlyText,