formanitor 0.2.3 → 0.2.4

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.
Files changed (118) hide show
  1. package/dist/BpeChartWidget-HATASHAC.mjs +7 -0
  2. package/dist/BpeChartWidget-HATASHAC.mjs.map +1 -0
  3. package/dist/BpeChartWidget-VZRH7M7L.cjs +28 -0
  4. package/dist/BpeChartWidget-VZRH7M7L.cjs.map +1 -0
  5. package/dist/{DateTimeWidget-3AUBZYYK.mjs → DateTimeWidget-KRX4O6OD.mjs} +5 -4
  6. package/dist/DateTimeWidget-KRX4O6OD.mjs.map +1 -0
  7. package/dist/{DateTimeWidget-OS7ER5F6.cjs → DateTimeWidget-RJ7SATVA.cjs} +6 -5
  8. package/dist/DateTimeWidget-RJ7SATVA.cjs.map +1 -0
  9. package/dist/{DateWidget-KCTE6N5G.mjs → DateWidget-JEKDKPNS.mjs} +4 -3
  10. package/dist/DateWidget-JEKDKPNS.mjs.map +1 -0
  11. package/dist/{DateWidget-UNLX544Z.cjs → DateWidget-T7IQUWEA.cjs} +8 -7
  12. package/dist/DateWidget-T7IQUWEA.cjs.map +1 -0
  13. package/dist/DentalChartWidget-LYLOFWZU.cjs +21 -0
  14. package/dist/DentalChartWidget-LYLOFWZU.cjs.map +1 -0
  15. package/dist/DentalChartWidget-P2YPKAMO.mjs +8 -0
  16. package/dist/DentalChartWidget-P2YPKAMO.mjs.map +1 -0
  17. package/dist/{EditableTable-VQ72UEFF.cjs → EditableTable-OW5LC6OC.cjs} +6 -5
  18. package/dist/EditableTable-OW5LC6OC.cjs.map +1 -0
  19. package/dist/{EditableTable-XFCPKSUY.mjs → EditableTable-VZ66IXYI.mjs} +5 -4
  20. package/dist/EditableTable-VZ66IXYI.mjs.map +1 -0
  21. package/dist/ExtraOralExamWidget-JVKJ4ZWC.mjs +438 -0
  22. package/dist/ExtraOralExamWidget-JVKJ4ZWC.mjs.map +1 -0
  23. package/dist/ExtraOralExamWidget-ZIOSKMIO.cjs +440 -0
  24. package/dist/ExtraOralExamWidget-ZIOSKMIO.cjs.map +1 -0
  25. package/dist/{FollowupWidget-MAYTHM2E.cjs → FollowupWidget-2STSJSDY.cjs} +8 -7
  26. package/dist/FollowupWidget-2STSJSDY.cjs.map +1 -0
  27. package/dist/{FollowupWidget-BFZ6P2JE.mjs → FollowupWidget-GCGPWZVY.mjs} +4 -3
  28. package/dist/FollowupWidget-GCGPWZVY.mjs.map +1 -0
  29. package/dist/{OBGPathwayWidget-X67XKRIH.mjs → OBGPathwayWidget-QJNWUIEM.mjs} +4 -3
  30. package/dist/OBGPathwayWidget-QJNWUIEM.mjs.map +1 -0
  31. package/dist/{OBGPathwayWidget-XGN3HEWS.cjs → OBGPathwayWidget-YRU36UL7.cjs} +13 -12
  32. package/dist/OBGPathwayWidget-YRU36UL7.cjs.map +1 -0
  33. package/dist/{ObstetricHistoryWidget-Z4VAXH3E.mjs → ObstetricHistoryWidget-EW6JLNQ7.mjs} +4 -3
  34. package/dist/ObstetricHistoryWidget-EW6JLNQ7.mjs.map +1 -0
  35. package/dist/{ObstetricHistoryWidget-RP7NY4PV.cjs → ObstetricHistoryWidget-OOWCVFRB.cjs} +10 -9
  36. package/dist/ObstetricHistoryWidget-OOWCVFRB.cjs.map +1 -0
  37. package/dist/PregnancyStatusWidget-QTTVFBOE.cjs +96 -0
  38. package/dist/PregnancyStatusWidget-QTTVFBOE.cjs.map +1 -0
  39. package/dist/PregnancyStatusWidget-U2BEJGBJ.mjs +94 -0
  40. package/dist/PregnancyStatusWidget-U2BEJGBJ.mjs.map +1 -0
  41. package/dist/{SuggestionTextareaWidget-DY6M5JPO.cjs → SuggestionTextareaWidget-FWRZ46MV.cjs} +5 -5
  42. package/dist/{SuggestionTextareaWidget-DY6M5JPO.cjs.map → SuggestionTextareaWidget-FWRZ46MV.cjs.map} +1 -1
  43. package/dist/{SuggestionTextareaWidget-GQTWCFBG.mjs → SuggestionTextareaWidget-UNL3FZRI.mjs} +3 -3
  44. package/dist/{SuggestionTextareaWidget-GQTWCFBG.mjs.map → SuggestionTextareaWidget-UNL3FZRI.mjs.map} +1 -1
  45. package/dist/TreatmentPlanWidget-665HLKYV.mjs +317 -0
  46. package/dist/TreatmentPlanWidget-665HLKYV.mjs.map +1 -0
  47. package/dist/TreatmentPlanWidget-TATWSPLY.cjs +319 -0
  48. package/dist/TreatmentPlanWidget-TATWSPLY.cjs.map +1 -0
  49. package/dist/{chunk-4PMNVBJD.mjs → chunk-2OMQV2ZB.mjs} +4 -3
  50. package/dist/chunk-2OMQV2ZB.mjs.map +1 -0
  51. package/dist/chunk-5RT3S67O.cjs +30 -0
  52. package/dist/chunk-5RT3S67O.cjs.map +1 -0
  53. package/dist/chunk-6YUVILN5.mjs +42 -0
  54. package/dist/chunk-6YUVILN5.mjs.map +1 -0
  55. package/dist/{chunk-YEFM2ERQ.cjs → chunk-7OQFO6TM.cjs} +8 -7
  56. package/dist/chunk-7OQFO6TM.cjs.map +1 -0
  57. package/dist/chunk-BBD3Y37O.cjs +220 -0
  58. package/dist/chunk-BBD3Y37O.cjs.map +1 -0
  59. package/dist/chunk-EJ7MKHER.mjs +45 -0
  60. package/dist/chunk-EJ7MKHER.mjs.map +1 -0
  61. package/dist/{chunk-XN2QLBLT.mjs → chunk-G6Y4UJPN.mjs} +5 -4
  62. package/dist/chunk-G6Y4UJPN.mjs.map +1 -0
  63. package/dist/{chunk-AZSAPO2V.cjs → chunk-HXY3IX3G.cjs} +3 -44
  64. package/dist/chunk-HXY3IX3G.cjs.map +1 -0
  65. package/dist/{chunk-BMNY7F6H.mjs → chunk-JM7WNDNT.mjs} +4 -21
  66. package/dist/chunk-JM7WNDNT.mjs.map +1 -0
  67. package/dist/chunk-MQHZ7HD2.mjs +215 -0
  68. package/dist/chunk-MQHZ7HD2.mjs.map +1 -0
  69. package/dist/{chunk-ML47UEDU.cjs → chunk-O4FSJPU3.cjs} +2 -27
  70. package/dist/chunk-O4FSJPU3.cjs.map +1 -0
  71. package/dist/chunk-Q66LXMRR.mjs +28 -0
  72. package/dist/chunk-Q66LXMRR.mjs.map +1 -0
  73. package/dist/chunk-RILRMRXB.cjs +50 -0
  74. package/dist/chunk-RILRMRXB.cjs.map +1 -0
  75. package/dist/chunk-SQ2KNAUD.cjs +64 -0
  76. package/dist/chunk-SQ2KNAUD.cjs.map +1 -0
  77. package/dist/{chunk-TVFUWRTE.cjs → chunk-TCQQUJCL.cjs} +5 -4
  78. package/dist/chunk-TCQQUJCL.cjs.map +1 -0
  79. package/dist/chunk-UKSP3B3W.mjs +600 -0
  80. package/dist/chunk-UKSP3B3W.mjs.map +1 -0
  81. package/dist/chunk-X4AJCTON.cjs +607 -0
  82. package/dist/chunk-X4AJCTON.cjs.map +1 -0
  83. package/dist/chunk-ZZX3IG2T.mjs +25 -0
  84. package/dist/chunk-ZZX3IG2T.mjs.map +1 -0
  85. package/dist/index.cjs +104 -46
  86. package/dist/index.cjs.map +1 -1
  87. package/dist/index.d.cts +67 -3
  88. package/dist/index.d.ts +67 -3
  89. package/dist/index.mjs +70 -42
  90. package/dist/index.mjs.map +1 -1
  91. package/dist/read-only-table.d.cts +1 -1
  92. package/dist/read-only-table.d.ts +1 -1
  93. package/dist/smart.d.cts +1 -1
  94. package/dist/smart.d.ts +1 -1
  95. package/dist/{types-CYtJk8H9.d.ts → types-BbOnd5IN.d.cts} +53 -3
  96. package/dist/{types-CYtJk8H9.d.cts → types-BbOnd5IN.d.ts} +53 -3
  97. package/package.json +1 -1
  98. package/dist/DateTimeWidget-3AUBZYYK.mjs.map +0 -1
  99. package/dist/DateTimeWidget-OS7ER5F6.cjs.map +0 -1
  100. package/dist/DateWidget-KCTE6N5G.mjs.map +0 -1
  101. package/dist/DateWidget-UNLX544Z.cjs.map +0 -1
  102. package/dist/EditableTable-VQ72UEFF.cjs.map +0 -1
  103. package/dist/EditableTable-XFCPKSUY.mjs.map +0 -1
  104. package/dist/FollowupWidget-BFZ6P2JE.mjs.map +0 -1
  105. package/dist/FollowupWidget-MAYTHM2E.cjs.map +0 -1
  106. package/dist/OBGPathwayWidget-X67XKRIH.mjs.map +0 -1
  107. package/dist/OBGPathwayWidget-XGN3HEWS.cjs.map +0 -1
  108. package/dist/ObstetricHistoryWidget-RP7NY4PV.cjs.map +0 -1
  109. package/dist/ObstetricHistoryWidget-Z4VAXH3E.mjs.map +0 -1
  110. package/dist/chunk-4HDMR2LX.mjs +0 -69
  111. package/dist/chunk-4HDMR2LX.mjs.map +0 -1
  112. package/dist/chunk-4PMNVBJD.mjs.map +0 -1
  113. package/dist/chunk-AZSAPO2V.cjs.map +0 -1
  114. package/dist/chunk-BMNY7F6H.mjs.map +0 -1
  115. package/dist/chunk-ML47UEDU.cjs.map +0 -1
  116. package/dist/chunk-TVFUWRTE.cjs.map +0 -1
  117. package/dist/chunk-XN2QLBLT.mjs.map +0 -1
  118. package/dist/chunk-YEFM2ERQ.cjs.map +0 -1
