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.mjs CHANGED
@@ -62,6 +62,15 @@ function validateField(value, field) {
62
62
  return `Must be at most ${rules.max}`;
63
63
  }
64
64
  }
65
+ if (field.type === "slider") {
66
+ const num = Number(value);
67
+ if (isNaN(num)) return "Must be a valid number";
68
+ const s = field;
69
+ const min = s.min ?? 0;
70
+ const max = s.max ?? 10;
71
+ if (num < min) return `Must be at least ${min}`;
72
+ if (num > max) return `Must be at most ${max}`;
73
+ }
65
74
  if (typeof value === "string") {
66
75
  if (rules.minLength !== void 0 && value.length < rules.minLength) {
67
76
  return `Must be at least ${rules.minLength} characters`;
@@ -200,6 +209,227 @@ function applyPrefill(currentValues, fields, prefilledData = {}) {
200
209
  return newValues;
201
210
  }
202
211
 
212
+ // src/core/generalSurgeryPathway.ts
213
+ var defaultGeneralSurgerySmartHistory = () => ({
214
+ pain: {
215
+ site: "",
216
+ onset: "",
217
+ character: "",
218
+ radiation: "",
219
+ associated: "",
220
+ timing: "",
221
+ exacerbating: "",
222
+ severity: 0
223
+ },
224
+ swelling: { duration: "", sizeProgression: "", painfulPainless: "", checks: [] },
225
+ gi: { appetite: "", weightLoss: "", bowelHabits: "", checks: [] },
226
+ breast: { lumpDuration: "", nippleDischarge: "", checks: [] },
227
+ ano: { checks: [] },
228
+ thyroid: { swellingDuration: "", checks: [] },
229
+ systemic: ""
230
+ });
231
+ var defaultGeneralSurgeryExamination = () => ({
232
+ general: [],
233
+ regions: [],
234
+ abdomen: {
235
+ inspection: [],
236
+ palpation: [],
237
+ percussion: [],
238
+ massNotes: "",
239
+ bowelSounds: "none"
240
+ },
241
+ hernia: { site: "", reducible: false, coughImpulse: false, tenderness: false },
242
+ breast: { lumpSizeCm: "", mobile: false, skinInvolvement: false, axillaryNodes: false },
243
+ thyroid: { size: "", mobileDeglutition: false, nodules: false, cervicalNodes: false },
244
+ anorectal: { inspection: "", dreDone: false, proctoscopyDone: false, notes: "" },
245
+ limb: { dilatedVeins: false, ulcer: false, oedema: false }
246
+ });
247
+ var ALL_GS_CONDITIONS = [
248
+ "hernia",
249
+ "appendicitis",
250
+ "gallbladder",
251
+ "breast",
252
+ "thyroid",
253
+ "piles",
254
+ "varicose",
255
+ "ulcer"
256
+ ];
257
+ var defaultGeneralSurgeryGrading = () => ({
258
+ hernia: 0,
259
+ appendicitis: 0,
260
+ gallbladder: 0,
261
+ breast: 0,
262
+ thyroid: 0,
263
+ piles: 0,
264
+ varicose: 0,
265
+ ulcer: 0
266
+ });
267
+ var GS_CONDITION_TRIGGERS = {
268
+ hernia: { regions: ["hernia", "abdomen"], chips: ["swelling_lump", "obstruction"] },
269
+ appendicitis: { regions: ["abdomen"], chips: ["pain", "obstruction"] },
270
+ gallbladder: { regions: ["abdomen"], chips: ["pain"] },
271
+ breast: { regions: ["breast"], chips: ["breast", "swelling_lump"] },
272
+ thyroid: { regions: ["thyroid"], chips: ["thyroid", "swelling_lump"] },
273
+ piles: { regions: ["anorectal"], chips: ["anorectal", "bleeding"] },
274
+ varicose: { regions: ["limb"], chips: ["swelling_lump"] },
275
+ ulcer: { regions: ["limb", "anorectal"], chips: ["ulcer_wound", "discharge"] }
276
+ };
277
+ var GS_CONDITION_LABELS = {
278
+ hernia: "Hernia",
279
+ appendicitis: "Appendicitis",
280
+ gallbladder: "Gallbladder disease",
281
+ breast: "Breast lump (BIRADS)",
282
+ thyroid: "Thyroid nodule (TIRADS)",
283
+ piles: "Haemorrhoids",
284
+ varicose: "Varicose veins (CEAP)",
285
+ ulcer: "Ulcer / wound"
286
+ };
287
+ var GS_GRADE_DESCRIPTIONS = {
288
+ hernia: ["\u2014", "Small reducible", "Large reducible", "Irreducible", "Obstructed", "Strangulated"],
289
+ appendicitis: ["\u2014", "Mild (clinical)", "Confirmed (USG/CT)", "Complicated (mass)", "Abscess", "Perforation"],
290
+ gallbladder: ["\u2014", "Asymptomatic stones", "Symptomatic", "Acute cholecystitis", "Complicated (CBD stone)", "Perforation/empyema"],
291
+ breast: ["\u2014", "BIRADS 1 \u2014 Negative", "BIRADS 2 \u2014 Benign", "BIRADS 3 \u2014 Probably benign", "BIRADS 4 \u2014 Suspicious", "BIRADS 5 \u2014 Malignant"],
292
+ thyroid: ["\u2014", "TIRADS 1 \u2014 Normal", "TIRADS 2 \u2014 Benign", "TIRADS 3 \u2014 Indeterminate", "TIRADS 4 \u2014 Suspicious", "TIRADS 5 \u2014 Highly suspicious"],
293
+ piles: ["\u2014", "Grade 1", "Grade 2", "Grade 3", "Grade 4", "Grade 5"],
294
+ varicose: ["\u2014", "C1 telangiectasia", "C2 varicose", "C3 oedema", "C4 skin changes", "C5-C6 ulcer"],
295
+ ulcer: ["\u2014", "Superficial", "Deep", "Infected", "Necrotic", "Gangrene"]
296
+ };
297
+ function normalizeGeneralSurgerySmartHistory(raw) {
298
+ const d = defaultGeneralSurgerySmartHistory();
299
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) return d;
300
+ const v = raw;
301
+ const painIn = v.pain && typeof v.pain === "object" ? v.pain : {};
302
+ const sev = Number(painIn.severity);
303
+ const pain = {
304
+ ...d.pain,
305
+ ...painIn,
306
+ severity: Number.isFinite(sev) ? Math.min(10, Math.max(0, Math.round(sev))) : d.pain.severity
307
+ };
308
+ const str2 = (x) => typeof x === "string" ? x : "";
309
+ const strArr = (x) => Array.isArray(x) ? x.filter((i) => typeof i === "string") : [];
310
+ const swell = v.swelling && typeof v.swelling === "object" ? v.swelling : {};
311
+ const gi = v.gi && typeof v.gi === "object" ? v.gi : {};
312
+ const breast = v.breast && typeof v.breast === "object" ? v.breast : {};
313
+ const ano = v.ano && typeof v.ano === "object" ? v.ano : {};
314
+ const thy = v.thyroid && typeof v.thyroid === "object" ? v.thyroid : {};
315
+ return {
316
+ pain,
317
+ swelling: {
318
+ duration: str2(swell.duration),
319
+ sizeProgression: str2(swell.sizeProgression),
320
+ painfulPainless: str2(swell.painfulPainless),
321
+ checks: strArr(swell.checks)
322
+ },
323
+ gi: {
324
+ appetite: str2(gi.appetite),
325
+ weightLoss: str2(gi.weightLoss),
326
+ bowelHabits: str2(gi.bowelHabits),
327
+ checks: strArr(gi.checks)
328
+ },
329
+ breast: {
330
+ lumpDuration: str2(breast.lumpDuration),
331
+ nippleDischarge: str2(breast.nippleDischarge),
332
+ checks: strArr(breast.checks)
333
+ },
334
+ ano: { checks: strArr(ano.checks) },
335
+ thyroid: {
336
+ swellingDuration: str2(thy.swellingDuration),
337
+ checks: strArr(thy.checks)
338
+ },
339
+ systemic: typeof v.systemic === "string" ? v.systemic : d.systemic
340
+ };
341
+ }
342
+ function normalizeGeneralSurgeryExamination(raw) {
343
+ const d = defaultGeneralSurgeryExamination();
344
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) return d;
345
+ const v = raw;
346
+ const strArr = (x) => Array.isArray(x) ? x.filter((i) => typeof i === "string") : [];
347
+ const ab = v.abdomen && typeof v.abdomen === "object" ? v.abdomen : {};
348
+ const bowel = ab.bowelSounds;
349
+ const bowels = bowel === "normal" || bowel === "up" || bowel === "down" || bowel === "absent" ? bowel : "none";
350
+ const hb = v.hernia && typeof v.hernia === "object" ? v.hernia : {};
351
+ const br = v.breast && typeof v.breast === "object" ? v.breast : {};
352
+ const th = v.thyroid && typeof v.thyroid === "object" ? v.thyroid : {};
353
+ const ar = v.anorectal && typeof v.anorectal === "object" ? v.anorectal : {};
354
+ const lm = v.limb && typeof v.limb === "object" ? v.limb : {};
355
+ const bool = (x) => x === true;
356
+ return {
357
+ general: strArr(v.general),
358
+ regions: strArr(v.regions),
359
+ abdomen: {
360
+ inspection: strArr(ab.inspection),
361
+ palpation: strArr(ab.palpation),
362
+ percussion: strArr(ab.percussion),
363
+ massNotes: typeof ab.massNotes === "string" ? ab.massNotes : d.abdomen.massNotes,
364
+ bowelSounds: bowels
365
+ },
366
+ hernia: {
367
+ site: typeof hb.site === "string" ? hb.site : "",
368
+ reducible: bool(hb.reducible),
369
+ coughImpulse: bool(hb.coughImpulse),
370
+ tenderness: bool(hb.tenderness)
371
+ },
372
+ breast: {
373
+ lumpSizeCm: typeof br.lumpSizeCm === "string" ? br.lumpSizeCm : "",
374
+ mobile: bool(br.mobile),
375
+ skinInvolvement: bool(br.skinInvolvement),
376
+ axillaryNodes: bool(br.axillaryNodes)
377
+ },
378
+ thyroid: {
379
+ size: typeof th.size === "string" ? th.size : "",
380
+ mobileDeglutition: bool(th.mobileDeglutition),
381
+ nodules: bool(th.nodules),
382
+ cervicalNodes: bool(th.cervicalNodes)
383
+ },
384
+ anorectal: {
385
+ inspection: typeof ar.inspection === "string" ? ar.inspection : "",
386
+ dreDone: bool(ar.dreDone),
387
+ proctoscopyDone: bool(ar.proctoscopyDone),
388
+ notes: typeof ar.notes === "string" ? ar.notes : ""
389
+ },
390
+ limb: {
391
+ dilatedVeins: bool(lm.dilatedVeins),
392
+ ulcer: bool(lm.ulcer),
393
+ oedema: bool(lm.oedema)
394
+ }
395
+ };
396
+ }
397
+ function normalizeGeneralSurgeryGrading(raw) {
398
+ const d = defaultGeneralSurgeryGrading();
399
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) return d;
400
+ const v = raw;
401
+ const out = { ...d };
402
+ for (const k of ALL_GS_CONDITIONS) {
403
+ const n = Number(v[k]);
404
+ if (Number.isFinite(n) && n >= 0 && n <= 5) out[k] = Math.round(n);
405
+ }
406
+ return out;
407
+ }
408
+ function gsGradingRowVisible(cond, chips, regions, grade) {
409
+ if (grade > 0) return true;
410
+ const t = GS_CONDITION_TRIGGERS[cond];
411
+ if (t.chips.some((c) => chips.includes(c))) return true;
412
+ if (t.regions.some((r) => regions.includes(r))) return true;
413
+ return false;
414
+ }
415
+
416
+ // src/core/painScaleFlags.ts
417
+ function normalizePainScaleFlags(raw, bounds) {
418
+ const min = bounds?.min ?? 0;
419
+ const max = bounds?.max ?? 10;
420
+ let pain = min;
421
+ let flags = [];
422
+ if (raw && typeof raw === "object" && !Array.isArray(raw)) {
423
+ const o = raw;
424
+ const p = Number(o.pain);
425
+ if (Number.isFinite(p)) pain = Math.min(max, Math.max(min, p));
426
+ if (Array.isArray(o.flags)) {
427
+ flags = o.flags.filter((x) => typeof x === "string");
428
+ }
429
+ }
430
+ return { pain, flags };
431
+ }
432
+
203
433
  // src/core/store.ts
204
434
  var FormStore = class {
205
435
  state;
@@ -286,7 +516,22 @@ var FormStore = class {
286
516
  else if (field.type === "surgical_risk_flags")
287
517
  values[field.id] = { OD: [], OS: [] };
288
518
  else if (field.type === "toggle") values[field.id] = false;
289
- else values[field.id] = null;
519
+ else if (field.type === "slider") {
520
+ const s = field;
521
+ values[field.id] = s.defaultValue ?? s.min ?? 0;
522
+ } else if (field.type === "general_surgery_smart_history") {
523
+ values[field.id] = field.defaultValue ?? defaultGeneralSurgerySmartHistory();
524
+ } else if (field.type === "general_surgery_examination") {
525
+ values[field.id] = field.defaultValue ?? defaultGeneralSurgeryExamination();
526
+ } else if (field.type === "general_surgery_grading") {
527
+ values[field.id] = field.defaultValue ?? defaultGeneralSurgeryGrading();
528
+ } else if (field.type === "pain_scale_flags") {
529
+ const f = field;
530
+ values[field.id] = normalizePainScaleFlags(
531
+ f.defaultValue ?? { pain: f.min ?? 0, flags: [] },
532
+ { min: f.min, max: f.max }
533
+ );
534
+ } else values[field.id] = null;
290
535
  }
291
536
  });
