formanitor 0.0.38 → 0.0.40

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
@@ -97,6 +97,15 @@ function validateField(value, field) {
97
97
  return `Must be at most ${rules.max}`;
98
98
  }
99
99
  }
100
+ if (field.type === "slider") {
101
+ const num = Number(value);
102
+ if (isNaN(num)) return "Must be a valid number";
103
+ const s = field;
104
+ const min = s.min ?? 0;
105
+ const max = s.max ?? 10;
106
+ if (num < min) return `Must be at least ${min}`;
107
+ if (num > max) return `Must be at most ${max}`;
108
+ }
100
109
  if (typeof value === "string") {
101
110
  if (rules.minLength !== void 0 && value.length < rules.minLength) {
102
111
  return `Must be at least ${rules.minLength} characters`;
@@ -235,6 +244,227 @@ function applyPrefill(currentValues, fields, prefilledData = {}) {
235
244
  return newValues;
236
245
  }
237
246
 
247
+ // src/core/generalSurgeryPathway.ts
248
+ var defaultGeneralSurgerySmartHistory = () => ({
249
+ pain: {
250
+ site: "",
251
+ onset: "",
252
+ character: "",
253
+ radiation: "",
254
+ associated: "",
255
+ timing: "",
256
+ exacerbating: "",
257
+ severity: 0
258
+ },
259
+ swelling: { duration: "", sizeProgression: "", painfulPainless: "", checks: [] },
260
+ gi: { appetite: "", weightLoss: "", bowelHabits: "", checks: [] },
261
+ breast: { lumpDuration: "", nippleDischarge: "", checks: [] },
262
+ ano: { checks: [] },
263
+ thyroid: { swellingDuration: "", checks: [] },
264
+ systemic: ""
265
+ });
266
+ var defaultGeneralSurgeryExamination = () => ({
267
+ general: [],
268
+ regions: [],
269
+ abdomen: {
270
+ inspection: [],
271
+ palpation: [],
272
+ percussion: [],
273
+ massNotes: "",
274
+ bowelSounds: "none"
275
+ },
276
+ hernia: { site: "", reducible: false, coughImpulse: false, tenderness: false },
277
+ breast: { lumpSizeCm: "", mobile: false, skinInvolvement: false, axillaryNodes: false },
278
+ thyroid: { size: "", mobileDeglutition: false, nodules: false, cervicalNodes: false },
279
+ anorectal: { inspection: "", dreDone: false, proctoscopyDone: false, notes: "" },
280
+ limb: { dilatedVeins: false, ulcer: false, oedema: false }
281
+ });
282
+ var ALL_GS_CONDITIONS = [
283
+ "hernia",
284
+ "appendicitis",
285
+ "gallbladder",
286
+ "breast",
287
+ "thyroid",
288
+ "piles",
289
+ "varicose",
290
+ "ulcer"
291
+ ];
292
+ var defaultGeneralSurgeryGrading = () => ({
293
+ hernia: 0,
294
+ appendicitis: 0,
295
+ gallbladder: 0,
296
+ breast: 0,
297
+ thyroid: 0,
298
+ piles: 0,
299
+ varicose: 0,
300
+ ulcer: 0
301
+ });
302
+ var GS_CONDITION_TRIGGERS = {
303
+ hernia: { regions: ["hernia", "abdomen"], chips: ["swelling_lump", "obstruction"] },
304
+ appendicitis: { regions: ["abdomen"], chips: ["pain", "obstruction"] },
305
+ gallbladder: { regions: ["abdomen"], chips: ["pain"] },
306
+ breast: { regions: ["breast"], chips: ["breast", "swelling_lump"] },
307
+ thyroid: { regions: ["thyroid"], chips: ["thyroid", "swelling_lump"] },
308
+ piles: { regions: ["anorectal"], chips: ["anorectal", "bleeding"] },
309
+ varicose: { regions: ["limb"], chips: ["swelling_lump"] },
310
+ ulcer: { regions: ["limb", "anorectal"], chips: ["ulcer_wound", "discharge"] }
311
+ };
312
+ var GS_CONDITION_LABELS = {
313
+ hernia: "Hernia",
314
+ appendicitis: "Appendicitis",
315
+ gallbladder: "Gallbladder disease",
316
+ breast: "Breast lump (BIRADS)",
317
+ thyroid: "Thyroid nodule (TIRADS)",
318
+ piles: "Haemorrhoids",
319
+ varicose: "Varicose veins (CEAP)",
320
+ ulcer: "Ulcer / wound"
321
+ };
322
+ var GS_GRADE_DESCRIPTIONS = {
323
+ hernia: ["\u2014", "Small reducible", "Large reducible", "Irreducible", "Obstructed", "Strangulated"],
324
+ appendicitis: ["\u2014", "Mild (clinical)", "Confirmed (USG/CT)", "Complicated (mass)", "Abscess", "Perforation"],
325
+ gallbladder: ["\u2014", "Asymptomatic stones", "Symptomatic", "Acute cholecystitis", "Complicated (CBD stone)", "Perforation/empyema"],
326
+ breast: ["\u2014", "BIRADS 1 \u2014 Negative", "BIRADS 2 \u2014 Benign", "BIRADS 3 \u2014 Probably benign", "BIRADS 4 \u2014 Suspicious", "BIRADS 5 \u2014 Malignant"],
327
+ thyroid: ["\u2014", "TIRADS 1 \u2014 Normal", "TIRADS 2 \u2014 Benign", "TIRADS 3 \u2014 Indeterminate", "TIRADS 4 \u2014 Suspicious", "TIRADS 5 \u2014 Highly suspicious"],
328
+ piles: ["\u2014", "Grade 1", "Grade 2", "Grade 3", "Grade 4", "Grade 5"],
329
+ varicose: ["\u2014", "C1 telangiectasia", "C2 varicose", "C3 oedema", "C4 skin changes", "C5-C6 ulcer"],
330
+ ulcer: ["\u2014", "Superficial", "Deep", "Infected", "Necrotic", "Gangrene"]
331
+ };
332
+ function normalizeGeneralSurgerySmartHistory(raw) {
333
+ const d = defaultGeneralSurgerySmartHistory();
334
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) return d;
335
+ const v = raw;
336
+ const painIn = v.pain && typeof v.pain === "object" ? v.pain : {};
337
+ const sev = Number(painIn.severity);
338
+ const pain = {
339
+ ...d.pain,
340
+ ...painIn,
341
+ severity: Number.isFinite(sev) ? Math.min(10, Math.max(0, Math.round(sev))) : d.pain.severity
342
+ };
343
+ const str2 = (x) => typeof x === "string" ? x : "";
344
+ const strArr = (x) => Array.isArray(x) ? x.filter((i) => typeof i === "string") : [];
345
+ const swell = v.swelling && typeof v.swelling === "object" ? v.swelling : {};
346
+ const gi = v.gi && typeof v.gi === "object" ? v.gi : {};
347
+ const breast = v.breast && typeof v.breast === "object" ? v.breast : {};
348
+ const ano = v.ano && typeof v.ano === "object" ? v.ano : {};
349
+ const thy = v.thyroid && typeof v.thyroid === "object" ? v.thyroid : {};
350
+ return {
351
+ pain,
352
+ swelling: {
353
+ duration: str2(swell.duration),
354
+ sizeProgression: str2(swell.sizeProgression),
355
+ painfulPainless: str2(swell.painfulPainless),
356
+ checks: strArr(swell.checks)
357
+ },
358
+ gi: {
359
+ appetite: str2(gi.appetite),
360
+ weightLoss: str2(gi.weightLoss),
361
+ bowelHabits: str2(gi.bowelHabits),
362
+ checks: strArr(gi.checks)
363
+ },
364
+ breast: {
365
+ lumpDuration: str2(breast.lumpDuration),
366
+ nippleDischarge: str2(breast.nippleDischarge),
367
+ checks: strArr(breast.checks)
368
+ },
369
+ ano: { checks: strArr(ano.checks) },
370
+ thyroid: {
371
+ swellingDuration: str2(thy.swellingDuration),
372
+ checks: strArr(thy.checks)
373
+ },
374
+ systemic: typeof v.systemic === "string" ? v.systemic : d.systemic
375
+ };
376
+ }
377
+ function normalizeGeneralSurgeryExamination(raw) {
378
+ const d = defaultGeneralSurgeryExamination();
379
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) return d;
380
+ const v = raw;
381
+ const strArr = (x) => Array.isArray(x) ? x.filter((i) => typeof i === "string") : [];
382
+ const ab = v.abdomen && typeof v.abdomen === "object" ? v.abdomen : {};
383
+ const bowel = ab.bowelSounds;
384
+ const bowels = bowel === "normal" || bowel === "up" || bowel === "down" || bowel === "absent" ? bowel : "none";
385
+ const hb = v.hernia && typeof v.hernia === "object" ? v.hernia : {};
386
+ const br = v.breast && typeof v.breast === "object" ? v.breast : {};
387
+ const th = v.thyroid && typeof v.thyroid === "object" ? v.thyroid : {};
388
+ const ar = v.anorectal && typeof v.anorectal === "object" ? v.anorectal : {};
389
+ const lm = v.limb && typeof v.limb === "object" ? v.limb : {};
390
+ const bool = (x) => x === true;
391
+ return {
392
+ general: strArr(v.general),
393
+ regions: strArr(v.regions),
394
+ abdomen: {
395
+ inspection: strArr(ab.inspection),
396
+ palpation: strArr(ab.palpation),
397
+ percussion: strArr(ab.percussion),
398
+ massNotes: typeof ab.massNotes === "string" ? ab.massNotes : d.abdomen.massNotes,
399
+ bowelSounds: bowels
400
+ },
401
+ hernia: {
402
+ site: typeof hb.site === "string" ? hb.site : "",
403
+ reducible: bool(hb.reducible),
404
+ coughImpulse: bool(hb.coughImpulse),
405
+ tenderness: bool(hb.tenderness)
406
+ },
407
+ breast: {
408
+ lumpSizeCm: typeof br.lumpSizeCm === "string" ? br.lumpSizeCm : "",
409
+ mobile: bool(br.mobile),
410
+ skinInvolvement: bool(br.skinInvolvement),
411
+ axillaryNodes: bool(br.axillaryNodes)
412
+ },
413
+ thyroid: {
414
+ size: typeof th.size === "string" ? th.size : "",
415
+ mobileDeglutition: bool(th.mobileDeglutition),
416
+ nodules: bool(th.nodules),
417
+ cervicalNodes: bool(th.cervicalNodes)
418
+ },
419
+ anorectal: {
420
+ inspection: typeof ar.inspection === "string" ? ar.inspection : "",
421
+ dreDone: bool(ar.dreDone),
422
+ proctoscopyDone: bool(ar.proctoscopyDone),
423
+ notes: typeof ar.notes === "string" ? ar.notes : ""
424
+ },
425
+ limb: {
426
+ dilatedVeins: bool(lm.dilatedVeins),
427
+ ulcer: bool(lm.ulcer),
428
+ oedema: bool(lm.oedema)
429
+ }
430
+ };
431
+ }
432
+ function normalizeGeneralSurgeryGrading(raw) {
433
+ const d = defaultGeneralSurgeryGrading();
434
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) return d;
435
+ const v = raw;
436
+ const out = { ...d };
437
+ for (const k of ALL_GS_CONDITIONS) {
438
+ const n = Number(v[k]);
439
+ if (Number.isFinite(n) && n >= 0 && n <= 5) out[k] = Math.round(n);
440
+ }
441
+ return out;
442
+ }
443
+ function gsGradingRowVisible(cond, chips, regions, grade) {
444
+ if (grade > 0) return true;
445
+ const t = GS_CONDITION_TRIGGERS[cond];
446
+ if (t.chips.some((c) => chips.includes(c))) return true;
447
+ if (t.regions.some((r) => regions.includes(r))) return true;
448
+ return false;
449
+ }
450
+
451
+ // src/core/painScaleFlags.ts
452
+ function normalizePainScaleFlags(raw, bounds) {
453
+ const min = bounds?.min ?? 0;
454
+ const max = bounds?.max ?? 10;
455
+ let pain = min;
456
+ let flags = [];
457
+ if (raw && typeof raw === "object" && !Array.isArray(raw)) {
458
+ const o = raw;
459
+ const p = Number(o.pain);
460
+ if (Number.isFinite(p)) pain = Math.min(max, Math.max(min, p));
461
+ if (Array.isArray(o.flags)) {
462
+ flags = o.flags.filter((x) => typeof x === "string");
463
+ }
464
+ }
465
+ return { pain, flags };
466
+ }
467
+
238
468
  // src/core/store.ts