@@ -0,0 +1,215 @@
1
+ import { isLabelVisible, FieldRequiredIndicator, fieldLabelClass, fieldWrapperClass } from './chunk-WYVXXEZI.mjs';
2
+ import { useField } from './chunk-2BGJZ44Q.mjs';
3
+ import { Label } from './chunk-HEFZA2AH.mjs';
4
+ import { cn } from './chunk-VPU66PI6.mjs';
5
+ import { useMemo } from 'react';
6
+ import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
7
+
8
+ var BPE_SCORES = ["0", "1", "2", "3", "4", "*"];
9
+ var SCORE_LABEL = {
10
+ "0": "0 \u2013 Healthy",
11
+ "1": "1 \u2013 Bleeding on probing",
12
+ "2": "2 \u2013 Calculus / plaque retentive factor",
13
+ "3": "3 \u2013 Pocket 3.5\u20135.5 mm",
14
+ "4": "4 \u2013 Pocket \u22656 mm",
15
+ "*": "* \u2013 Furcation involvement"
16
+ };
17
+ var SEXTANTS = [
18
+ { key: "upper_right", label: "UR", arch: "upper", teeth: "17\u201314" },
19
+ { key: "upper_anterior", label: "UA", arch: "upper", teeth: "13\u201323" },
20
+ { key: "upper_left", label: "UL", arch: "upper", teeth: "24\u201327" },
21
+ { key: "lower_right", label: "LR", arch: "lower", teeth: "44\u201347" },
22
+ { key: "lower_anterior", label: "LA", arch: "lower", teeth: "33\u201343" },
23
+ { key: "lower_left", label: "LL", arch: "lower", teeth: "34\u201337" }
24
+ ];
25
+ function normalizeBpeChart(raw) {
26
+ if (raw && typeof raw === "object" && !Array.isArray(raw)) {
27
+ const o = raw;
28
+ if (o.scores || o.bleeding) {
29
+ return {
30
+ scores: o.scores ?? {},
31
+ bleeding: o.bleeding ?? {}
32
+ };
33
+ }
34
+ return { scores: raw, bleeding: {} };
35
+ }
36
+ return { scores: {}, bleeding: {} };
37
+ }
38
+ function ArchGrid({
39
+ arch,
40
+ data,
41
+ onScoreChange,
42
+ onBleedingChange,
43
+ disabled
44
+ }) {
45
+ const sextants = SEXTANTS.filter((s) => s.arch === arch);
46
+ const isUpper = arch === "upper";
47
+ const editable = !!onScoreChange;
48
+ const boxesRow = /* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
49
+ /* @__PURE__ */ jsx("div", { className: "w-16 shrink-0" }),
50
+ sextants.map((s) => /* @__PURE__ */ jsx(
51
+ "div",
52
+ {
53
+ className: "relative flex h-12 w-14 shrink-0 items-center justify-center rounded-md border-2 border-gray-200 bg-white text-xl font-bold",
54
+ children: editable ? /* @__PURE__ */ jsxs(
55
+ "select",
56
+ {
57
+ value: data.scores[s.key] ?? "",
58
+ disabled,
59
+ onChange: (e) => onScoreChange(s.key, e.target.value || void 0),
60
+ title: s.label,
61
+ className: "absolute inset-0 h-full w-full cursor-pointer appearance-none bg-transparent text-center text-xl font-bold text-gray-700 focus:outline-none",
62
+ children: [
63
+ /* @__PURE__ */ jsx("option", { value: "", children: "\u2014" }),
64
+ BPE_SCORES.map((sc) => /* @__PURE__ */ jsx("option", { value: sc, children: sc }, sc))
65
+ ]
66
+ }
67
+ ) : /* @__PURE__ */ jsx(
68
+ "span",
69
+ {
70
+ className: "text-gray-700 select-none",
71
+ title: data.scores[s.key] ? `${s.label}: ${SCORE_LABEL[data.scores[s.key]]}` : `${s.label}: not recorded`,
72
+ children: data.scores[s.key] ?? "\u2014"
73
+ }
74
+ )
75
+ },
76
+ s.key
77
+ ))
78
+ ] });
79
+ const labelsRow = /* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
80
+ /* @__PURE__ */ jsx("div", { className: "w-16 shrink-0" }),
81
+ sextants.map((s) => /* @__PURE__ */ jsx(
82
+ "div",
83
+ {
84
+ className: "w-14 shrink-0 text-center text-xs font-semibold uppercase tracking-wider text-muted-foreground",
85
+ children: s.label
86
+ },
87
+ s.key
88
+ ))
89
+ ] });
90
+ const bleedingRow = /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
91
+ /* @__PURE__ */ jsx("span", { className: "w-16 shrink-0 text-right text-xs text-muted-foreground pr-1", children: "Bleeding" }),
92
+ sextants.map((s) => /* @__PURE__ */ jsx("div", { className: "flex w-14 shrink-0 justify-center", children: editable ? /* @__PURE__ */ jsx(
93
+ "input",
94
+ {
95
+ type: "checkbox",
96
+ checked: !!data.bleeding[s.key],
97
+ disabled,
98
+ onChange: (e) => onBleedingChange?.(s.key, e.target.checked),
99
+ title: `Bleeding on probing \u2013 ${s.label}`,
100
+ className: cn(
101
+ "h-3.5 w-3.5 cursor-pointer accent-rose-500",
102
+ disabled && "pointer-events-none opacity-50"
103
+ )
104
+ }
105
+ ) : /* @__PURE__ */ jsx(
106
+ "div",
107
+ {
108
+ className: cn(
109
+ "h-3.5 w-3.5 rounded-sm border border-gray-300",
110
+ data.bleeding[s.key] ? "bg-rose-500 border-rose-500" : "bg-white"
111
+ )
112
+ }
113
+ ) }, s.key))
114
+ ] });
115
+ return /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-1", children: isUpper ? /* @__PURE__ */ jsxs(Fragment, { children: [
116
+ bleedingRow,
117
+ boxesRow,
118
+ labelsRow
119
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
120
+ labelsRow,
121
+ boxesRow,
122
+ bleedingRow
123
+ ] }) });
124
+ }
125
+ var BpeChartWidget = ({ fieldId }) => {
126
+ const { fieldDef, value, setValue, setTouched, disabled } = useField(fieldId);
127
+ const data = useMemo(() => normalizeBpeChart(value), [value]);
128
+ const handleScoreChange = (key, score) => {
129
+ const next = { ...data, scores: { ...data.scores } };
130
+ if (score === void 0) delete next.scores[key];
131
+ else next.scores[key] = score;
132
+ setValue(next);
133
+ setTouched();
134
+ };
135
+ const handleBleedingChange = (key, v) => {
136
+ const next = { ...data, bleeding: { ...data.bleeding } };
137
+ if (!v) delete next.bleeding[key];
138
+ else next.bleeding[key] = true;
139
+ setValue(next);
140
+ setTouched();
141
+ };
142
+ if (!fieldDef) return null;
143
+ const showLabel = isLabelVisible(fieldDef);
144
+ return /* @__PURE__ */ jsxs("div", { className: fieldWrapperClass(fieldDef, "space-y-3"), children: [
145
+ showLabel && /* @__PURE__ */ jsxs(Label, { className: fieldLabelClass(fieldDef), children: [
146
+ fieldDef.label,
147
+ " ",
148
+ /* @__PURE__ */ jsx(FieldRequiredIndicator, { fieldDef })
149
+ ] }),
150
+ /* @__PURE__ */ jsx("div", { className: "rounded-xl border border-border/60 bg-card shadow-sm", children: /* @__PURE__ */ jsx("div", { className: "px-4 py-4", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-3", children: [
151
+ /* @__PURE__ */ jsx(
152
+ ArchGrid,
153
+ {
154
+ arch: "upper",
155
+ data,
156
+ onScoreChange: handleScoreChange,
157
+ onBleedingChange: handleBleedingChange,
158
+ disabled
159
+ }
160
+ ),
161
+ /* @__PURE__ */ jsxs("div", { className: "flex w-full items-center gap-2", children: [
162
+ /* @__PURE__ */ jsx("div", { className: "h-px flex-1 bg-border" }),
163
+ /* @__PURE__ */ jsx("span", { className: "text-xs font-semibold uppercase tracking-wider text-muted-foreground", children: "Occlusal plane" }),
164
+ /* @__PURE__ */ jsx("div", { className: "h-px flex-1 bg-border" })
165
+ ] }),
166
+ /* @__PURE__ */ jsx(
167
+ ArchGrid,
168
+ {
169
+ arch: "lower",
170
+ data,
171
+ onScoreChange: handleScoreChange,
172
+ onBleedingChange: handleBleedingChange,
173
+ disabled
174
+ }
175
+ )
176
+ ] }) }) })
177
+ ] });
178
+ };
179
+ function BpeChartReadOnly({
180
+ data: rawData,
181
+ label,
182
+ className
183
+ }) {
184
+ const data = useMemo(() => normalizeBpeChart(rawData), [rawData]);
185
+ const hasData = SEXTANTS.some((s) => data.scores[s.key] !== void 0);
186
+ return /* @__PURE__ */ jsxs("div", { className: `rounded-xl border border-border/60 bg-card shadow-sm ${className ?? ""}`, children: [
187
+ label && /* @__PURE__ */ jsx("div", { className: "border-b border-border/60 px-4 py-3", children: /* @__PURE__ */ jsx("h3", { className: "text-sm font-semibold text-foreground", children: label }) }),
188
+ !hasData ? /* @__PURE__ */ jsx("div", { className: "px-4 py-6 text-center text-sm text-muted-foreground", children: "No BPE scores recorded" }) : /* @__PURE__ */ jsxs(Fragment, { children: [
189
+ /* @__PURE__ */ jsx("div", { className: "px-4 py-4", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-3", children: [
190
+ /* @__PURE__ */ jsx(ArchGrid, { arch: "upper", data }),
191
+ /* @__PURE__ */ jsxs("div", { className: "flex w-full items-center gap-2", children: [
192
+ /* @__PURE__ */ jsx("div", { className: "h-px flex-1 bg-border" }),
193
+ /* @__PURE__ */ jsx("span", { className: "text-xs font-semibold uppercase tracking-wider text-muted-foreground", children: "Occlusal plane" }),
194
+ /* @__PURE__ */ jsx("div", { className: "h-px flex-1 bg-border" })
195
+ ] }),
196
+ /* @__PURE__ */ jsx(ArchGrid, { arch: "lower", data })
197
+ ] }) }),
198
+ /* @__PURE__ */ jsx("div", { className: "border-t border-border/60 px-4 py-3", children: /* @__PURE__ */ jsx("div", { className: "space-y-0.5", children: SEXTANTS.filter((s) => data.scores[s.key]).map((s) => /* @__PURE__ */ jsxs("p", { className: "text-xs text-foreground", children: [
199
+ /* @__PURE__ */ jsxs("span", { className: "font-medium", children: [
200
+ s.label,
201
+ ":"
202
+ ] }),
203
+ " ",
204
+ /* @__PURE__ */ jsxs("span", { className: "text-muted-foreground", children: [
205
+ SCORE_LABEL[data.scores[s.key]],
206
+ data.bleeding[s.key] ? " \xB7 BOP" : ""
207
+ ] })
208
+ ] }, s.key)) }) })
209
+ ] })
210
+ ] });
211
+ }
212
+
213
+ export { BPE_SCORES, BpeChartReadOnly, BpeChartWidget, SEXTANTS };
214
+ //# sourceMappingURL=chunk-MQHZ7HD2.mjs.map
215
+ //# sourceMappingURL=chunk-MQHZ7HD2.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/ui/widgets/BpeChartWidget.tsx"],"names":[],"mappings":"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","file":"chunk-MQHZ7HD2.mjs","sourcesContent":["import React, { useMemo } from 'react';\nimport { useField } from '../../react/useField';\nimport { Label } from '../shadcn/label';\nimport {\n FieldRequiredIndicator,\n fieldLabelClass,\n fieldWrapperClass,\n isLabelVisible,\n} from '../../react/fieldStyle';\nimport { cn } from '../../core/utils';\n\n// ─── BPE constants ────────────────────────────────────────────────────────────\n\nexport const BPE_SCORES = ['0', '1', '2', '3', '4', '*'] as const;\nexport type BpeScore = (typeof BPE_SCORES)[number];\n\nconst SCORE_LABEL: Record<BpeScore, string> = {\n '0': '0 – Healthy',\n '1': '1 – Bleeding on probing',\n '2': '2 – Calculus / plaque retentive factor',\n '3': '3 – Pocket 3.5–5.5 mm',\n '4': '4 – Pocket ≥6 mm',\n '*': '* – Furcation involvement',\n};\n\nexport const SEXTANTS = [\n { key: 'upper_right', label: 'UR', arch: 'upper' as const, teeth: '17–14' },\n { key: 'upper_anterior', label: 'UA', arch: 'upper' as const, teeth: '13–23' },\n { key: 'upper_left', label: 'UL', arch: 'upper' as const, teeth: '24–27' },\n { key: 'lower_right', label: 'LR', arch: 'lower' as const, teeth: '44–47' },\n { key: 'lower_anterior', label: 'LA', arch: 'lower' as const, teeth: '33–43' },\n { key: 'lower_left', label: 'LL', arch: 'lower' as const, teeth: '34–37' },\n] as const;\n\nexport type SextantKey = (typeof SEXTANTS)[number]['key'];\n\nexport type BpeChartData = {\n scores: Partial<Record<SextantKey, BpeScore>>;\n bleeding: Partial<Record<SextantKey, boolean>>;\n};\n\nfunction normalizeBpeChart(raw: unknown): BpeChartData {\n if (raw && typeof raw === 'object' && !Array.isArray(raw)) {\n const o = raw as Record<string, unknown>;\n if (o.scores || o.bleeding) {\n return {\n scores: (o.scores ?? {}) as Partial<Record<SextantKey, BpeScore>>,\n bleeding: (o.bleeding ?? {}) as Partial<Record<SextantKey, boolean>>,\n };\n }\n return { scores: raw as Partial<Record<SextantKey, BpeScore>>, bleeding: {} };\n }\n return { scores: {}, bleeding: {} };\n}\n\n// ─── Arch grid ────────────────────────────────────────────────────────────────\n// Layout:\n// Upper: [boxes row] → [labels row] → [bleeding row]\n// Lower: [bleeding row] → [labels row] → [boxes row]\n// Each row shares a fixed left spacer matching the \"Bleeding\" label width so\n// checkboxes align under their respective sextant boxes.\n\nfunction ArchGrid({\n arch,\n data,\n onScoreChange,\n onBleedingChange,\n disabled,\n}: {\n arch: 'upper' | 'lower';\n data: BpeChartData;\n onScoreChange?: (key: SextantKey, score: BpeScore | undefined) => void;\n onBleedingChange?: (key: SextantKey, v: boolean) => void;\n disabled?: boolean;\n}) {\n const sextants = SEXTANTS.filter((s) => s.arch === arch);\n const isUpper = arch === 'upper';\n const editable = !!onScoreChange;\n\n const boxesRow = (\n <div className=\"flex gap-2\">\n {/* spacer matching \"Bleeding\" label column */}\n <div className=\"w-16 shrink-0\" />\n {sextants.map((s) => (\n <div\n key={s.key}\n className=\"relative flex h-12 w-14 shrink-0 items-center justify-center rounded-md border-2 border-gray-200 bg-white text-xl font-bold\"\n >\n {editable ? (\n <select\n value={data.scores[s.key] ?? ''}\n disabled={disabled}\n onChange={(e) =>\n onScoreChange!(s.key, (e.target.value || undefined) as BpeScore | undefined)\n }\n title={s.label}\n className=\"absolute inset-0 h-full w-full cursor-pointer appearance-none bg-transparent text-center text-xl font-bold text-gray-700 focus:outline-none\"\n >\n <option value=\"\">—</option>\n {BPE_SCORES.map((sc) => (\n <option key={sc} value={sc}>{sc}</option>\n ))}\n </select>\n ) : (\n <span\n className=\"text-gray-700 select-none\"\n title={data.scores[s.key] ? `${s.label}: ${SCORE_LABEL[data.scores[s.key]!]}` : `${s.label}: not recorded`}\n >\n {data.scores[s.key] ?? '—'}\n </span>\n )}\n </div>\n ))}\n </div>\n );\n\n const labelsRow = (\n <div className=\"flex gap-2\">\n <div className=\"w-16 shrink-0\" />\n {sextants.map((s) => (\n <div\n key={s.key}\n className=\"w-14 shrink-0 text-center text-xs font-semibold uppercase tracking-wider text-muted-foreground\"\n >\n {s.label}\n </div>\n ))}\n </div>\n );\n\n const bleedingRow = (\n <div className=\"flex items-center gap-2\">\n <span className=\"w-16 shrink-0 text-right text-xs text-muted-foreground pr-1\">\n Bleeding\n </span>\n {sextants.map((s) => (\n <div key={s.key} className=\"flex w-14 shrink-0 justify-center\">\n {editable ? (\n <input\n type=\"checkbox\"\n checked={!!data.bleeding[s.key]}\n disabled={disabled}\n onChange={(e) => onBleedingChange?.(s.key, e.target.checked)}\n title={`Bleeding on probing – ${s.label}`}\n className={cn(\n 'h-3.5 w-3.5 cursor-pointer accent-rose-500',\n disabled && 'pointer-events-none opacity-50',\n )}\n />\n ) : (\n <div\n className={cn(\n 'h-3.5 w-3.5 rounded-sm border border-gray-300',\n data.bleeding[s.key] ? 'bg-rose-500 border-rose-500' : 'bg-white',\n )}\n />\n )}\n </div>\n ))}\n </div>\n );\n\n return (\n <div className=\"flex flex-col gap-1\">\n {isUpper ? (\n <>\n {bleedingRow}\n {boxesRow}\n {labelsRow}\n </>\n ) : (\n <>\n {labelsRow}\n {boxesRow}\n {bleedingRow}\n </>\n )}\n </div>\n );\n}\n\n// ─── Editable widget ──────────────────────────────────────────────────────────\n\nexport const BpeChartWidget: React.FC<{ fieldId: string }> = ({ fieldId }) => {\n const { fieldDef, value, setValue, setTouched, disabled } = useField(fieldId);\n const data = useMemo(() => normalizeBpeChart(value), [value]);\n\n const handleScoreChange = (key: SextantKey, score: BpeScore | undefined) => {\n const next: BpeChartData = { ...data, scores: { ...data.scores } };\n if (score === undefined) delete next.scores[key];\n else next.scores[key] = score;\n setValue(next);\n setTouched();\n };\n\n const handleBleedingChange = (key: SextantKey, v: boolean) => {\n const next: BpeChartData = { ...data, bleeding: { ...data.bleeding } };\n if (!v) delete next.bleeding[key];\n else next.bleeding[key] = true;\n setValue(next);\n setTouched();\n };\n\n if (!fieldDef) return null;\n const showLabel = isLabelVisible(fieldDef);\n\n return (\n <div className={fieldWrapperClass(fieldDef, 'space-y-3')}>\n {showLabel && (\n <Label className={fieldLabelClass(fieldDef)}>\n {fieldDef.label} <FieldRequiredIndicator fieldDef={fieldDef} />\n </Label>\n )}\n\n <div className=\"rounded-xl border border-border/60 bg-card shadow-sm\">\n <div className=\"px-4 py-4\">\n <div className=\"flex flex-col items-center gap-3\">\n <ArchGrid\n arch=\"upper\"\n data={data}\n onScoreChange={handleScoreChange}\n onBleedingChange={handleBleedingChange}\n disabled={disabled}\n />\n\n <div className=\"flex w-full items-center gap-2\">\n <div className=\"h-px flex-1 bg-border\" />\n <span className=\"text-xs font-semibold uppercase tracking-wider text-muted-foreground\">\n Occlusal plane\n </span>\n <div className=\"h-px flex-1 bg-border\" />\n </div>\n\n <ArchGrid\n arch=\"lower\"\n data={data}\n onScoreChange={handleScoreChange}\n onBleedingChange={handleBleedingChange}\n disabled={disabled}\n />\n </div>\n </div>\n </div>\n </div>\n );\n};\n\n// ─── Read-only view ───────────────────────────────────────────────────────────\n\nexport function BpeChartReadOnly({\n data: rawData,\n label,\n className,\n}: {\n data: unknown;\n label?: string;\n className?: string;\n}) {\n const data = useMemo(() => normalizeBpeChart(rawData), [rawData]);\n const hasData = SEXTANTS.some((s) => data.scores[s.key] !== undefined);\n\n return (\n <div className={`rounded-xl border border-border/60 bg-card shadow-sm ${className ?? ''}`}>\n {label && (\n <div className=\"border-b border-border/60 px-4 py-3\">\n <h3 className=\"text-sm font-semibold text-foreground\">{label}</h3>\n </div>\n )}\n\n {!hasData ? (\n <div className=\"px-4 py-6 text-center text-sm text-muted-foreground\">\n No BPE scores recorded\n </div>\n ) : (\n <>\n <div className=\"px-4 py-4\">\n <div className=\"flex flex-col items-center gap-3\">\n <ArchGrid arch=\"upper\" data={data} />\n <div className=\"flex w-full items-center gap-2\">\n <div className=\"h-px flex-1 bg-border\" />\n <span className=\"text-xs font-semibold uppercase tracking-wider text-muted-foreground\">\n Occlusal plane\n </span>\n <div className=\"h-px flex-1 bg-border\" />\n </div>\n <ArchGrid arch=\"lower\" data={data} />\n </div>\n </div>\n\n <div className=\"border-t border-border/60 px-4 py-3\">\n <div className=\"space-y-0.5\">\n {SEXTANTS.filter((s) => data.scores[s.key]).map((s) => (\n <p key={s.key} className=\"text-xs text-foreground\">\n <span className=\"font-medium\">{s.label}:</span>{' '}\n <span className=\"text-muted-foreground\">\n {SCORE_LABEL[data.scores[s.key]!]}\n {data.bleeding[s.key] ? ' · BOP' : ''}\n </span>\n </p>\n ))}\n </div>\n </div>\n </>\n )}\n </div>\n );\n}\n"]}
@@ -1,7 +1,5 @@
1
1
  'use strict';