292
537
  this.state.values = values;
@@ -1006,7 +1251,8 @@ var TextWidget = ({ fieldId }) => {
1006
1251
  fieldDef.required && /* @__PURE__ */ jsx("span", { className: "text-red-500", children: "*" })
1007
1252
  ] });
1008
1253
  const labelEl = theme ? /* @__PURE__ */ jsx(Label, { htmlFor: fieldId, className: labelClass, children: labelContent }) : /* @__PURE__ */ jsx(Label, { htmlFor: fieldId, children: labelContent });
1009
- return /* @__PURE__ */ jsxs("div", { className: wrapperClass, children: [
1254
+ const placeholder = typeof fieldDef.placeholder === "string" && fieldDef.placeholder.trim() ? fieldDef.placeholder : void 0;
1255
+ return /* @__PURE__ */ jsxs("div", { className: cn(wrapperClass, isTextarea && "flex h-full min-h-0 flex-col"), children: [
1010
1256
  hasVoice ? /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
1011
1257
  labelEl,
1012
1258
  /* @__PURE__ */ jsx(VoiceMicButton, { fieldId, onTranscriptReady: setValue })
@@ -1020,7 +1266,8 @@ var TextWidget = ({ fieldId }) => {
1020
1266
  onBlur: setTouched,
1021
1267
  disabled,
1022
1268
  type: fieldDef.type === "number" ? "number" : "text",
1023
- className: inputClass,
1269
+ className: cn(inputClass, isTextarea && height == null && "min-h-[80px] flex-1"),
1270
+ placeholder,
1024
1271
  ...isTextarea && { height }
1025
1272
  }
1026
1273
  ),
@@ -1496,6 +1743,8 @@ var SelectWidget = ({ fieldId }) => {
1496
1743
  }
1497
1744
  }, [fieldDef]);
1498
1745
  if (!fieldDef) return null;
1746
+ const schemaPlaceholder = typeof fieldDef.placeholder === "string" && fieldDef.placeholder.trim() ? fieldDef.placeholder : void 0;
1747
+ const selectPlaceholder = loading ? "Loading..." : schemaPlaceholder ?? "Select...";
1499
1748
  return /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
1500
1749
  /* @__PURE__ */ jsxs(Label, { htmlFor: fieldId, children: [
1501
1750
  fieldDef.label,
@@ -1513,7 +1762,7 @@ var SelectWidget = ({ fieldId }) => {
1513
1762
  setTouched();
1514
1763
  },
1515
1764
  children: [
1516
- /* @__PURE__ */ jsx(SelectTrigger, { id: fieldId, className: showError ? "border-red-500" : "", children: /* @__PURE__ */ jsx(SelectValue, { placeholder: loading ? "Loading..." : "Select..." }) }),
1765
+ /* @__PURE__ */ jsx(SelectTrigger, { id: fieldId, className: showError ? "border-red-500" : "", children: /* @__PURE__ */ jsx(SelectValue, { placeholder: selectPlaceholder }) }),
1517
1766
  /* @__PURE__ */ jsx(SelectContent, { children: options.map((opt) => /* @__PURE__ */ jsx(SelectItem, { value: String(opt.value), children: opt.label }, String(opt.value))) })
1518
1767
  ]
1519
1768
  }
@@ -6385,7 +6634,11 @@ var OphthalmologyWidget = ({ fieldId }) => {
6385
6634
  ] })
6386
6635
  ] }),