239
469
  var FormStore = class {
240
470
  state;
@@ -321,7 +551,22 @@ var FormStore = class {
321
551
  else if (field.type === "surgical_risk_flags")
322
552
  values[field.id] = { OD: [], OS: [] };
323
553
  else if (field.type === "toggle") values[field.id] = false;
324
- else values[field.id] = null;
554
+ else if (field.type === "slider") {
555
+ const s = field;
556
+ values[field.id] = s.defaultValue ?? s.min ?? 0;
557
+ } else if (field.type === "general_surgery_smart_history") {
558
+ values[field.id] = field.defaultValue ?? defaultGeneralSurgerySmartHistory();
559
+ } else if (field.type === "general_surgery_examination") {
560
+ values[field.id] = field.defaultValue ?? defaultGeneralSurgeryExamination();
561
+ } else if (field.type === "general_surgery_grading") {
562
+ values[field.id] = field.defaultValue ?? defaultGeneralSurgeryGrading();
563
+ } else if (field.type === "pain_scale_flags") {
564
+ const f = field;
565
+ values[field.id] = normalizePainScaleFlags(
566
+ f.defaultValue ?? { pain: f.min ?? 0, flags: [] },
567
+ { min: f.min, max: f.max }
568
+ );
569
+ } else values[field.id] = null;
325
570
  }
326
571
  });
327
572
  this.state.values = values;
@@ -1041,7 +1286,8 @@ var TextWidget = ({ fieldId }) => {
1041
1286
  fieldDef.required && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-red-500", children: "*" })
1042
1287
  ] });
1043
1288
  const labelEl = theme ? /* @__PURE__ */ jsxRuntime.jsx(Label, { htmlFor: fieldId, className: labelClass, children: labelContent }) : /* @__PURE__ */ jsxRuntime.jsx(Label, { htmlFor: fieldId, children: labelContent });
1044
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: wrapperClass, children: [
1289
+ const placeholder = typeof fieldDef.placeholder === "string" && fieldDef.placeholder.trim() ? fieldDef.placeholder : void 0;
1290
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn(wrapperClass, isTextarea && "flex h-full min-h-0 flex-col"), children: [
1045
1291
  hasVoice ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
1046
1292
  labelEl,
1047
1293
  /* @__PURE__ */ jsxRuntime.jsx(VoiceMicButton, { fieldId, onTranscriptReady: setValue })
@@ -1055,7 +1301,8 @@ var TextWidget = ({ fieldId }) => {
1055
1301
  onBlur: setTouched,
1056
1302
  disabled,
1057
1303
  type: fieldDef.type === "number" ? "number" : "text",
1058
- className: inputClass,
1304
+ className: cn(inputClass, isTextarea && height == null && "min-h-[80px] flex-1"),
1305
+ placeholder,
1059
1306
  ...isTextarea && { height }
1060
1307
  }
1061
1308
  ),
@@ -1531,6 +1778,8 @@ var SelectWidget = ({ fieldId }) => {
1531
1778
  }
1532
1779
  }, [fieldDef]);
1533
1780
  if (!fieldDef) return null;
1781
+ const schemaPlaceholder = typeof fieldDef.placeholder === "string" && fieldDef.placeholder.trim() ? fieldDef.placeholder : void 0;
1782
+ const selectPlaceholder = loading ? "Loading..." : schemaPlaceholder ?? "Select...";
1534
1783
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
1535
1784
  /* @__PURE__ */ jsxRuntime.jsxs(Label, { htmlFor: fieldId, children: [
1536
1785
  fieldDef.label,
@@ -1548,7 +1797,7 @@ var SelectWidget = ({ fieldId }) => {
1548
1797
  setTouched();
1549
1798
  },
1550
1799
  children: [
1551
- /* @__PURE__ */ jsxRuntime.jsx(SelectTrigger, { id: fieldId, className: showError ? "border-red-500" : "", children: /* @__PURE__ */ jsxRuntime.jsx(SelectValue, { placeholder: loading ? "Loading..." : "Select..." }) }),
1800
+ /* @__PURE__ */ jsxRuntime.jsx(SelectTrigger, { id: fieldId, className: showError ? "border-red-500" : "", children: /* @__PURE__ */ jsxRuntime.jsx(SelectValue, { placeholder: selectPlaceholder }) }),
1552
1801
  /* @__PURE__ */ jsxRuntime.jsx(SelectContent, { children: options.map((opt) => /* @__PURE__ */ jsxRuntime.jsx(SelectItem, { value: String(opt.value), children: opt.label }, String(opt.value))) })
1553
1802
  ]
1554
1803
  }
@@ -6420,7 +6669,11 @@ var OphthalmologyWidget = ({ fieldId }) => {
6420
6669
  ] })
6421
6670
  ] }),
6422
6671
  /* @__PURE__ */ jsxRuntime.jsx("tbody", { children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
6423
- /* @__PURE__ */ jsxRuntime.jsx("td", { className: refractionLabelCellClass, children: "Current Glass" }),
6672
+ /* @__PURE__ */ jsxRuntime.jsx("td", { className: `${refractionLabelCellClass} whitespace-normal`, children: /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "block leading-tight", children: [
6673
+ "Current",
6674
+ /* @__PURE__ */ jsxRuntime.jsx("br", {}),
6675
+ "Glass"
6676
+ ] }) }),
6424
6677
  /* @__PURE__ */ jsxRuntime.jsx("td", { className: refractionDataCellClass, children: /* @__PURE__ */ jsxRuntime.jsx(
6425
6678
  Input,
6426
6679
  {
@@ -6675,12 +6928,12 @@ var OphthalmologyWidget = ({ fieldId }) => {
6675
6928
  /* @__PURE__ */ jsxRuntime.jsx("th", { className: refractionHeaderCellClass, children: "Sph" }),
6676
6929
  /* @__PURE__ */ jsxRuntime.jsx("th", { className: refractionHeaderCellClass, children: "Cyl" }),
6677
6930
  /* @__PURE__ */ jsxRuntime.jsx("th", { className: refractionHeaderCellClass, children: "Axis" }),
6678
- /* @__PURE__ */ jsxRuntime.jsx("th", { className: refractionHeaderCellClass, children: "V/A" }),
6931
+ /* @__PURE__ */ jsxRuntime.jsx("th", { className: refractionHeaderCellClass, children: "BCVA" }),
6679
6932
  /* @__PURE__ */ jsxRuntime.jsx("th", { className: refractionHeaderCellClass, children: "P/D" }),
6680
6933
  /* @__PURE__ */ jsxRuntime.jsx("th", { className: refractionHeaderCellClass, children: "Sph" }),
6681
6934
  /* @__PURE__ */ jsxRuntime.jsx("th", { className: refractionHeaderCellClass, children: "Cyl" }),
6682
6935
  /* @__PURE__ */ jsxRuntime.jsx("th", { className: refractionHeaderCellClass, children: "Axis" }),
6683
- /* @__PURE__ */ jsxRuntime.jsx("th", { className: refractionHeaderCellClass, children: "V/A" }),
6936
+ /* @__PURE__ */ jsxRuntime.jsx("th", { className: refractionHeaderCellClass, children: "BCVA" }),
6684
6937
  /* @__PURE__ */ jsxRuntime.jsx("th", { className: refractionHeaderCellClass, children: "P/D" })
6685
6938
  ] })
6686
6939
  ] }),