2
2
 
3
- var chunkQKJ7BQSR_cjs = require('./chunk-QKJ7BQSR.cjs');
4
- var chunkTB33A4PD_cjs = require('./chunk-TB33A4PD.cjs');
5
3
  var chunkFHHISVCH_cjs = require('./chunk-FHHISVCH.cjs');
6
4
  require('react');
7
5
  var jsxRuntime = require('react/jsx-runtime');
@@ -44,30 +42,7 @@ function ChipRow({
44
42
  }) });
45
43
  }
46
44
 
47
- // src/ui/widgets/_obgSymptomsSync.ts
48
- var SYMPTOMS_FIELD = "symptoms";
49
- function useObgSymptomsSync() {
50
- const symptomsField = chunkTB33A4PD_cjs.useField(SYMPTOMS_FIELD);
51
- const writeSymptoms = (prev, next, overrideProse) => {
52
- if (symptomsField.disabled) return;
53
- const cur = typeof symptomsField.value === "string" ? symptomsField.value : "";
54
- const { prose: curProse } = chunkTB33A4PD_cjs.parseProseAndChipTokens(
55
- cur,
56
- chunkQKJ7BQSR_cjs.OBG_ZONE_ALLOWED_CHIP_LABELS
57
- );
58
- const prevProse = chunkQKJ7BQSR_cjs.formatObgPathwayProse(prev);
59
- const generatedProse = chunkQKJ7BQSR_cjs.formatObgPathwayProse(next);
60
- const isAutoOwned = curProse === "" || curProse === prevProse;
61
- const proseInput = overrideProse !== void 0 ? overrideProse : isAutoOwned ? generatedProse : curProse;
62
- const chipLabels = next.zones.map(chunkQKJ7BQSR_cjs.obgZoneLabel);
63
- const composed = chunkTB33A4PD_cjs.composeProseAndChips(proseInput, chipLabels);
64
- if (composed !== cur) symptomsField.setValue(composed);
65
- };
66
- return { writeSymptoms, symptomsField };
67
- }
68
-
69
45
  exports.ChipRow = ChipRow;