6387
6636
  /* @__PURE__ */ jsx("tbody", { children: /* @__PURE__ */ jsxs("tr", { children: [
6388
- /* @__PURE__ */ jsx("td", { className: refractionLabelCellClass, children: "Current Glass" }),
6637
+ /* @__PURE__ */ jsx("td", { className: `${refractionLabelCellClass} whitespace-normal`, children: /* @__PURE__ */ jsxs("span", { className: "block leading-tight", children: [
6638
+ "Current",
6639
+ /* @__PURE__ */ jsx("br", {}),
6640
+ "Glass"
6641
+ ] }) }),
6389
6642
  /* @__PURE__ */ jsx("td", { className: refractionDataCellClass, children: /* @__PURE__ */ jsx(
6390
6643
  Input,
6391
6644
  {
@@ -6640,12 +6893,12 @@ var OphthalmologyWidget = ({ fieldId }) => {
6640
6893
  /* @__PURE__ */ jsx("th", { className: refractionHeaderCellClass, children: "Sph" }),
6641
6894
  /* @__PURE__ */ jsx("th", { className: refractionHeaderCellClass, children: "Cyl" }),
6642
6895
  /* @__PURE__ */ jsx("th", { className: refractionHeaderCellClass, children: "Axis" }),
6643
- /* @__PURE__ */ jsx("th", { className: refractionHeaderCellClass, children: "V/A" }),
6896
+ /* @__PURE__ */ jsx("th", { className: refractionHeaderCellClass, children: "BCVA" }),
6644
6897
  /* @__PURE__ */ jsx("th", { className: refractionHeaderCellClass, children: "P/D" }),
6645
6898
  /* @__PURE__ */ jsx("th", { className: refractionHeaderCellClass, children: "Sph" }),
6646
6899
  /* @__PURE__ */ jsx("th", { className: refractionHeaderCellClass, children: "Cyl" }),
6647
6900
  /* @__PURE__ */ jsx("th", { className: refractionHeaderCellClass, children: "Axis" }),
6648
- /* @__PURE__ */ jsx("th", { className: refractionHeaderCellClass, children: "V/A" }),
6901
+ /* @__PURE__ */ jsx("th", { className: refractionHeaderCellClass, children: "BCVA" }),
6649
6902
  /* @__PURE__ */ jsx("th", { className: refractionHeaderCellClass, children: "P/D" })
6650
6903
  ] })
6651
6904
  ] }),
@@ -8034,6 +8287,21 @@ function parallelChipArraysEqual(a, b) {
8034
8287
  function isSuggestionField(type) {
8035
8288
  return type === "suggestion_textarea" || type === "complaint_chips";
8036
8289
  }
8290
+ function EmbeddedSchemaField({ fieldId }) {
8291
+ const store = useFormStore();
8292
+ const fieldDef = store.getFieldDef(fieldId);
8293
+ if (!fieldDef) return null;
8294
+ switch (fieldDef.type) {
8295
+ case "text":
8296
+ case "number":
8297
+ case "textarea":
8298
+ return /* @__PURE__ */ jsx(TextWidget, { fieldId });
8299
+ case "select":
8300
+ return /* @__PURE__ */ jsx(SelectWidget, { fieldId });
8301
+ default:
8302
+ return null;
8303
+ }
8304
+ }
8037
8305
  var SuggestionTextareaWidget = ({ fieldId }) => {
8038
8306
  const { fieldDef, value, setValue, setTouched, error, disabled, touched } = useField(fieldId);
8039
8307
  const { state } = useForm();
@@ -8045,6 +8313,10 @@ var SuggestionTextareaWidget = ({ fieldId }) => {
8045
8313
  const def = fieldDef && isSuggestionField(fieldDef.type) ? fieldDef : void 0;
8046
8314
  const textValue = value == null || typeof value === "string" ? value || "" : String(value);
8047
8315
  const parallelChipFieldId = def?.meta && typeof def.meta.parallelChipFieldId === "string" ? def.meta.parallelChipFieldId.trim() : void 0;
8316
+ const embeddedFieldIds = useMemo(() => {
8317
+ const raw = def?.meta && Array.isArray(def.meta.embeddedFieldIds) ? def.meta.embeddedFieldIds : [];
8318
+ return raw.filter((id) => typeof id === "string" && id.trim().length > 0).map((id) => id.trim()).filter((id) => store.getFieldDef(id));
8319
+ }, [def?.meta, store]);
8048
8320
  useEffect(() => {
8049
8321
  if (!def) {
8050
8322
  setOptions([]);
@@ -8089,19 +8361,26 @@ var SuggestionTextareaWidget = ({ fieldId }) => {
8089
8361
  setValue(toggleSuggestionTokenInText(textValue, String(optValue), appendSeparator));
8090
8362
  };
8091
8363
  const hasSuggestions = options.length > 0;
8364
+ const hasEmbedded = embeddedFieldIds.length > 0;
8365
+ const hasShell = hasSuggestions || hasEmbedded;
8092
8366
  const isHighlightLabel = def.theme === "highlight-label";
8093
8367
  const suggestionShellClass = cn(
8094
8368
  "flex min-w-0 flex-col overflow-hidden",
8095
- hasSuggestions && (isHighlightLabel ? "-mt-1 rounded-b-md border-[#D0D0D0] bg-white" : "rounded-md border border-input bg-background")
8369
+ hasShell && (isHighlightLabel ? "-mt-1 rounded-b-md border-[#D0D0D0] bg-white" : "rounded-md border border-input bg-background")
8096
8370
  );
8097
8371
  const chipsRowClass = cn(
8098
8372
  "flex flex-wrap gap-2 px-3 pb-2 pt-3",
8099
8373
  hasSuggestions && (isHighlightLabel ? "" : "border-b border-input/70"),
8100
8374
  disabled && "pointer-events-none opacity-50"
8101
8375
  );
8376
+ const embeddedRowClass = cn(
8377
+ "grid gap-3 px-3 sm:grid-cols-3",
8378
+ hasEmbedded && (hasSuggestions ? cn("py-2", isHighlightLabel && "border-t border-input/70") : "border-b border-input/70 py-3"),
8379
+ disabled && "pointer-events-none opacity-50"
8380
+ );
8102
8381
  const textareaShellClass = cn(
8103
8382
  inputClass,
8104
- hasSuggestions && cn(
8383
+ hasShell && cn(
8105
8384
  "mt-0 rounded-t-none rounded-b-md border-0 shadow-none focus-visible:ring-offset-0",
8106
8385
  isHighlightLabel ? "border-t-0" : "min-h-[80px]"
8107
8386
  )
@@ -8128,8 +8407,9 @@ var SuggestionTextareaWidget = ({ fieldId }) => {
8128
8407
  /* @__PURE__ */ jsx(VoiceMicButton, { fieldId, onTranscriptReady: setValue })
8129
8408
  ] }) : labelEl,
8130
8409
  def.description && /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: def.description }),
8131
- hasSuggestions ? /* @__PURE__ */ jsxs("div", { className: suggestionShellClass, children: [
8132
- /* @__PURE__ */ jsx("div", { className: chipsRowClass, role: "group", "aria-label": suggestionsAria, children: suggestionButtons }),
8410
+ hasShell ? /* @__PURE__ */ jsxs("div", { className: suggestionShellClass, children: [
8411
+ hasSuggestions && /* @__PURE__ */ jsx("div", { className: chipsRowClass, role: "group", "aria-label": suggestionsAria, children: suggestionButtons }),
8412
+ hasEmbedded && /* @__PURE__ */ jsx("div", { className: embeddedRowClass, children: embeddedFieldIds.map((id) => /* @__PURE__ */ jsx(EmbeddedSchemaField, { fieldId: id }, id)) }),
8133
8413
  /* @__PURE__ */ jsx(
8134
8414
  Textarea,
8135
8415
  {
@@ -8909,178 +9189,1176 @@ var SurgicalRiskFlagsWidget = ({ fieldId }) => {
8909
9189
  }
8910
9190
  );
8911
9191
  };
8912
- var FieldRenderer = ({ fieldId }) => {
8913
- const { fieldDef, visible } = useField(fieldId);
8914
- if (!visible || !fieldDef) {
8915
- return null;
8916
- }
8917
- return renderWidget(fieldId, fieldDef);
8918
- };
8919
- function renderWidget(fieldId, fieldDef) {
8920
- switch (fieldDef.type) {
8921
- case "text":
8922
- case "number":
8923
- return /* @__PURE__ */ jsx(TextWidget, { fieldId });
8924
- case "textarea":
8925
- if (fieldMetaRequestsMarMedicationOrdersButton(fieldDef.meta)) {
8926
- return /* @__PURE__ */ jsx(MarMedicationOrdersWidget, { fieldId });
8927
- }
8928
- return /* @__PURE__ */ jsx(TextWidget, { fieldId });
8929
- case "richtext":
8930
- return /* @__PURE__ */ jsx(RichTextWidget, { fieldId });
8931
- case "date":
8932
- return /* @__PURE__ */ jsx(DateWidget, { fieldId });
8933
- case "datetime":
8934
- return /* @__PURE__ */ jsx(DateTimeWidget, { fieldId });
8935
- case "select":
8936
- return /* @__PURE__ */ jsx(SelectWidget, { fieldId });
8937
- case "radio":
8938
- return /* @__PURE__ */ jsx(RadioWidget, { fieldId });
8939
- case "checkbox":
8940
- return /* @__PURE__ */ jsx(CheckboxWidget, { fieldId });
8941
- case "multiselect":
8942
- return /* @__PURE__ */ jsx(MultiSelectWidget, { fieldId });
8943
- case "repeatable":
8944
- return /* @__PURE__ */ jsx(RepeatableWidget, { fieldId });
8945
- case "image_upload":
8946
- return /* @__PURE__ */ jsx(ImageUploadWidget, { fieldId });
8947
- case "media_upload":
8948
- return /* @__PURE__ */ jsx(MediaUploadWidget, { fieldId });
8949
- case "signature":
8950
- return /* @__PURE__ */ jsx(SignatureUploadWidget, { fieldId });
8951
- case "editable_table":
8952
- return /* @__PURE__ */ jsx(EditableTableWidget, { fieldId });
8953
- case "medications":
8954
- return /* @__PURE__ */ jsx(AddMedicationWidget, { fieldId });
8955
- case "discharge_medication_orders":
8956
- return /* @__PURE__ */ jsx(DischargeMedicationOrdersWidget, { fieldId });
8957
- case "investigations":
8958
- return /* @__PURE__ */ jsx(AddInvestigationWidget, { fieldId });
8959
- case "procedures":
8960
- return /* @__PURE__ */ jsx(AddProcedureWidget, { fieldId });
8961
- case "differential_diagnosis":
8962
- return /* @__PURE__ */ jsx(DifferentialDiagnosisWidget, { fieldId });
8963
- case "vitals":
8964
- return /* @__PURE__ */ jsx(VitalsWidget, { fieldId });
8965
- case "hidden_vitals":
8966
- return /* @__PURE__ */ jsx(HiddenVitalsWidget, { fieldId });
8967
- case "referral":
8968
- return /* @__PURE__ */ jsx(ReferralWidget, { fieldId });
8969
- case "followup":
8970
- return /* @__PURE__ */ jsx(FollowupWidget, { fieldId });
8971
- case "smart_textarea":
8972
- return /* @__PURE__ */ jsx(SmartTextareaWidget, { fieldId });
8973
- case "diagnosis_textarea":
8974
- return /* @__PURE__ */ jsx(DiagnosisTextareaWidget, { fieldId });
8975
- case "obstetric_history":
8976
- return /* @__PURE__ */ jsx(ObstetricHistoryWidget, { fieldId });
8977
- case "eye_prescription":
8978
- return /* @__PURE__ */ jsx(OphthalmologyWidget, { fieldId });
8979
- case "ophthal_diagnosis":
8980
- return /* @__PURE__ */ jsx(OphthalDiagnosisWidget, { fieldId });
8981
- case "orthopedic_exam":
8982
- return /* @__PURE__ */ jsx(OrthopedicExamWidget, { fieldId });
8983
- case "toggle": {
8984
- const { value, setValue, setTouched, disabled } = useField(fieldId);
8985
- const store = useFormStore();
8986
- const excludes = fieldDef.excludes ?? [];
8987
- return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
8988
- /* @__PURE__ */ jsx(
8989
- Switch,
8990
- {
8991
- checked: value === true,
8992
- disabled,
8993
- onCheckedChange: (checked) => {
8994
- setValue(checked);
8995
- setTouched();
8996
- if (checked) excludes.forEach((id) => store.setValue(id, false));
8997
- }
8998
- }
8999
- ),
9000
- /* @__PURE__ */ jsx(Label, { className: "text-sm font-medium leading-none cursor-pointer select-none", children: fieldDef.label })
9001
- ] });
9002
- }
9003
- case "suggestion_textarea":
9004
- case "complaint_chips":
9005
- return /* @__PURE__ */ jsx(SuggestionTextareaWidget, { fieldId });
9006
- case "lens_assessment":
9007
- return /* @__PURE__ */ jsx(LensAssessmentWidget, { fieldId });
9008
- case "functional_impairment_score":
9009
- return /* @__PURE__ */ jsx(FunctionalImpairmentScoreWidget, { fieldId });
9010
- case "biometry_iol_workup":
9011
- return /* @__PURE__ */ jsx(BiometryIolWorkupWidget, { fieldId });
9012
- case "surgical_risk_flags":
9013
- return /* @__PURE__ */ jsx(SurgicalRiskFlagsWidget, { fieldId });
9014
- case "static_text": {
9015
- const def = fieldDef;
9016
- const size = def.size ?? "regular";
9017
- const labelClass = size === "large" ? "text-base" : "text-sm";
9018
- const descClass = size === "large" ? "text-sm" : "text-xs";
9019
- return /* @__PURE__ */ jsxs("div", { className: `${labelClass} text-muted-foreground`, children: [
9020
- def.label,
9021
- def.description && /* @__PURE__ */ jsx("p", { className: `mt-1 ${descClass} opacity-90`, children: def.description })
9022
- ] });
9023
- }
9024
- default:
9025
- return /* @__PURE__ */ jsxs("div", { className: "text-red-500", children: [
9026
- "Unknown field type: ",
9027
- fieldDef.type
9028
- ] });
9029
- }
9030
- }
9031
- var Section = ({ title, children }) => {
9032
- const [expanded, setExpanded] = useState(true);
9033
- const handleToggle = () => setExpanded((prev) => !prev);
9034
- const contentClassName = cn(
9035
- "overflow-hidden transition-[height] duration-200 ease-in-out",
9036
- !expanded && "hidden"
9037
- );
9038
- return /* @__PURE__ */ jsxs("div", { className: "mb-6 border rounded-lg bg-white shadow-sm overflow-hidden", children: [
9039
- /* @__PURE__ */ jsxs(
9040
- "button",
9192
+ var SliderWidget = ({ fieldId }) => {
9193
+ const { fieldDef, value, setValue, setTouched, error, disabled, touched } = useField(fieldId);
9194
+ const { state } = useForm();
9195
+ const showError = !!error && (touched || state.submitAttempted);
9196
+ if (!fieldDef || fieldDef.type !== "slider") return null;
9197
+ const def = fieldDef;
9198
+ const min = def.min ?? 0;
9199
+ const max = def.max ?? 10;
9200
+ const step = def.step ?? 1;
9201
+ const raw = value == null || value === "" ? min : Number(value);
9202
+ const num = Number.isFinite(raw) ? Math.min(max, Math.max(min, raw)) : min;
9203
+ const theme = getThemeConfig("textarea", def.theme);
9204
+ const wrapperClass = theme?.wrapperClassName ?? "space-y-2";
9205
+ const labelClass = theme?.labelClassName;
9206
+ const labelContent = /* @__PURE__ */ jsxs(Fragment, { children: [
9207
+ def.label,
9208
+ " ",
9209
+ def.required && /* @__PURE__ */ jsx("span", { className: "text-red-500", children: "*" }),
9210
+ /* @__PURE__ */ jsxs("span", { className: "ml-2 text-muted-foreground font-normal tabular-nums", children: [
9211
+ num,
9212
+ "/",
9213
+ max
9214
+ ] })
9215
+ ] });
9216
+ const labelEl = theme ? /* @__PURE__ */ jsx(Label, { className: labelClass, children: labelContent }) : /* @__PURE__ */ jsx(Label, { children: labelContent });
9217
+ return /* @__PURE__ */ jsxs("div", { className: wrapperClass, children: [
9218
+ labelEl,
9219
+ /* @__PURE__ */ jsx(
9220
+ Slider,
9041
9221
  {
9042
- type: "button",
9043
- onClick: handleToggle,
9044
- className: "w-full flex items-center justify-between gap-2 p-4 text-left border-b hover:bg-gray-50/80 transition-colors",
9045
- children: [
9046
- /* @__PURE__ */ jsx("h3", { className: "text-lg font-medium", children: title }),
9047
- /* @__PURE__ */ jsx("span", { className: "flex-shrink-0 text-muted-foreground", "aria-hidden": true, children: expanded ? /* @__PURE__ */ jsx(ChevronDown, { className: "h-5 w-5" }) : /* @__PURE__ */ jsx(ChevronRight, { className: "h-5 w-5" }) })
9048
- ]
9222
+ className: cn("py-1", showError && "opacity-90 ring-1 ring-red-500 rounded"),
9223
+ disabled,
9224
+ min,
9225
+ max,
9226
+ step,
9227
+ value: [num],
9228
+ onValueChange: (v) => {
9229
+ const n = v[0] ?? min;
9230
+ setValue(n);
9231
+ setTouched();
9232
+ }
9049
9233
  }
9050
9234
  ),
9051
- /* @__PURE__ */ jsx("div", { className: contentClassName, children: /* @__PURE__ */ jsx("div", { className: "p-4 pt-4 space-y-4 border-t-0", children }) })
9235
+ showError && /* @__PURE__ */ jsx("p", { className: "text-xs text-red-500", children: error })
9052
9236
  ] });
9053
9237
  };
9054
- var ColumnLayout = ({
9055
- columns,
9056
- label,
9057
- children
9058
- }) => {
9059
- const gridCols = Math.max(1, Math.min(columns, 12));
9060
- const gridClass = `grid gap-4 w-full`;
9061
- const style = {
9062
- gridTemplateColumns: `repeat(${gridCols}, minmax(0, 1fr))`
9063
- };
9064
- return /* @__PURE__ */ jsxs("div", { className: "mb-6", children: [
9065
- label != null && label !== "" && /* @__PURE__ */ jsx("div", { className: "mb-2 text-sm font-medium text-gray-700", children: label }),
9066
- /* @__PURE__ */ jsx("div", { className: gridClass, style, children })
9238
+ var CHIEF_CHIPS_FIELD = "chief_complaints_chips";
9239
+ var SWELLING_OPTS = [
9240
+ { value: "reducible_hernia", label: "Reducible (hernia)" },
9241
+ { value: "cough_impulse", label: "Cough impulse" },
9242
+ { value: "skin_changes", label: "Skin changes" }
9243
+ ];
9244
+ var GI_OPTS = [
9245
+ { value: "bleeding_pr", label: "Bleeding PR" },
9246
+ { value: "vomiting", label: "Vomiting" },
9247
+ { value: "haematemesis", label: "Haematemesis" }
9248
+ ];
9249
+ var BREAST_OPTS = [
9250
+ { value: "pain", label: "Pain" },
9251
+ { value: "fh_ca_breast", label: "Family history of Ca breast" }
9252
+ ];
9253
+ var ANO_OPTS = [
9254
+ { value: "pain_defecation", label: "Pain during defecation" },
9255
+ { value: "bleeding", label: "Bleeding" },
9256
+ { value: "constipation", label: "Constipation" },
9257
+ { value: "discharge", label: "Discharge" }
9258
+ ];
9259
+ var THYROID_OPTS = [
9260
+ { value: "dysphagia", label: "Dysphagia" },
9261
+ { value: "voice_change", label: "Voice change" },
9262
+ { value: "thyrotoxicosis", label: "Thyrotoxicosis symptoms" }
9263
+ ];
9264
+ var SOCRATES_KEYS = [
9265
+ "site",
9266
+ "onset",
9267
+ "character",
9268
+ "radiation",
9269
+ "associated",
9270
+ "timing",
9271
+ "exacerbating"
9272
+ ];
9273
+ function Panel({ title, children }) {
9274
+ return /* @__PURE__ */ jsxs("div", { className: "overflow-hidden rounded-md border border-[#D0D0D0] bg-white", children: [
9275
+ /* @__PURE__ */ jsx("div", { className: "border-b border-[#D0D0D0] bg-[#FEE8EC]/50 px-3 py-1.5 text-xs font-semibold text-slate-700", children: title }),
9276
+ /* @__PURE__ */ jsx("div", { className: "p-3", children })
9067
9277
  ] });
9068
- };
9069
- var DynamicForm = () => {
9070
- const store = useFormStore();
9071
- const schema = store.getSchema();
9072
- return /* @__PURE__ */ jsxs("div", { className: "space-y-6", children: [
9073
- /* @__PURE__ */ jsx("div", { className: "mb-4", children: /* @__PURE__ */ jsx("h1", { className: "text-2xl font-bold", children: schema.title }) }),
9074
- schema.layout.map((node) => {
9075
- if (node.type === "section") {
9076
- return /* @__PURE__ */ jsx(Section, { title: node.title, children: node.children.map(
9077
- (child, index) => typeof child === "string" ? /* @__PURE__ */ jsx(FieldRenderer, { fieldId: child }, child) : child.type === "column_layout" ? /* @__PURE__ */ jsx(
9078
- ColumnLayout,
9079
- {
9080
- columns: child.columns,
9081
- label: child.label,
9082
- children: child.children.map((fieldId) => /* @__PURE__ */ jsx(FieldRenderer, { fieldId }, fieldId))
9083
- },
9278
+ }
9279
+ function chipList(state) {
9280
+ const raw = state.values[CHIEF_CHIPS_FIELD];
9281
+ return Array.isArray(raw) ? raw.filter((x) => typeof x === "string") : [];
9282
+ }
9283
+ var GsSmartHistoryWidget = ({ fieldId }) => {
9284
+ const { fieldDef, value, setValue, setTouched, error, touched, disabled } = useField(fieldId);
9285
+ const { state } = useForm();
9286
+ const showError = !!error && (touched || state.submitAttempted);
9287
+ const safe = useMemo(() => normalizeGeneralSurgerySmartHistory(value), [value]);
9288
+ const chips = useMemo(() => chipList(state), [state]);
9289
+ const showPain = chips.includes("pain");
9290
+ const showSwelling = chips.includes("swelling_lump");
9291
+ const showGI = chips.includes("bleeding") || chips.includes("obstruction");
9292
+ const showBreast = chips.includes("breast");
9293
+ const showAno = chips.includes("anorectal");
9294
+ const showThyroid = chips.includes("thyroid");
9295
+ const update = (next) => {
9296
+ setValue(next);
9297
+ setTouched();
9298
+ };
9299
+ const setPain = (key, v) => {
9300
+ if (key === "severity") {
9301
+ const n = typeof v === "number" ? v : Number(v);
9302
+ const sev = Number.isFinite(n) ? Math.min(10, Math.max(0, Math.round(n))) : 0;
9303
+ update({ ...safe, pain: { ...safe.pain, severity: sev } });
9304
+ return;
9305
+ }
9306
+ update({ ...safe, pain: { ...safe.pain, [key]: String(v) } });
9307
+ };
9308
+ const toggleArr = (section, val) => {
9309
+ if (section === "swelling") {
9310
+ const a = safe.swelling.checks;
9311
+ const next = a.includes(val) ? a.filter((x) => x !== val) : [...a, val];
9312
+ update({ ...safe, swelling: { ...safe.swelling, checks: next } });
9313
+ } else if (section === "gi") {
9314
+ const a = safe.gi.checks;
9315
+ const next = a.includes(val) ? a.filter((x) => x !== val) : [...a, val];
9316
+ update({ ...safe, gi: { ...safe.gi, checks: next } });
9317
+ } else if (section === "breast") {
9318
+ const a = safe.breast.checks;
9319
+ const next = a.includes(val) ? a.filter((x) => x !== val) : [...a, val];
9320
+ update({ ...safe, breast: { ...safe.breast, checks: next } });
9321
+ } else if (section === "ano") {
9322
+ const a = safe.ano.checks;
9323
+ const next = a.includes(val) ? a.filter((x) => x !== val) : [...a, val];
9324
+ update({ ...safe, ano: { ...safe.ano, checks: next } });
9325
+ } else {
9326
+ const a = safe.thyroid.checks;
9327
+ const next = a.includes(val) ? a.filter((x) => x !== val) : [...a, val];
9328
+ update({ ...safe, thyroid: { ...safe.thyroid, checks: next } });
9329
+ }
9330
+ };
9331
+ if (!fieldDef) return null;
9332
+ const theme = getThemeConfig("textarea", fieldDef.theme);
9333
+ const wrapperClass = theme?.wrapperClassName ?? "rounded-md overflow-hidden flex flex-col border border-[#D0D0D0]";
9334
+ const labelClass = theme?.labelClassName;
9335
+ const labelContent = /* @__PURE__ */ jsxs(Fragment, { children: [
9336
+ fieldDef.label,
9337
+ fieldDef.required ? /* @__PURE__ */ jsx("span", { className: "ml-1 text-red-500", children: "*" }) : null
9338
+ ] });
9339
+ const labelEl = theme ? /* @__PURE__ */ jsx(Label, { className: labelClass, children: labelContent }) : /* @__PURE__ */ jsx(Label, { className: "text-sm font-medium", children: labelContent });
9340
+ const bodyClass = cn(
9341
+ "-mt-1 flex min-w-0 flex-col gap-3 border-t border-[#D0D0D0] bg-white px-3 py-3",
9342
+ disabled && "pointer-events-none opacity-60"
9343
+ );
9344
+ return /* @__PURE__ */ jsxs("div", { className: cn("w-full min-w-0", wrapperClass), children: [
9345
+ labelEl,
9346
+ /* @__PURE__ */ jsxs("div", { className: bodyClass, children: [
9347
+ showPain ? /* @__PURE__ */ jsx(Panel, { title: "SOCRATES \u2014 pain", children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-2 md:grid-cols-4", children: [
9348
+ SOCRATES_KEYS.map((k) => /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
9349
+ /* @__PURE__ */ jsx("span", { className: "text-[10px] font-medium uppercase tracking-wide text-muted-foreground", children: k }),
9350
+ /* @__PURE__ */ jsx(
9351
+ Input,
9352
+ {
9353
+ className: "h-8 text-xs",
9354
+ value: safe.pain[k],
9355
+ onChange: (e) => setPain(k, e.target.value),
9356
+ disabled
9357
+ }
9358
+ )
9359
+ ] }, k)),
9360
+ /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
9361
+ /* @__PURE__ */ jsx("span", { className: "text-[10px] font-medium uppercase tracking-wide text-muted-foreground", children: "Severity 0\u201310" }),
9362
+ /* @__PURE__ */ jsx(
9363
+ Input,
9364
+ {
9365
+ type: "number",
9366
+ min: 0,
9367
+ max: 10,
9368
+ className: "h-8 text-xs",
9369
+ value: safe.pain.severity,
9370
+ onChange: (e) => setPain("severity", e.target.value),
9371
+ disabled
9372
+ }
9373
+ )
9374
+ ] })
9375
+ ] }) }) : null,
9376
+ showSwelling ? /* @__PURE__ */ jsxs(Panel, { title: "Swelling history", children: [
9377
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 gap-3 text-xs md:grid-cols-3", children: [
9378
+ /* @__PURE__ */ jsxs("label", { className: "flex flex-col gap-1", children: [
9379
+ /* @__PURE__ */ jsx("span", { className: "font-medium", children: "Duration" }),
9380
+ /* @__PURE__ */ jsx(
9381
+ Input,
9382
+ {
9383
+ className: "h-8 text-xs",
9384
+ value: safe.swelling.duration,
9385
+ onChange: (e) => update({ ...safe, swelling: { ...safe.swelling, duration: e.target.value } }),
9386
+ disabled
9387
+ }
9388
+ )
9389
+ ] }),
9390
+ /* @__PURE__ */ jsxs("label", { className: "flex flex-col gap-1", children: [
9391
+ /* @__PURE__ */ jsx("span", { className: "font-medium", children: "Size progression" }),
9392
+ /* @__PURE__ */ jsx(
9393
+ Input,
9394
+ {
9395
+ className: "h-8 text-xs",
9396
+ value: safe.swelling.sizeProgression,
9397
+ onChange: (e) => update({ ...safe, swelling: { ...safe.swelling, sizeProgression: e.target.value } }),
9398
+ disabled
9399
+ }
9400
+ )
9401
+ ] }),
9402
+ /* @__PURE__ */ jsxs("label", { className: "flex flex-col gap-1", children: [
9403
+ /* @__PURE__ */ jsx("span", { className: "font-medium", children: "Painful / painless" }),
9404
+ /* @__PURE__ */ jsx(
9405
+ Input,
9406
+ {
9407
+ className: "h-8 text-xs",
9408
+ value: safe.swelling.painfulPainless,
9409
+ onChange: (e) => update({ ...safe, swelling: { ...safe.swelling, painfulPainless: e.target.value } }),
9410
+ disabled
9411
+ }
9412
+ )
9413
+ ] })
9414
+ ] }),
9415
+ /* @__PURE__ */ jsx("div", { className: "mt-3 flex flex-wrap gap-x-4 gap-y-2", children: SWELLING_OPTS.map((o) => /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2 text-xs", children: [
9416
+ /* @__PURE__ */ jsx(
9417
+ Checkbox,
9418
+ {
9419
+ checked: safe.swelling.checks.includes(o.value),
9420
+ onCheckedChange: () => toggleArr("swelling", o.value),
9421
+ disabled
9422
+ }
9423
+ ),
9424
+ o.label
9425
+ ] }, o.value)) })
9426
+ ] }) : null,
9427
+ showGI ? /* @__PURE__ */ jsxs(Panel, { title: "GI history", children: [
9428
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 gap-2 text-xs md:grid-cols-3", children: [
9429
+ /* @__PURE__ */ jsxs("label", { className: "flex flex-col gap-1", children: [
9430
+ "Appetite",
9431
+ /* @__PURE__ */ jsx(
9432
+ Input,
9433
+ {
9434
+ className: "h-8 text-xs",
9435
+ value: safe.gi.appetite,
9436
+ onChange: (e) => update({ ...safe, gi: { ...safe.gi, appetite: e.target.value } }),
9437
+ disabled
9438
+ }
9439
+ )
9440
+ ] }),
9441
+ /* @__PURE__ */ jsxs("label", { className: "flex flex-col gap-1", children: [
9442
+ "Weight loss",
9443
+ /* @__PURE__ */ jsx(
9444
+ Input,
9445
+ {
9446
+ className: "h-8 text-xs",
9447
+ value: safe.gi.weightLoss,
9448
+ onChange: (e) => update({ ...safe, gi: { ...safe.gi, weightLoss: e.target.value } }),
9449
+ disabled
9450
+ }
9451
+ )
9452
+ ] }),
9453
+ /* @__PURE__ */ jsxs("label", { className: "flex flex-col gap-1", children: [
9454
+ "Bowel habits",
9455
+ /* @__PURE__ */ jsx(
9456
+ Input,
9457
+ {
9458
+ className: "h-8 text-xs",
9459
+ value: safe.gi.bowelHabits,
9460
+ onChange: (e) => update({ ...safe, gi: { ...safe.gi, bowelHabits: e.target.value } }),
9461
+ disabled
9462
+ }
9463
+ )
9464
+ ] })
9465
+ ] }),
9466
+ /* @__PURE__ */ jsx("div", { className: "mt-3 flex flex-wrap gap-x-4 gap-y-2", children: GI_OPTS.map((o) => /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2 text-xs", children: [
9467
+ /* @__PURE__ */ jsx(
9468
+ Checkbox,
9469
+ {
9470
+ checked: safe.gi.checks.includes(o.value),
9471
+ onCheckedChange: () => toggleArr("gi", o.value),
9472
+ disabled
9473
+ }
9474
+ ),
9475
+ o.label
9476
+ ] }, o.value)) })
9477
+ ] }) : null,
9478
+ showBreast ? /* @__PURE__ */ jsxs(Panel, { title: "Breast history", children: [
9479
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 gap-2 text-xs md:grid-cols-2", children: [
9480
+ /* @__PURE__ */ jsxs("label", { className: "flex flex-col gap-1", children: [
9481
+ "Lump duration",
9482
+ /* @__PURE__ */ jsx(
9483
+ Input,
9484
+ {
9485
+ className: "h-8 text-xs",
9486
+ value: safe.breast.lumpDuration,
9487
+ onChange: (e) => update({ ...safe, breast: { ...safe.breast, lumpDuration: e.target.value } }),
9488
+ disabled
9489
+ }
9490
+ )
9491
+ ] }),
9492
+ /* @__PURE__ */ jsxs("label", { className: "flex flex-col gap-1", children: [
9493
+ "Nipple discharge",
9494
+ /* @__PURE__ */ jsx(
9495
+ Input,
9496
+ {
9497
+ className: "h-8 text-xs",
9498
+ value: safe.breast.nippleDischarge,
9499
+ onChange: (e) => update({ ...safe, breast: { ...safe.breast, nippleDischarge: e.target.value } }),
9500
+ disabled
9501
+ }
9502
+ )
9503
+ ] })
9504
+ ] }),
9505
+ /* @__PURE__ */ jsx("div", { className: "mt-3 flex flex-wrap gap-x-4 gap-y-2", children: BREAST_OPTS.map((o) => /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2 text-xs", children: [
9506
+ /* @__PURE__ */ jsx(
9507
+ Checkbox,
9508
+ {
9509
+ checked: safe.breast.checks.includes(o.value),
9510
+ onCheckedChange: () => toggleArr("breast", o.value),
9511
+ disabled
9512
+ }
9513
+ ),
9514
+ o.label
9515
+ ] }, o.value)) })
9516
+ ] }) : null,
9517
+ showAno ? /* @__PURE__ */ jsx(Panel, { title: "Anorectal history", children: /* @__PURE__ */ jsx("div", { className: "grid grid-cols-1 gap-2 text-xs md:grid-cols-2", children: ANO_OPTS.map((o) => /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2", children: [
9518
+ /* @__PURE__ */ jsx(
9519
+ Checkbox,
9520
+ {
9521
+ checked: safe.ano.checks.includes(o.value),
9522
+ onCheckedChange: () => toggleArr("ano", o.value),
9523
+ disabled
9524
+ }
9525
+ ),
9526
+ o.label
9527
+ ] }, o.value)) }) }) : null,
9528
+ showThyroid ? /* @__PURE__ */ jsxs(Panel, { title: "Thyroid history", children: [
9529
+ /* @__PURE__ */ jsx("div", { className: "grid grid-cols-1 gap-2 text-xs md:grid-cols-2", children: /* @__PURE__ */ jsxs("label", { className: "flex flex-col gap-1 md:col-span-2", children: [
9530
+ "Swelling duration",
9531
+ /* @__PURE__ */ jsx(
9532
+ Input,
9533
+ {
9534
+ className: "h-8 text-xs",
9535
+ value: safe.thyroid.swellingDuration,
9536
+ onChange: (e) => update({ ...safe, thyroid: { ...safe.thyroid, swellingDuration: e.target.value } }),
9537
+ disabled
9538
+ }
9539
+ )
9540
+ ] }) }),
9541
+ /* @__PURE__ */ jsx("div", { className: "mt-3 flex flex-wrap gap-x-4 gap-y-2", children: THYROID_OPTS.map((o) => /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2 text-xs", children: [
9542
+ /* @__PURE__ */ jsx(
9543
+ Checkbox,
9544
+ {
9545
+ checked: safe.thyroid.checks.includes(o.value),
9546
+ onCheckedChange: () => toggleArr("thyroid", o.value),
9547
+ disabled
9548
+ }
9549
+ ),
9550
+ o.label
9551
+ ] }, o.value)) })
9552
+ ] }) : null,
9553
+ /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
9554
+ /* @__PURE__ */ jsx(Label, { className: "text-xs font-medium text-slate-700", children: "Systemic surgical screening" }),
9555
+ /* @__PURE__ */ jsx(
9556
+ Textarea,
9557
+ {
9558
+ className: "min-h-[72px] rounded-md border border-input bg-white text-sm",
9559
+ placeholder: "Fever, weight loss, appetite loss, fatigue, malignancy red flags\u2026",
9560
+ value: safe.systemic,
9561
+ onChange: (e) => update({ ...safe, systemic: e.target.value }),
9562
+ disabled
9563
+ }
9564
+ )
9565
+ ] })
9566
+ ] }),
9567
+ showError ? /* @__PURE__ */ jsx("p", { className: "px-3 pb-2 text-xs text-red-500", children: error }) : null
9568
+ ] });
9569
+ };
9570
+ var GS_CLINICAL_EXAMINATION_FIELD = "clinical_examination";
9571
+ var GENERAL = [
9572
+ { value: "pallor", label: "Pallor" },
9573
+ { value: "icterus", label: "Icterus" },
9574
+ { value: "cyanosis", label: "Cyanosis" },
9575
+ { value: "clubbing", label: "Clubbing" },
9576
+ { value: "lymphadenopathy", label: "Lymphadenopathy" },
9577
+ { value: "oedema", label: "Oedema" }
9578
+ ];
9579
+ var REGIONS = [
9580
+ { key: "abdomen", label: "Abdomen" },
9581
+ { key: "hernia", label: "Hernia" },
9582
+ { key: "breast", label: "Breast" },
9583
+ { key: "thyroid", label: "Thyroid" },
9584
+ { key: "anorectal", label: "Anorectal" },
9585
+ { key: "limb", label: "Limb / varicose" }
9586
+ ];
9587
+ var ABD_INSP = [
9588
+ { value: "distension", label: "Distension" },
9589
+ { value: "scars", label: "Scars" },
9590
+ { value: "visible_peristalsis", label: "Visible peristalsis" }
9591
+ ];
9592
+ var ABD_PALP = [
9593
+ { value: "tenderness", label: "Tenderness" },
9594
+ { value: "guarding", label: "Guarding" },
9595
+ { value: "rigidity", label: "Rigidity" },
9596
+ { value: "mass", label: "Palpable mass" }
9597
+ ];
9598
+ var ABD_PERC = [
9599
+ { value: "tympany", label: "Tympany" },
9600
+ { value: "shifting_dullness", label: "Shifting dullness" }
9601
+ ];
9602
+ function SubGroup({ title, children }) {
9603
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
9604
+ /* @__PURE__ */ jsx("p", { className: "text-[11px] font-semibold uppercase tracking-wide text-muted-foreground", children: title }),
9605
+ /* @__PURE__ */ jsx("div", { className: "space-y-2", children })
9606
+ ] });
9607
+ }
9608
+ function RegionCard({ title, children }) {
9609
+ return /* @__PURE__ */ jsxs("div", { className: "overflow-hidden rounded-md border border-[#D0D0D0] bg-white", children: [
9610
+ /* @__PURE__ */ jsx("div", { className: "border-b border-[#D0D0D0] bg-[#FEE8EC]/50 px-3 py-1.5 text-xs font-semibold text-slate-700", children: title }),
9611
+ /* @__PURE__ */ jsx("div", { className: "p-3", children })
9612
+ ] });
9613
+ }
9614
+ var GsExaminationWidget = ({ fieldId }) => {
9615
+ const { fieldDef, value, setValue, setTouched, error, touched, disabled } = useField(fieldId);
9616
+ const clinicalField = useField(GS_CLINICAL_EXAMINATION_FIELD);
9617
+ const { state } = useForm();
9618
+ const showError = !!error && (touched || state.submitAttempted);
9619
+ const safe = useMemo(() => normalizeGeneralSurgeryExamination(value), [value]);
9620
+ const update = (next) => {
9621
+ setValue(next);
9622
+ setTouched();
9623
+ };
9624
+ const toggleIn = (arr, val) => arr.includes(val) ? arr.filter((x) => x !== val) : [...arr, val];
9625
+ const toggleGeneral = (val) => {
9626
+ update({ ...safe, general: toggleIn(safe.general, val) });
9627
+ };
9628
+ const toggleRegion = (key) => {
9629
+ update({ ...safe, regions: toggleIn(safe.regions, key) });
9630
+ };
9631
+ const toggleAbd = (key, val) => {
9632
+ update({
9633
+ ...safe,
9634
+ abdomen: { ...safe.abdomen, [key]: toggleIn(safe.abdomen[key], val) }
9635
+ });
9636
+ };
9637
+ if (!fieldDef) return null;
9638
+ const has = (r) => safe.regions.includes(r);
9639
+ const theme = getThemeConfig("textarea", fieldDef.theme);
9640
+ const wrapperClass = theme?.wrapperClassName ?? "rounded-md overflow-hidden flex flex-col border border-[#D0D0D0]";
9641
+ const labelClass = theme?.labelClassName;
9642
+ const labelContent = /* @__PURE__ */ jsxs(Fragment, { children: [
9643
+ fieldDef.label,
9644
+ fieldDef.required ? /* @__PURE__ */ jsx("span", { className: "ml-1 text-red-500", children: "*" }) : null
9645
+ ] });
9646
+ const labelEl = theme ? /* @__PURE__ */ jsx(Label, { className: labelClass, children: labelContent }) : /* @__PURE__ */ jsx(Label, { className: "text-sm font-medium", children: labelContent });
9647
+ const bodyClass = cn(
9648
+ "-mt-1 flex min-w-0 flex-col gap-3 border-t border-[#D0D0D0] bg-white px-3 py-3",
9649
+ disabled && "pointer-events-none opacity-60"
9650
+ );
9651
+ return /* @__PURE__ */ jsxs("div", { className: cn("w-full min-w-0", wrapperClass), children: [
9652
+ labelEl,
9653
+ /* @__PURE__ */ jsxs("div", { className: bodyClass, children: [
9654
+ /* @__PURE__ */ jsxs("div", { className: "overflow-hidden rounded-md border border-[#D0D0D0] bg-white", children: [
9655
+ /* @__PURE__ */ 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" }),
9656
+ /* @__PURE__ */ jsx("div", { className: "p-3", children: /* @__PURE__ */ jsx("div", { className: "grid grid-cols-2 gap-2 text-xs md:grid-cols-3 lg:grid-cols-6", children: GENERAL.map((g) => /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2", children: [
9657
+ /* @__PURE__ */ jsx(
9658
+ Checkbox,
9659
+ {
9660
+ checked: safe.general.includes(g.value),
9661
+ onCheckedChange: () => toggleGeneral(g.value),
9662
+ disabled
9663
+ }
9664
+ ),
9665
+ g.label
9666
+ ] }, g.value)) }) })
9667
+ ] }),
9668
+ /* @__PURE__ */ jsxs("div", { children: [
9669
+ /* @__PURE__ */ jsx("p", { className: "mb-2 text-xs font-semibold text-slate-700", children: "Regional examination \u2014 select region(s)" }),
9670
+ /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-2", children: REGIONS.map((r) => {
9671
+ const on = safe.regions.includes(r.key);
9672
+ return /* @__PURE__ */ jsx(
9673
+ Button,
9674
+ {
9675
+ type: "button",
9676
+ size: "sm",
9677
+ variant: on ? "default" : "outline",
9678
+ className: "h-7 rounded-full px-3 text-xs",
9679
+ onClick: () => toggleRegion(r.key),
9680
+ disabled,
9681
+ children: r.label
9682
+ },
9683
+ r.key
9684
+ );
9685
+ }) })
9686
+ ] }),
9687
+ /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
9688
+ has("abdomen") ? /* @__PURE__ */ jsx(RegionCard, { title: "Abdomen \u2014 inspection \xB7 palpation \xB7 percussion \xB7 auscultation", children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-4", children: [
9689
+ /* @__PURE__ */ jsx(SubGroup, { title: "Inspection", children: ABD_INSP.map((o) => /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2 text-xs", children: [
9690
+ /* @__PURE__ */ jsx(
9691
+ Checkbox,
9692
+ {
9693
+ checked: safe.abdomen.inspection.includes(o.value),
9694
+ onCheckedChange: () => toggleAbd("inspection", o.value),
9695
+ disabled
9696
+ }
9697
+ ),
9698
+ o.label
9699
+ ] }, o.value)) }),
9700
+ /* @__PURE__ */ jsxs(SubGroup, { title: "Palpation", children: [
9701
+ ABD_PALP.map((o) => /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2 text-xs", children: [
9702
+ /* @__PURE__ */ jsx(
9703
+ Checkbox,
9704
+ {
9705
+ checked: safe.abdomen.palpation.includes(o.value),
9706
+ onCheckedChange: () => toggleAbd("palpation", o.value),
9707
+ disabled
9708
+ }
9709
+ ),
9710
+ o.label
9711
+ ] }, o.value)),
9712
+ /* @__PURE__ */ jsxs("label", { className: "mt-2 block text-xs", children: [
9713
+ /* @__PURE__ */ jsx("span", { className: "mb-1 block font-medium", children: "Mass size / mobility" }),
9714
+ /* @__PURE__ */ jsx(
9715
+ Input,
9716
+ {
9717
+ className: "h-8 text-xs",
9718
+ value: safe.abdomen.massNotes,
9719
+ onChange: (e) => update({ ...safe, abdomen: { ...safe.abdomen, massNotes: e.target.value } }),
9720
+ disabled
9721
+ }
9722
+ )
9723
+ ] })
9724
+ ] }),
9725
+ /* @__PURE__ */ jsx(SubGroup, { title: "Percussion", children: ABD_PERC.map((o) => /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2 text-xs", children: [
9726
+ /* @__PURE__ */ jsx(
9727
+ Checkbox,
9728
+ {
9729
+ checked: safe.abdomen.percussion.includes(o.value),
9730
+ onCheckedChange: () => toggleAbd("percussion", o.value),
9731
+ disabled
9732
+ }
9733
+ ),
9734
+ o.label
9735
+ ] }, o.value)) }),
9736
+ /* @__PURE__ */ jsxs(SubGroup, { title: "Auscultation", children: [
9737
+ /* @__PURE__ */ jsx("span", { className: "mb-1 block text-xs font-medium", children: "Bowel sounds" }),
9738
+ /* @__PURE__ */ jsxs(
9739
+ Select,
9740
+ {
9741
+ value: safe.abdomen.bowelSounds,
9742
+ onValueChange: (val) => update({
9743
+ ...safe,
9744
+ abdomen: {
9745
+ ...safe.abdomen,
9746
+ bowelSounds: val
9747
+ }
9748
+ }),
9749
+ disabled,
9750
+ children: [
9751
+ /* @__PURE__ */ jsx(SelectTrigger, { className: "h-8 text-xs", children: /* @__PURE__ */ jsx(SelectValue, { placeholder: "Select\u2026" }) }),
9752
+ /* @__PURE__ */ jsxs(SelectContent, { children: [
9753
+ /* @__PURE__ */ jsx(SelectItem, { value: "none", children: "\u2014" }),
9754
+ /* @__PURE__ */ jsx(SelectItem, { value: "normal", children: "Normal" }),
9755
+ /* @__PURE__ */ jsx(SelectItem, { value: "up", children: "\u2191" }),
9756
+ /* @__PURE__ */ jsx(SelectItem, { value: "down", children: "\u2193" }),
9757
+ /* @__PURE__ */ jsx(SelectItem, { value: "absent", children: "Absent" })
9758
+ ] })
9759
+ ]
9760
+ }
9761
+ )
9762
+ ] })
9763
+ ] }) }) : null,
9764
+ has("hernia") ? /* @__PURE__ */ jsx(RegionCard, { title: "Hernia exam", children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 gap-3 text-xs md:grid-cols-4", children: [
9765
+ /* @__PURE__ */ jsxs("label", { className: "block", children: [
9766
+ /* @__PURE__ */ jsx("span", { className: "mb-1 block font-medium", children: "Site" }),
9767
+ /* @__PURE__ */ jsx(
9768
+ Input,
9769
+ {
9770
+ className: "h-8 text-xs",
9771
+ value: safe.hernia.site,
9772
+ onChange: (e) => update({ ...safe, hernia: { ...safe.hernia, site: e.target.value } }),
9773
+ disabled
9774
+ }
9775
+ )
9776
+ ] }),
9777
+ /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2", children: [
9778
+ /* @__PURE__ */ jsx(
9779
+ Checkbox,
9780
+ {
9781
+ checked: safe.hernia.reducible,
9782
+ onCheckedChange: (c) => update({ ...safe, hernia: { ...safe.hernia, reducible: c === true } }),
9783
+ disabled
9784
+ }
9785
+ ),
9786
+ "Reducible"
9787
+ ] }),
9788
+ /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2", children: [
9789
+ /* @__PURE__ */ jsx(
9790
+ Checkbox,
9791
+ {
9792
+ checked: safe.hernia.coughImpulse,
9793
+ onCheckedChange: (c) => update({ ...safe, hernia: { ...safe.hernia, coughImpulse: c === true } }),
9794
+ disabled
9795
+ }
9796
+ ),
9797
+ "Cough impulse"
9798
+ ] }),
9799
+ /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2", children: [
9800
+ /* @__PURE__ */ jsx(
9801
+ Checkbox,
9802
+ {
9803
+ checked: safe.hernia.tenderness,
9804
+ onCheckedChange: (c) => update({ ...safe, hernia: { ...safe.hernia, tenderness: c === true } }),
9805
+ disabled
9806
+ }
9807
+ ),
9808
+ "Tenderness"
9809
+ ] })
9810
+ ] }) }) : null,
9811
+ has("breast") ? /* @__PURE__ */ jsx(RegionCard, { title: "Breast exam", children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 gap-3 text-xs md:grid-cols-4", children: [
9812
+ /* @__PURE__ */ jsxs("label", { className: "block", children: [
9813
+ /* @__PURE__ */ jsx("span", { className: "mb-1 block font-medium", children: "Lump size (cm)" }),
9814
+ /* @__PURE__ */ jsx(
9815
+ Input,
9816
+ {
9817
+ className: "h-8 text-xs",
9818
+ value: safe.breast.lumpSizeCm,
9819
+ onChange: (e) => update({ ...safe, breast: { ...safe.breast, lumpSizeCm: e.target.value } }),
9820
+ disabled
9821
+ }
9822
+ )
9823
+ ] }),
9824
+ /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2", children: [
9825
+ /* @__PURE__ */ jsx(
9826
+ Checkbox,
9827
+ {
9828
+ checked: safe.breast.mobile,
9829
+ onCheckedChange: (c) => update({ ...safe, breast: { ...safe.breast, mobile: c === true } }),
9830
+ disabled
9831
+ }
9832
+ ),
9833
+ "Mobile"
9834
+ ] }),
9835
+ /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2", children: [
9836
+ /* @__PURE__ */ jsx(
9837
+ Checkbox,
9838
+ {
9839
+ checked: safe.breast.skinInvolvement,
9840
+ onCheckedChange: (c) => update({ ...safe, breast: { ...safe.breast, skinInvolvement: c === true } }),
9841
+ disabled
9842
+ }
9843
+ ),
9844
+ "Skin involvement"
9845
+ ] }),
9846
+ /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2", children: [
9847
+ /* @__PURE__ */ jsx(
9848
+ Checkbox,
9849
+ {
9850
+ checked: safe.breast.axillaryNodes,
9851
+ onCheckedChange: (c) => update({ ...safe, breast: { ...safe.breast, axillaryNodes: c === true } }),
9852
+ disabled
9853
+ }
9854
+ ),
9855
+ "Axillary nodes"
9856
+ ] })
9857
+ ] }) }) : null,
9858
+ has("thyroid") ? /* @__PURE__ */ jsx(RegionCard, { title: "Thyroid exam", children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 gap-3 text-xs md:grid-cols-4", children: [
9859
+ /* @__PURE__ */ jsxs("label", { className: "block", children: [
9860
+ /* @__PURE__ */ jsx("span", { className: "mb-1 block font-medium", children: "Size" }),
9861
+ /* @__PURE__ */ jsx(
9862
+ Input,
9863
+ {
9864
+ className: "h-8 text-xs",
9865
+ value: safe.thyroid.size,
9866
+ onChange: (e) => update({ ...safe, thyroid: { ...safe.thyroid, size: e.target.value } }),
9867
+ disabled
9868
+ }
9869
+ )
9870
+ ] }),
9871
+ /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2", children: [
9872
+ /* @__PURE__ */ jsx(
9873
+ Checkbox,
9874
+ {
9875
+ checked: safe.thyroid.mobileDeglutition,
9876
+ onCheckedChange: (c) => update({ ...safe, thyroid: { ...safe.thyroid, mobileDeglutition: c === true } }),
9877
+ disabled
9878
+ }
9879
+ ),
9880
+ "Mobile with deglutition"
9881
+ ] }),
9882
+ /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2", children: [
9883
+ /* @__PURE__ */ jsx(
9884
+ Checkbox,
9885
+ {
9886
+ checked: safe.thyroid.nodules,
9887
+ onCheckedChange: (c) => update({ ...safe, thyroid: { ...safe.thyroid, nodules: c === true } }),
9888
+ disabled
9889
+ }
9890
+ ),
9891
+ "Nodules"
9892
+ ] }),
9893
+ /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2", children: [
9894
+ /* @__PURE__ */ jsx(
9895
+ Checkbox,
9896
+ {
9897
+ checked: safe.thyroid.cervicalNodes,
9898
+ onCheckedChange: (c) => update({ ...safe, thyroid: { ...safe.thyroid, cervicalNodes: c === true } }),
9899
+ disabled
9900
+ }
9901
+ ),
9902
+ "Cervical lymph nodes"
9903
+ ] })
9904
+ ] }) }) : null,
9905
+ has("anorectal") ? /* @__PURE__ */ jsx(RegionCard, { title: "Anorectal exam", children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 gap-3 text-xs md:grid-cols-3", children: [
9906
+ /* @__PURE__ */ jsxs("label", { className: "block md:col-span-3", children: [
9907
+ /* @__PURE__ */ jsx("span", { className: "mb-1 block font-medium", children: "Inspection findings" }),
9908
+ /* @__PURE__ */ jsx(
9909
+ Input,
9910
+ {
9911
+ className: "h-8 text-xs",
9912
+ value: safe.anorectal.inspection,
9913
+ onChange: (e) => update({ ...safe, anorectal: { ...safe.anorectal, inspection: e.target.value } }),
9914
+ disabled
9915
+ }
9916
+ )
9917
+ ] }),
9918
+ /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2", children: [
9919
+ /* @__PURE__ */ jsx(
9920
+ Checkbox,
9921
+ {
9922
+ checked: safe.anorectal.dreDone,
9923
+ onCheckedChange: (c) => update({ ...safe, anorectal: { ...safe.anorectal, dreDone: c === true } }),
9924
+ disabled
9925
+ }
9926
+ ),
9927
+ "DRE done"
9928
+ ] }),
9929
+ /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2", children: [
9930
+ /* @__PURE__ */ jsx(
9931
+ Checkbox,
9932
+ {
9933
+ checked: safe.anorectal.proctoscopyDone,
9934
+ onCheckedChange: (c) => update({ ...safe, anorectal: { ...safe.anorectal, proctoscopyDone: c === true } }),
9935
+ disabled
9936
+ }
9937
+ ),
9938
+ "Proctoscopy done"
9939
+ ] }),
9940
+ /* @__PURE__ */ jsxs("div", { className: "md:col-span-3", children: [
9941
+ /* @__PURE__ */ jsx(Label, { className: "text-xs font-semibold", children: "DRE / proctoscopy notes" }),
9942
+ /* @__PURE__ */ jsx(
9943
+ Textarea,
9944
+ {
9945
+ className: "mt-1 min-h-[64px] text-sm",
9946
+ placeholder: "Sphincter tone, masses, prostate, bleeding\u2026",
9947
+ value: safe.anorectal.notes,
9948
+ onChange: (e) => update({ ...safe, anorectal: { ...safe.anorectal, notes: e.target.value } }),
9949
+ disabled
9950
+ }
9951
+ )
9952
+ ] })
9953
+ ] }) }) : null,
9954
+ has("limb") ? /* @__PURE__ */ jsx(RegionCard, { title: "Limb / varicose veins", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap gap-x-4 gap-y-2 text-xs", children: [
9955
+ /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2", children: [
9956
+ /* @__PURE__ */ jsx(
9957
+ Checkbox,
9958
+ {
9959
+ checked: safe.limb.dilatedVeins,
9960
+ onCheckedChange: (c) => update({ ...safe, limb: { ...safe.limb, dilatedVeins: c === true } }),
9961
+ disabled
9962
+ }
9963
+ ),
9964
+ "Dilated veins"
9965
+ ] }),
9966
+ /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2", children: [
9967
+ /* @__PURE__ */ jsx(
9968
+ Checkbox,
9969
+ {
9970
+ checked: safe.limb.ulcer,
9971
+ onCheckedChange: (c) => update({ ...safe, limb: { ...safe.limb, ulcer: c === true } }),
9972
+ disabled
9973
+ }
9974
+ ),
9975
+ "Ulcer"
9976
+ ] }),
9977
+ /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2", children: [
9978
+ /* @__PURE__ */ jsx(
9979
+ Checkbox,
9980
+ {
9981
+ checked: safe.limb.oedema,
9982
+ onCheckedChange: (c) => update({ ...safe, limb: { ...safe.limb, oedema: c === true } }),
9983
+ disabled
9984
+ }
9985
+ ),
9986
+ "Oedema"
9987
+ ] })
9988
+ ] }) }) : null
9989
+ ] }),
9990
+ /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
9991
+ /* @__PURE__ */ jsx(Label, { className: "text-xs font-semibold text-slate-700", children: clinicalField.fieldDef?.label ?? "Clinical examination" }),
9992
+ /* @__PURE__ */ jsx(
9993
+ Textarea,
9994
+ {
9995
+ className: "min-h-[88px] rounded-md border border-input bg-white text-sm",
9996
+ value: typeof clinicalField.value === "string" ? clinicalField.value : clinicalField.value == null ? "" : String(clinicalField.value),
9997
+ onChange: (e) => {
9998
+ clinicalField.setValue(e.target.value);
9999
+ clinicalField.setTouched();
10000
+ },
10001
+ disabled: disabled || clinicalField.disabled
10002
+ }
10003
+ )
10004
+ ] })
10005
+ ] }),
10006
+ showError ? /* @__PURE__ */ jsx("p", { className: "px-3 pb-2 text-xs text-red-500", children: error }) : null
10007
+ ] });
10008
+ };
10009
+ var CHIEF_CHIPS_FIELD2 = "chief_complaints_chips";
10010
+ var GS_EXAMINATION_FIELD = "gs_examination";
10011
+ function chipList2(state) {
10012
+ const raw = state.values[CHIEF_CHIPS_FIELD2];
10013
+ return Array.isArray(raw) ? raw.filter((x) => typeof x === "string") : [];
10014
+ }
10015
+ function regionList(state) {
10016
+ const raw = state.values[GS_EXAMINATION_FIELD];
10017
+ const ex = normalizeGeneralSurgeryExamination(raw);
10018
+ return ex.regions;
10019
+ }
10020
+ var GsGradingWidget = ({ fieldId }) => {
10021
+ const { fieldDef, value, setValue, setTouched, error, touched, disabled } = useField(fieldId);
10022
+ const { state } = useForm();
10023
+ const showError = !!error && (touched || state.submitAttempted);
10024
+ const safe = useMemo(() => normalizeGeneralSurgeryGrading(value), [value]);
10025
+ const chips = useMemo(() => chipList2(state), [state]);
10026
+ const regions = useMemo(() => regionList(state), [state]);
10027
+ const visibleRows = useMemo(() => {
10028
+ return ALL_GS_CONDITIONS.filter(
10029
+ (c) => gsGradingRowVisible(c, chips, regions, safe[c] ?? 0)
10030
+ );
10031
+ }, [chips, regions, safe]);
10032
+ const update = (next) => {
10033
+ setValue(next);
10034
+ setTouched();
10035
+ };
10036
+ const setGrade = (cond, gradeStr) => {
10037
+ const n = Math.min(5, Math.max(0, Math.round(Number(gradeStr)) || 0));
10038
+ update({ ...safe, [cond]: n });
10039
+ };
10040
+ if (!fieldDef) return null;
10041
+ const theme = getThemeConfig("textarea", fieldDef.theme);
10042
+ const wrapperClass = theme?.wrapperClassName ?? "rounded-md overflow-hidden flex flex-col border border-[#D0D0D0]";
10043
+ const labelClass = theme?.labelClassName;
10044
+ const labelContent = /* @__PURE__ */ jsxs(Fragment, { children: [
10045
+ fieldDef.label,
10046
+ fieldDef.required ? /* @__PURE__ */ jsx("span", { className: "ml-1 text-red-500", children: "*" }) : null
10047
+ ] });
10048
+ const labelEl = theme ? /* @__PURE__ */ jsx(Label, { className: labelClass, children: labelContent }) : /* @__PURE__ */ jsx(Label, { className: "text-sm font-medium", children: labelContent });
10049
+ const bodyClass = cn(
10050
+ "-mt-1 flex min-w-0 flex-col gap-3 border-t border-[#D0D0D0] bg-white px-3 py-3",
10051
+ disabled && "pointer-events-none opacity-60"
10052
+ );
10053
+ return /* @__PURE__ */ jsxs("div", { className: cn("w-full min-w-0", wrapperClass), children: [
10054
+ labelEl,
10055
+ /* @__PURE__ */ jsx("div", { className: bodyClass, children: visibleRows.length === 0 ? /* @__PURE__ */ 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__ */ jsx("div", { className: "overflow-x-auto rounded-md border border-[#D0D0D0]", children: /* @__PURE__ */ jsxs("table", { className: "w-full min-w-[520px] border-collapse text-xs", children: [
10056
+ /* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { className: "border-b border-[#D0D0D0] bg-[#FEE8EC]/50", children: [
10057
+ /* @__PURE__ */ jsx("th", { className: "px-3 py-2 text-left font-semibold text-slate-700", children: "Condition" }),
10058
+ /* @__PURE__ */ jsx("th", { className: "w-24 px-2 py-2 font-semibold text-slate-700", children: "Grade" }),
10059
+ /* @__PURE__ */ jsx("th", { className: "px-3 py-2 text-left font-semibold text-slate-700", children: "Description" })
10060
+ ] }) }),
10061
+ /* @__PURE__ */ jsx("tbody", { className: "bg-white", children: visibleRows.map((c) => {
10062
+ const g = safe[c] ?? 0;
10063
+ const desc = GS_GRADE_DESCRIPTIONS[c][g] ?? "\u2014";
10064
+ return /* @__PURE__ */ jsxs("tr", { className: "border-b border-[#D0D0D0]/80 last:border-0", children: [
10065
+ /* @__PURE__ */ jsx("td", { className: "px-3 py-2 font-medium", children: GS_CONDITION_LABELS[c] }),
10066
+ /* @__PURE__ */ jsx("td", { className: "px-2 py-1.5 align-middle", children: /* @__PURE__ */ jsxs(
10067
+ Select,
10068
+ {
10069
+ value: String(g),
10070
+ onValueChange: (v) => setGrade(c, v),
10071
+ disabled,
10072
+ children: [
10073
+ /* @__PURE__ */ jsx(SelectTrigger, { className: "h-8 text-xs", children: /* @__PURE__ */ jsx(SelectValue, {}) }),
10074
+ /* @__PURE__ */ jsx(SelectContent, { children: [0, 1, 2, 3, 4, 5].map((n) => /* @__PURE__ */ jsx(SelectItem, { value: String(n), children: n === 0 ? "\u2014" : String(n) }, n)) })
10075
+ ]
10076
+ }
10077
+ ) }),
10078
+ /* @__PURE__ */ jsx("td", { className: "px-3 py-2 text-muted-foreground", children: desc })
10079
+ ] }, c);
10080
+ }) })
10081
+ ] }) }) }),
10082
+ showError ? /* @__PURE__ */ jsx("p", { className: "px-3 pb-2 text-xs text-red-500", children: error }) : null
10083
+ ] });
10084
+ };
10085
+ function isFlagSelected(selected, optValue) {
10086
+ return selected.some((v) => v === optValue || String(v) === String(optValue));
10087
+ }
10088
+ var PainScaleFlagsWidget = ({ fieldId }) => {
10089
+ const { fieldDef, value, setValue, setTouched, error, touched, disabled } = useField(fieldId);
10090
+ const { state } = useForm();
10091
+ const showError = !!error && (touched || state.submitAttempted);
10092
+ if (!fieldDef || fieldDef.type !== "pain_scale_flags") return null;
10093
+ const def = fieldDef;
10094
+ const min = def.min ?? 0;
10095
+ const max = def.max ?? 10;
10096
+ const step = def.step ?? 1;
10097
+ const flagOptions = def.options ?? [];
10098
+ const safe = useMemo(
10099
+ () => normalizePainScaleFlags(value, { min, max }),
10100
+ [value, min, max]
10101
+ );
10102
+ const theme = getThemeConfig("textarea", def.theme);
10103
+ const wrapperClass = theme?.wrapperClassName ?? "space-y-2";
10104
+ const labelClass = theme?.labelClassName;
10105
+ const update = (next) => {
10106
+ setValue(normalizePainScaleFlags(next, { min, max }));
10107
+ setTouched();
10108
+ };
10109
+ const toggleFlag = (optValue) => {
10110
+ const sel = safe.flags;
10111
+ const isSelected = isFlagSelected(sel, optValue);
10112
+ const nextFlags = isSelected ? sel.filter((v) => v !== optValue && String(v) !== String(optValue)) : [...sel, String(optValue)];
10113
+ update({ pain: safe.pain, flags: nextFlags });
10114
+ };
10115
+ const labelContent = /* @__PURE__ */ jsxs(Fragment, { children: [
10116
+ def.label,
10117
+ " ",
10118
+ def.required && /* @__PURE__ */ jsx("span", { className: "text-red-500", children: "*" })
10119
+ ] });
10120
+ const labelEl = theme ? /* @__PURE__ */ jsx(Label, { className: labelClass, children: labelContent }) : /* @__PURE__ */ jsx(Label, { children: labelContent });
10121
+ const bodyClass = cn(
10122
+ "-mt-1 flex min-w-0 flex-col border-t border-[#D0D0D0] bg-white px-3 py-3",
10123
+ disabled && "pointer-events-none opacity-60"
10124
+ );
10125
+ return /* @__PURE__ */ jsxs("div", { className: cn(wrapperClass, "h-full min-h-0 flex flex-col"), children: [
10126
+ labelEl,
10127
+ def.description && /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: def.description }),
10128
+ /* @__PURE__ */ jsx("div", { className: cn(bodyClass, "min-h-0 flex-1"), children: /* @__PURE__ */ jsxs("div", { className: "min-w-0 space-y-3", children: [
10129
+ /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
10130
+ /* @__PURE__ */ jsxs(Label, { className: "text-sm font-medium text-slate-700", children: [
10131
+ "Pain score (VAS)",
10132
+ /* @__PURE__ */ jsxs("span", { className: "ml-2 font-normal tabular-nums text-muted-foreground", children: [
10133
+ safe.pain,
10134
+ "/",
10135
+ max
10136
+ ] })
10137
+ ] }),
10138
+ /* @__PURE__ */ jsx(
10139
+ Slider,
10140
+ {
10141
+ className: cn("py-1", showError && "rounded opacity-90 ring-1 ring-red-500"),
10142
+ disabled,
10143
+ min,
10144
+ max,
10145
+ step,
10146
+ value: [safe.pain],
10147
+ onValueChange: (v) => {
10148
+ const n = v[0] ?? min;
10149
+ update({ pain: n, flags: safe.flags });
10150
+ }
10151
+ }
10152
+ )
10153
+ ] }),
10154
+ flagOptions.length > 0 ? /* @__PURE__ */ jsxs("div", { className: "min-w-0 space-y-1.5", children: [
10155
+ /* @__PURE__ */ jsx(Label, { className: "text-sm font-medium text-slate-700", children: "Triage flags" }),
10156
+ /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-x-4 gap-y-2", children: flagOptions.map((opt) => /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
10157
+ /* @__PURE__ */ jsx(
10158
+ Checkbox,
10159
+ {
10160
+ id: `${fieldId}-flag-${String(opt.value)}`,
10161
+ checked: isFlagSelected(safe.flags, opt.value),
10162
+ onCheckedChange: () => toggleFlag(opt.value),
10163
+ disabled
10164
+ }
10165
+ ),
10166
+ /* @__PURE__ */ jsx(
10167
+ Label,
10168
+ {
10169
+ htmlFor: `${fieldId}-flag-${String(opt.value)}`,
10170
+ className: "cursor-pointer text-sm font-normal leading-none",
10171
+ children: opt.label
10172
+ }
10173
+ )
10174
+ ] }, String(opt.value))) })
10175
+ ] }) : null
10176
+ ] }) }),
10177
+ showError && /* @__PURE__ */ jsx("p", { className: "text-xs text-red-500", children: error })
10178
+ ] });
10179
+ };
10180
+ var FieldRenderer = ({ fieldId }) => {
10181
+ const { fieldDef, visible } = useField(fieldId);
10182
+ if (!visible || !fieldDef) {
10183
+ return null;
10184
+ }
10185
+ return renderWidget(fieldId, fieldDef);
10186
+ };
10187
+ function renderWidget(fieldId, fieldDef) {
10188
+ switch (fieldDef.type) {
10189
+ case "text":
10190
+ case "number":
10191
+ return /* @__PURE__ */ jsx(TextWidget, { fieldId });
10192
+ case "slider":
10193
+ return /* @__PURE__ */ jsx(SliderWidget, { fieldId });
10194
+ case "textarea":
10195
+ if (fieldMetaRequestsMarMedicationOrdersButton(fieldDef.meta)) {
10196
+ return /* @__PURE__ */ jsx(MarMedicationOrdersWidget, { fieldId });
10197
+ }
10198
+ return /* @__PURE__ */ jsx(TextWidget, { fieldId });
10199
+ case "richtext":
10200
+ return /* @__PURE__ */ jsx(RichTextWidget, { fieldId });
10201
+ case "date":
10202
+ return /* @__PURE__ */ jsx(DateWidget, { fieldId });
10203
+ case "datetime":
10204
+ return /* @__PURE__ */ jsx(DateTimeWidget, { fieldId });
10205
+ case "select":
10206
+ return /* @__PURE__ */ jsx(SelectWidget, { fieldId });
10207
+ case "radio":
10208
+ return /* @__PURE__ */ jsx(RadioWidget, { fieldId });
10209
+ case "checkbox":
10210
+ return /* @__PURE__ */ jsx(CheckboxWidget, { fieldId });
10211
+ case "multiselect":
10212
+ return /* @__PURE__ */ jsx(MultiSelectWidget, { fieldId });
10213
+ case "repeatable":
10214
+ return /* @__PURE__ */ jsx(RepeatableWidget, { fieldId });
10215
+ case "image_upload":
10216
+ return /* @__PURE__ */ jsx(ImageUploadWidget, { fieldId });
10217
+ case "media_upload":
10218
+ return /* @__PURE__ */ jsx(MediaUploadWidget, { fieldId });
10219
+ case "signature":
10220
+ return /* @__PURE__ */ jsx(SignatureUploadWidget, { fieldId });
10221
+ case "editable_table":
10222
+ return /* @__PURE__ */ jsx(EditableTableWidget, { fieldId });
10223
+ case "medications":
10224
+ return /* @__PURE__ */ jsx(AddMedicationWidget, { fieldId });
10225
+ case "discharge_medication_orders":
10226
+ return /* @__PURE__ */ jsx(DischargeMedicationOrdersWidget, { fieldId });
10227
+ case "investigations":
10228
+ return /* @__PURE__ */ jsx(AddInvestigationWidget, { fieldId });
10229
+ case "procedures":
10230
+ return /* @__PURE__ */ jsx(AddProcedureWidget, { fieldId });
10231
+ case "differential_diagnosis":
10232
+ return /* @__PURE__ */ jsx(DifferentialDiagnosisWidget, { fieldId });
10233
+ case "vitals":
10234
+ return /* @__PURE__ */ jsx(VitalsWidget, { fieldId });
10235
+ case "hidden_vitals":
10236
+ return /* @__PURE__ */ jsx(HiddenVitalsWidget, { fieldId });
10237
+ case "referral":
10238
+ return /* @__PURE__ */ jsx(ReferralWidget, { fieldId });
10239
+ case "followup":
10240
+ return /* @__PURE__ */ jsx(FollowupWidget, { fieldId });
10241
+ case "smart_textarea":
10242
+ return /* @__PURE__ */ jsx(SmartTextareaWidget, { fieldId });
10243
+ case "diagnosis_textarea":
10244
+ return /* @__PURE__ */ jsx(DiagnosisTextareaWidget, { fieldId });
10245
+ case "obstetric_history":
10246
+ return /* @__PURE__ */ jsx(ObstetricHistoryWidget, { fieldId });
10247
+ case "eye_prescription":
10248
+ return /* @__PURE__ */ jsx(OphthalmologyWidget, { fieldId });
10249
+ case "ophthal_diagnosis":
10250
+ return /* @__PURE__ */ jsx(OphthalDiagnosisWidget, { fieldId });
10251
+ case "orthopedic_exam":
10252
+ return /* @__PURE__ */ jsx(OrthopedicExamWidget, { fieldId });
10253
+ case "general_surgery_smart_history":
10254
+ return /* @__PURE__ */ jsx(GsSmartHistoryWidget, { fieldId });
10255
+ case "general_surgery_examination":
10256
+ return /* @__PURE__ */ jsx(GsExaminationWidget, { fieldId });
10257
+ case "general_surgery_grading":
10258
+ return /* @__PURE__ */ jsx(GsGradingWidget, { fieldId });
10259
+ case "pain_scale_flags":
10260
+ return /* @__PURE__ */ jsx(PainScaleFlagsWidget, { fieldId });
10261
+ case "toggle": {
10262
+ const { value, setValue, setTouched, disabled } = useField(fieldId);
10263
+ const store = useFormStore();
10264
+ const excludes = fieldDef.excludes ?? [];
10265
+ return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
10266
+ /* @__PURE__ */ jsx(
10267
+ Switch,
10268
+ {
10269
+ checked: value === true,
10270
+ disabled,
10271
+ onCheckedChange: (checked) => {
10272
+ setValue(checked);
10273
+ setTouched();
10274
+ if (checked) excludes.forEach((id) => store.setValue(id, false));
10275
+ }
10276
+ }
10277
+ ),
10278
+ /* @__PURE__ */ jsx(Label, { className: "text-sm font-medium leading-none cursor-pointer select-none", children: fieldDef.label })
10279
+ ] });
10280
+ }
10281
+ case "suggestion_textarea":
10282
+ case "complaint_chips":
10283
+ return /* @__PURE__ */ jsx(SuggestionTextareaWidget, { fieldId });
10284
+ case "lens_assessment":
10285
+ return /* @__PURE__ */ jsx(LensAssessmentWidget, { fieldId });
10286
+ case "functional_impairment_score":
10287
+ return /* @__PURE__ */ jsx(FunctionalImpairmentScoreWidget, { fieldId });
10288
+ case "biometry_iol_workup":
10289
+ return /* @__PURE__ */ jsx(BiometryIolWorkupWidget, { fieldId });
10290
+ case "surgical_risk_flags":
10291
+ return /* @__PURE__ */ jsx(SurgicalRiskFlagsWidget, { fieldId });
10292
+ case "static_text": {
10293
+ const def = fieldDef;
10294
+ const size = def.size ?? "regular";
10295
+ const labelClass = size === "large" ? "text-base" : "text-sm";
10296
+ const descClass = size === "large" ? "text-sm" : "text-xs";
10297
+ return /* @__PURE__ */ jsxs("div", { className: `${labelClass} text-muted-foreground`, children: [
10298
+ def.label,
10299
+ def.description && /* @__PURE__ */ jsx("p", { className: `mt-1 ${descClass} opacity-90`, children: def.description })
10300
+ ] });
10301
+ }
10302
+ default:
10303
+ return /* @__PURE__ */ jsxs("div", { className: "text-red-500", children: [
10304
+ "Unknown field type: ",
10305
+ fieldDef.type
10306
+ ] });
10307
+ }
10308
+ }
10309
+ var Section = ({ title, children }) => {
10310
+ const [expanded, setExpanded] = useState(true);
10311
+ const handleToggle = () => setExpanded((prev) => !prev);
10312
+ const contentClassName = cn(
10313
+ "overflow-hidden transition-[height] duration-200 ease-in-out",
10314
+ !expanded && "hidden"
10315
+ );
10316
+ return /* @__PURE__ */ jsxs("div", { className: "mb-6 border rounded-lg bg-white shadow-sm overflow-hidden", children: [
10317
+ /* @__PURE__ */ jsxs(
10318
+ "button",
10319
+ {
10320
+ type: "button",
10321
+ onClick: handleToggle,
10322
+ className: "w-full flex items-center justify-between gap-2 p-4 text-left border-b hover:bg-gray-50/80 transition-colors",
10323
+ children: [
10324
+ /* @__PURE__ */ jsx("h3", { className: "text-lg font-medium", children: title }),
10325
+ /* @__PURE__ */ jsx("span", { className: "flex-shrink-0 text-muted-foreground", "aria-hidden": true, children: expanded ? /* @__PURE__ */ jsx(ChevronDown, { className: "h-5 w-5" }) : /* @__PURE__ */ jsx(ChevronRight, { className: "h-5 w-5" }) })
10326
+ ]
10327
+ }
10328
+ ),
10329
+ /* @__PURE__ */ jsx("div", { className: contentClassName, children: /* @__PURE__ */ jsx("div", { className: "p-4 pt-4 space-y-4 border-t-0", children }) })
10330
+ ] });
10331
+ };
10332
+ var ColumnLayout = ({
10333
+ columns,
10334
+ label,
10335
+ children
10336
+ }) => {
10337
+ const gridCols = Math.max(1, Math.min(columns, 12));
10338
+ const gridClass = `grid gap-4 w-full`;
10339
+ const style = {
10340
+ gridTemplateColumns: `repeat(${gridCols}, minmax(0, 1fr))`
10341
+ };
10342
+ return /* @__PURE__ */ jsxs("div", { className: "mb-6", children: [
10343
+ label != null && label !== "" && /* @__PURE__ */ jsx("div", { className: "mb-2 text-sm font-medium text-gray-700", children: label }),
10344
+ /* @__PURE__ */ jsx("div", { className: gridClass, style, children })
10345
+ ] });
10346
+ };
10347
+ var DynamicForm = () => {
10348
+ const store = useFormStore();
10349
+ const schema = store.getSchema();
10350
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-6", children: [
10351
+ /* @__PURE__ */ jsx("div", { className: "mb-4", children: /* @__PURE__ */ jsx("h1", { className: "text-2xl font-bold", children: schema.title }) }),
10352
+ schema.layout.map((node) => {
10353
+ if (node.type === "section") {
10354
+ return /* @__PURE__ */ jsx(Section, { title: node.title, children: node.children.map(
10355
+ (child, index) => typeof child === "string" ? /* @__PURE__ */ jsx(FieldRenderer, { fieldId: child }, child) : child.type === "column_layout" ? /* @__PURE__ */ jsx(
10356
+ ColumnLayout,
10357
+ {
10358
+ columns: child.columns,
10359
+ label: child.label,
10360
+ children: child.children.map((fieldId) => /* @__PURE__ */ jsx(FieldRenderer, { fieldId }, fieldId))
10361
+ },
9084
10362
  child.id
9085
10363
  ) : /* @__PURE__ */ jsx(React15__default.Fragment, {}, child.id ?? index)
9086
10364
  ) }, node.id);
@@ -9215,14 +10493,24 @@ var SmartForm = ({
9215
10493
  if (position !== "left") return null;
9216
10494
  return /* @__PURE__ */ jsx(FieldRenderer, { fieldId }, fieldId);
9217
10495
  }) }),
9218
- /* @__PURE__ */ jsx("div", { className: "col-span-2 grid grid-cols-2 gap-x-2 space-y-2", children: fieldIds.map((fieldId) => {
10496
+ /* @__PURE__ */ jsx("div", { className: "col-span-2 grid grid-cols-2 gap-2", children: fieldIds.map((fieldId) => {
9219
10497
  const fieldDef = store.getFieldDef(fieldId);
9220
10498
  if (!fieldDef) return null;
9221
10499
  const position = fieldDef.position ?? "center";
9222
10500
  if (position !== "center") return null;
9223
10501
  const colSpanRaw = fieldDef.colSpan ?? 1;
9224
10502
  const colSpan = colSpanRaw === 2 ? 2 : 1;
9225
- return /* @__PURE__ */ jsx("div", { className: colSpan === 2 ? "col-span-2" : "col-span-1", children: /* @__PURE__ */ jsx(FieldRenderer, { fieldId }) }, fieldId);
10503
+ return /* @__PURE__ */ jsx(
10504
+ "div",
10505
+ {
10506
+ className: cn(
10507
+ "min-h-0 flex flex-col",
10508
+ colSpan === 2 ? "col-span-2" : "col-span-1 h-full"
10509
+ ),
10510
+ children: /* @__PURE__ */ jsx(FieldRenderer, { fieldId })
10511
+ },
10512
+ fieldId
10513
+ );
9226
10514
  }) }),
9227
10515
  /* @__PURE__ */ jsx("div", { className: "col-span-1 flex flex-col gap-2", children: fieldIds.map((fieldId) => {
9228
10516
  const fieldDef = store.getFieldDef(fieldId);
@@ -9670,11 +10958,17 @@ var ReadOnlyDischargeMedicationOrders = ({ fieldDef, value }) => {
9670
10958
  }) })
9671
10959
  ] });
9672
10960
  };
9673
- var ReadOnlyFieldRenderer = ({ fieldDef, value }) => {
10961
+ var ReadOnlyFieldRenderer = ({
10962
+ fieldDef,
10963
+ value,
10964
+ allValues,
10965
+ resolveFieldDef
10966
+ }) => {
9674
10967
  if (!fieldDef) return null;
9675
10968
  switch (fieldDef.type) {
9676
10969
  case "text":
9677
10970
  case "number":
10971
+ case "slider":
9678
10972
  case "textarea":
9679
10973
  case "richtext":
9680
10974
  return /* @__PURE__ */ jsx(ReadOnlyText, { fieldDef, value });
@@ -9712,8 +11006,30 @@ var ReadOnlyFieldRenderer = ({ fieldDef, value }) => {
9712
11006
  ] });
9713
11007
  }
9714
11008
  case "suggestion_textarea":
9715
- case "complaint_chips":
9716
- return /* @__PURE__ */ jsx(ReadOnlyText, { fieldDef, value });
11009
+ case "complaint_chips": {
11010
+ 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()) : [];
11011
+ const showEmbedded = embeddedIds.length > 0 && resolveFieldDef && allValues && typeof allValues === "object";
11012
+ if (!showEmbedded) {
11013
+ return /* @__PURE__ */ jsx(ReadOnlyText, { fieldDef, value });
11014
+ }
11015
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
11016
+ /* @__PURE__ */ jsx(ReadOnlyText, { fieldDef, value }),
11017
+ /* @__PURE__ */ jsx("div", { className: "grid gap-3 border-t border-muted-foreground/20 pt-3 sm:grid-cols-3", children: embeddedIds.map((id) => {
11018
+ const fd = resolveFieldDef(id);
11019
+ if (!fd) return null;
11020
+ return /* @__PURE__ */ jsx(
11021
+ ReadOnlyFieldRenderer,
11022
+ {
11023
+ fieldDef: fd,
11024
+ value: allValues[id],
11025
+ allValues,
11026
+ resolveFieldDef
11027
+ },
11028
+ id
11029
+ );
11030
+ }) })
11031
+ ] });
11032
+ }
9717
11033
  case "lens_assessment": {
9718
11034
  const v = value && typeof value === "object" && !Array.isArray(value) ? value : null;
9719
11035
  const notes = typeof v?.notes === "string" ? v.notes : "";
@@ -9789,6 +11105,44 @@ var ReadOnlyFieldRenderer = ({ fieldDef, value }) => {
9789
11105
  const lines = [`Right eye (OD): ${od}`, `Left eye (OS): ${os}`].join("\n");
9790
11106
  return /* @__PURE__ */ jsx(ReadOnlyText, { fieldDef, value: lines });
9791
11107
  }
11108
+ case "pain_scale_flags": {
11109
+ const def = fieldDef;
11110
+ const min = def.min ?? 0;
11111
+ const max = def.max ?? 10;
11112
+ const safe = normalizePainScaleFlags(value, { min, max });
11113
+ const opts = def.options ?? [];
11114
+ const flagLabels = safe.flags.map((fv) => {
11115
+ const o = opts.find((x) => x.value === fv || String(x.value) === String(fv));
11116
+ return o?.label ?? fv;
11117
+ });
11118
+ const lines = [
11119
+ `Pain score (VAS): ${safe.pain}/${max}`,
11120
+ flagLabels.length > 0 ? `Triage flags: ${flagLabels.join(", ")}` : "Triage flags: \u2014"
11121
+ ].join("\n");
11122
+ return /* @__PURE__ */ jsx(ReadOnlyText, { fieldDef, value: lines });
11123
+ }
11124
+ case "general_surgery_smart_history":
11125
+ case "general_surgery_grading":
11126
+ return /* @__PURE__ */ jsx(
11127
+ ReadOnlyText,
11128
+ {
11129
+ fieldDef,
11130
+ value: value && typeof value === "object" ? JSON.stringify(value, null, 2) : value == null || value === "" ? "\u2014" : String(value)
11131
+ }
11132
+ );
11133
+ case "general_surgery_examination": {
11134
+ const structuredDisplay = value && typeof value === "object" ? JSON.stringify(value, null, 2) : value == null || value === "" ? "\u2014" : String(value);
11135
+ const clinicalDef = resolveFieldDef?.("clinical_examination");
11136
+ const clinicalRaw = allValues?.["clinical_examination"];
11137
+ const clinicalStr = typeof clinicalRaw === "string" ? clinicalRaw : clinicalRaw != null && clinicalRaw !== "" ? String(clinicalRaw) : "";
11138
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
11139
+ /* @__PURE__ */ jsx(ReadOnlyText, { fieldDef, value: structuredDisplay }),
11140
+ clinicalDef ? /* @__PURE__ */ jsx(ReadOnlyText, { fieldDef: clinicalDef, value: clinicalStr }) : clinicalStr ? /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
11141
+ /* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-gray-700", children: "Clinical examination" }),
11142
+ /* @__PURE__ */ jsx("div", { className: "text-gray-900 border border-gray-200 rounded-md p-3 bg-gray-50 min-h-[2.5rem] whitespace-pre-wrap", children: clinicalStr })
11143
+ ] }) : null
11144
+ ] });
11145
+ }
9792
11146
  case "static_text": {
9793
11147
  const def = fieldDef;
9794
11148
  const size = def.size ?? "regular";
@@ -9835,7 +11189,9 @@ var ReadOnlyForm = ({ schema, submission }) => {
9835
11189
  ReadOnlyFieldRenderer,
9836
11190
  {
9837
11191
  fieldDef,
9838
- value: formData[child]
11192
+ value: formData[child],
11193
+ allValues: formData,
11194
+ resolveFieldDef: (id) => fieldMap.get(id)
9839
11195
  },
9840
11196
  child
9841
11197
  ) : null;
@@ -9854,7 +11210,9 @@ var ReadOnlyForm = ({ schema, submission }) => {
9854
11210
  ReadOnlyFieldRenderer,
9855
11211
  {
9856
11212
  fieldDef,
9857
- value: formData[fieldId]
11213
+ value: formData[fieldId],
11214
+ allValues: formData,
11215
+ resolveFieldDef: (id) => fieldMap.get(id)
9858
11216
  },
9859
11217
  fieldId
9860
11218
  ))
@@ -9885,7 +11243,9 @@ var ReadOnlyForm = ({ schema, submission }) => {
9885
11243
  ReadOnlyFieldRenderer,
9886
11244
  {
9887
11245
  fieldDef,
9888
- value: formData[fieldId]
11246
+ value: formData[fieldId],
11247
+ allValues: formData,
11248
+ resolveFieldDef: (id) => fieldMap.get(id)
9889
11249
  },
9890
11250
  fieldId
9891
11251
  ))