@@ -8069,6 +8322,21 @@ function parallelChipArraysEqual(a, b) {
8069
8322
  function isSuggestionField(type) {
8070
8323
  return type === "suggestion_textarea" || type === "complaint_chips";
8071
8324
  }
8325
+ function EmbeddedSchemaField({ fieldId }) {
8326
+ const store = useFormStore();
8327
+ const fieldDef = store.getFieldDef(fieldId);
8328
+ if (!fieldDef) return null;
8329
+ switch (fieldDef.type) {
8330
+ case "text":
8331
+ case "number":
8332
+ case "textarea":
8333
+ return /* @__PURE__ */ jsxRuntime.jsx(TextWidget, { fieldId });
8334
+ case "select":
8335
+ return /* @__PURE__ */ jsxRuntime.jsx(SelectWidget, { fieldId });
8336
+ default:
8337
+ return null;
8338
+ }
8339
+ }
8072
8340
  var SuggestionTextareaWidget = ({ fieldId }) => {
8073
8341
  const { fieldDef, value, setValue, setTouched, error, disabled, touched } = useField(fieldId);
8074
8342
  const { state } = useForm();
@@ -8080,6 +8348,10 @@ var SuggestionTextareaWidget = ({ fieldId }) => {
8080
8348
  const def = fieldDef && isSuggestionField(fieldDef.type) ? fieldDef : void 0;
8081
8349
  const textValue = value == null || typeof value === "string" ? value || "" : String(value);
8082
8350
  const parallelChipFieldId = def?.meta && typeof def.meta.parallelChipFieldId === "string" ? def.meta.parallelChipFieldId.trim() : void 0;
8351
+ const embeddedFieldIds = React15.useMemo(() => {
8352
+ const raw = def?.meta && Array.isArray(def.meta.embeddedFieldIds) ? def.meta.embeddedFieldIds : [];
8353
+ return raw.filter((id) => typeof id === "string" && id.trim().length > 0).map((id) => id.trim()).filter((id) => store.getFieldDef(id));
8354
+ }, [def?.meta, store]);
8083
8355
  React15.useEffect(() => {
8084
8356
  if (!def) {
8085
8357
  setOptions([]);
@@ -8124,19 +8396,26 @@ var SuggestionTextareaWidget = ({ fieldId }) => {
8124
8396
  setValue(toggleSuggestionTokenInText(textValue, String(optValue), appendSeparator));
8125
8397
  };
8126
8398
  const hasSuggestions = options.length > 0;
8399
+ const hasEmbedded = embeddedFieldIds.length > 0;
8400
+ const hasShell = hasSuggestions || hasEmbedded;
8127
8401
  const isHighlightLabel = def.theme === "highlight-label";
8128
8402
  const suggestionShellClass = cn(
8129
8403
  "flex min-w-0 flex-col overflow-hidden",
8130
- hasSuggestions && (isHighlightLabel ? "-mt-1 rounded-b-md border-[#D0D0D0] bg-white" : "rounded-md border border-input bg-background")
8404
+ hasShell && (isHighlightLabel ? "-mt-1 rounded-b-md border-[#D0D0D0] bg-white" : "rounded-md border border-input bg-background")
8131
8405
  );
8132
8406
  const chipsRowClass = cn(
8133
8407
  "flex flex-wrap gap-2 px-3 pb-2 pt-3",
8134
8408
  hasSuggestions && (isHighlightLabel ? "" : "border-b border-input/70"),
8135
8409
  disabled && "pointer-events-none opacity-50"
8136
8410
  );
8411
+ const embeddedRowClass = cn(
8412
+ "grid gap-3 px-3 sm:grid-cols-3",
8413
+ hasEmbedded && (hasSuggestions ? cn("py-2", isHighlightLabel && "border-t border-input/70") : "border-b border-input/70 py-3"),
8414
+ disabled && "pointer-events-none opacity-50"
8415
+ );
8137
8416
  const textareaShellClass = cn(
8138
8417
  inputClass,
8139
- hasSuggestions && cn(
8418
+ hasShell && cn(
8140
8419
  "mt-0 rounded-t-none rounded-b-md border-0 shadow-none focus-visible:ring-offset-0",
8141
8420
  isHighlightLabel ? "border-t-0" : "min-h-[80px]"
8142
8421
  )
@@ -8163,8 +8442,9 @@ var SuggestionTextareaWidget = ({ fieldId }) => {
8163
8442
  /* @__PURE__ */ jsxRuntime.jsx(VoiceMicButton, { fieldId, onTranscriptReady: setValue })
8164
8443
  ] }) : labelEl,
8165
8444
  def.description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground", children: def.description }),
8166
- hasSuggestions ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: suggestionShellClass, children: [
8167
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: chipsRowClass, role: "group", "aria-label": suggestionsAria, children: suggestionButtons }),
8445
+ hasShell ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: suggestionShellClass, children: [
8446
+ hasSuggestions && /* @__PURE__ */ jsxRuntime.jsx("div", { className: chipsRowClass, role: "group", "aria-label": suggestionsAria, children: suggestionButtons }),
8447
+ hasEmbedded && /* @__PURE__ */ jsxRuntime.jsx("div", { className: embeddedRowClass, children: embeddedFieldIds.map((id) => /* @__PURE__ */ jsxRuntime.jsx(EmbeddedSchemaField, { fieldId: id }, id)) }),
8168
8448
  /* @__PURE__ */ jsxRuntime.jsx(
8169
8449
  Textarea,
8170
8450
  {
@@ -8944,178 +9224,1176 @@ var SurgicalRiskFlagsWidget = ({ fieldId }) => {
8944
9224
  }
8945
9225
  );
8946
9226
  };
8947
- var FieldRenderer = ({ fieldId }) => {
8948
- const { fieldDef, visible } = useField(fieldId);
8949
- if (!visible || !fieldDef) {
8950
- return null;
8951
- }
8952
- return renderWidget(fieldId, fieldDef);
8953
- };
8954
- function renderWidget(fieldId, fieldDef) {
8955
- switch (fieldDef.type) {
8956
- case "text":
8957
- case "number":
8958
- return /* @__PURE__ */ jsxRuntime.jsx(TextWidget, { fieldId });
8959
- case "textarea":
8960
- if (fieldMetaRequestsMarMedicationOrdersButton(fieldDef.meta)) {
8961
- return /* @__PURE__ */ jsxRuntime.jsx(MarMedicationOrdersWidget, { fieldId });
8962
- }
8963
- return /* @__PURE__ */ jsxRuntime.jsx(TextWidget, { fieldId });
8964
- case "richtext":
8965
- return /* @__PURE__ */ jsxRuntime.jsx(RichTextWidget, { fieldId });
8966
- case "date":
8967
- return /* @__PURE__ */ jsxRuntime.jsx(DateWidget, { fieldId });
8968
- case "datetime":
8969
- return /* @__PURE__ */ jsxRuntime.jsx(DateTimeWidget, { fieldId });
8970
- case "select":
8971
- return /* @__PURE__ */ jsxRuntime.jsx(SelectWidget, { fieldId });
8972
- case "radio":
8973
- return /* @__PURE__ */ jsxRuntime.jsx(RadioWidget, { fieldId });
8974
- case "checkbox":
8975
- return /* @__PURE__ */ jsxRuntime.jsx(CheckboxWidget, { fieldId });
8976
- case "multiselect":
8977
- return /* @__PURE__ */ jsxRuntime.jsx(MultiSelectWidget, { fieldId });
8978
- case "repeatable":
8979
- return /* @__PURE__ */ jsxRuntime.jsx(RepeatableWidget, { fieldId });
8980
- case "image_upload":
8981
- return /* @__PURE__ */ jsxRuntime.jsx(ImageUploadWidget, { fieldId });
8982
- case "media_upload":
8983
- return /* @__PURE__ */ jsxRuntime.jsx(MediaUploadWidget, { fieldId });
8984
- case "signature":
8985
- return /* @__PURE__ */ jsxRuntime.jsx(SignatureUploadWidget, { fieldId });
8986
- case "editable_table":
8987
- return /* @__PURE__ */ jsxRuntime.jsx(EditableTableWidget, { fieldId });
8988
- case "medications":
8989
- return /* @__PURE__ */ jsxRuntime.jsx(AddMedicationWidget, { fieldId });
8990
- case "discharge_medication_orders":
8991
- return /* @__PURE__ */ jsxRuntime.jsx(DischargeMedicationOrdersWidget, { fieldId });
8992
- case "investigations":
8993
- return /* @__PURE__ */ jsxRuntime.jsx(AddInvestigationWidget, { fieldId });
8994
- case "procedures":
8995
- return /* @__PURE__ */ jsxRuntime.jsx(AddProcedureWidget, { fieldId });
8996
- case "differential_diagnosis":
8997
- return /* @__PURE__ */ jsxRuntime.jsx(DifferentialDiagnosisWidget, { fieldId });
8998
- case "vitals":
8999
- return /* @__PURE__ */ jsxRuntime.jsx(VitalsWidget, { fieldId });
9000
- case "hidden_vitals":
9001
- return /* @__PURE__ */ jsxRuntime.jsx(HiddenVitalsWidget, { fieldId });
9002
- case "referral":
9003
- return /* @__PURE__ */ jsxRuntime.jsx(ReferralWidget, { fieldId });
9004
- case "followup":
9005
- return /* @__PURE__ */ jsxRuntime.jsx(FollowupWidget, { fieldId });
9006
- case "smart_textarea":
9007
- return /* @__PURE__ */ jsxRuntime.jsx(SmartTextareaWidget, { fieldId });
9008
- case "diagnosis_textarea":
9009
- return /* @__PURE__ */ jsxRuntime.jsx(DiagnosisTextareaWidget, { fieldId });
9010
- case "obstetric_history":
9011
- return /* @__PURE__ */ jsxRuntime.jsx(ObstetricHistoryWidget, { fieldId });
9012
- case "eye_prescription":
9013
- return /* @__PURE__ */ jsxRuntime.jsx(OphthalmologyWidget, { fieldId });
9014
- case "ophthal_diagnosis":
9015
- return /* @__PURE__ */ jsxRuntime.jsx(OphthalDiagnosisWidget, { fieldId });
9016
- case "orthopedic_exam":
9017
- return /* @__PURE__ */ jsxRuntime.jsx(OrthopedicExamWidget, { fieldId });
9018
- case "toggle": {
9019
- const { value, setValue, setTouched, disabled } = useField(fieldId);
9020
- const store = useFormStore();
9021
- const excludes = fieldDef.excludes ?? [];
9022
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
9023
- /* @__PURE__ */ jsxRuntime.jsx(
9024
- Switch,
9025
- {
9026
- checked: value === true,
9027
- disabled,
9028
- onCheckedChange: (checked) => {
9029
- setValue(checked);
9030
- setTouched();
9031
- if (checked) excludes.forEach((id) => store.setValue(id, false));
9032
- }
9033
- }
9034
- ),
9035
- /* @__PURE__ */ jsxRuntime.jsx(Label, { className: "text-sm font-medium leading-none cursor-pointer select-none", children: fieldDef.label })
9036
- ] });
9037
- }
9038
- case "suggestion_textarea":
9039
- case "complaint_chips":
9040
- return /* @__PURE__ */ jsxRuntime.jsx(SuggestionTextareaWidget, { fieldId });
9041
- case "lens_assessment":
9042
- return /* @__PURE__ */ jsxRuntime.jsx(LensAssessmentWidget, { fieldId });
9043
- case "functional_impairment_score":
9044
- return /* @__PURE__ */ jsxRuntime.jsx(FunctionalImpairmentScoreWidget, { fieldId });
9045
- case "biometry_iol_workup":
9046
- return /* @__PURE__ */ jsxRuntime.jsx(BiometryIolWorkupWidget, { fieldId });
9047
- case "surgical_risk_flags":
9048
- return /* @__PURE__ */ jsxRuntime.jsx(SurgicalRiskFlagsWidget, { fieldId });
9049
- case "static_text": {
9050
- const def = fieldDef;
9051
- const size = def.size ?? "regular";
9052
- const labelClass = size === "large" ? "text-base" : "text-sm";
9053
- const descClass = size === "large" ? "text-sm" : "text-xs";
9054
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `${labelClass} text-muted-foreground`, children: [
9055
- def.label,
9056
- def.description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: `mt-1 ${descClass} opacity-90`, children: def.description })
9057
- ] });
9058
- }
9059
- default:
9060
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-red-500", children: [
9061
- "Unknown field type: ",
9062
- fieldDef.type
9063
- ] });
9064
- }
9065
- }
9066
- var Section = ({ title, children }) => {
9067
- const [expanded, setExpanded] = React15.useState(true);
9068
- const handleToggle = () => setExpanded((prev) => !prev);
9069
- const contentClassName = cn(
9070
- "overflow-hidden transition-[height] duration-200 ease-in-out",
9071
- !expanded && "hidden"
9072
- );
9073
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-6 border rounded-lg bg-white shadow-sm overflow-hidden", children: [
9074
- /* @__PURE__ */ jsxRuntime.jsxs(
9075
- "button",
9227
+ var SliderWidget = ({ fieldId }) => {
9228
+ const { fieldDef, value, setValue, setTouched, error, disabled, touched } = useField(fieldId);
9229
+ const { state } = useForm();
9230
+ const showError = !!error && (touched || state.submitAttempted);
9231
+ if (!fieldDef || fieldDef.type !== "slider") return null;
9232
+ const def = fieldDef;
9233
+ const min = def.min ?? 0;
9234
+ const max = def.max ?? 10;
9235
+ const step = def.step ?? 1;
9236
+ const raw = value == null || value === "" ? min : Number(value);
9237
+ const num = Number.isFinite(raw) ? Math.min(max, Math.max(min, raw)) : min;
9238
+ const theme = getThemeConfig("textarea", def.theme);
9239
+ const wrapperClass = theme?.wrapperClassName ?? "space-y-2";
9240
+ const labelClass = theme?.labelClassName;
9241
+ const labelContent = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
9242
+ def.label,
9243
+ " ",
9244
+ def.required && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-red-500", children: "*" }),
9245
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "ml-2 text-muted-foreground font-normal tabular-nums", children: [
9246
+ num,
9247
+ "/",
9248
+ max
9249
+ ] })
9250
+ ] });
9251
+ const labelEl = theme ? /* @__PURE__ */ jsxRuntime.jsx(Label, { className: labelClass, children: labelContent }) : /* @__PURE__ */ jsxRuntime.jsx(Label, { children: labelContent });
9252
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: wrapperClass, children: [
9253
+ labelEl,
9254
+ /* @__PURE__ */ jsxRuntime.jsx(
9255
+ Slider,
9076
9256
  {
9077
- type: "button",
9078
- onClick: handleToggle,
9079
- className: "w-full flex items-center justify-between gap-2 p-4 text-left border-b hover:bg-gray-50/80 transition-colors",
9080
- children: [
9081
- /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-lg font-medium", children: title }),
9082
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-shrink-0 text-muted-foreground", "aria-hidden": true, children: expanded ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { className: "h-5 w-5" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronRight, { className: "h-5 w-5" }) })
9083
- ]
9257
+ className: cn("py-1", showError && "opacity-90 ring-1 ring-red-500 rounded"),
9258
+ disabled,
9259
+ min,
9260
+ max,
9261
+ step,
9262
+ value: [num],
9263
+ onValueChange: (v) => {
9264
+ const n = v[0] ?? min;
9265
+ setValue(n);
9266
+ setTouched();
9267
+ }
9084
9268
  }
9085
9269
  ),
9086
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: contentClassName, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-4 pt-4 space-y-4 border-t-0", children }) })
9270
+ showError && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-red-500", children: error })
9087
9271
  ] });
9088
9272
  };
9089
- var ColumnLayout = ({
9090
- columns,
9091
- label,
9092
- children
9093
- }) => {
9094
- const gridCols = Math.max(1, Math.min(columns, 12));
9095
- const gridClass = `grid gap-4 w-full`;
9096
- const style = {
9097
- gridTemplateColumns: `repeat(${gridCols}, minmax(0, 1fr))`
9098
- };
9099
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-6", children: [
9100
- label != null && label !== "" && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mb-2 text-sm font-medium text-gray-700", children: label }),
9101
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: gridClass, style, children })
9273
+ var CHIEF_CHIPS_FIELD = "chief_complaints_chips";
9274
+ var SWELLING_OPTS = [
9275
+ { value: "reducible_hernia", label: "Reducible (hernia)" },
9276
+ { value: "cough_impulse", label: "Cough impulse" },
9277
+ { value: "skin_changes", label: "Skin changes" }
9278
+ ];
9279
+ var GI_OPTS = [
9280
+ { value: "bleeding_pr", label: "Bleeding PR" },
9281
+ { value: "vomiting", label: "Vomiting" },
9282
+ { value: "haematemesis", label: "Haematemesis" }
9283
+ ];
9284
+ var BREAST_OPTS = [
9285
+ { value: "pain", label: "Pain" },
9286
+ { value: "fh_ca_breast", label: "Family history of Ca breast" }
9287
+ ];
9288
+ var ANO_OPTS = [
9289
+ { value: "pain_defecation", label: "Pain during defecation" },
9290
+ { value: "bleeding", label: "Bleeding" },
9291
+ { value: "constipation", label: "Constipation" },
9292
+ { value: "discharge", label: "Discharge" }
9293
+ ];
9294
+ var THYROID_OPTS = [
9295
+ { value: "dysphagia", label: "Dysphagia" },
9296
+ { value: "voice_change", label: "Voice change" },
9297
+ { value: "thyrotoxicosis", label: "Thyrotoxicosis symptoms" }
9298
+ ];
9299
+ var SOCRATES_KEYS = [
9300
+ "site",
9301
+ "onset",
9302
+ "character",
9303
+ "radiation",
9304
+ "associated",
9305
+ "timing",
9306
+ "exacerbating"
9307
+ ];
9308
+ function Panel({ title, children }) {
9309
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "overflow-hidden rounded-md border border-[#D0D0D0] bg-white", children: [
9310
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-b border-[#D0D0D0] bg-[#FEE8EC]/50 px-3 py-1.5 text-xs font-semibold text-slate-700", children: title }),
9311
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-3", children })
9102
9312
  ] });