70
46
  exports.Panel = Panel;
71
- exports.useObgSymptomsSync = useObgSymptomsSync;
72
- //# sourceMappingURL=chunk-ML47UEDU.cjs.map
73
- //# sourceMappingURL=chunk-ML47UEDU.cjs.map
47
+ //# sourceMappingURL=chunk-O4FSJPU3.cjs.map
48
+ //# sourceMappingURL=chunk-O4FSJPU3.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/ui/widgets/_obgPanels.tsx"],"names":["jsxs","jsx","cn"],"mappings":";;;;;;AAGO,SAAS,KAAA,CAAM;AAAA,EACpB,KAAA;AAAA,EACA,KAAA;AAAA,EACA;AACF,CAAA,EAIG;AACD,EAAA,uBACEA,eAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,6DAAA,EACb,QAAA,EAAA;AAAA,oBAAAA,eAAA,CAAC,KAAA,EAAA,EAAI,WAAU,yFAAA,EACb,QAAA,EAAA;AAAA,sBAAAC,cAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,sCAAA,EAAwC,QAAA,EAAA,KAAA,EAAM,CAAA;AAAA,MAC7D;AAAA,KAAA,EACH,CAAA;AAAA,oBACAA,cAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,aAAA,EAAe,QAAA,EAAS;AAAA,GAAA,EACzC,CAAA;AAEJ;AAEO,SAAS,OAAA,CAAQ;AAAA,EACtB,OAAA;AAAA,EACA,QAAA;AAAA,EACA,QAAA;AAAA,EACA;AACF,CAAA,EAKG;AACD,EAAA,sCACG,KAAA,EAAA,EAAI,SAAA,EAAU,wBACZ,QAAA,EAAA,OAAA,CAAQ,GAAA,CAAI,CAAC,CAAA,KAAM;AAClB,IAAA,MAAM,EAAA,GAAK,CAAC,CAAC,QAAA,CAAS,EAAE,GAAG,CAAA;AAC3B,IAAA,uBACEA,cAAA;AAAA,MAAC,QAAA;AAAA,MAAA;AAAA,QAEC,IAAA,EAAK,QAAA;AAAA,QACL,OAAA,EAAS,MAAM,QAAA,CAAS,CAAA,CAAE,GAAG,CAAA;AAAA,QAC7B,QAAA;AAAA,QACA,SAAA,EAAWC,oBAAA;AAAA,UACT,6DAAA;AAAA,UACA,KACI,0CAAA,GACA;AAAA,SACN;AAAA,QAEC,QAAA,EAAA,CAAA,CAAE;AAAA,OAAA;AAAA,MAXE,CAAA,CAAE;AAAA,KAYT;AAAA,EAEJ,CAAC,CAAA,EACH,CAAA;AAEJ","file":"chunk-O4FSJPU3.cjs","sourcesContent":["import React from 'react';\nimport { cn } from '../../core/utils';\n\nexport function Panel({\n title,\n right,\n children,\n}: {\n title: string;\n right?: React.ReactNode;\n children: React.ReactNode;\n}) {\n return (\n <div className=\"overflow-hidden rounded-md border border-[#D0D0D0] bg-white\">\n <div className=\"flex items-center justify-between border-b border-[#D0D0D0] bg-[#FEE8EC]/50 px-3 py-1.5\">\n <span className=\"text-xs font-semibold text-slate-700\">{title}</span>\n {right}\n </div>\n <div className=\"p-3 text-xs\">{children}</div>\n </div>\n );\n}\n\nexport function ChipRow({\n options,\n selected,\n onToggle,\n disabled,\n}: {\n options: { key: string; label: string }[];\n selected: Record<string, boolean>;\n onToggle: (key: string) => void;\n disabled?: boolean;\n}) {\n return (\n <div className=\"flex flex-wrap gap-2\">\n {options.map((o) => {\n const on = !!selected[o.key];\n return (\n <button\n key={o.key}\n type=\"button\"\n onClick={() => onToggle(o.key)}\n disabled={disabled}\n className={cn(\n 'rounded-full border px-3 py-1 text-[11px] transition-colors',\n on\n ? 'border-rose-500 bg-rose-50 text-rose-700'\n : 'border-slate-300 bg-white text-slate-600 hover:bg-slate-50',\n )}\n >\n {o.label}\n </button>\n );\n })}\n </div>\n );\n}\n"]}
@@ -0,0 +1,28 @@
1
+ import { OBG_ZONE_ALLOWED_CHIP_LABELS, formatObgPathwayProse, obgZoneLabel } from './chunk-IKAKE7TR.mjs';
2
+ import { useField, parseProseAndChipTokens, composeProseAndChips } from './chunk-2BGJZ44Q.mjs';
3
+
4
+ // src/ui/widgets/_obgSymptomsSync.ts
5
+ var SYMPTOMS_FIELD = "symptoms";
6
+ function useObgSymptomsSync() {
7
+ const symptomsField = useField(SYMPTOMS_FIELD);
8
+ const writeSymptoms = (prev, next, overrideProse) => {
9
+ if (symptomsField.disabled) return;
10
+ const cur = typeof symptomsField.value === "string" ? symptomsField.value : "";
11
+ const { prose: curProse } = parseProseAndChipTokens(
12
+ cur,
13
+ OBG_ZONE_ALLOWED_CHIP_LABELS
14
+ );
15
+ const prevProse = formatObgPathwayProse(prev);
16
+ const generatedProse = formatObgPathwayProse(next);
17
+ const isAutoOwned = curProse === "" || curProse === prevProse;
18
+ const proseInput = overrideProse !== void 0 ? overrideProse : isAutoOwned ? generatedProse : curProse;
19
+ const chipLabels = next.zones.map(obgZoneLabel);
20
+ const composed = composeProseAndChips(proseInput, chipLabels);
21
+ if (composed !== cur) symptomsField.setValue(composed);
22
+ };
23
+ return { writeSymptoms, symptomsField };
24
+ }
25
+
26
+ export { useObgSymptomsSync };
27
+ //# sourceMappingURL=chunk-Q66LXMRR.mjs.map
28
+ //# sourceMappingURL=chunk-Q66LXMRR.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/ui/widgets/_obgSymptomsSync.ts"],"names":[],"mappings":";;;;AAYA,IAAM,cAAA,GAAiB,UAAA;AAgBhB,SAAS,kBAAA,GAAqB;AACnC,EAAA,MAAM,aAAA,GAAgB,SAAS,cAAc,CAAA;AAE7C,EAAA,MAAM,aAAA,GAAgB,CACpB,IAAA,EACA,IAAA,EACA,aAAA,KACG;AACH,IAAA,IAAI,cAAc,QAAA,EAAU;AAC5B,IAAA,MAAM,MACJ,OAAO,aAAA,CAAc,KAAA,KAAU,QAAA,GAAW,cAAc,KAAA,GAAQ,EAAA;AAClE,IAAA,MAAM,EAAE,KAAA,EAAO,QAAA,EAAS,GAAI,uBAAA;AAAA,MAC1B,GAAA;AAAA,MACA;AAAA,KACF;AAEA,IAAA,MAAM,SAAA,GAAY,sBAAsB,IAAI,CAAA;AAC5C,IAAA,MAAM,cAAA,GAAiB,sBAAsB,IAAI,CAAA;AACjD,IAAA,MAAM,WAAA,GAAc,QAAA,KAAa,EAAA,IAAM,QAAA,KAAa,SAAA;AAEpD,IAAA,MAAM,UAAA,GACJ,aAAA,KAAkB,MAAA,GACd,aAAA,GACA,cACE,cAAA,GACA,QAAA;AAER,IAAA,MAAM,UAAA,GAAa,IAAA,CAAK,KAAA,CAAM,GAAA,CAAI,YAAY,CAAA;AAC9C,IAAA,MAAM,QAAA,GAAW,oBAAA,CAAqB,UAAA,EAAY,UAAU,CAAA;AAC5D,IAAA,IAAI,QAAA,KAAa,GAAA,EAAK,aAAA,CAAc,QAAA,CAAS,QAAQ,CAAA;AAAA,EACvD,CAAA;AAEA,EAAA,OAAO,EAAE,eAAe,aAAA,EAAc;AACxC","file":"chunk-Q66LXMRR.mjs","sourcesContent":["import { useField } from '../../react/useField';\nimport {\n formatObgPathwayProse,\n obgZoneLabel,\n OBG_ZONE_ALLOWED_CHIP_LABELS,\n type ObgPathwayValue,\n} from '../../core/obgPathway';\nimport {\n composeProseAndChips,\n parseProseAndChipTokens,\n} from '../../core/suggestionTokens';\n\nconst SYMPTOMS_FIELD = 'symptoms';\n\n/**\n * Mirror an OBG pathway value into the `symptoms` (HOPC) textarea as\n * prose + chips. Multiple widgets (OBGPathwayWidget, AntenatalPanels) write\n * through this hook simultaneously, so the \"is current prose user-owned?\"\n * check is stateless: we compare the current prose against the prose that\n * the *previous* pathway value would have generated. If they match, the\n * textarea is still auto-owned and may be refreshed; otherwise the user has\n * edited prose and we preserve it (only the chip line is kept in sync).\n *\n * Because `formatObgPathwayProse` is deterministic, this approach is\n * correct across multiple writers and across remounts without any shared\n * ref — a previous `lastAutoProseRef`-based design fought itself when\n * OBGPathwayWidget and AntenatalPanels both wrote on the same tick.\n */\nexport function useObgSymptomsSync() {\n const symptomsField = useField(SYMPTOMS_FIELD);\n\n const writeSymptoms = (\n prev: ObgPathwayValue,\n next: ObgPathwayValue,\n overrideProse?: string,\n ) => {\n if (symptomsField.disabled) return;\n const cur =\n typeof symptomsField.value === 'string' ? symptomsField.value : '';\n const { prose: curProse } = parseProseAndChipTokens(\n cur,\n OBG_ZONE_ALLOWED_CHIP_LABELS,\n );\n\n const prevProse = formatObgPathwayProse(prev);\n const generatedProse = formatObgPathwayProse(next);\n const isAutoOwned = curProse === '' || curProse === prevProse;\n\n const proseInput =\n overrideProse !== undefined\n ? overrideProse\n : isAutoOwned\n ? generatedProse\n : curProse;\n\n const chipLabels = next.zones.map(obgZoneLabel);\n const composed = composeProseAndChips(proseInput, chipLabels);\n if (composed !== cur) symptomsField.setValue(composed);\n };\n\n return { writeSymptoms, symptomsField };\n}\n"]}
@@ -0,0 +1,50 @@
1
+ 'use strict';
2
+
3
+ var chunkFHHISVCH_cjs = require('./chunk-FHHISVCH.cjs');
4
+ var React = require('react');
5
+ var PopoverPrimitive = require('@radix-ui/react-popover');
6
+ var jsxRuntime = require('react/jsx-runtime');
7
+
8
+ function _interopNamespace(e) {
9
+ if (e && e.__esModule) return e;
10
+ var n = Object.create(null);
11
+ if (e) {
12
+ Object.keys(e).forEach(function (k) {
13
+ if (k !== 'default') {
14
+ var d = Object.getOwnPropertyDescriptor(e, k);
15
+ Object.defineProperty(n, k, d.get ? d : {
16
+ enumerable: true,
17
+ get: function () { return e[k]; }
18
+ });
19
+ }
20
+ });
21
+ }
22
+ n.default = e;
23
+ return Object.freeze(n);
24
+ }
25
+
26
+ var React__namespace = /*#__PURE__*/_interopNamespace(React);
27
+ var PopoverPrimitive__namespace = /*#__PURE__*/_interopNamespace(PopoverPrimitive);
28
+
29
+ var Popover = PopoverPrimitive__namespace.Root;
30
+ var PopoverTrigger = PopoverPrimitive__namespace.Trigger;
31
+ var PopoverContent = React__namespace.forwardRef(({ className, align = "center", sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(PopoverPrimitive__namespace.Portal, { children: /* @__PURE__ */ jsxRuntime.jsx(
32
+ PopoverPrimitive__namespace.Content,
33
+ {
34
+ ref,
35
+ align,
36
+ sideOffset,
37
+ className: chunkFHHISVCH_cjs.cn(
38
+ "z-50 w-72 rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
39
+ className
40
+ ),
41
+ ...props
42
+ }
43
+ ) }));
44
+ PopoverContent.displayName = PopoverPrimitive__namespace.Content.displayName;
45
+
46
+ exports.Popover = Popover;
47
+ exports.PopoverContent = PopoverContent;
48
+ exports.PopoverTrigger = PopoverTrigger;
49
+ //# sourceMappingURL=chunk-RILRMRXB.cjs.map
50
+ //# sourceMappingURL=chunk-RILRMRXB.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/ui/shadcn/popover.tsx"],"names":["PopoverPrimitive","React","jsx","cn"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAKA,IAAM,OAAA,GAA2BA,2BAAA,CAAA;AAEjC,IAAM,cAAA,GAAkCA,2BAAA,CAAA;AAExC,IAAM,cAAA,GAAuBC,gBAAA,CAAA,UAAA,CAG3B,CAAC,EAAE,WAAW,KAAA,GAAQ,QAAA,EAAU,UAAA,GAAa,CAAA,EAAG,GAAG,KAAA,EAAM,EAAG,GAAA,qBAC5DC,cAAA,CAAkBF,oCAAjB,EACC,QAAA,kBAAAE,cAAA;AAAA,EAAkBF,2BAAA,CAAA,OAAA;AAAA,EAAjB;AAAA,IACC,GAAA;AAAA,IACA,KAAA;AAAA,IACA,UAAA;AAAA,IACA,SAAA,EAAWG,oBAAA;AAAA,MACT,4aAAA;AAAA,MACA;AAAA,KACF;AAAA,IACC,GAAG;AAAA;AACN,CAAA,EACF,CACD;AACD,cAAA,CAAe,cAA+BH,2BAAA,CAAA,OAAA,CAAQ,WAAA","file":"chunk-RILRMRXB.cjs","sourcesContent":["import * as React from \"react\"\nimport * as PopoverPrimitive from \"@radix-ui/react-popover\"\n\nimport { cn } from \"../../core/utils\"\n\nconst Popover = PopoverPrimitive.Root\n\nconst PopoverTrigger = PopoverPrimitive.Trigger\n\nconst PopoverContent = React.forwardRef<\n React.ElementRef<typeof PopoverPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof PopoverPrimitive.Content>\n>(({ className, align = \"center\", sideOffset = 4, ...props }, ref) => (\n <PopoverPrimitive.Portal>\n <PopoverPrimitive.Content\n ref={ref}\n align={align}\n sideOffset={sideOffset}\n className={cn(\n \"z-50 w-72 rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2\",\n className\n )}\n {...props}\n />\n </PopoverPrimitive.Portal>\n))\nPopoverContent.displayName = PopoverPrimitive.Content.displayName\n\nexport { Popover, PopoverTrigger, PopoverContent }\n\n"]}
@@ -0,0 +1,64 @@
1
+ 'use strict';
2
+
3
+ var chunkFHHISVCH_cjs = require('./chunk-FHHISVCH.cjs');
4
+ var React = require('react');
5
+ var jsxRuntime = require('react/jsx-runtime');
6
+
7
+ function _interopNamespace(e) {
8
+ if (e && e.__esModule) return e;
9
+ var n = Object.create(null);
10
+ if (e) {
11
+ Object.keys(e).forEach(function (k) {
12
+ if (k !== 'default') {
13
+ var d = Object.getOwnPropertyDescriptor(e, k);
14
+ Object.defineProperty(n, k, d.get ? d : {
15
+ enumerable: true,
16
+ get: function () { return e[k]; }
17
+ });
18
+ }
19
+ });
20
+ }
21
+ n.default = e;
22
+ return Object.freeze(n);
23
+ }
24
+
25
+ var React__namespace = /*#__PURE__*/_interopNamespace(React);
26
+
27
+ var Switch = React__namespace.forwardRef(
28
+ ({ className, checked, onCheckedChange, disabled, ...props }, ref) => {
29
+ return /* @__PURE__ */ jsxRuntime.jsx(
30
+ "button",
31
+ {
32
+ type: "button",
33
+ role: "switch",
34
+ "aria-checked": checked,
35
+ "data-state": checked ? "checked" : "unchecked",
36
+ disabled,
37
+ ref,
38
+ onClick: () => {
39
+ if (!disabled && onCheckedChange) {
40
+ onCheckedChange(!checked);
41
+ }
42
+ },
43
+ className: chunkFHHISVCH_cjs.cn(
44
+ "peer inline-flex h-5 w-9 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=unchecked]:bg-input",
45
+ className
46
+ ),
47
+ ...props,
48
+ children: /* @__PURE__ */ jsxRuntime.jsx(
49
+ "span",
50
+ {
51
+ "data-state": checked ? "checked" : "unchecked",
52
+ className: "pointer-events-none block h-4 w-4 rounded-full bg-background shadow-lg ring-0 transition-transform",
53
+ style: { transform: checked ? "translateX(1rem)" : "translateX(0)" }
54
+ }
55
+ )
56
+ }
57
+ );
58
+ }
59
+ );
60
+ Switch.displayName = "Switch";
61
+
62
+ exports.Switch = Switch;
63
+ //# sourceMappingURL=chunk-SQ2KNAUD.cjs.map
64
+ //# sourceMappingURL=chunk-SQ2KNAUD.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/ui/shadcn/switch.tsx"],"names":["React","jsx","cn"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AASA,IAAM,MAAA,GAAeA,gBAAA,CAAA,UAAA;AAAA,EACnB,CAAC,EAAE,SAAA,EAAW,OAAA,EAAS,iBAAiB,QAAA,EAAU,GAAG,KAAA,EAAM,EAAG,GAAA,KAAQ;AACpE,IAAA,uBACEC,cAAA;AAAA,MAAC,QAAA;AAAA,MAAA;AAAA,QACC,IAAA,EAAK,QAAA;AAAA,QACL,IAAA,EAAK,QAAA;AAAA,QACL,cAAA,EAAc,OAAA;AAAA,QACd,YAAA,EAAY,UAAU,SAAA,GAAY,WAAA;AAAA,QAClC,QAAA;AAAA,QACA,GAAA;AAAA,QACA,SAAS,MAAM;AACb,UAAA,IAAI,CAAC,YAAY,eAAA,EAAiB;AAChC,YAAA,eAAA,CAAgB,CAAC,OAAO,CAAA;AAAA,UAC1B;AAAA,QACF,CAAA;AAAA,QACA,SAAA,EAAWC,oBAAA;AAAA,UACT,mXAAA;AAAA,UACA;AAAA,SACF;AAAA,QACC,GAAG,KAAA;AAAA,QAEJ,QAAA,kBAAAD,cAAA;AAAA,UAAC,MAAA;AAAA,UAAA;AAAA,YACC,YAAA,EAAY,UAAU,SAAA,GAAY,WAAA;AAAA,YAClC,SAAA,EAAU,oGAAA;AAAA,YACV,KAAA,EAAO,EAAE,SAAA,EAAW,OAAA,GAAU,qBAAqB,eAAA;AAAgB;AAAA;AACrE;AAAA,KACF;AAAA,EAEJ;AACF;AACA,MAAA,CAAO,WAAA,GAAc,QAAA","file":"chunk-SQ2KNAUD.cjs","sourcesContent":["import * as React from \"react\";\nimport { cn } from \"../../core/utils\";\n\nexport interface SwitchProps\n extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n checked?: boolean;\n onCheckedChange?: (checked: boolean) => void;\n}\n\nconst Switch = React.forwardRef<HTMLButtonElement, SwitchProps>(\n ({ className, checked, onCheckedChange, disabled, ...props }, ref) => {\n return (\n <button\n type=\"button\"\n role=\"switch\"\n aria-checked={checked}\n data-state={checked ? \"checked\" : \"unchecked\"}\n disabled={disabled}\n ref={ref}\n onClick={() => {\n if (!disabled && onCheckedChange) {\n onCheckedChange(!checked);\n }\n }}\n className={cn(\n \"peer inline-flex h-5 w-9 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=unchecked]:bg-input\",\n className\n )}\n {...props}\n >\n <span\n data-state={checked ? \"checked\" : \"unchecked\"}\n className=\"pointer-events-none block h-4 w-4 rounded-full bg-background shadow-lg ring-0 transition-transform\"\n style={{ transform: checked ? 'translateX(1rem)' : 'translateX(0)' }}\n />\n </button>\n );\n }\n);\nSwitch.displayName = \"Switch\";\n\nexport { Switch };\n"]}
@@ -21,8 +21,9 @@ var TextWidget = ({ fieldId }) => {
21
21
  const hasVoice = !!(fieldDef?.voice && store.getVoice());
22
22
  const showError = !!error && (touched || state.submitAttempted);
23
23
  if (!fieldDef) return null;
24
- const Component = fieldDef.type === "textarea" ? chunkPHADAQSH_cjs.Textarea : chunkTJHG5WHX_cjs.Input;
25
- const isTextarea = fieldDef.type === "textarea";
24
+ const TEXTAREA_TYPES = /* @__PURE__ */ new Set(["textarea", "social_history"]);
25
+ const isTextarea = TEXTAREA_TYPES.has(fieldDef.type);
26
+ const Component = isTextarea ? chunkPHADAQSH_cjs.Textarea : chunkTJHG5WHX_cjs.Input;
26
27
  const height = isTextarea && "height" in fieldDef ? fieldDef.height : void 0;
27
28
  const theme = chunkP62377LB_cjs.getThemeConfig(
28
29
  isTextarea ? "textarea" : "text",
@@ -136,5 +137,5 @@ var SelectWidget = ({ fieldId }) => {
136
137
 
137
138
  exports.SelectWidget = SelectWidget;
138
139
  exports.TextWidget = TextWidget;
139
- //# sourceMappingURL=chunk-TVFUWRTE.cjs.map
140
- //# sourceMappingURL=chunk-TVFUWRTE.cjs.map
140
+ //# sourceMappingURL=chunk-TCQQUJCL.cjs.map
141
+ //# sourceMappingURL=chunk-TCQQUJCL.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/ui/widgets/Text.tsx","../src/ui/widgets/Select.tsx"],"names":["useField","useForm","useFormStore","Textarea","Input","getThemeConfig","cn","isLabelVisible","jsxs","Fragment","jsx","FieldRequiredIndicator","Label","fieldLabelClass","fieldWrapperClass","VoiceMicButton","fieldControlClass","fieldErrorClass","useState","useEffect","fetchOptions","Select","SelectTrigger","SelectValue","SelectContent","SelectItem"],"mappings":"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","file":"chunk-TCQQUJCL.cjs","sourcesContent":["import React from 'react';\nimport { useField } from '../../react/useField';\nimport { useForm } from '../../react/useForm';\nimport { useFormStore } from '../../react/FormProvider';\nimport { VoiceMicButton } from '../../react/VoiceMicButton';\nimport { Input } from '../shadcn/input';\nimport { Label } from '../shadcn/label';\nimport { Textarea } from '../shadcn/textarea';\nimport { getThemeConfig } from '../themes';\nimport { cn } from '../../core/utils';\nimport {\n FieldRequiredIndicator,\n fieldControlClass,\n fieldErrorClass,\n fieldLabelClass,\n fieldWrapperClass,\n isLabelVisible,\n} from '../../react/fieldStyle';\n\nexport const TextWidget: React.FC<{ fieldId: string }> = ({ fieldId }) => {\n const { fieldDef, value, setValue, setTouched, error, disabled, touched } = useField(fieldId);\n const { state } = useForm();\n const store = useFormStore();\n const hasVoice = !!(fieldDef?.voice && store.getVoice());\n\n const showError = !!error && (touched || state.submitAttempted);\n\n if (!fieldDef) return null;\n\n const TEXTAREA_TYPES = new Set(['textarea', 'social_history']);\n const isTextarea = TEXTAREA_TYPES.has(fieldDef.type);\n const Component = isTextarea ? Textarea : Input;\n const height = isTextarea && 'height' in fieldDef ? fieldDef.height : undefined;\n const theme = getThemeConfig(\n isTextarea ? 'textarea' : 'text',\n fieldDef.theme\n );\n\n const wrapperClass = theme?.wrapperClassName ?? 'space-y-2';\n const labelClass = theme?.labelClassName;\n const inputClass = cn(theme?.inputClassName, showError && 'border-red-500');\n const showLabel = isLabelVisible(fieldDef);\n\n const labelContent = (\n <>\n {fieldDef.label}{' '}\n <FieldRequiredIndicator fieldDef={fieldDef} />\n </>\n );\n\n const labelEl = showLabel\n ? theme ? (\n <Label htmlFor={fieldId} className={fieldLabelClass(fieldDef, labelClass)}>\n {labelContent}\n </Label>\n ) : (\n <Label htmlFor={fieldId} className={fieldLabelClass(fieldDef)}>\n {labelContent}\n </Label>\n )\n : null;\n\n const placeholder =\n typeof fieldDef.placeholder === 'string' && fieldDef.placeholder.trim()\n ? fieldDef.placeholder\n : undefined;\n\n return (\n <div\n className={fieldWrapperClass(\n fieldDef,\n wrapperClass,\n isTextarea ? 'flex h-full min-h-0 flex-col' : undefined,\n )}\n >\n {hasVoice ? (\n <div className=\"flex items-center justify-between\">\n {labelEl}\n <VoiceMicButton fieldId={fieldId} onTranscriptReady={setValue} />\n </div>\n ) : (\n labelEl\n )}\n <Component\n id={fieldId}\n value={value || ''}\n onChange={(e) => setValue(fieldDef.type === 'number' ? Number(e.target.value) : e.target.value)}\n onBlur={setTouched}\n disabled={disabled}\n type={fieldDef.type === 'number' ? 'number' : 'text'}\n className={fieldControlClass(\n fieldDef,\n inputClass,\n isTextarea && height == null ? 'min-h-[80px] flex-1' : undefined,\n )}\n placeholder={placeholder}\n aria-label={!showLabel ? fieldDef.label : undefined}\n {...(isTextarea && { height })}\n />\n {showError && (\n <p className={fieldErrorClass(fieldDef, 'text-xs text-red-500')}>{error}</p>\n )}\n </div>\n );\n};\n\n","import React, { useEffect, useState } from 'react';\nimport { useField } from '../../react/useField';\nimport { useForm } from '../../react/useForm';\nimport { Label } from '../shadcn/label';\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '../shadcn/select';\nimport { fetchOptions } from '../../core/asyncOptions';\nimport type { SelectFieldDef } from '../../core/types';\nimport {\n FieldRequiredIndicator,\n fieldControlClass,\n fieldErrorClass,\n fieldLabelClass,\n fieldWrapperClass,\n isLabelVisible,\n} from '../../react/fieldStyle';\n\nexport const SelectWidget: React.FC<{ fieldId: string }> = ({ fieldId }) => {\n const { fieldDef, value, setValue, setTouched, error, disabled, touched } = useField(fieldId);\n const [options, setOptions] = useState<{ label: string; value: any }[]>([]);\n const [loading, setLoading] = useState(false);\n const { state } = useForm();\n const showError = !!error && (touched || state.submitAttempted);\n\n useEffect(() => {\n if (!fieldDef) return;\n const def = fieldDef as SelectFieldDef; // Cast safe due to Renderer check\n\n if (def.options) {\n setOptions(def.options);\n } else if (def.dataSource) {\n setLoading(true);\n fetchOptions(def.dataSource.source, def.dataSource.params)\n .then(opts => {\n setOptions(opts);\n })\n .finally(() => setLoading(false));\n }\n }, [fieldDef]);\n\n if (!fieldDef) return null;\n\n const schemaPlaceholder =\n typeof fieldDef.placeholder === 'string' && fieldDef.placeholder.trim()\n ? fieldDef.placeholder\n : undefined;\n const selectPlaceholder = loading ? 'Loading...' : schemaPlaceholder ?? 'Select...';\n\n const showLabel = isLabelVisible(fieldDef);\n\n return (\n <div className={fieldWrapperClass(fieldDef, 'space-y-2')}>\n {showLabel ? (\n <Label htmlFor={fieldId} className={fieldLabelClass(fieldDef)}>\n {fieldDef.label}{' '}\n <FieldRequiredIndicator fieldDef={fieldDef} />\n </Label>\n ) : null}\n\n <Select \n disabled={disabled || loading} \n value={value ? String(value) : undefined} \n onValueChange={(val) => {\n // Try to find original value type (number vs string)\n const opt = options.find(o => String(o.value) === val);\n setValue(opt ? opt.value : val);\n setTouched();\n }}\n >\n <SelectTrigger\n id={fieldId}\n className={fieldControlClass(\n fieldDef,\n showError ? 'border-red-500' : '',\n )}\n >\n <SelectValue placeholder={selectPlaceholder} />\n </SelectTrigger>\n <SelectContent>\n {options.map(opt => (\n <SelectItem key={String(opt.value)} value={String(opt.value)}>\n {opt.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n \n {showError && (\n <p className={fieldErrorClass(fieldDef, 'text-xs text-red-500')}>{error}</p>\n )}\n </div>\n );\n};\n\n"]}