9103
- };
9104
- var DynamicForm = () => {
9105
- const store = useFormStore();
9106
- const schema = store.getSchema();
9107
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-6", children: [
9108
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mb-4", children: /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-2xl font-bold", children: schema.title }) }),
9109
- schema.layout.map((node) => {
9110
- if (node.type === "section") {
9111
- return /* @__PURE__ */ jsxRuntime.jsx(Section, { title: node.title, children: node.children.map(
9112
- (child, index) => typeof child === "string" ? /* @__PURE__ */ jsxRuntime.jsx(FieldRenderer, { fieldId: child }, child) : child.type === "column_layout" ? /* @__PURE__ */ jsxRuntime.jsx(
9113
- ColumnLayout,
9114
- {
9115
- columns: child.columns,
9116
- label: child.label,
9117
- children: child.children.map((fieldId) => /* @__PURE__ */ jsxRuntime.jsx(FieldRenderer, { fieldId }, fieldId))
9118
- },
9313
+ }
9314
+ function chipList(state) {
9315
+ const raw = state.values[CHIEF_CHIPS_FIELD];
9316
+ return Array.isArray(raw) ? raw.filter((x) => typeof x === "string") : [];
9317
+ }
9318
+ var GsSmartHistoryWidget = ({ fieldId }) => {
9319
+ const { fieldDef, value, setValue, setTouched, error, touched, disabled } = useField(fieldId);
9320
+ const { state } = useForm();
9321
+ const showError = !!error && (touched || state.submitAttempted);
9322
+ const safe = React15.useMemo(() => normalizeGeneralSurgerySmartHistory(value), [value]);
9323
+ const chips = React15.useMemo(() => chipList(state), [state]);
9324
+ const showPain = chips.includes("pain");
9325
+ const showSwelling = chips.includes("swelling_lump");
9326
+ const showGI = chips.includes("bleeding") || chips.includes("obstruction");
9327
+ const showBreast = chips.includes("breast");
9328
+ const showAno = chips.includes("anorectal");
9329
+ const showThyroid = chips.includes("thyroid");
9330
+ const update = (next) => {
9331
+ setValue(next);
9332
+ setTouched();
9333
+ };
9334
+ const setPain = (key, v) => {
9335
+ if (key === "severity") {
9336
+ const n = typeof v === "number" ? v : Number(v);
9337
+ const sev = Number.isFinite(n) ? Math.min(10, Math.max(0, Math.round(n))) : 0;
9338
+ update({ ...safe, pain: { ...safe.pain, severity: sev } });
9339
+ return;
9340
+ }
9341
+ update({ ...safe, pain: { ...safe.pain, [key]: String(v) } });
9342
+ };
9343
+ const toggleArr = (section, val) => {
9344
+ if (section === "swelling") {
9345
+ const a = safe.swelling.checks;
9346
+ const next = a.includes(val) ? a.filter((x) => x !== val) : [...a, val];
9347
+ update({ ...safe, swelling: { ...safe.swelling, checks: next } });
9348
+ } else if (section === "gi") {
9349
+ const a = safe.gi.checks;
9350
+ const next = a.includes(val) ? a.filter((x) => x !== val) : [...a, val];
9351
+ update({ ...safe, gi: { ...safe.gi, checks: next } });
9352
+ } else if (section === "breast") {
9353
+ const a = safe.breast.checks;
9354
+ const next = a.includes(val) ? a.filter((x) => x !== val) : [...a, val];
9355
+ update({ ...safe, breast: { ...safe.breast, checks: next } });
9356
+ } else if (section === "ano") {
9357
+ const a = safe.ano.checks;
9358
+ const next = a.includes(val) ? a.filter((x) => x !== val) : [...a, val];
9359
+ update({ ...safe, ano: { ...safe.ano, checks: next } });
9360
+ } else {
9361
+ const a = safe.thyroid.checks;
9362
+ const next = a.includes(val) ? a.filter((x) => x !== val) : [...a, val];
9363
+ update({ ...safe, thyroid: { ...safe.thyroid, checks: next } });
9364
+ }
9365
+ };
9366
+ if (!fieldDef) return null;
9367
+ const theme = getThemeConfig("textarea", fieldDef.theme);
9368
+ const wrapperClass = theme?.wrapperClassName ?? "rounded-md overflow-hidden flex flex-col border border-[#D0D0D0]";
9369
+ const labelClass = theme?.labelClassName;
9370
+ const labelContent = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
9371
+ fieldDef.label,
9372
+ fieldDef.required ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-1 text-red-500", children: "*" }) : null
9373
+ ] });
9374
+ const labelEl = theme ? /* @__PURE__ */ jsxRuntime.jsx(Label, { className: labelClass, children: labelContent }) : /* @__PURE__ */ jsxRuntime.jsx(Label, { className: "text-sm font-medium", children: labelContent });
9375
+ const bodyClass = cn(
9376
+ "-mt-1 flex min-w-0 flex-col gap-3 border-t border-[#D0D0D0] bg-white px-3 py-3",
9377
+ disabled && "pointer-events-none opacity-60"
9378
+ );
9379
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("w-full min-w-0", wrapperClass), children: [
9380
+ labelEl,
9381
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: bodyClass, children: [
9382
+ showPain ? /* @__PURE__ */ jsxRuntime.jsx(Panel, { title: "SOCRATES \u2014 pain", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-2 gap-2 md:grid-cols-4", children: [
9383
+ SOCRATES_KEYS.map((k) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1", children: [
9384
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] font-medium uppercase tracking-wide text-muted-foreground", children: k }),
9385
+ /* @__PURE__ */ jsxRuntime.jsx(
9386
+ Input,
9387
+ {
9388
+ className: "h-8 text-xs",
9389
+ value: safe.pain[k],
9390
+ onChange: (e) => setPain(k, e.target.value),
9391
+ disabled
9392
+ }
9393
+ )
9394
+ ] }, k)),
9395
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1", children: [
9396
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] font-medium uppercase tracking-wide text-muted-foreground", children: "Severity 0\u201310" }),
9397
+ /* @__PURE__ */ jsxRuntime.jsx(
9398
+ Input,
9399
+ {
9400
+ type: "number",
9401
+ min: 0,
9402
+ max: 10,
9403
+ className: "h-8 text-xs",
9404
+ value: safe.pain.severity,
9405
+ onChange: (e) => setPain("severity", e.target.value),
9406
+ disabled
9407
+ }
9408
+ )
9409
+ ] })
9410
+ ] }) }) : null,
9411
+ showSwelling ? /* @__PURE__ */ jsxRuntime.jsxs(Panel, { title: "Swelling history", children: [
9412
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 gap-3 text-xs md:grid-cols-3", children: [
9413
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex flex-col gap-1", children: [
9414
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: "Duration" }),
9415
+ /* @__PURE__ */ jsxRuntime.jsx(
9416
+ Input,
9417
+ {
9418
+ className: "h-8 text-xs",
9419
+ value: safe.swelling.duration,
9420
+ onChange: (e) => update({ ...safe, swelling: { ...safe.swelling, duration: e.target.value } }),
9421
+ disabled
9422
+ }
9423
+ )
9424
+ ] }),
9425
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex flex-col gap-1", children: [
9426
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: "Size progression" }),
9427
+ /* @__PURE__ */ jsxRuntime.jsx(
9428
+ Input,
9429
+ {
9430
+ className: "h-8 text-xs",
9431
+ value: safe.swelling.sizeProgression,
9432
+ onChange: (e) => update({ ...safe, swelling: { ...safe.swelling, sizeProgression: e.target.value } }),
9433
+ disabled
9434
+ }
9435
+ )
9436
+ ] }),
9437
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex flex-col gap-1", children: [
9438
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: "Painful / painless" }),
9439
+ /* @__PURE__ */ jsxRuntime.jsx(
9440
+ Input,
9441
+ {
9442
+ className: "h-8 text-xs",
9443
+ value: safe.swelling.painfulPainless,
9444
+ onChange: (e) => update({ ...safe, swelling: { ...safe.swelling, painfulPainless: e.target.value } }),
9445
+ disabled
9446
+ }
9447
+ )
9448
+ ] })
9449
+ ] }),
9450
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-3 flex flex-wrap gap-x-4 gap-y-2", children: SWELLING_OPTS.map((o) => /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex items-center gap-2 text-xs", children: [
9451
+ /* @__PURE__ */ jsxRuntime.jsx(
9452
+ Checkbox,
9453
+ {
9454
+ checked: safe.swelling.checks.includes(o.value),
9455
+ onCheckedChange: () => toggleArr("swelling", o.value),
9456
+ disabled
9457
+ }
9458
+ ),
9459
+ o.label
9460
+ ] }, o.value)) })
9461
+ ] }) : null,
9462
+ showGI ? /* @__PURE__ */ jsxRuntime.jsxs(Panel, { title: "GI history", children: [
9463
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 gap-2 text-xs md:grid-cols-3", children: [
9464
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex flex-col gap-1", children: [
9465
+ "Appetite",
9466
+ /* @__PURE__ */ jsxRuntime.jsx(
9467
+ Input,
9468
+ {
9469
+ className: "h-8 text-xs",
9470
+ value: safe.gi.appetite,
9471
+ onChange: (e) => update({ ...safe, gi: { ...safe.gi, appetite: e.target.value } }),
9472
+ disabled
9473
+ }
9474
+ )
9475
+ ] }),
9476
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex flex-col gap-1", children: [
9477
+ "Weight loss",
9478
+ /* @__PURE__ */ jsxRuntime.jsx(
9479
+ Input,
9480
+ {
9481
+ className: "h-8 text-xs",
9482
+ value: safe.gi.weightLoss,
9483
+ onChange: (e) => update({ ...safe, gi: { ...safe.gi, weightLoss: e.target.value } }),
9484
+ disabled
9485
+ }
9486
+ )
9487
+ ] }),
9488
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex flex-col gap-1", children: [
9489
+ "Bowel habits",
9490
+ /* @__PURE__ */ jsxRuntime.jsx(
9491
+ Input,
9492
+ {
9493
+ className: "h-8 text-xs",
9494
+ value: safe.gi.bowelHabits,
9495
+ onChange: (e) => update({ ...safe, gi: { ...safe.gi, bowelHabits: e.target.value } }),
9496
+ disabled
9497
+ }
9498
+ )
9499
+ ] })
9500
+ ] }),
9501
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-3 flex flex-wrap gap-x-4 gap-y-2", children: GI_OPTS.map((o) => /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex items-center gap-2 text-xs", children: [
9502
+ /* @__PURE__ */ jsxRuntime.jsx(
9503
+ Checkbox,
9504
+ {
9505
+ checked: safe.gi.checks.includes(o.value),
9506
+ onCheckedChange: () => toggleArr("gi", o.value),
9507
+ disabled
9508
+ }
9509
+ ),
9510
+ o.label
9511
+ ] }, o.value)) })
9512
+ ] }) : null,
9513
+ showBreast ? /* @__PURE__ */ jsxRuntime.jsxs(Panel, { title: "Breast history", children: [
9514
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 gap-2 text-xs md:grid-cols-2", children: [
9515
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex flex-col gap-1", children: [
9516
+ "Lump duration",
9517
+ /* @__PURE__ */ jsxRuntime.jsx(
9518
+ Input,
9519
+ {
9520
+ className: "h-8 text-xs",
9521
+ value: safe.breast.lumpDuration,
9522
+ onChange: (e) => update({ ...safe, breast: { ...safe.breast, lumpDuration: e.target.value } }),
9523
+ disabled
9524
+ }
9525
+ )
9526
+ ] }),
9527
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex flex-col gap-1", children: [
9528
+ "Nipple discharge",
9529
+ /* @__PURE__ */ jsxRuntime.jsx(
9530
+ Input,
9531
+ {
9532
+ className: "h-8 text-xs",
9533
+ value: safe.breast.nippleDischarge,
9534
+ onChange: (e) => update({ ...safe, breast: { ...safe.breast, nippleDischarge: e.target.value } }),
9535
+ disabled
9536
+ }
9537
+ )
9538
+ ] })
9539
+ ] }),
9540
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-3 flex flex-wrap gap-x-4 gap-y-2", children: BREAST_OPTS.map((o) => /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex items-center gap-2 text-xs", children: [
9541
+ /* @__PURE__ */ jsxRuntime.jsx(
9542
+ Checkbox,
9543
+ {
9544
+ checked: safe.breast.checks.includes(o.value),
9545
+ onCheckedChange: () => toggleArr("breast", o.value),
9546
+ disabled
9547
+ }
9548
+ ),
9549
+ o.label
9550
+ ] }, o.value)) })
9551
+ ] }) : null,
9552
+ showAno ? /* @__PURE__ */ jsxRuntime.jsx(Panel, { title: "Anorectal history", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-1 gap-2 text-xs md:grid-cols-2", children: ANO_OPTS.map((o) => /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex items-center gap-2", children: [
9553
+ /* @__PURE__ */ jsxRuntime.jsx(
9554
+ Checkbox,
9555
+ {
9556
+ checked: safe.ano.checks.includes(o.value),
9557
+ onCheckedChange: () => toggleArr("ano", o.value),
9558
+ disabled
9559
+ }
9560
+ ),
9561
+ o.label
9562
+ ] }, o.value)) }) }) : null,
9563
+ showThyroid ? /* @__PURE__ */ jsxRuntime.jsxs(Panel, { title: "Thyroid history", children: [
9564
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-1 gap-2 text-xs md:grid-cols-2", children: /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex flex-col gap-1 md:col-span-2", children: [
9565
+ "Swelling duration",
9566
+ /* @__PURE__ */ jsxRuntime.jsx(
9567
+ Input,
9568
+ {
9569
+ className: "h-8 text-xs",
9570
+ value: safe.thyroid.swellingDuration,
9571
+ onChange: (e) => update({ ...safe, thyroid: { ...safe.thyroid, swellingDuration: e.target.value } }),
9572
+ disabled
9573
+ }
9574
+ )
9575
+ ] }) }),
9576
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-3 flex flex-wrap gap-x-4 gap-y-2", children: THYROID_OPTS.map((o) => /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex items-center gap-2 text-xs", children: [
9577
+ /* @__PURE__ */ jsxRuntime.jsx(
9578
+ Checkbox,
9579
+ {
9580
+ checked: safe.thyroid.checks.includes(o.value),
9581
+ onCheckedChange: () => toggleArr("thyroid", o.value),
9582
+ disabled
9583
+ }
9584
+ ),
9585
+ o.label
9586
+ ] }, o.value)) })
9587
+ ] }) : null,
9588
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1", children: [
9589
+ /* @__PURE__ */ jsxRuntime.jsx(Label, { className: "text-xs font-medium text-slate-700", children: "Systemic surgical screening" }),
9590
+ /* @__PURE__ */ jsxRuntime.jsx(
9591
+ Textarea,
9592
+ {
9593
+ className: "min-h-[72px] rounded-md border border-input bg-white text-sm",
9594
+ placeholder: "Fever, weight loss, appetite loss, fatigue, malignancy red flags\u2026",
9595
+ value: safe.systemic,
9596
+ onChange: (e) => update({ ...safe, systemic: e.target.value }),
9597
+ disabled
9598
+ }
9599
+ )
9600
+ ] })
9601
+ ] }),
9602
+ showError ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "px-3 pb-2 text-xs text-red-500", children: error }) : null
9603
+ ] });
9604
+ };
9605
+ var GS_CLINICAL_EXAMINATION_FIELD = "clinical_examination";
9606
+ var GENERAL = [
9607
+ { value: "pallor", label: "Pallor" },
9608
+ { value: "icterus", label: "Icterus" },
9609
+ { value: "cyanosis", label: "Cyanosis" },
9610
+ { value: "clubbing", label: "Clubbing" },
9611
+ { value: "lymphadenopathy", label: "Lymphadenopathy" },
9612
+ { value: "oedema", label: "Oedema" }
9613
+ ];
9614
+ var REGIONS = [
9615
+ { key: "abdomen", label: "Abdomen" },
9616
+ { key: "hernia", label: "Hernia" },
9617
+ { key: "breast", label: "Breast" },
9618
+ { key: "thyroid", label: "Thyroid" },
9619
+ { key: "anorectal", label: "Anorectal" },
9620
+ { key: "limb", label: "Limb / varicose" }
9621
+ ];
9622
+ var ABD_INSP = [
9623
+ { value: "distension", label: "Distension" },
9624
+ { value: "scars", label: "Scars" },
9625
+ { value: "visible_peristalsis", label: "Visible peristalsis" }
9626
+ ];
9627
+ var ABD_PALP = [
9628
+ { value: "tenderness", label: "Tenderness" },
9629
+ { value: "guarding", label: "Guarding" },
9630
+ { value: "rigidity", label: "Rigidity" },
9631
+ { value: "mass", label: "Palpable mass" }
9632
+ ];
9633
+ var ABD_PERC = [
9634
+ { value: "tympany", label: "Tympany" },
9635
+ { value: "shifting_dullness", label: "Shifting dullness" }
9636
+ ];
9637
+ function SubGroup({ title, children }) {
9638
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
9639
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[11px] font-semibold uppercase tracking-wide text-muted-foreground", children: title }),
9640
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-2", children })
9641
+ ] });
9642
+ }
9643
+ function RegionCard({ title, children }) {
9644
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "overflow-hidden rounded-md border border-[#D0D0D0] bg-white", children: [
9645
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-b border-[#D0D0D0] bg-[#FEE8EC]/50 px-3 py-1.5 text-xs font-semibold text-slate-700", children: title }),
9646
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-3", children })
9647
+ ] });
9648
+ }
9649
+ var GsExaminationWidget = ({ fieldId }) => {
9650
+ const { fieldDef, value, setValue, setTouched, error, touched, disabled } = useField(fieldId);
9651
+ const clinicalField = useField(GS_CLINICAL_EXAMINATION_FIELD);
9652
+ const { state } = useForm();
9653
+ const showError = !!error && (touched || state.submitAttempted);
9654
+ const safe = React15.useMemo(() => normalizeGeneralSurgeryExamination(value), [value]);
9655
+ const update = (next) => {
9656
+ setValue(next);
9657
+ setTouched();
9658
+ };
9659
+ const toggleIn = (arr, val) => arr.includes(val) ? arr.filter((x) => x !== val) : [...arr, val];
9660
+ const toggleGeneral = (val) => {
9661
+ update({ ...safe, general: toggleIn(safe.general, val) });
9662
+ };
9663
+ const toggleRegion = (key) => {
9664
+ update({ ...safe, regions: toggleIn(safe.regions, key) });
9665
+ };
9666
+ const toggleAbd = (key, val) => {
9667
+ update({
9668
+ ...safe,
9669
+ abdomen: { ...safe.abdomen, [key]: toggleIn(safe.abdomen[key], val) }
9670
+ });
9671
+ };
9672
+ if (!fieldDef) return null;
9673
+ const has = (r) => safe.regions.includes(r);
9674
+ const theme = getThemeConfig("textarea", fieldDef.theme);
9675
+ const wrapperClass = theme?.wrapperClassName ?? "rounded-md overflow-hidden flex flex-col border border-[#D0D0D0]";
9676
+ const labelClass = theme?.labelClassName;
9677
+ const labelContent = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
9678
+ fieldDef.label,
9679
+ fieldDef.required ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-1 text-red-500", children: "*" }) : null
9680
+ ] });
9681
+ const labelEl = theme ? /* @__PURE__ */ jsxRuntime.jsx(Label, { className: labelClass, children: labelContent }) : /* @__PURE__ */ jsxRuntime.jsx(Label, { className: "text-sm font-medium", children: labelContent });
9682
+ const bodyClass = cn(
9683
+ "-mt-1 flex min-w-0 flex-col gap-3 border-t border-[#D0D0D0] bg-white px-3 py-3",
9684
+ disabled && "pointer-events-none opacity-60"
9685
+ );
9686
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("w-full min-w-0", wrapperClass), children: [
9687
+ labelEl,
9688
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: bodyClass, children: [
9689
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "overflow-hidden rounded-md border border-[#D0D0D0] bg-white", children: [
9690
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-b border-[#D0D0D0] bg-[#FEE8EC]/50 px-3 py-1.5 text-xs font-semibold text-slate-700", children: "General examination" }),
9691
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-3", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-2 gap-2 text-xs md:grid-cols-3 lg:grid-cols-6", children: GENERAL.map((g) => /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex items-center gap-2", children: [
9692
+ /* @__PURE__ */ jsxRuntime.jsx(
9693
+ Checkbox,
9694
+ {
9695
+ checked: safe.general.includes(g.value),
9696
+ onCheckedChange: () => toggleGeneral(g.value),
9697
+ disabled
9698
+ }
9699
+ ),
9700
+ g.label
9701
+ ] }, g.value)) }) })
9702
+ ] }),
9703
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
9704
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mb-2 text-xs font-semibold text-slate-700", children: "Regional examination \u2014 select region(s)" }),
9705
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap gap-2", children: REGIONS.map((r) => {
9706
+ const on = safe.regions.includes(r.key);
9707
+ return /* @__PURE__ */ jsxRuntime.jsx(
9708
+ Button,
9709
+ {
9710
+ type: "button",
9711
+ size: "sm",
9712
+ variant: on ? "default" : "outline",
9713
+ className: "h-7 rounded-full px-3 text-xs",
9714
+ onClick: () => toggleRegion(r.key),
9715
+ disabled,
9716
+ children: r.label
9717
+ },
9718
+ r.key
9719
+ );
9720
+ }) })
9721
+ ] }),
9722
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-3", children: [
9723
+ has("abdomen") ? /* @__PURE__ */ jsxRuntime.jsx(RegionCard, { title: "Abdomen \u2014 inspection \xB7 palpation \xB7 percussion \xB7 auscultation", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-4", children: [
9724
+ /* @__PURE__ */ jsxRuntime.jsx(SubGroup, { title: "Inspection", children: ABD_INSP.map((o) => /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex items-center gap-2 text-xs", children: [
9725
+ /* @__PURE__ */ jsxRuntime.jsx(
9726
+ Checkbox,
9727
+ {
9728
+ checked: safe.abdomen.inspection.includes(o.value),
9729
+ onCheckedChange: () => toggleAbd("inspection", o.value),
9730
+ disabled
9731
+ }
9732
+ ),
9733
+ o.label
9734
+ ] }, o.value)) }),
9735
+ /* @__PURE__ */ jsxRuntime.jsxs(SubGroup, { title: "Palpation", children: [
9736
+ ABD_PALP.map((o) => /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex items-center gap-2 text-xs", children: [
9737
+ /* @__PURE__ */ jsxRuntime.jsx(
9738
+ Checkbox,
9739
+ {
9740
+ checked: safe.abdomen.palpation.includes(o.value),
9741
+ onCheckedChange: () => toggleAbd("palpation", o.value),
9742
+ disabled
9743
+ }
9744
+ ),
9745
+ o.label
9746
+ ] }, o.value)),
9747
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "mt-2 block text-xs", children: [
9748
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "mb-1 block font-medium", children: "Mass size / mobility" }),
9749
+ /* @__PURE__ */ jsxRuntime.jsx(
9750
+ Input,
9751
+ {
9752
+ className: "h-8 text-xs",
9753
+ value: safe.abdomen.massNotes,
9754
+ onChange: (e) => update({ ...safe, abdomen: { ...safe.abdomen, massNotes: e.target.value } }),
9755
+ disabled
9756
+ }
9757
+ )
9758
+ ] })
9759
+ ] }),
9760
+ /* @__PURE__ */ jsxRuntime.jsx(SubGroup, { title: "Percussion", children: ABD_PERC.map((o) => /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex items-center gap-2 text-xs", children: [
9761
+ /* @__PURE__ */ jsxRuntime.jsx(
9762
+ Checkbox,
9763
+ {
9764
+ checked: safe.abdomen.percussion.includes(o.value),
9765
+ onCheckedChange: () => toggleAbd("percussion", o.value),
9766
+ disabled
9767
+ }
9768
+ ),
9769
+ o.label
9770
+ ] }, o.value)) }),
9771
+ /* @__PURE__ */ jsxRuntime.jsxs(SubGroup, { title: "Auscultation", children: [
9772
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "mb-1 block text-xs font-medium", children: "Bowel sounds" }),
9773
+ /* @__PURE__ */ jsxRuntime.jsxs(
9774
+ Select,
9775
+ {
9776
+ value: safe.abdomen.bowelSounds,
9777
+ onValueChange: (val) => update({
9778
+ ...safe,
9779
+ abdomen: {
9780
+ ...safe.abdomen,
9781
+ bowelSounds: val
9782
+ }
9783
+ }),
9784
+ disabled,
9785
+ children: [
9786
+ /* @__PURE__ */ jsxRuntime.jsx(SelectTrigger, { className: "h-8 text-xs", children: /* @__PURE__ */ jsxRuntime.jsx(SelectValue, { placeholder: "Select\u2026" }) }),
9787
+ /* @__PURE__ */ jsxRuntime.jsxs(SelectContent, { children: [
9788
+ /* @__PURE__ */ jsxRuntime.jsx(SelectItem, { value: "none", children: "\u2014" }),
9789
+ /* @__PURE__ */ jsxRuntime.jsx(SelectItem, { value: "normal", children: "Normal" }),
9790
+ /* @__PURE__ */ jsxRuntime.jsx(SelectItem, { value: "up", children: "\u2191" }),
9791
+ /* @__PURE__ */ jsxRuntime.jsx(SelectItem, { value: "down", children: "\u2193" }),
9792
+ /* @__PURE__ */ jsxRuntime.jsx(SelectItem, { value: "absent", children: "Absent" })
9793
+ ] })
9794
+ ]
9795
+ }
9796
+ )
9797
+ ] })
9798
+ ] }) }) : null,
9799
+ has("hernia") ? /* @__PURE__ */ jsxRuntime.jsx(RegionCard, { title: "Hernia exam", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 gap-3 text-xs md:grid-cols-4", children: [
9800
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "block", children: [
9801
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "mb-1 block font-medium", children: "Site" }),
9802
+ /* @__PURE__ */ jsxRuntime.jsx(
9803
+ Input,
9804
+ {
9805
+ className: "h-8 text-xs",
9806
+ value: safe.hernia.site,
9807
+ onChange: (e) => update({ ...safe, hernia: { ...safe.hernia, site: e.target.value } }),
9808
+ disabled
9809
+ }
9810
+ )
9811
+ ] }),
9812
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex items-center gap-2", children: [
9813
+ /* @__PURE__ */ jsxRuntime.jsx(
9814
+ Checkbox,
9815
+ {
9816
+ checked: safe.hernia.reducible,
9817
+ onCheckedChange: (c) => update({ ...safe, hernia: { ...safe.hernia, reducible: c === true } }),
9818
+ disabled
9819
+ }
9820
+ ),
9821
+ "Reducible"
9822
+ ] }),
9823
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex items-center gap-2", children: [
9824
+ /* @__PURE__ */ jsxRuntime.jsx(
9825
+ Checkbox,
9826
+ {
9827
+ checked: safe.hernia.coughImpulse,
9828
+ onCheckedChange: (c) => update({ ...safe, hernia: { ...safe.hernia, coughImpulse: c === true } }),
9829
+ disabled
9830
+ }
9831
+ ),
9832
+ "Cough impulse"
9833
+ ] }),
9834
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex items-center gap-2", children: [
9835
+ /* @__PURE__ */ jsxRuntime.jsx(
9836
+ Checkbox,
9837
+ {
9838
+ checked: safe.hernia.tenderness,
9839
+ onCheckedChange: (c) => update({ ...safe, hernia: { ...safe.hernia, tenderness: c === true } }),
9840
+ disabled
9841
+ }
9842
+ ),
9843
+ "Tenderness"
9844
+ ] })
9845
+ ] }) }) : null,
9846
+ has("breast") ? /* @__PURE__ */ jsxRuntime.jsx(RegionCard, { title: "Breast exam", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 gap-3 text-xs md:grid-cols-4", children: [
9847
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "block", children: [
9848
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "mb-1 block font-medium", children: "Lump size (cm)" }),
9849
+ /* @__PURE__ */ jsxRuntime.jsx(
9850
+ Input,
9851
+ {
9852
+ className: "h-8 text-xs",
9853
+ value: safe.breast.lumpSizeCm,
9854
+ onChange: (e) => update({ ...safe, breast: { ...safe.breast, lumpSizeCm: e.target.value } }),
9855
+ disabled
9856
+ }
9857
+ )
9858
+ ] }),
9859
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex items-center gap-2", children: [
9860
+ /* @__PURE__ */ jsxRuntime.jsx(
9861
+ Checkbox,
9862
+ {
9863
+ checked: safe.breast.mobile,
9864
+ onCheckedChange: (c) => update({ ...safe, breast: { ...safe.breast, mobile: c === true } }),
9865
+ disabled
9866
+ }
9867
+ ),
9868
+ "Mobile"
9869
+ ] }),
9870
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex items-center gap-2", children: [
9871
+ /* @__PURE__ */ jsxRuntime.jsx(
9872
+ Checkbox,
9873
+ {
9874
+ checked: safe.breast.skinInvolvement,
9875
+ onCheckedChange: (c) => update({ ...safe, breast: { ...safe.breast, skinInvolvement: c === true } }),
9876
+ disabled
9877
+ }
9878
+ ),
9879
+ "Skin involvement"
9880
+ ] }),
9881
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex items-center gap-2", children: [
9882
+ /* @__PURE__ */ jsxRuntime.jsx(
9883
+ Checkbox,
9884
+ {
9885
+ checked: safe.breast.axillaryNodes,
9886
+ onCheckedChange: (c) => update({ ...safe, breast: { ...safe.breast, axillaryNodes: c === true } }),
9887
+ disabled
9888
+ }
9889
+ ),
9890
+ "Axillary nodes"
9891
+ ] })
9892
+ ] }) }) : null,
9893
+ has("thyroid") ? /* @__PURE__ */ jsxRuntime.jsx(RegionCard, { title: "Thyroid exam", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 gap-3 text-xs md:grid-cols-4", children: [
9894
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "block", children: [
9895
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "mb-1 block font-medium", children: "Size" }),
9896
+ /* @__PURE__ */ jsxRuntime.jsx(
9897
+ Input,
9898
+ {
9899
+ className: "h-8 text-xs",
9900
+ value: safe.thyroid.size,
9901
+ onChange: (e) => update({ ...safe, thyroid: { ...safe.thyroid, size: e.target.value } }),
9902
+ disabled
9903
+ }
9904
+ )
9905
+ ] }),
9906
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex items-center gap-2", children: [
9907
+ /* @__PURE__ */ jsxRuntime.jsx(
9908
+ Checkbox,
9909
+ {
9910
+ checked: safe.thyroid.mobileDeglutition,
9911
+ onCheckedChange: (c) => update({ ...safe, thyroid: { ...safe.thyroid, mobileDeglutition: c === true } }),
9912
+ disabled
9913
+ }
9914
+ ),
9915
+ "Mobile with deglutition"
9916
+ ] }),
9917
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex items-center gap-2", children: [
9918
+ /* @__PURE__ */ jsxRuntime.jsx(
9919
+ Checkbox,
9920
+ {
9921
+ checked: safe.thyroid.nodules,
9922
+ onCheckedChange: (c) => update({ ...safe, thyroid: { ...safe.thyroid, nodules: c === true } }),
9923
+ disabled
9924
+ }
9925
+ ),
9926
+ "Nodules"
9927
+ ] }),
9928
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex items-center gap-2", children: [
9929
+ /* @__PURE__ */ jsxRuntime.jsx(
9930
+ Checkbox,
9931
+ {
9932
+ checked: safe.thyroid.cervicalNodes,
9933
+ onCheckedChange: (c) => update({ ...safe, thyroid: { ...safe.thyroid, cervicalNodes: c === true } }),
9934
+ disabled
9935
+ }
9936
+ ),
9937
+ "Cervical lymph nodes"
9938
+ ] })
9939
+ ] }) }) : null,
9940
+ has("anorectal") ? /* @__PURE__ */ jsxRuntime.jsx(RegionCard, { title: "Anorectal exam", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 gap-3 text-xs md:grid-cols-3", children: [
9941
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "block md:col-span-3", children: [
9942
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "mb-1 block font-medium", children: "Inspection findings" }),
9943
+ /* @__PURE__ */ jsxRuntime.jsx(
9944
+ Input,
9945
+ {
9946
+ className: "h-8 text-xs",
9947
+ value: safe.anorectal.inspection,
9948
+ onChange: (e) => update({ ...safe, anorectal: { ...safe.anorectal, inspection: e.target.value } }),
9949
+ disabled
9950
+ }
9951
+ )
9952
+ ] }),
9953
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex items-center gap-2", children: [
9954
+ /* @__PURE__ */ jsxRuntime.jsx(
9955
+ Checkbox,
9956
+ {
9957
+ checked: safe.anorectal.dreDone,
9958
+ onCheckedChange: (c) => update({ ...safe, anorectal: { ...safe.anorectal, dreDone: c === true } }),
9959
+ disabled
9960
+ }
9961
+ ),
9962
+ "DRE done"
9963
+ ] }),
9964
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex items-center gap-2", children: [
9965
+ /* @__PURE__ */ jsxRuntime.jsx(
9966
+ Checkbox,
9967
+ {
9968
+ checked: safe.anorectal.proctoscopyDone,
9969
+ onCheckedChange: (c) => update({ ...safe, anorectal: { ...safe.anorectal, proctoscopyDone: c === true } }),
9970
+ disabled
9971
+ }
9972
+ ),
9973
+ "Proctoscopy done"
9974
+ ] }),
9975
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "md:col-span-3", children: [
9976
+ /* @__PURE__ */ jsxRuntime.jsx(Label, { className: "text-xs font-semibold", children: "DRE / proctoscopy notes" }),
9977
+ /* @__PURE__ */ jsxRuntime.jsx(
9978
+ Textarea,
9979
+ {
9980
+ className: "mt-1 min-h-[64px] text-sm",
9981
+ placeholder: "Sphincter tone, masses, prostate, bleeding\u2026",
9982
+ value: safe.anorectal.notes,
9983
+ onChange: (e) => update({ ...safe, anorectal: { ...safe.anorectal, notes: e.target.value } }),
9984
+ disabled
9985
+ }
9986
+ )
9987
+ ] })
9988
+ ] }) }) : null,
9989
+ has("limb") ? /* @__PURE__ */ jsxRuntime.jsx(RegionCard, { title: "Limb / varicose veins", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap gap-x-4 gap-y-2 text-xs", children: [
9990
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex items-center gap-2", children: [
9991
+ /* @__PURE__ */ jsxRuntime.jsx(
9992
+ Checkbox,
9993
+ {
9994
+ checked: safe.limb.dilatedVeins,
9995
+ onCheckedChange: (c) => update({ ...safe, limb: { ...safe.limb, dilatedVeins: c === true } }),
9996
+ disabled
9997
+ }
9998
+ ),
9999
+ "Dilated veins"
10000
+ ] }),
10001
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex items-center gap-2", children: [
10002
+ /* @__PURE__ */ jsxRuntime.jsx(
10003
+ Checkbox,
10004
+ {
10005
+ checked: safe.limb.ulcer,
10006
+ onCheckedChange: (c) => update({ ...safe, limb: { ...safe.limb, ulcer: c === true } }),
10007
+ disabled
10008
+ }
10009
+ ),
10010
+ "Ulcer"
10011
+ ] }),
10012
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex items-center gap-2", children: [
10013
+ /* @__PURE__ */ jsxRuntime.jsx(
10014
+ Checkbox,
10015
+ {
10016
+ checked: safe.limb.oedema,
10017
+ onCheckedChange: (c) => update({ ...safe, limb: { ...safe.limb, oedema: c === true } }),
10018
+ disabled
10019
+ }
10020
+ ),
10021
+ "Oedema"
10022
+ ] })
10023
+ ] }) }) : null
10024
+ ] }),
10025
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1", children: [
10026
+ /* @__PURE__ */ jsxRuntime.jsx(Label, { className: "text-xs font-semibold text-slate-700", children: clinicalField.fieldDef?.label ?? "Clinical examination" }),
10027
+ /* @__PURE__ */ jsxRuntime.jsx(
10028
+ Textarea,
10029
+ {
10030
+ className: "min-h-[88px] rounded-md border border-input bg-white text-sm",
10031
+ value: typeof clinicalField.value === "string" ? clinicalField.value : clinicalField.value == null ? "" : String(clinicalField.value),
10032
+ onChange: (e) => {
10033
+ clinicalField.setValue(e.target.value);
10034
+ clinicalField.setTouched();
10035
+ },
10036
+ disabled: disabled || clinicalField.disabled
10037
+ }
10038
+ )
10039
+ ] })
10040
+ ] }),
10041
+ showError ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "px-3 pb-2 text-xs text-red-500", children: error }) : null
10042
+ ] });
10043
+ };
10044
+ var CHIEF_CHIPS_FIELD2 = "chief_complaints_chips";
10045
+ var GS_EXAMINATION_FIELD = "gs_examination";
10046
+ function chipList2(state) {
10047
+ const raw = state.values[CHIEF_CHIPS_FIELD2];
10048
+ return Array.isArray(raw) ? raw.filter((x) => typeof x === "string") : [];
10049
+ }
10050
+ function regionList(state) {
10051
+ const raw = state.values[GS_EXAMINATION_FIELD];
10052
+ const ex = normalizeGeneralSurgeryExamination(raw);
10053
+ return ex.regions;
10054
+ }
10055
+ var GsGradingWidget = ({ fieldId }) => {
10056
+ const { fieldDef, value, setValue, setTouched, error, touched, disabled } = useField(fieldId);
10057
+ const { state } = useForm();
10058
+ const showError = !!error && (touched || state.submitAttempted);
10059
+ const safe = React15.useMemo(() => normalizeGeneralSurgeryGrading(value), [value]);
10060
+ const chips = React15.useMemo(() => chipList2(state), [state]);
10061
+ const regions = React15.useMemo(() => regionList(state), [state]);
10062
+ const visibleRows = React15.useMemo(() => {
10063
+ return ALL_GS_CONDITIONS.filter(
10064
+ (c) => gsGradingRowVisible(c, chips, regions, safe[c] ?? 0)
10065
+ );
10066
+ }, [chips, regions, safe]);
10067
+ const update = (next) => {
10068
+ setValue(next);
10069
+ setTouched();
10070
+ };
10071
+ const setGrade = (cond, gradeStr) => {
10072
+ const n = Math.min(5, Math.max(0, Math.round(Number(gradeStr)) || 0));
10073
+ update({ ...safe, [cond]: n });
10074
+ };
10075
+ if (!fieldDef) return null;
10076
+ const theme = getThemeConfig("textarea", fieldDef.theme);
10077
+ const wrapperClass = theme?.wrapperClassName ?? "rounded-md overflow-hidden flex flex-col border border-[#D0D0D0]";
10078
+ const labelClass = theme?.labelClassName;
10079
+ const labelContent = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
10080
+ fieldDef.label,
10081
+ fieldDef.required ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-1 text-red-500", children: "*" }) : null
10082
+ ] });
10083
+ const labelEl = theme ? /* @__PURE__ */ jsxRuntime.jsx(Label, { className: labelClass, children: labelContent }) : /* @__PURE__ */ jsxRuntime.jsx(Label, { className: "text-sm font-medium", children: labelContent });
10084
+ const bodyClass = cn(
10085
+ "-mt-1 flex min-w-0 flex-col gap-3 border-t border-[#D0D0D0] bg-white px-3 py-3",
10086
+ disabled && "pointer-events-none opacity-60"
10087
+ );
10088
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("w-full min-w-0", wrapperClass), children: [
10089
+ labelEl,
10090
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: bodyClass, children: visibleRows.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-md border border-dashed border-[#D0D0D0] bg-white p-6 text-center text-xs text-muted-foreground", children: "No conditions to grade yet. Select a chief complaint category or pick an examination region." }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-x-auto rounded-md border border-[#D0D0D0]", children: /* @__PURE__ */ jsxRuntime.jsxs("table", { className: "w-full min-w-[520px] border-collapse text-xs", children: [
10091
+ /* @__PURE__ */ jsxRuntime.jsx("thead", { children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { className: "border-b border-[#D0D0D0] bg-[#FEE8EC]/50", children: [
10092
+ /* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-3 py-2 text-left font-semibold text-slate-700", children: "Condition" }),
10093
+ /* @__PURE__ */ jsxRuntime.jsx("th", { className: "w-24 px-2 py-2 font-semibold text-slate-700", children: "Grade" }),
10094
+ /* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-3 py-2 text-left font-semibold text-slate-700", children: "Description" })
10095
+ ] }) }),
10096
+ /* @__PURE__ */ jsxRuntime.jsx("tbody", { className: "bg-white", children: visibleRows.map((c) => {
10097
+ const g = safe[c] ?? 0;
10098
+ const desc = GS_GRADE_DESCRIPTIONS[c][g] ?? "\u2014";
10099
+ return /* @__PURE__ */ jsxRuntime.jsxs("tr", { className: "border-b border-[#D0D0D0]/80 last:border-0", children: [
10100
+ /* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-3 py-2 font-medium", children: GS_CONDITION_LABELS[c] }),
10101
+ /* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-2 py-1.5 align-middle", children: /* @__PURE__ */ jsxRuntime.jsxs(
10102
+ Select,
10103
+ {
10104
+ value: String(g),
10105
+ onValueChange: (v) => setGrade(c, v),
10106
+ disabled,
10107
+ children: [
10108
+ /* @__PURE__ */ jsxRuntime.jsx(SelectTrigger, { className: "h-8 text-xs", children: /* @__PURE__ */ jsxRuntime.jsx(SelectValue, {}) }),
10109
+ /* @__PURE__ */ jsxRuntime.jsx(SelectContent, { children: [0, 1, 2, 3, 4, 5].map((n) => /* @__PURE__ */ jsxRuntime.jsx(SelectItem, { value: String(n), children: n === 0 ? "\u2014" : String(n) }, n)) })
10110
+ ]
10111
+ }
10112
+ ) }),
10113
+ /* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-3 py-2 text-muted-foreground", children: desc })
10114
+ ] }, c);
10115
+ }) })
10116
+ ] }) }) }),
10117
+ showError ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "px-3 pb-2 text-xs text-red-500", children: error }) : null
10118
+ ] });
10119
+ };
10120
+ function isFlagSelected(selected, optValue) {
10121
+ return selected.some((v) => v === optValue || String(v) === String(optValue));
10122
+ }
10123
+ var PainScaleFlagsWidget = ({ fieldId }) => {
10124
+ const { fieldDef, value, setValue, setTouched, error, touched, disabled } = useField(fieldId);
10125
+ const { state } = useForm();
10126
+ const showError = !!error && (touched || state.submitAttempted);
10127
+ if (!fieldDef || fieldDef.type !== "pain_scale_flags") return null;
10128
+ const def = fieldDef;
10129
+ const min = def.min ?? 0;
10130
+ const max = def.max ?? 10;
10131
+ const step = def.step ?? 1;
10132
+ const flagOptions = def.options ?? [];
10133
+ const safe = React15.useMemo(
10134
+ () => normalizePainScaleFlags(value, { min, max }),
10135
+ [value, min, max]
10136
+ );
10137
+ const theme = getThemeConfig("textarea", def.theme);
10138
+ const wrapperClass = theme?.wrapperClassName ?? "space-y-2";
10139
+ const labelClass = theme?.labelClassName;
10140
+ const update = (next) => {
10141
+ setValue(normalizePainScaleFlags(next, { min, max }));
10142
+ setTouched();
10143
+ };
10144
+ const toggleFlag = (optValue) => {
10145
+ const sel = safe.flags;
10146
+ const isSelected = isFlagSelected(sel, optValue);
10147
+ const nextFlags = isSelected ? sel.filter((v) => v !== optValue && String(v) !== String(optValue)) : [...sel, String(optValue)];
10148
+ update({ pain: safe.pain, flags: nextFlags });
10149
+ };
10150
+ const labelContent = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
10151
+ def.label,
10152
+ " ",
10153
+ def.required && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-red-500", children: "*" })
10154
+ ] });
10155
+ const labelEl = theme ? /* @__PURE__ */ jsxRuntime.jsx(Label, { className: labelClass, children: labelContent }) : /* @__PURE__ */ jsxRuntime.jsx(Label, { children: labelContent });
10156
+ const bodyClass = cn(
10157
+ "-mt-1 flex min-w-0 flex-col border-t border-[#D0D0D0] bg-white px-3 py-3",
10158
+ disabled && "pointer-events-none opacity-60"
10159
+ );
10160
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn(wrapperClass, "h-full min-h-0 flex flex-col"), children: [
10161
+ labelEl,
10162
+ def.description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground", children: def.description }),
10163
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn(bodyClass, "min-h-0 flex-1"), children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 space-y-3", children: [
10164
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
10165
+ /* @__PURE__ */ jsxRuntime.jsxs(Label, { className: "text-sm font-medium text-slate-700", children: [
10166
+ "Pain score (VAS)",
10167
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "ml-2 font-normal tabular-nums text-muted-foreground", children: [
10168
+ safe.pain,
10169
+ "/",
10170
+ max
10171
+ ] })
10172
+ ] }),
10173
+ /* @__PURE__ */ jsxRuntime.jsx(
10174
+ Slider,
10175
+ {
10176
+ className: cn("py-1", showError && "rounded opacity-90 ring-1 ring-red-500"),
10177
+ disabled,
10178
+ min,
10179
+ max,
10180
+ step,
10181
+ value: [safe.pain],
10182
+ onValueChange: (v) => {
10183
+ const n = v[0] ?? min;
10184
+ update({ pain: n, flags: safe.flags });
10185
+ }
10186
+ }
10187
+ )
10188
+ ] }),
10189
+ flagOptions.length > 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 space-y-1.5", children: [
10190
+ /* @__PURE__ */ jsxRuntime.jsx(Label, { className: "text-sm font-medium text-slate-700", children: "Triage flags" }),
10191
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap gap-x-4 gap-y-2", children: flagOptions.map((opt) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
10192
+ /* @__PURE__ */ jsxRuntime.jsx(
10193
+ Checkbox,
10194
+ {
10195
+ id: `${fieldId}-flag-${String(opt.value)}`,
10196
+ checked: isFlagSelected(safe.flags, opt.value),
10197
+ onCheckedChange: () => toggleFlag(opt.value),
10198
+ disabled
10199
+ }
10200
+ ),
10201
+ /* @__PURE__ */ jsxRuntime.jsx(
10202
+ Label,
10203
+ {
10204
+ htmlFor: `${fieldId}-flag-${String(opt.value)}`,
10205
+ className: "cursor-pointer text-sm font-normal leading-none",
10206
+ children: opt.label
10207
+ }
10208
+ )
10209
+ ] }, String(opt.value))) })
10210
+ ] }) : null
10211
+ ] }) }),
10212
+ showError && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-red-500", children: error })
10213
+ ] });
10214
+ };
10215
+ var FieldRenderer = ({ fieldId }) => {
10216
+ const { fieldDef, visible } = useField(fieldId);
10217
+ if (!visible || !fieldDef) {
10218
+ return null;
10219
+ }
10220
+ return renderWidget(fieldId, fieldDef);
10221
+ };
10222
+ function renderWidget(fieldId, fieldDef) {
10223
+ switch (fieldDef.type) {
10224
+ case "text":
10225
+ case "number":
10226
+ return /* @__PURE__ */ jsxRuntime.jsx(TextWidget, { fieldId });
10227
+ case "slider":
10228
+ return /* @__PURE__ */ jsxRuntime.jsx(SliderWidget, { fieldId });
10229
+ case "textarea":
10230
+ if (fieldMetaRequestsMarMedicationOrdersButton(fieldDef.meta)) {
10231
+ return /* @__PURE__ */ jsxRuntime.jsx(MarMedicationOrdersWidget, { fieldId });
10232
+ }
10233
+ return /* @__PURE__ */ jsxRuntime.jsx(TextWidget, { fieldId });
10234
+ case "richtext":
10235
+ return /* @__PURE__ */ jsxRuntime.jsx(RichTextWidget, { fieldId });
10236
+ case "date":
10237
+ return /* @__PURE__ */ jsxRuntime.jsx(DateWidget, { fieldId });
10238
+ case "datetime":
10239
+ return /* @__PURE__ */ jsxRuntime.jsx(DateTimeWidget, { fieldId });
10240
+ case "select":
10241
+ return /* @__PURE__ */ jsxRuntime.jsx(SelectWidget, { fieldId });
10242
+ case "radio":
10243
+ return /* @__PURE__ */ jsxRuntime.jsx(RadioWidget, { fieldId });
10244
+ case "checkbox":
10245
+ return /* @__PURE__ */ jsxRuntime.jsx(CheckboxWidget, { fieldId });
10246
+ case "multiselect":
10247
+ return /* @__PURE__ */ jsxRuntime.jsx(MultiSelectWidget, { fieldId });
10248
+ case "repeatable":
10249
+ return /* @__PURE__ */ jsxRuntime.jsx(RepeatableWidget, { fieldId });
10250
+ case "image_upload":
10251
+ return /* @__PURE__ */ jsxRuntime.jsx(ImageUploadWidget, { fieldId });
10252
+ case "media_upload":
10253
+ return /* @__PURE__ */ jsxRuntime.jsx(MediaUploadWidget, { fieldId });
10254
+ case "signature":
10255
+ return /* @__PURE__ */ jsxRuntime.jsx(SignatureUploadWidget, { fieldId });
10256
+ case "editable_table":
10257
+ return /* @__PURE__ */ jsxRuntime.jsx(EditableTableWidget, { fieldId });
10258
+ case "medications":
10259
+ return /* @__PURE__ */ jsxRuntime.jsx(AddMedicationWidget, { fieldId });
10260
+ case "discharge_medication_orders":
10261
+ return /* @__PURE__ */ jsxRuntime.jsx(DischargeMedicationOrdersWidget, { fieldId });
10262
+ case "investigations":
10263
+ return /* @__PURE__ */ jsxRuntime.jsx(AddInvestigationWidget, { fieldId });
10264
+ case "procedures":
10265
+ return /* @__PURE__ */ jsxRuntime.jsx(AddProcedureWidget, { fieldId });
10266
+ case "differential_diagnosis":
10267
+ return /* @__PURE__ */ jsxRuntime.jsx(DifferentialDiagnosisWidget, { fieldId });
10268
+ case "vitals":
10269
+ return /* @__PURE__ */ jsxRuntime.jsx(VitalsWidget, { fieldId });
10270
+ case "hidden_vitals":
10271
+ return /* @__PURE__ */ jsxRuntime.jsx(HiddenVitalsWidget, { fieldId });
10272
+ case "referral":
10273
+ return /* @__PURE__ */ jsxRuntime.jsx(ReferralWidget, { fieldId });
10274
+ case "followup":
10275
+ return /* @__PURE__ */ jsxRuntime.jsx(FollowupWidget, { fieldId });
10276
+ case "smart_textarea":
10277
+ return /* @__PURE__ */ jsxRuntime.jsx(SmartTextareaWidget, { fieldId });
10278
+ case "diagnosis_textarea":
10279
+ return /* @__PURE__ */ jsxRuntime.jsx(DiagnosisTextareaWidget, { fieldId });
10280
+ case "obstetric_history":
10281
+ return /* @__PURE__ */ jsxRuntime.jsx(ObstetricHistoryWidget, { fieldId });
10282
+ case "eye_prescription":
10283
+ return /* @__PURE__ */ jsxRuntime.jsx(OphthalmologyWidget, { fieldId });
10284
+ case "ophthal_diagnosis":
10285
+ return /* @__PURE__ */ jsxRuntime.jsx(OphthalDiagnosisWidget, { fieldId });
10286
+ case "orthopedic_exam":
10287
+ return /* @__PURE__ */ jsxRuntime.jsx(OrthopedicExamWidget, { fieldId });
10288
+ case "general_surgery_smart_history":
10289
+ return /* @__PURE__ */ jsxRuntime.jsx(GsSmartHistoryWidget, { fieldId });
10290
+ case "general_surgery_examination":
10291
+ return /* @__PURE__ */ jsxRuntime.jsx(GsExaminationWidget, { fieldId });
10292
+ case "general_surgery_grading":
10293
+ return /* @__PURE__ */ jsxRuntime.jsx(GsGradingWidget, { fieldId });
10294
+ case "pain_scale_flags":
10295
+ return /* @__PURE__ */ jsxRuntime.jsx(PainScaleFlagsWidget, { fieldId });
10296
+ case "toggle": {
10297
+ const { value, setValue, setTouched, disabled } = useField(fieldId);
10298
+ const store = useFormStore();
10299
+ const excludes = fieldDef.excludes ?? [];
10300
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
10301
+ /* @__PURE__ */ jsxRuntime.jsx(
10302
+ Switch,
10303
+ {
10304
+ checked: value === true,
10305
+ disabled,
10306
+ onCheckedChange: (checked) => {
10307
+ setValue(checked);
10308
+ setTouched();
10309
+ if (checked) excludes.forEach((id) => store.setValue(id, false));
10310
+ }
10311
+ }
10312
+ ),
10313
+ /* @__PURE__ */ jsxRuntime.jsx(Label, { className: "text-sm font-medium leading-none cursor-pointer select-none", children: fieldDef.label })
10314
+ ] });
10315
+ }
10316
+ case "suggestion_textarea":
10317
+ case "complaint_chips":
10318
+ return /* @__PURE__ */ jsxRuntime.jsx(SuggestionTextareaWidget, { fieldId });
10319
+ case "lens_assessment":
10320
+ return /* @__PURE__ */ jsxRuntime.jsx(LensAssessmentWidget, { fieldId });
10321
+ case "functional_impairment_score":
10322
+ return /* @__PURE__ */ jsxRuntime.jsx(FunctionalImpairmentScoreWidget, { fieldId });
10323
+ case "biometry_iol_workup":
10324
+ return /* @__PURE__ */ jsxRuntime.jsx(BiometryIolWorkupWidget, { fieldId });
10325
+ case "surgical_risk_flags":
10326
+ return /* @__PURE__ */ jsxRuntime.jsx(SurgicalRiskFlagsWidget, { fieldId });
10327
+ case "static_text": {
10328
+ const def = fieldDef;
10329
+ const size = def.size ?? "regular";
10330
+ const labelClass = size === "large" ? "text-base" : "text-sm";
10331
+ const descClass = size === "large" ? "text-sm" : "text-xs";
10332
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `${labelClass} text-muted-foreground`, children: [
10333
+ def.label,
10334
+ def.description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: `mt-1 ${descClass} opacity-90`, children: def.description })
10335
+ ] });
10336
+ }
10337
+ default:
10338
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-red-500", children: [
10339
+ "Unknown field type: ",
10340
+ fieldDef.type
10341
+ ] });
10342
+ }
10343
+ }
10344
+ var Section = ({ title, children }) => {
10345
+ const [expanded, setExpanded] = React15.useState(true);
10346
+ const handleToggle = () => setExpanded((prev) => !prev);
10347
+ const contentClassName = cn(
10348
+ "overflow-hidden transition-[height] duration-200 ease-in-out",
10349
+ !expanded && "hidden"
10350
+ );
10351
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-6 border rounded-lg bg-white shadow-sm overflow-hidden", children: [
10352
+ /* @__PURE__ */ jsxRuntime.jsxs(
10353
+ "button",
10354
+ {
10355
+ type: "button",
10356
+ onClick: handleToggle,
10357
+ className: "w-full flex items-center justify-between gap-2 p-4 text-left border-b hover:bg-gray-50/80 transition-colors",
10358
+ children: [
10359
+ /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-lg font-medium", children: title }),
10360
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-shrink-0 text-muted-foreground", "aria-hidden": true, children: expanded ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { className: "h-5 w-5" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronRight, { className: "h-5 w-5" }) })
10361
+ ]
10362
+ }
10363
+ ),
10364
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: contentClassName, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-4 pt-4 space-y-4 border-t-0", children }) })
10365
+ ] });
10366
+ };
10367
+ var ColumnLayout = ({
10368
+ columns,
10369
+ label,
10370
+ children
10371
+ }) => {
10372
+ const gridCols = Math.max(1, Math.min(columns, 12));
10373
+ const gridClass = `grid gap-4 w-full`;
10374
+ const style = {
10375
+ gridTemplateColumns: `repeat(${gridCols}, minmax(0, 1fr))`
10376
+ };
10377
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-6", children: [
10378
+ label != null && label !== "" && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mb-2 text-sm font-medium text-gray-700", children: label }),
10379
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: gridClass, style, children })
10380
+ ] });
10381
+ };
10382
+ var DynamicForm = () => {
10383
+ const store = useFormStore();
10384
+ const schema = store.getSchema();
10385
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-6", children: [
10386
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mb-4", children: /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-2xl font-bold", children: schema.title }) }),
10387
+ schema.layout.map((node) => {
10388
+ if (node.type === "section") {
10389
+ return /* @__PURE__ */ jsxRuntime.jsx(Section, { title: node.title, children: node.children.map(
10390
+ (child, index) => typeof child === "string" ? /* @__PURE__ */ jsxRuntime.jsx(FieldRenderer, { fieldId: child }, child) : child.type === "column_layout" ? /* @__PURE__ */ jsxRuntime.jsx(
10391
+ ColumnLayout,
10392
+ {
10393
+ columns: child.columns,
10394
+ label: child.label,
10395
+ children: child.children.map((fieldId) => /* @__PURE__ */ jsxRuntime.jsx(FieldRenderer, { fieldId }, fieldId))
10396
+ },
9119
10397
  child.id
9120
10398
  ) : /* @__PURE__ */ jsxRuntime.jsx(React15__namespace.default.Fragment, {}, child.id ?? index)
9121
10399
  ) }, node.id);
@@ -9250,14 +10528,24 @@ var SmartForm = ({
9250
10528
  if (position !== "left") return null;
9251
10529
  return /* @__PURE__ */ jsxRuntime.jsx(FieldRenderer, { fieldId }, fieldId);
9252
10530
  }) }),
9253
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "col-span-2 grid grid-cols-2 gap-x-2 space-y-2", children: fieldIds.map((fieldId) => {
10531
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "col-span-2 grid grid-cols-2 gap-2", children: fieldIds.map((fieldId) => {
9254
10532
  const fieldDef = store.getFieldDef(fieldId);
9255
10533
  if (!fieldDef) return null;
9256
10534
  const position = fieldDef.position ?? "center";
9257
10535
  if (position !== "center") return null;
9258
10536
  const colSpanRaw = fieldDef.colSpan ?? 1;
9259
10537
  const colSpan = colSpanRaw === 2 ? 2 : 1;
9260
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: colSpan === 2 ? "col-span-2" : "col-span-1", children: /* @__PURE__ */ jsxRuntime.jsx(FieldRenderer, { fieldId }) }, fieldId);
10538
+ return /* @__PURE__ */ jsxRuntime.jsx(
10539
+ "div",
10540
+ {
10541
+ className: cn(
10542
+ "min-h-0 flex flex-col",
10543
+ colSpan === 2 ? "col-span-2" : "col-span-1 h-full"
10544
+ ),
10545
+ children: /* @__PURE__ */ jsxRuntime.jsx(FieldRenderer, { fieldId })
10546
+ },
10547
+ fieldId
10548
+ );
9261
10549
  }) }),
9262
10550
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "col-span-1 flex flex-col gap-2", children: fieldIds.map((fieldId) => {
9263
10551
  const fieldDef = store.getFieldDef(fieldId);
@@ -9705,11 +10993,17 @@ var ReadOnlyDischargeMedicationOrders = ({ fieldDef, value }) => {
9705
10993
  }) })
9706
10994
  ] });
9707
10995
  };
9708
- var ReadOnlyFieldRenderer = ({ fieldDef, value }) => {
10996
+ var ReadOnlyFieldRenderer = ({
10997
+ fieldDef,
10998
+ value,
10999
+ allValues,
11000
+ resolveFieldDef
11001
+ }) => {
9709
11002
  if (!fieldDef) return null;
9710
11003
  switch (fieldDef.type) {
9711
11004
  case "text":
9712
11005
  case "number":
11006
+ case "slider":
9713
11007
  case "textarea":
9714
11008
  case "richtext":
9715
11009
  return /* @__PURE__ */ jsxRuntime.jsx(ReadOnlyText, { fieldDef, value });
@@ -9747,8 +11041,30 @@ var ReadOnlyFieldRenderer = ({ fieldDef, value }) => {
9747
11041
  ] });
9748
11042
  }
9749
11043
  case "suggestion_textarea":
9750
- case "complaint_chips":
9751
- return /* @__PURE__ */ jsxRuntime.jsx(ReadOnlyText, { fieldDef, value });
11044
+ case "complaint_chips": {
11045
+ const embeddedIds = fieldDef.meta && Array.isArray(fieldDef.meta.embeddedFieldIds) ? fieldDef.meta.embeddedFieldIds.filter((id) => typeof id === "string" && id.trim().length > 0).map((id) => id.trim()) : [];
11046
+ const showEmbedded = embeddedIds.length > 0 && resolveFieldDef && allValues && typeof allValues === "object";
11047
+ if (!showEmbedded) {
11048
+ return /* @__PURE__ */ jsxRuntime.jsx(ReadOnlyText, { fieldDef, value });
11049
+ }
11050
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-3", children: [
11051
+ /* @__PURE__ */ jsxRuntime.jsx(ReadOnlyText, { fieldDef, value }),
11052
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid gap-3 border-t border-muted-foreground/20 pt-3 sm:grid-cols-3", children: embeddedIds.map((id) => {
11053
+ const fd = resolveFieldDef(id);
11054
+ if (!fd) return null;
11055
+ return /* @__PURE__ */ jsxRuntime.jsx(
11056
+ ReadOnlyFieldRenderer,
11057
+ {
11058
+ fieldDef: fd,
11059
+ value: allValues[id],
11060
+ allValues,
11061
+ resolveFieldDef
11062
+ },
11063
+ id
11064
+ );
11065
+ }) })
11066
+ ] });
11067
+ }
9752
11068
  case "lens_assessment": {
9753
11069
  const v = value && typeof value === "object" && !Array.isArray(value) ? value : null;
9754
11070
  const notes = typeof v?.notes === "string" ? v.notes : "";
@@ -9824,6 +11140,44 @@ var ReadOnlyFieldRenderer = ({ fieldDef, value }) => {
9824
11140
  const lines = [`Right eye (OD): ${od}`, `Left eye (OS): ${os}`].join("\n");
9825
11141
  return /* @__PURE__ */ jsxRuntime.jsx(ReadOnlyText, { fieldDef, value: lines });
9826
11142
  }
11143
+ case "pain_scale_flags": {
11144
+ const def = fieldDef;
11145
+ const min = def.min ?? 0;
11146
+ const max = def.max ?? 10;
11147
+ const safe = normalizePainScaleFlags(value, { min, max });
11148
+ const opts = def.options ?? [];
11149
+ const flagLabels = safe.flags.map((fv) => {
11150
+ const o = opts.find((x) => x.value === fv || String(x.value) === String(fv));
11151
+ return o?.label ?? fv;
11152
+ });
11153
+ const lines = [
11154
+ `Pain score (VAS): ${safe.pain}/${max}`,
11155
+ flagLabels.length > 0 ? `Triage flags: ${flagLabels.join(", ")}` : "Triage flags: \u2014"
11156
+ ].join("\n");
11157
+ return /* @__PURE__ */ jsxRuntime.jsx(ReadOnlyText, { fieldDef, value: lines });
11158
+ }
11159
+ case "general_surgery_smart_history":
11160
+ case "general_surgery_grading":
11161
+ return /* @__PURE__ */ jsxRuntime.jsx(
11162
+ ReadOnlyText,
11163
+ {
11164
+ fieldDef,
11165
+ value: value && typeof value === "object" ? JSON.stringify(value, null, 2) : value == null || value === "" ? "\u2014" : String(value)
11166
+ }
11167
+ );
11168
+ case "general_surgery_examination": {
11169
+ const structuredDisplay = value && typeof value === "object" ? JSON.stringify(value, null, 2) : value == null || value === "" ? "\u2014" : String(value);
11170
+ const clinicalDef = resolveFieldDef?.("clinical_examination");
11171
+ const clinicalRaw = allValues?.["clinical_examination"];
11172
+ const clinicalStr = typeof clinicalRaw === "string" ? clinicalRaw : clinicalRaw != null && clinicalRaw !== "" ? String(clinicalRaw) : "";
11173
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4", children: [
11174
+ /* @__PURE__ */ jsxRuntime.jsx(ReadOnlyText, { fieldDef, value: structuredDisplay }),
11175
+ clinicalDef ? /* @__PURE__ */ jsxRuntime.jsx(ReadOnlyText, { fieldDef: clinicalDef, value: clinicalStr }) : clinicalStr ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
11176
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium text-gray-700", children: "Clinical examination" }),
11177
+ /* @__PURE__ */ jsxRuntime.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: clinicalStr })
11178
+ ] }) : null
11179
+ ] });
11180
+ }
9827
11181
  case "static_text": {
9828
11182
  const def = fieldDef;
9829
11183
  const size = def.size ?? "regular";
@@ -9870,7 +11224,9 @@ var ReadOnlyForm = ({ schema, submission }) => {
9870
11224
  ReadOnlyFieldRenderer,
9871
11225
  {
9872
11226
  fieldDef,
9873
- value: formData[child]
11227
+ value: formData[child],
11228
+ allValues: formData,
11229
+ resolveFieldDef: (id) => fieldMap.get(id)
9874
11230
  },
9875
11231
  child
9876
11232
  ) : null;
@@ -9889,7 +11245,9 @@ var ReadOnlyForm = ({ schema, submission }) => {
9889
11245
  ReadOnlyFieldRenderer,
9890
11246
  {
9891
11247
  fieldDef,
9892
- value: formData[fieldId]
11248
+ value: formData[fieldId],
11249
+ allValues: formData,
11250
+ resolveFieldDef: (id) => fieldMap.get(id)
9893
11251
  },
9894
11252
  fieldId
9895
11253
  ))
@@ -9920,7 +11278,9 @@ var ReadOnlyForm = ({ schema, submission }) => {
9920
11278
  ReadOnlyFieldRenderer,
9921
11279
  {
9922
11280
  fieldDef,
9923
- value: formData[fieldId]
11281
+ value: formData[fieldId],
11282
+ allValues: formData,
11283
+ resolveFieldDef: (id) => fieldMap.get(id)
9924
11284
  },
9925
11285
  fieldId
9926
11286
  ))