@mieweb/ui 0.6.1-dev.158 → 0.6.1-dev.164

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 (134) hide show
  1. package/dist/MedicationEditor-Bp4NLy7y.d.cts +352 -0
  2. package/dist/MedicationEditor-Bp4NLy7y.d.ts +352 -0
  3. package/dist/ag-grid.cjs +5 -5
  4. package/dist/ag-grid.js +1 -1
  5. package/dist/{chunk-H4T5T65N.cjs → chunk-2JQBPU3Y.cjs} +3 -3
  6. package/dist/{chunk-H4T5T65N.cjs.map → chunk-2JQBPU3Y.cjs.map} +1 -1
  7. package/dist/{chunk-6555OYRU.js → chunk-5BQE6BEL.js} +2 -2
  8. package/dist/{chunk-6555OYRU.js.map → chunk-5BQE6BEL.js.map} +1 -1
  9. package/dist/chunk-67CEEDAP.cjs +1605 -0
  10. package/dist/chunk-67CEEDAP.cjs.map +1 -0
  11. package/dist/{chunk-ULF4PWHW.cjs → chunk-7BARESXI.cjs} +3 -3
  12. package/dist/{chunk-ULF4PWHW.cjs.map → chunk-7BARESXI.cjs.map} +1 -1
  13. package/dist/{chunk-UHPQYBXQ.js → chunk-7QZSJFYT.js} +3 -6
  14. package/dist/chunk-7QZSJFYT.js.map +1 -0
  15. package/dist/chunk-7ZVTLTJF.js +109 -0
  16. package/dist/chunk-7ZVTLTJF.js.map +1 -0
  17. package/dist/{chunk-2T4JU5RH.cjs → chunk-CB4JX5EJ.cjs} +3 -6
  18. package/dist/chunk-CB4JX5EJ.cjs.map +1 -0
  19. package/dist/{chunk-FADQVM4M.cjs → chunk-CDMWZBDD.cjs} +6 -6
  20. package/dist/{chunk-FADQVM4M.cjs.map → chunk-CDMWZBDD.cjs.map} +1 -1
  21. package/dist/chunk-DHKYGVP7.js +3 -0
  22. package/dist/{chunk-LEMY57MI.js.map → chunk-DHKYGVP7.js.map} +1 -1
  23. package/dist/{chunk-FSBFQBNE.cjs → chunk-DKGUOMBC.cjs} +2 -2
  24. package/dist/{chunk-FSBFQBNE.cjs.map → chunk-DKGUOMBC.cjs.map} +1 -1
  25. package/dist/{chunk-4FALCEJI.cjs → chunk-EL2RSQTJ.cjs} +2 -2
  26. package/dist/{chunk-4FALCEJI.cjs.map → chunk-EL2RSQTJ.cjs.map} +1 -1
  27. package/dist/{chunk-ASLZUFH4.js → chunk-ETGZ5DSA.js} +4 -4
  28. package/dist/{chunk-ASLZUFH4.js.map → chunk-ETGZ5DSA.js.map} +1 -1
  29. package/dist/{chunk-TXYTMU3K.js → chunk-FJG7KUDJ.js} +4 -4
  30. package/dist/{chunk-TXYTMU3K.js.map → chunk-FJG7KUDJ.js.map} +1 -1
  31. package/dist/{chunk-6R2ZPDN7.cjs → chunk-GBRPZGSI.cjs} +8 -8
  32. package/dist/{chunk-6R2ZPDN7.cjs.map → chunk-GBRPZGSI.cjs.map} +1 -1
  33. package/dist/{chunk-M7BLVBL4.js → chunk-GSOOPTGM.js} +3 -3
  34. package/dist/{chunk-M7BLVBL4.js.map → chunk-GSOOPTGM.js.map} +1 -1
  35. package/dist/chunk-HUXOASEB.js +1568 -0
  36. package/dist/chunk-HUXOASEB.js.map +1 -0
  37. package/dist/chunk-IQ4KQJAO.js +3 -0
  38. package/dist/{chunk-4ZU53GNR.cjs.map → chunk-IQ4KQJAO.js.map} +1 -1
  39. package/dist/{chunk-RXY5SD3O.js → chunk-NBD236EH.js} +50 -2
  40. package/dist/chunk-NBD236EH.js.map +1 -0
  41. package/dist/chunk-OF7NTZ2I.js +3 -0
  42. package/dist/chunk-OF7NTZ2I.js.map +1 -0
  43. package/dist/chunk-RHNPILZQ.cjs +4 -0
  44. package/dist/chunk-RHNPILZQ.cjs.map +1 -0
  45. package/dist/chunk-RI56YPED.cjs +201 -0
  46. package/dist/chunk-RI56YPED.cjs.map +1 -0
  47. package/dist/{chunk-DCER2QQB.js → chunk-T42BCIUA.js} +2 -2
  48. package/dist/{chunk-DCER2QQB.js.map → chunk-T42BCIUA.js.map} +1 -1
  49. package/dist/{chunk-4ZU53GNR.cjs → chunk-UTYUT5YY.cjs} +62 -2
  50. package/dist/chunk-UTYUT5YY.cjs.map +1 -0
  51. package/dist/{chunk-Q7NBJFEB.js → chunk-UVQEHZRF.js} +2 -2
  52. package/dist/{chunk-Q7NBJFEB.js.map → chunk-UVQEHZRF.js.map} +1 -1
  53. package/dist/chunk-VBWRH4UW.cjs +4 -0
  54. package/dist/chunk-VBWRH4UW.cjs.map +1 -0
  55. package/dist/{chunk-LZPPH5BW.cjs → chunk-VJOVJTFP.cjs} +14 -12
  56. package/dist/chunk-VJOVJTFP.cjs.map +1 -0
  57. package/dist/{chunk-OVQKCUTZ.js → chunk-WFS6R2F5.js} +3 -3
  58. package/dist/{chunk-OVQKCUTZ.js.map → chunk-WFS6R2F5.js.map} +1 -1
  59. package/dist/chunk-Y5KEFV5O.js +192 -0
  60. package/dist/chunk-Y5KEFV5O.js.map +1 -0
  61. package/dist/{chunk-3SSXDWD7.js → chunk-YBLIDESO.js} +14 -12
  62. package/dist/chunk-YBLIDESO.js.map +1 -0
  63. package/dist/chunk-YVPC65ZJ.cjs +134 -0
  64. package/dist/chunk-YVPC65ZJ.cjs.map +1 -0
  65. package/dist/{chunk-7PA26KBF.cjs → chunk-YYDW3ZZS.cjs} +50 -2
  66. package/dist/chunk-YYDW3ZZS.cjs.map +1 -0
  67. package/dist/{chunk-3M4P2KMG.cjs → chunk-ZHBANUBI.cjs} +2 -2
  68. package/dist/{chunk-3M4P2KMG.cjs.map → chunk-ZHBANUBI.cjs.map} +1 -1
  69. package/dist/components/Badge/index.cjs +4 -3
  70. package/dist/components/Badge/index.js +2 -1
  71. package/dist/components/Card/index.cjs +16 -15
  72. package/dist/components/Card/index.js +2 -1
  73. package/dist/components/CountryCodeDropdown/index.cjs +5 -5
  74. package/dist/components/CountryCodeDropdown/index.js +2 -2
  75. package/dist/components/Dropdown/index.cjs +8 -8
  76. package/dist/components/Dropdown/index.js +2 -2
  77. package/dist/components/RichTextEditor/index.cjs +7 -7
  78. package/dist/components/RichTextEditor/index.js +4 -4
  79. package/dist/components/Skeleton/index.d.cts +1 -1
  80. package/dist/components/Skeleton/index.d.ts +1 -1
  81. package/dist/components/SuperChat/index.cjs +71 -19
  82. package/dist/components/SuperChat/index.cjs.map +1 -1
  83. package/dist/components/SuperChat/index.js +65 -13
  84. package/dist/components/SuperChat/index.js.map +1 -1
  85. package/dist/components/SuperChat/plugins/index.cjs +7 -4
  86. package/dist/components/SuperChat/plugins/index.cjs.map +1 -1
  87. package/dist/components/SuperChat/plugins/index.js +6 -3
  88. package/dist/components/SuperChat/plugins/index.js.map +1 -1
  89. package/dist/datavis.cjs +273 -5
  90. package/dist/datavis.cjs.map +1 -1
  91. package/dist/datavis.d.cts +62 -1
  92. package/dist/datavis.d.ts +62 -1
  93. package/dist/datavis.js +251 -1
  94. package/dist/datavis.js.map +1 -1
  95. package/dist/esheet.cjs +182 -0
  96. package/dist/esheet.cjs.map +1 -1
  97. package/dist/esheet.d.cts +117 -0
  98. package/dist/esheet.d.ts +117 -0
  99. package/dist/esheet.js +161 -0
  100. package/dist/esheet.js.map +1 -1
  101. package/dist/hooks/index.cjs +33 -16
  102. package/dist/hooks/index.d.cts +62 -1
  103. package/dist/hooks/index.d.ts +62 -1
  104. package/dist/hooks/index.js +3 -2
  105. package/dist/index.cjs +3937 -952
  106. package/dist/index.cjs.map +1 -1
  107. package/dist/index.d.cts +981 -2
  108. package/dist/index.d.ts +981 -2
  109. package/dist/index.js +3316 -455
  110. package/dist/index.js.map +1 -1
  111. package/dist/kerebron.cjs +15 -0
  112. package/dist/kerebron.cjs.map +1 -1
  113. package/dist/kerebron.js +15 -0
  114. package/dist/kerebron.js.map +1 -1
  115. package/dist/{nitroTableGrid-J7F6D2QA.cjs → nitroTableGrid-3J2GY6CK.cjs} +14 -11
  116. package/dist/nitroTableGrid-3J2GY6CK.cjs.map +1 -0
  117. package/dist/nitroTableGrid-SIMT7635.js +25 -0
  118. package/dist/nitroTableGrid-SIMT7635.js.map +1 -0
  119. package/dist/orderRows-BUJYgSc7.d.cts +221 -0
  120. package/dist/orderRows-BUJYgSc7.d.ts +221 -0
  121. package/dist/styles.css +1 -1
  122. package/dist/tailwind-preset.cjs +4 -4
  123. package/dist/tailwind-preset.js +1 -1
  124. package/package.json +4 -4
  125. package/dist/chunk-2T4JU5RH.cjs.map +0 -1
  126. package/dist/chunk-3SSXDWD7.js.map +0 -1
  127. package/dist/chunk-7PA26KBF.cjs.map +0 -1
  128. package/dist/chunk-LEMY57MI.js +0 -3
  129. package/dist/chunk-LZPPH5BW.cjs.map +0 -1
  130. package/dist/chunk-RXY5SD3O.js.map +0 -1
  131. package/dist/chunk-UHPQYBXQ.js.map +0 -1
  132. package/dist/nitroTableGrid-GKJAX3J4.js +0 -22
  133. package/dist/nitroTableGrid-GKJAX3J4.js.map +0 -1
  134. package/dist/nitroTableGrid-J7F6D2QA.cjs.map +0 -1
@@ -0,0 +1,1605 @@
1
+ 'use strict';
2
+
3
+ var chunkU3ABLVYH_cjs = require('./chunk-U3ABLVYH.cjs');
4
+ var chunkRH43XBNV_cjs = require('./chunk-RH43XBNV.cjs');
5
+ var chunkXP6HELVG_cjs = require('./chunk-XP6HELVG.cjs');
6
+ var chunkFRT6RQND_cjs = require('./chunk-FRT6RQND.cjs');
7
+ var chunkUOOH356R_cjs = require('./chunk-UOOH356R.cjs');
8
+ var chunkZHBANUBI_cjs = require('./chunk-ZHBANUBI.cjs');
9
+ var chunkNINI4WVS_cjs = require('./chunk-NINI4WVS.cjs');
10
+ var chunkKJPOFUF5_cjs = require('./chunk-KJPOFUF5.cjs');
11
+ var chunkMSRU3XBH_cjs = require('./chunk-MSRU3XBH.cjs');
12
+ var chunkUTYUT5YY_cjs = require('./chunk-UTYUT5YY.cjs');
13
+ var chunkA2QVQF54_cjs = require('./chunk-A2QVQF54.cjs');
14
+ var chunkEL2RSQTJ_cjs = require('./chunk-EL2RSQTJ.cjs');
15
+ var chunkYVPC65ZJ_cjs = require('./chunk-YVPC65ZJ.cjs');
16
+ var chunkOR5DRJCW_cjs = require('./chunk-OR5DRJCW.cjs');
17
+ var jsxRuntime = require('react/jsx-runtime');
18
+ var React3 = require('react');
19
+
20
+ function _interopNamespace(e) {
21
+ if (e && e.__esModule) return e;
22
+ var n = Object.create(null);
23
+ if (e) {
24
+ Object.keys(e).forEach(function (k) {
25
+ if (k !== 'default') {
26
+ var d = Object.getOwnPropertyDescriptor(e, k);
27
+ Object.defineProperty(n, k, d.get ? d : {
28
+ enumerable: true,
29
+ get: function () { return e[k]; }
30
+ });
31
+ }
32
+ });
33
+ }
34
+ n.default = e;
35
+ return Object.freeze(n);
36
+ }
37
+
38
+ var React3__namespace = /*#__PURE__*/_interopNamespace(React3);
39
+
40
+ function toolbarKeyNav(e) {
41
+ if (e.altKey || e.ctrlKey || e.metaKey) return;
42
+ if (!["ArrowLeft", "ArrowRight", "Home", "End"].includes(e.key)) return;
43
+ const buttons = Array.from(
44
+ e.currentTarget.querySelectorAll(
45
+ "button:not([disabled])"
46
+ )
47
+ );
48
+ const i = buttons.indexOf(document.activeElement);
49
+ if (i === -1 || buttons.length === 0) return;
50
+ e.preventDefault();
51
+ e.stopPropagation();
52
+ const next = e.key === "ArrowLeft" ? (i - 1 + buttons.length) % buttons.length : e.key === "ArrowRight" ? (i + 1) % buttons.length : e.key === "Home" ? 0 : buttons.length - 1;
53
+ buttons[next]?.focus();
54
+ }
55
+ var ALIGN = {
56
+ /** Vertically centered on the row's right edge (single-line rows). */
57
+ center: "pointer-fine:top-1/2 pointer-fine:right-0 pointer-fine:-translate-y-1/2",
58
+ /** Pinned near the row's top-right corner (multi-line rows). */
59
+ top: "pointer-fine:top-1.5 pointer-fine:right-1.5"
60
+ };
61
+ var REVEAL = {
62
+ row: chunkOR5DRJCW_cjs.cn(
63
+ "group-hover:pointer-events-auto group-hover:opacity-100",
64
+ "group-focus-within:pointer-events-auto group-focus-within:opacity-100",
65
+ "group-focus:pointer-events-auto group-focus:opacity-100"
66
+ ),
67
+ order: chunkOR5DRJCW_cjs.cn(
68
+ "group-hover/order:pointer-events-auto group-hover/order:opacity-100",
69
+ "group-focus-within/order:pointer-events-auto group-focus-within/order:opacity-100",
70
+ "group-focus/order:pointer-events-auto group-focus/order:opacity-100"
71
+ ),
72
+ grid: chunkOR5DRJCW_cjs.cn(
73
+ "[.wcdv-tr:hover_&]:pointer-events-auto [.wcdv-tr:hover_&]:opacity-100",
74
+ "[.wcdv-tr:focus-within_&]:pointer-events-auto [.wcdv-tr:focus-within_&]:opacity-100"
75
+ )
76
+ };
77
+ function RowActionToolbar({
78
+ label,
79
+ align = "center",
80
+ group = "row",
81
+ className,
82
+ children
83
+ }) {
84
+ return /* @__PURE__ */ jsxRuntime.jsx(
85
+ "div",
86
+ {
87
+ role: "toolbar",
88
+ "aria-label": label,
89
+ onKeyDown: toolbarKeyNav,
90
+ className: chunkOR5DRJCW_cjs.cn(
91
+ "z-10 ml-auto flex items-center gap-0.5 transition-opacity",
92
+ // Inside a grid cell the column already reserves the space, so the
93
+ // toolbar stays in flow — no absolute overlay. It keeps the card
94
+ // chrome, though: pair with a `sticky right-0` actions column and it
95
+ // floats over scrolled-under content at the grid's right edge.
96
+ group !== "grid" && [
97
+ "pointer-fine:absolute",
98
+ ALIGN[align],
99
+ "pointer-fine:bg-card pointer-fine:border-border pointer-fine:rounded-md pointer-fine:border pointer-fine:p-0.5 pointer-fine:shadow-sm"
100
+ ],
101
+ group === "grid" && "bg-card border-border rounded-md border p-0.5 shadow-sm",
102
+ "pointer-fine:pointer-events-none pointer-fine:opacity-0",
103
+ REVEAL[group],
104
+ "focus-within:pointer-events-auto focus-within:opacity-100",
105
+ className
106
+ ),
107
+ children
108
+ }
109
+ );
110
+ }
111
+ function RowIconButton({
112
+ label,
113
+ icon: Icon,
114
+ onClick,
115
+ active,
116
+ size = "md"
117
+ }) {
118
+ return /* @__PURE__ */ jsxRuntime.jsx(chunkRH43XBNV_cjs.Tooltip, { content: label, children: /* @__PURE__ */ jsxRuntime.jsx(
119
+ chunkA2QVQF54_cjs.Button,
120
+ {
121
+ type: "button",
122
+ variant: "ghost",
123
+ size: "icon",
124
+ "aria-label": label,
125
+ "aria-pressed": active,
126
+ onClick: (e) => {
127
+ e.stopPropagation();
128
+ onClick();
129
+ },
130
+ className: chunkOR5DRJCW_cjs.cn(
131
+ size === "sm" ? "h-7 w-7" : "h-8 w-8",
132
+ "shrink-0",
133
+ active && "bg-primary-50 text-primary-700 dark:bg-primary-950 dark:text-primary-400"
134
+ ),
135
+ children: /* @__PURE__ */ jsxRuntime.jsx(Icon, { size: size === "sm" ? 14 : 16 })
136
+ }
137
+ ) });
138
+ }
139
+ var TYPE_ORDER = ["drug", "food", "environmental", "other"];
140
+ var ALLERGY_TYPE_LABELS = {
141
+ drug: "Drug",
142
+ food: "Food",
143
+ environmental: "Environmental",
144
+ other: "Other"
145
+ };
146
+ var SEVERITY_BADGE = {
147
+ severe: "danger",
148
+ moderate: "warning",
149
+ mild: "secondary"
150
+ };
151
+ var DEFAULT_ACTIONS = ["correct", "note", "remove"];
152
+ var ACTION_META = {
153
+ correct: { label: "Correct", icon: chunkUTYUT5YY_cjs.Pencil },
154
+ note: { label: "Notes", icon: chunkUTYUT5YY_cjs.StickyNote },
155
+ remove: { label: "Remove", icon: chunkUTYUT5YY_cjs.Ban }
156
+ };
157
+ function AllergyRow({
158
+ allergy,
159
+ actions,
160
+ readOnly,
161
+ drag,
162
+ onMove,
163
+ onAction
164
+ }) {
165
+ const handleRowKeyDown = (e) => {
166
+ if (e.target !== e.currentTarget) return;
167
+ if (e.altKey && (e.key === "ArrowUp" || e.key === "ArrowDown")) {
168
+ e.preventDefault();
169
+ onMove?.(allergy, e.key === "ArrowUp" ? -1 : 1);
170
+ } else if (e.key === "ArrowUp" || e.key === "ArrowDown") {
171
+ e.preventDefault();
172
+ const list = e.currentTarget.closest("ul");
173
+ if (!list) return;
174
+ const rows = Array.from(
175
+ list.querySelectorAll("li[data-allergy-id]")
176
+ );
177
+ const i = rows.indexOf(e.currentTarget);
178
+ rows[e.key === "ArrowUp" ? Math.max(0, i - 1) : Math.min(rows.length - 1, i + 1)]?.focus();
179
+ }
180
+ };
181
+ return (
182
+ // Rows are focus stops when reordering is enabled so drag & drop has a
183
+ // keyboard equivalent (Alt+↑/↓) — 508.
184
+ /* eslint-disable jsx-a11y/no-noninteractive-element-interactions, jsx-a11y/no-noninteractive-tabindex */
185
+ /* @__PURE__ */ jsxRuntime.jsxs(
186
+ "li",
187
+ {
188
+ "data-allergy-id": allergy.id,
189
+ tabIndex: drag.enabled ? 0 : void 0,
190
+ onKeyDown: drag.enabled ? handleRowKeyDown : void 0,
191
+ "aria-label": drag.enabled ? `${allergy.allergen}. Alt plus arrow keys to reorder.` : void 0,
192
+ ...drag.rowProps(allergy.id),
193
+ className: chunkOR5DRJCW_cjs.cn(
194
+ "group border-border/60 relative flex min-h-11 flex-wrap items-center gap-x-2 gap-y-1 border-b px-1 py-2",
195
+ "focus-visible:ring-ring focus-visible:ring-2 focus-visible:outline-none",
196
+ drag.enabled && "cursor-grab active:cursor-grabbing",
197
+ chunkYVPC65ZJ_cjs.dragIndicatorClasses(drag, allergy.id)
198
+ ),
199
+ children: [
200
+ drag.enabled ? /* @__PURE__ */ jsxRuntime.jsx(
201
+ chunkUTYUT5YY_cjs.GripVertical,
202
+ {
203
+ size: 14,
204
+ "aria-hidden": true,
205
+ className: "text-muted-foreground/50 shrink-0"
206
+ }
207
+ ) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground/60 select-none", children: "\u2022" }),
208
+ /* @__PURE__ */ jsxRuntime.jsx(
209
+ "span",
210
+ {
211
+ className: chunkOR5DRJCW_cjs.cn(
212
+ "text-foreground font-medium",
213
+ allergy.inactive && "text-muted-foreground line-through"
214
+ ),
215
+ children: allergy.allergen
216
+ }
217
+ ),
218
+ allergy.code && /* @__PURE__ */ jsxRuntime.jsxs(
219
+ "span",
220
+ {
221
+ className: "text-muted-foreground/70 text-xs",
222
+ title: allergy.code.display,
223
+ children: [
224
+ allergy.code.system,
225
+ " ",
226
+ allergy.code.code
227
+ ]
228
+ }
229
+ ),
230
+ allergy.severity && /* @__PURE__ */ jsxRuntime.jsx(chunkEL2RSQTJ_cjs.Badge, { variant: SEVERITY_BADGE[allergy.severity], size: "sm", children: allergy.severity }),
231
+ allergy.kind === "intolerance" && /* @__PURE__ */ jsxRuntime.jsx(chunkEL2RSQTJ_cjs.Badge, { variant: "secondary", size: "sm", children: "intolerance" }),
232
+ allergy.reaction && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-muted-foreground text-sm", children: [
233
+ "\u2014 ",
234
+ allergy.reaction
235
+ ] }),
236
+ allergy.onsetDate && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-muted-foreground text-xs", children: [
237
+ "since ",
238
+ allergy.onsetDate
239
+ ] }),
240
+ allergy.inactive && /* @__PURE__ */ jsxRuntime.jsx(chunkEL2RSQTJ_cjs.Badge, { variant: "secondary", size: "sm", children: "inactive" }),
241
+ allergy.note && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex w-full basis-full items-center gap-1.5 pl-4", children: [
242
+ /* @__PURE__ */ jsxRuntime.jsx(chunkUTYUT5YY_cjs.StickyNote, { size: 12, className: "text-muted-foreground" }),
243
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground text-xs", children: allergy.note })
244
+ ] }),
245
+ !readOnly && actions.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(RowActionToolbar, { label: `Actions for ${allergy.allergen}`, children: actions.map((action) => /* @__PURE__ */ jsxRuntime.jsx(
246
+ RowIconButton,
247
+ {
248
+ label: ACTION_META[action].label,
249
+ icon: ACTION_META[action].icon,
250
+ onClick: () => onAction?.(allergy, action)
251
+ },
252
+ action
253
+ )) })
254
+ ]
255
+ }
256
+ )
257
+ );
258
+ }
259
+ var AllergyList = React3__namespace.forwardRef(
260
+ ({
261
+ allergies,
262
+ noKnownAllergies,
263
+ onNoKnownAllergiesChange,
264
+ title = "Allergies",
265
+ actions = DEFAULT_ACTIONS,
266
+ onAction,
267
+ onReorder,
268
+ addSearch,
269
+ onAdd,
270
+ readOnly = false,
271
+ className,
272
+ "data-testid": dataTestId,
273
+ ...props
274
+ }, ref) => {
275
+ const [announcement, setAnnouncement] = chunkYVPC65ZJ_cjs.useLiveAnnouncement();
276
+ const groups = TYPE_ORDER.map((type) => ({
277
+ type,
278
+ label: ALLERGY_TYPE_LABELS[type],
279
+ items: allergies.filter((a) => (a.type ?? "other") === type)
280
+ })).filter((g) => g.items.length > 0);
281
+ const empty = allergies.length === 0;
282
+ const typeOf = React3__namespace.useCallback(
283
+ (id) => allergies.find((a) => a.id === id)?.type ?? "other",
284
+ [allergies]
285
+ );
286
+ const drag = chunkYVPC65ZJ_cjs.useDragReorder({
287
+ ids: allergies.map((a) => a.id),
288
+ onReorder: readOnly || !onReorder ? void 0 : (ids) => {
289
+ setAnnouncement("Allergy list reordered");
290
+ onReorder(ids);
291
+ },
292
+ canDropOn: (dragged, target) => typeOf(dragged) === typeOf(target)
293
+ });
294
+ const moveAllergy = React3__namespace.useCallback(
295
+ (allergy, dir) => {
296
+ if (readOnly || !onReorder) return;
297
+ const ids = allergies.map((a) => a.id);
298
+ const from = ids.indexOf(allergy.id);
299
+ let to = from + dir;
300
+ while (to >= 0 && to < allergies.length && (allergies[to].type ?? "other") !== (allergy.type ?? "other")) {
301
+ to += dir;
302
+ }
303
+ if (to < 0 || to >= allergies.length) return;
304
+ [ids[from], ids[to]] = [ids[to], ids[from]];
305
+ setAnnouncement(
306
+ `${allergy.allergen} moved ${dir === -1 ? "up" : "down"}`
307
+ );
308
+ onReorder(ids);
309
+ },
310
+ [allergies, onReorder, readOnly, setAnnouncement]
311
+ );
312
+ return /* @__PURE__ */ jsxRuntime.jsxs(
313
+ chunkZHBANUBI_cjs.Card,
314
+ {
315
+ ref,
316
+ padding: "none",
317
+ className: chunkOR5DRJCW_cjs.cn("w-full", className),
318
+ "data-testid": dataTestId,
319
+ ...props,
320
+ children: [
321
+ title !== null && /* @__PURE__ */ jsxRuntime.jsx(chunkZHBANUBI_cjs.CardHeader, { className: "border-border bg-muted/50 border-b px-4 py-3", children: /* @__PURE__ */ jsxRuntime.jsxs("h3", { className: "text-foreground flex items-center gap-2 text-sm font-semibold tracking-wide uppercase", children: [
322
+ /* @__PURE__ */ jsxRuntime.jsx(
323
+ chunkUTYUT5YY_cjs.AlertCircle,
324
+ {
325
+ size: 16,
326
+ className: "text-red-600 dark:text-red-400"
327
+ }
328
+ ),
329
+ title
330
+ ] }) }),
331
+ /* @__PURE__ */ jsxRuntime.jsxs(chunkZHBANUBI_cjs.CardContent, { className: "space-y-5 px-4 py-4", children: [
332
+ empty ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
333
+ noKnownAllergies ? /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-foreground flex items-center gap-1.5 text-sm", children: [
334
+ /* @__PURE__ */ jsxRuntime.jsx(chunkEL2RSQTJ_cjs.Badge, { variant: "success", size: "sm", children: "\u2713" }),
335
+ "No known allergies (NKA)"
336
+ ] }) : /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-muted-foreground text-sm", children: "Allergy status not recorded." }),
337
+ !readOnly && onNoKnownAllergiesChange && /* @__PURE__ */ jsxRuntime.jsx(
338
+ chunkA2QVQF54_cjs.Button,
339
+ {
340
+ variant: noKnownAllergies ? "secondary" : "outline",
341
+ size: "sm",
342
+ onClick: () => onNoKnownAllergiesChange(!noKnownAllergies),
343
+ children: noKnownAllergies ? "Clear no-known-allergies" : "Confirm: no known allergies"
344
+ }
345
+ )
346
+ ] }) : groups.map(({ type, label, items }) => /* @__PURE__ */ jsxRuntime.jsxs("section", { "aria-label": label, children: [
347
+ /* @__PURE__ */ jsxRuntime.jsx("h4", { className: "border-border text-foreground border-b pb-1 text-sm font-semibold tracking-wide uppercase", children: label }),
348
+ /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "mt-1", children: items.map((allergy) => /* @__PURE__ */ jsxRuntime.jsx(
349
+ AllergyRow,
350
+ {
351
+ allergy,
352
+ actions,
353
+ readOnly,
354
+ drag,
355
+ onMove: moveAllergy,
356
+ onAction
357
+ },
358
+ allergy.id
359
+ )) })
360
+ ] }, type)),
361
+ !readOnly && (addSearch || onAdd) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
362
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground text-xs font-semibold tracking-wide uppercase", children: "Add allergy" }),
363
+ addSearch,
364
+ onAdd && /* @__PURE__ */ jsxRuntime.jsx(
365
+ chunkA2QVQF54_cjs.Button,
366
+ {
367
+ variant: "outline",
368
+ size: "sm",
369
+ onClick: onAdd,
370
+ leftIcon: /* @__PURE__ */ jsxRuntime.jsx(chunkUTYUT5YY_cjs.Plus, { size: 12 }),
371
+ className: "h-auto rounded-full px-2.5 py-1 text-xs",
372
+ children: "Add allergy\u2026"
373
+ }
374
+ )
375
+ ] })
376
+ ] }),
377
+ /* @__PURE__ */ jsxRuntime.jsx("div", { "aria-live": "polite", className: "sr-only", children: announcement })
378
+ ]
379
+ }
380
+ );
381
+ }
382
+ );
383
+ AllergyList.displayName = "AllergyList";
384
+ var CodeLookupContext = React3__namespace.createContext(
385
+ null
386
+ );
387
+ function CodeLookupProvider({
388
+ component,
389
+ indexUrl = "/codify",
390
+ locale = "en",
391
+ children
392
+ }) {
393
+ const value = React3__namespace.useMemo(
394
+ () => ({ component, indexUrl, locale }),
395
+ [component, indexUrl, locale]
396
+ );
397
+ return /* @__PURE__ */ jsxRuntime.jsx(CodeLookupContext.Provider, { value, children });
398
+ }
399
+ function useCodeLookupConfig() {
400
+ return React3__namespace.useContext(CodeLookupContext);
401
+ }
402
+ function newId() {
403
+ return `alg-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
404
+ }
405
+ var TYPE_OPTIONS = [
406
+ { value: "drug", label: "Drug" },
407
+ { value: "food", label: "Food" },
408
+ { value: "environmental", label: "Environmental" },
409
+ { value: "other", label: "Other" }
410
+ ];
411
+ function AllergyEditor({
412
+ allergy,
413
+ codeLookup,
414
+ onClose,
415
+ onSave
416
+ }) {
417
+ const [draft, setDraft] = React3__namespace.useState(
418
+ () => allergy ?? { id: newId(), allergen: "", type: "drug" }
419
+ );
420
+ const patch = (p) => setDraft((prev) => ({ ...prev, ...p }));
421
+ const bodyRef = React3__namespace.useRef(null);
422
+ React3__namespace.useEffect(() => {
423
+ bodyRef.current?.querySelector("input")?.focus();
424
+ }, []);
425
+ const canSave = draft.allergen.trim().length > 0;
426
+ const isDrug = (draft.type ?? "drug") === "drug";
427
+ return /* @__PURE__ */ jsxRuntime.jsxs(chunkKJPOFUF5_cjs.Modal, { open: true, onOpenChange: (o) => !o && onClose(), size: "md", children: [
428
+ /* @__PURE__ */ jsxRuntime.jsxs(chunkKJPOFUF5_cjs.ModalHeader, { children: [
429
+ /* @__PURE__ */ jsxRuntime.jsx(chunkKJPOFUF5_cjs.ModalTitle, { children: allergy ? "Correct Allergy" : "Add Allergy" }),
430
+ /* @__PURE__ */ jsxRuntime.jsx(chunkKJPOFUF5_cjs.ModalClose, {})
431
+ ] }),
432
+ /* @__PURE__ */ jsxRuntime.jsx(chunkKJPOFUF5_cjs.ModalBody, { className: "space-y-4", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { ref: bodyRef, className: "contents", children: [
433
+ /* @__PURE__ */ jsxRuntime.jsxs(
434
+ chunkXP6HELVG_cjs.RadioGroup,
435
+ {
436
+ name: "alg-kind",
437
+ label: "Mechanism",
438
+ description: "A true immune-mediated allergy, or a non-immune intolerance (e.g. GI upset)",
439
+ value: draft.kind ?? "allergy",
440
+ onValueChange: (v) => patch({ kind: v }),
441
+ orientation: "horizontal",
442
+ size: "sm",
443
+ children: [
444
+ /* @__PURE__ */ jsxRuntime.jsx(chunkXP6HELVG_cjs.Radio, { value: "allergy", label: "Allergy" }),
445
+ /* @__PURE__ */ jsxRuntime.jsx(chunkXP6HELVG_cjs.Radio, { value: "intolerance", label: "Intolerance" })
446
+ ]
447
+ }
448
+ ),
449
+ /* @__PURE__ */ jsxRuntime.jsx(
450
+ chunkFRT6RQND_cjs.Select,
451
+ {
452
+ label: "Type",
453
+ options: TYPE_OPTIONS,
454
+ value: draft.type ?? "drug",
455
+ onValueChange: (v) => {
456
+ const type = v;
457
+ patch({
458
+ type,
459
+ ...type !== "drug" && { code: void 0 }
460
+ });
461
+ }
462
+ }
463
+ ),
464
+ isDrug && codeLookup ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1.5", children: [
465
+ /* @__PURE__ */ jsxRuntime.jsx(chunkUOOH356R_cjs.Label, { htmlFor: "alg-search", children: "Allergen" }),
466
+ /* @__PURE__ */ jsxRuntime.jsx(
467
+ codeLookup.component,
468
+ {
469
+ indexUrl: codeLookup.indexUrl,
470
+ locale: codeLookup.locale,
471
+ domains: ["med"],
472
+ bare: true,
473
+ clearOnSelect: false,
474
+ placeholder: "Search drug allergens \u2014 e.g. penicillin",
475
+ onSelect: (result) => patch({
476
+ allergen: result.label,
477
+ code: {
478
+ system: result.codetype,
479
+ code: result.fullcode,
480
+ display: result.label
481
+ }
482
+ }),
483
+ onFreeText: (text) => patch({ allergen: text, code: void 0 })
484
+ }
485
+ ),
486
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-muted-foreground text-xs", children: draft.code ? `Coded: ${draft.code.system} ${draft.code.code}` : draft.allergen ? `Uncoded free text: "${draft.allergen}"` : "Pick a result to code the allergen, or press Enter for free text" })
487
+ ] }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1.5", children: [
488
+ /* @__PURE__ */ jsxRuntime.jsx(chunkUOOH356R_cjs.Label, { htmlFor: "alg-name", children: "Allergen" }),
489
+ /* @__PURE__ */ jsxRuntime.jsx(
490
+ chunkMSRU3XBH_cjs.Input,
491
+ {
492
+ id: "alg-name",
493
+ value: draft.allergen,
494
+ onChange: (e) => patch({ allergen: e.target.value })
495
+ }
496
+ )
497
+ ] }),
498
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1.5", children: [
499
+ /* @__PURE__ */ jsxRuntime.jsx(chunkUOOH356R_cjs.Label, { htmlFor: "alg-reaction", children: "Reaction" }),
500
+ /* @__PURE__ */ jsxRuntime.jsx(
501
+ chunkMSRU3XBH_cjs.Input,
502
+ {
503
+ id: "alg-reaction",
504
+ value: draft.reaction ?? "",
505
+ onChange: (e) => patch({ reaction: e.target.value })
506
+ }
507
+ )
508
+ ] }),
509
+ /* @__PURE__ */ jsxRuntime.jsxs(
510
+ chunkXP6HELVG_cjs.RadioGroup,
511
+ {
512
+ name: "alg-severity",
513
+ label: "Severity",
514
+ value: draft.severity ?? "",
515
+ onValueChange: (v) => patch({ severity: v || void 0 }),
516
+ orientation: "horizontal",
517
+ size: "sm",
518
+ children: [
519
+ /* @__PURE__ */ jsxRuntime.jsx(chunkXP6HELVG_cjs.Radio, { value: "mild", label: "Mild" }),
520
+ /* @__PURE__ */ jsxRuntime.jsx(chunkXP6HELVG_cjs.Radio, { value: "moderate", label: "Moderate" }),
521
+ /* @__PURE__ */ jsxRuntime.jsx(chunkXP6HELVG_cjs.Radio, { value: "severe", label: "Severe" })
522
+ ]
523
+ }
524
+ ),
525
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1.5", children: [
526
+ /* @__PURE__ */ jsxRuntime.jsx(chunkUOOH356R_cjs.Label, { htmlFor: "alg-onset", children: "Onset date" }),
527
+ /* @__PURE__ */ jsxRuntime.jsx(
528
+ chunkNINI4WVS_cjs.DateInput,
529
+ {
530
+ id: "alg-onset",
531
+ value: draft.onsetDate ?? "",
532
+ onChange: (v) => patch({ onsetDate: v })
533
+ }
534
+ )
535
+ ] }),
536
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1.5", children: [
537
+ /* @__PURE__ */ jsxRuntime.jsx(chunkUOOH356R_cjs.Label, { htmlFor: "alg-note", children: "Note" }),
538
+ /* @__PURE__ */ jsxRuntime.jsx(
539
+ chunkU3ABLVYH_cjs.Textarea,
540
+ {
541
+ id: "alg-note",
542
+ value: draft.note ?? "",
543
+ onChange: (e) => patch({ note: e.target.value }),
544
+ rows: 2
545
+ }
546
+ )
547
+ ] })
548
+ ] }) }),
549
+ /* @__PURE__ */ jsxRuntime.jsxs(chunkKJPOFUF5_cjs.ModalFooter, { children: [
550
+ /* @__PURE__ */ jsxRuntime.jsx(chunkA2QVQF54_cjs.Button, { variant: "secondary", onClick: onClose, children: "Cancel" }),
551
+ /* @__PURE__ */ jsxRuntime.jsx(
552
+ chunkA2QVQF54_cjs.Button,
553
+ {
554
+ onClick: () => {
555
+ onSave({ ...draft, allergen: draft.allergen.trim() });
556
+ onClose();
557
+ },
558
+ disabled: !canSave,
559
+ children: "Save"
560
+ }
561
+ )
562
+ ] })
563
+ ] });
564
+ }
565
+ function AllergyManager({
566
+ allergies: controlled,
567
+ defaultAllergies,
568
+ onChange,
569
+ noKnownAllergies,
570
+ onNoKnownAllergiesChange,
571
+ title = "Allergies",
572
+ codeLookup,
573
+ inlineAddSearch = false,
574
+ readOnly = false,
575
+ className,
576
+ "data-testid": dataTestId
577
+ }) {
578
+ const isControlled = controlled !== void 0;
579
+ const [internal, setInternal] = React3__namespace.useState(
580
+ defaultAllergies ?? []
581
+ );
582
+ const allergies = isControlled ? controlled : internal;
583
+ const ambientCodeLookup = useCodeLookupConfig();
584
+ const effectiveCodeLookup = codeLookup === false ? void 0 : codeLookup ?? ambientCodeLookup ?? void 0;
585
+ const [dialog, setDialog] = React3__namespace.useState(null);
586
+ const [noteDraft, setNoteDraft] = React3__namespace.useState("");
587
+ const commit = (next) => {
588
+ if (!isControlled) setInternal(next);
589
+ onChange?.(next);
590
+ if (next.length > 0 && noKnownAllergies) {
591
+ onNoKnownAllergiesChange?.(false);
592
+ }
593
+ };
594
+ const handleAction = (allergy, action) => {
595
+ switch (action) {
596
+ case "remove":
597
+ commit(allergies.filter((a) => a.id !== allergy.id));
598
+ break;
599
+ case "correct":
600
+ setDialog({ kind: "correct", allergy });
601
+ break;
602
+ case "note":
603
+ setNoteDraft(allergy.note ?? "");
604
+ setDialog({ kind: "note", allergy });
605
+ break;
606
+ }
607
+ };
608
+ const addSearch = inlineAddSearch && effectiveCodeLookup && !readOnly ? /* @__PURE__ */ jsxRuntime.jsx(
609
+ effectiveCodeLookup.component,
610
+ {
611
+ indexUrl: effectiveCodeLookup.indexUrl,
612
+ locale: effectiveCodeLookup.locale,
613
+ domains: ["med"],
614
+ bare: true,
615
+ clearOnSelect: true,
616
+ placeholder: "Search drug allergens to add \u2014 use Add allergy\u2026 for food/environmental",
617
+ onSelect: (result) => commit([
618
+ ...allergies,
619
+ {
620
+ id: newId(),
621
+ allergen: result.label,
622
+ type: "drug",
623
+ code: {
624
+ system: result.codetype,
625
+ code: result.fullcode,
626
+ display: result.label
627
+ }
628
+ }
629
+ ]),
630
+ onFreeText: (text) => (
631
+ // this search bar is explicitly for drug allergens — free-text
632
+ // entries carry type 'drug' like the coded path
633
+ commit([...allergies, { id: newId(), allergen: text, type: "drug" }])
634
+ )
635
+ }
636
+ ) : void 0;
637
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
638
+ /* @__PURE__ */ jsxRuntime.jsx(
639
+ AllergyList,
640
+ {
641
+ allergies,
642
+ noKnownAllergies,
643
+ onNoKnownAllergiesChange,
644
+ title,
645
+ onAction: handleAction,
646
+ onReorder: (ids) => commit(
647
+ [...allergies].sort((a, b) => ids.indexOf(a.id) - ids.indexOf(b.id))
648
+ ),
649
+ addSearch,
650
+ onAdd: () => setDialog({ kind: "add" }),
651
+ readOnly,
652
+ className,
653
+ "data-testid": dataTestId
654
+ }
655
+ ),
656
+ dialog && (dialog.kind === "correct" || dialog.kind === "add") && /* @__PURE__ */ jsxRuntime.jsx(
657
+ AllergyEditor,
658
+ {
659
+ allergy: dialog.kind === "correct" ? dialog.allergy : void 0,
660
+ codeLookup: effectiveCodeLookup,
661
+ onClose: () => setDialog(null),
662
+ onSave: (saved) => {
663
+ if (dialog.kind === "correct") {
664
+ commit(allergies.map((a) => a.id === saved.id ? saved : a));
665
+ } else {
666
+ commit([...allergies, saved]);
667
+ }
668
+ }
669
+ },
670
+ dialog.kind === "correct" ? dialog.allergy.id : "add"
671
+ ),
672
+ dialog?.kind === "note" && /* @__PURE__ */ jsxRuntime.jsxs(chunkKJPOFUF5_cjs.Modal, { open: true, onOpenChange: (o) => !o && setDialog(null), size: "md", children: [
673
+ /* @__PURE__ */ jsxRuntime.jsxs(chunkKJPOFUF5_cjs.ModalHeader, { children: [
674
+ /* @__PURE__ */ jsxRuntime.jsx(chunkKJPOFUF5_cjs.ModalTitle, { children: "Allergy Notes" }),
675
+ /* @__PURE__ */ jsxRuntime.jsx(chunkKJPOFUF5_cjs.ModalClose, {})
676
+ ] }),
677
+ /* @__PURE__ */ jsxRuntime.jsxs(chunkKJPOFUF5_cjs.ModalBody, { className: "space-y-4", children: [
678
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-muted-foreground text-sm", children: dialog.allergy.allergen }),
679
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1.5", children: [
680
+ /* @__PURE__ */ jsxRuntime.jsx(chunkUOOH356R_cjs.Label, { htmlFor: "alg-note-dlg", children: "Note" }),
681
+ /* @__PURE__ */ jsxRuntime.jsx(
682
+ chunkU3ABLVYH_cjs.Textarea,
683
+ {
684
+ id: "alg-note-dlg",
685
+ value: noteDraft,
686
+ onChange: (e) => setNoteDraft(e.target.value),
687
+ rows: 4
688
+ }
689
+ )
690
+ ] })
691
+ ] }),
692
+ /* @__PURE__ */ jsxRuntime.jsxs(chunkKJPOFUF5_cjs.ModalFooter, { children: [
693
+ /* @__PURE__ */ jsxRuntime.jsx(chunkA2QVQF54_cjs.Button, { variant: "secondary", onClick: () => setDialog(null), children: "Cancel" }),
694
+ /* @__PURE__ */ jsxRuntime.jsx(
695
+ chunkA2QVQF54_cjs.Button,
696
+ {
697
+ onClick: () => {
698
+ commit(
699
+ allergies.map(
700
+ (a) => a.id === dialog.allergy.id ? { ...a, note: noteDraft.trim() || void 0 } : a
701
+ )
702
+ );
703
+ setDialog(null);
704
+ },
705
+ children: "Save"
706
+ }
707
+ )
708
+ ] })
709
+ ] })
710
+ ] });
711
+ }
712
+ var GROUP_ORDER = [
713
+ "unreconciled",
714
+ "taking",
715
+ "taking-noncompliant",
716
+ "not-taking",
717
+ "unknown"
718
+ ];
719
+ var MEDICATION_STATUS_LABELS = {
720
+ unreconciled: "Unreconciled",
721
+ taking: "Taking as Directed",
722
+ "taking-noncompliant": "Not Taking as Directed",
723
+ "not-taking": "Not Taking",
724
+ unknown: "Unknown"
725
+ };
726
+ var DEFAULT_ACTIONS2 = [
727
+ "open",
728
+ "correct",
729
+ "refill",
730
+ "add-task",
731
+ "note",
732
+ "remove"
733
+ ];
734
+ var ACTION_META2 = {
735
+ open: { label: "Open", icon: chunkUTYUT5YY_cjs.ExternalLink },
736
+ correct: { label: "Correct", icon: chunkUTYUT5YY_cjs.Pencil },
737
+ refill: { label: "Refill", icon: chunkUTYUT5YY_cjs.RefreshCw },
738
+ "add-task": { label: "Add Task", icon: chunkUTYUT5YY_cjs.CalendarCheck },
739
+ note: { label: "Notes", icon: chunkUTYUT5YY_cjs.StickyNote },
740
+ remove: { label: "Remove", icon: chunkUTYUT5YY_cjs.Ban },
741
+ "move-up": { label: "Move Up", icon: chunkUTYUT5YY_cjs.ChevronUp },
742
+ "move-down": { label: "Move Down", icon: chunkUTYUT5YY_cjs.ChevronDown }
743
+ };
744
+ var STATUS_BUTTON_META = [
745
+ { status: "taking", label: "Taking", icon: chunkUTYUT5YY_cjs.ThumbsUp },
746
+ {
747
+ status: "taking-noncompliant",
748
+ label: "Taking \u2013 Noncompliant",
749
+ icon: chunkUTYUT5YY_cjs.HandMetal
750
+ },
751
+ { status: "not-taking", label: "Not Taking", icon: chunkUTYUT5YY_cjs.ThumbsDown },
752
+ { status: "unknown", label: "Unknown", icon: chunkUTYUT5YY_cjs.HelpCircle }
753
+ ];
754
+ function MedicationRow({
755
+ medication,
756
+ actions,
757
+ readOnly,
758
+ drag,
759
+ onMove,
760
+ onStatusChange,
761
+ onAction
762
+ }) {
763
+ const handleRowKeyDown = (e) => {
764
+ if (e.target !== e.currentTarget) return;
765
+ if (e.altKey && (e.key === "ArrowUp" || e.key === "ArrowDown")) {
766
+ e.preventDefault();
767
+ onMove?.(medication, e.key === "ArrowUp" ? -1 : 1);
768
+ } else if (e.key === "ArrowUp" || e.key === "ArrowDown") {
769
+ e.preventDefault();
770
+ const list = e.currentTarget.closest("ul");
771
+ if (!list) return;
772
+ const rows = Array.from(
773
+ list.querySelectorAll("li[data-medication-id]")
774
+ );
775
+ const i = rows.indexOf(e.currentTarget);
776
+ rows[e.key === "ArrowUp" ? Math.max(0, i - 1) : Math.min(rows.length - 1, i + 1)]?.focus();
777
+ }
778
+ };
779
+ return (
780
+ // Rows are focus stops when reordering is enabled so drag & drop has a
781
+ // keyboard equivalent (Alt+↑/↓) — 508.
782
+ /* eslint-disable jsx-a11y/no-noninteractive-element-interactions, jsx-a11y/no-noninteractive-tabindex */
783
+ /* @__PURE__ */ jsxRuntime.jsxs(
784
+ "li",
785
+ {
786
+ "data-medication-id": medication.id,
787
+ tabIndex: drag.enabled ? 0 : void 0,
788
+ onKeyDown: drag.enabled ? handleRowKeyDown : void 0,
789
+ "aria-label": drag.enabled ? `${medication.name}. Alt plus arrow keys to reorder.` : void 0,
790
+ ...drag.rowProps(medication.id),
791
+ className: chunkOR5DRJCW_cjs.cn(
792
+ "group border-border/60 relative flex min-h-11 flex-wrap items-center gap-x-2 gap-y-1 border-b px-1 py-2",
793
+ "focus-visible:ring-ring focus-visible:ring-2 focus-visible:outline-none",
794
+ drag.enabled && "cursor-grab active:cursor-grabbing",
795
+ chunkYVPC65ZJ_cjs.dragIndicatorClasses(drag, medication.id)
796
+ ),
797
+ children: [
798
+ drag.enabled ? /* @__PURE__ */ jsxRuntime.jsx(
799
+ chunkUTYUT5YY_cjs.GripVertical,
800
+ {
801
+ size: 14,
802
+ "aria-hidden": true,
803
+ className: "text-muted-foreground/50 shrink-0"
804
+ }
805
+ ) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground/60 select-none", children: "\u2022" }),
806
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-foreground font-medium", children: medication.name }),
807
+ medication.code && /* @__PURE__ */ jsxRuntime.jsxs(
808
+ "span",
809
+ {
810
+ className: "text-muted-foreground/70 text-xs",
811
+ title: medication.code.display,
812
+ children: [
813
+ medication.code.system,
814
+ " ",
815
+ medication.code.code
816
+ ]
817
+ }
818
+ ),
819
+ medication.sig && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground text-sm", children: medication.sig }),
820
+ medication.expired && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-bold text-red-600 dark:text-red-400", children: "EXPIRED" }),
821
+ medication.discontinuedDate && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-muted-foreground text-sm", children: [
822
+ "Discontinued on: ",
823
+ medication.discontinuedDate
824
+ ] }),
825
+ (medication.note || medication.task) && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex w-full basis-full flex-col gap-0.5 pl-4", children: [
826
+ medication.note && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-muted-foreground flex items-center gap-1.5 text-xs", children: [
827
+ /* @__PURE__ */ jsxRuntime.jsx(chunkUTYUT5YY_cjs.StickyNote, { size: 12 }),
828
+ medication.note
829
+ ] }),
830
+ medication.task && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-muted-foreground flex items-center gap-1.5 text-xs", children: [
831
+ /* @__PURE__ */ jsxRuntime.jsx(chunkUTYUT5YY_cjs.CalendarCheck, { size: 12 }),
832
+ "Task: ",
833
+ medication.task
834
+ ] })
835
+ ] }),
836
+ !readOnly && /* @__PURE__ */ jsxRuntime.jsxs(RowActionToolbar, { label: `Actions for ${medication.name}`, children: [
837
+ actions.includes("open") && /* @__PURE__ */ jsxRuntime.jsx(
838
+ RowIconButton,
839
+ {
840
+ label: ACTION_META2.open.label,
841
+ icon: ACTION_META2.open.icon,
842
+ onClick: () => onAction?.(medication, "open")
843
+ }
844
+ ),
845
+ STATUS_BUTTON_META.map(({ status, label, icon }) => /* @__PURE__ */ jsxRuntime.jsx(
846
+ RowIconButton,
847
+ {
848
+ label,
849
+ icon,
850
+ active: medication.status === status,
851
+ onClick: () => onStatusChange?.(medication, status)
852
+ },
853
+ status
854
+ )),
855
+ actions.filter((a) => a !== "open").map((action) => /* @__PURE__ */ jsxRuntime.jsx(
856
+ RowIconButton,
857
+ {
858
+ label: ACTION_META2[action].label,
859
+ icon: ACTION_META2[action].icon,
860
+ onClick: () => onAction?.(medication, action)
861
+ },
862
+ action
863
+ ))
864
+ ] })
865
+ ]
866
+ }
867
+ )
868
+ );
869
+ }
870
+ var MedicationList = React3__namespace.forwardRef(
871
+ ({
872
+ medications,
873
+ title = "Presenting medications",
874
+ onStatusChange,
875
+ onAction,
876
+ onReorder,
877
+ actions = DEFAULT_ACTIONS2,
878
+ quickAddOptions,
879
+ onQuickAdd,
880
+ onAddOther,
881
+ readOnly = false,
882
+ reconciledMessage = "All medications reconciled.",
883
+ emptyMessage = "No medications recorded.",
884
+ addSearch,
885
+ className,
886
+ "data-testid": dataTestId,
887
+ ...props
888
+ }, ref) => {
889
+ const [announcement, setAnnouncement] = chunkYVPC65ZJ_cjs.useLiveAnnouncement();
890
+ const handleStatusChange = React3__namespace.useCallback(
891
+ (medication, status) => {
892
+ setAnnouncement(
893
+ `${medication.name} marked ${MEDICATION_STATUS_LABELS[status]}`
894
+ );
895
+ onStatusChange?.(medication, status);
896
+ },
897
+ [onStatusChange, setAnnouncement]
898
+ );
899
+ const groups = GROUP_ORDER.map((status) => ({
900
+ status,
901
+ label: MEDICATION_STATUS_LABELS[status],
902
+ items: medications.filter((m) => m.status === status)
903
+ })).filter((g) => g.items.length > 0 || g.status === "unreconciled");
904
+ const statusById = React3__namespace.useMemo(
905
+ () => new Map(medications.map((m) => [m.id, m.status])),
906
+ [medications]
907
+ );
908
+ const statusOf = React3__namespace.useCallback(
909
+ (id) => statusById.get(id),
910
+ [statusById]
911
+ );
912
+ const drag = chunkYVPC65ZJ_cjs.useDragReorder({
913
+ ids: medications.map((m) => m.id),
914
+ onReorder: readOnly || !onReorder ? void 0 : (ids) => {
915
+ setAnnouncement("Medication list reordered");
916
+ onReorder(ids);
917
+ },
918
+ canDropOn: (dragged, target) => statusOf(dragged) === statusOf(target)
919
+ });
920
+ const moveMedication = React3__namespace.useCallback(
921
+ (medication, dir) => {
922
+ if (readOnly || !onReorder) return;
923
+ const ids = medications.map((m) => m.id);
924
+ const from = ids.indexOf(medication.id);
925
+ let to = from + dir;
926
+ while (to >= 0 && to < medications.length && medications[to].status !== medication.status) {
927
+ to += dir;
928
+ }
929
+ if (to < 0 || to >= medications.length) return;
930
+ [ids[from], ids[to]] = [ids[to], ids[from]];
931
+ setAnnouncement(
932
+ `${medication.name} moved ${dir === -1 ? "up" : "down"}`
933
+ );
934
+ onReorder(ids);
935
+ },
936
+ [medications, onReorder, readOnly, setAnnouncement]
937
+ );
938
+ return /* @__PURE__ */ jsxRuntime.jsxs(
939
+ chunkZHBANUBI_cjs.Card,
940
+ {
941
+ ref,
942
+ padding: "none",
943
+ className: chunkOR5DRJCW_cjs.cn("w-full", className),
944
+ "data-testid": dataTestId,
945
+ ...props,
946
+ children: [
947
+ title !== null && /* @__PURE__ */ jsxRuntime.jsx(chunkZHBANUBI_cjs.CardHeader, { className: "border-border bg-muted/50 border-b px-4 py-3", children: /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-foreground text-sm font-semibold tracking-wide uppercase", children: title }) }),
948
+ /* @__PURE__ */ jsxRuntime.jsxs(chunkZHBANUBI_cjs.CardContent, { className: "space-y-6 px-4 py-4", children: [
949
+ groups.map(({ status, label, items }) => /* @__PURE__ */ jsxRuntime.jsxs("section", { "aria-label": label, children: [
950
+ /* @__PURE__ */ jsxRuntime.jsx("h4", { className: "border-border text-foreground border-b pb-1 text-sm font-semibold tracking-wide uppercase", children: label }),
951
+ items.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "mt-1", children: items.map((medication) => /* @__PURE__ */ jsxRuntime.jsx(
952
+ MedicationRow,
953
+ {
954
+ medication,
955
+ actions,
956
+ readOnly,
957
+ drag,
958
+ onMove: moveMedication,
959
+ onStatusChange: handleStatusChange,
960
+ onAction
961
+ },
962
+ medication.id
963
+ )) }) : medications.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-muted-foreground mt-2 text-sm", children: emptyMessage }) : /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-muted-foreground mt-2 flex items-center gap-1.5 text-sm", children: [
964
+ /* @__PURE__ */ jsxRuntime.jsx(chunkEL2RSQTJ_cjs.Badge, { variant: "success", size: "sm", children: "\u2713" }),
965
+ reconciledMessage
966
+ ] })
967
+ ] }, status)),
968
+ !readOnly && (addSearch || quickAddOptions?.length || onAddOther) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
969
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground text-xs font-semibold tracking-wide uppercase", children: "Add medication" }),
970
+ addSearch,
971
+ (quickAddOptions?.length || onAddOther) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center gap-1.5", children: [
972
+ quickAddOptions?.map((name) => /* @__PURE__ */ jsxRuntime.jsx(
973
+ chunkA2QVQF54_cjs.Button,
974
+ {
975
+ variant: "ghost",
976
+ size: "sm",
977
+ onClick: () => onQuickAdd?.(name),
978
+ leftIcon: /* @__PURE__ */ jsxRuntime.jsx(chunkUTYUT5YY_cjs.Plus, { size: 12 }),
979
+ className: "border-border h-auto rounded-full border px-2.5 py-1 text-xs",
980
+ children: name
981
+ },
982
+ name
983
+ )),
984
+ onAddOther && /* @__PURE__ */ jsxRuntime.jsx(
985
+ chunkA2QVQF54_cjs.Button,
986
+ {
987
+ variant: "outline",
988
+ size: "sm",
989
+ onClick: onAddOther,
990
+ leftIcon: /* @__PURE__ */ jsxRuntime.jsx(chunkUTYUT5YY_cjs.Plus, { size: 12 }),
991
+ className: "h-auto rounded-full px-2.5 py-1 text-xs",
992
+ children: "Other\u2026"
993
+ }
994
+ )
995
+ ] })
996
+ ] })
997
+ ] }),
998
+ /* @__PURE__ */ jsxRuntime.jsx("div", { "aria-live": "polite", className: "sr-only", children: announcement })
999
+ ]
1000
+ }
1001
+ );
1002
+ }
1003
+ );
1004
+ MedicationList.displayName = "MedicationList";
1005
+ var DOSE_FORMS = [
1006
+ "tablet",
1007
+ "capsule",
1008
+ "solution",
1009
+ "suspension",
1010
+ "syrup",
1011
+ "cream",
1012
+ "ointment",
1013
+ "gel",
1014
+ "patch",
1015
+ "suppository",
1016
+ "spray",
1017
+ "drops",
1018
+ "inhaler",
1019
+ "injection",
1020
+ "lozenge",
1021
+ "powder",
1022
+ "film"
1023
+ ];
1024
+ var FORM_TO_UNIT = {
1025
+ tablet: "tablet",
1026
+ capsule: "capsule",
1027
+ solution: "milliliter",
1028
+ suspension: "milliliter",
1029
+ syrup: "milliliter",
1030
+ cream: "gram",
1031
+ ointment: "gram",
1032
+ gel: "gram",
1033
+ patch: "patch",
1034
+ suppository: "suppository",
1035
+ spray: "spray",
1036
+ drops: "milliliter",
1037
+ inhaler: "each",
1038
+ injection: "milliliter",
1039
+ lozenge: "each",
1040
+ powder: "gram",
1041
+ film: "each"
1042
+ };
1043
+ function parseMedicationLabel(label) {
1044
+ const lower = label.toLowerCase();
1045
+ const strengthMatch = lower.match(
1046
+ /(\d{1,7}(?:\.\d{1,4})?(?:\s{0,4}\/\s{0,4}\d{1,7}(?:\.\d{1,4})?)?)\s{0,4}(mg\/ml|mcg\/ml|mg|mcg|g|ml|units?|%|meq)\b/
1047
+ );
1048
+ const doseForm = DOSE_FORMS.find((f) => lower.includes(f));
1049
+ return {
1050
+ strength: strengthMatch ? `${strengthMatch[1].replace(/\s+/g, "")} ${strengthMatch[2]}` : void 0,
1051
+ doseForm
1052
+ };
1053
+ }
1054
+ var SIG_ROUTES = [
1055
+ [/\bby mouth\b|\boral(ly)?\b|\bpo\b/, "oral"],
1056
+ [/\bsublingual(ly)?\b|\bunder the tongue\b|\bsl\b/, "sublingual"],
1057
+ [/\bsubcutaneous(ly)?\b|\bsubq\b|\bsc\b|\bsq\b/, "subcutaneous"],
1058
+ [/\bintramuscular(ly)?\b|\bim\b/, "intramuscular"],
1059
+ [/\bintravenous(ly)?\b|\biv\b/, "intravenous"],
1060
+ [/\binhal(e|ation|ed)\b|\bpuffs?\b|\bnebuliz/, "inhalation"],
1061
+ [/\beyes?\b|\bophthalmic\b/, "ophthalmic"],
1062
+ [/\bears?\b|\botic\b/, "otic"],
1063
+ [/\bnostrils?\b|\bnasal(ly)?\b|\bintranasal/, "nasal"],
1064
+ [/\brectal(ly)?\b|\bpr\b/, "rectal"],
1065
+ [/\btransdermal\b|\bto (the )?skin\b|\bapply\b|\btopical(ly)?\b/, "topical"]
1066
+ ];
1067
+ var SIG_FREQUENCIES = [
1068
+ [/\bevery other day\b|\bqod\b/, "Every other day"],
1069
+ [/\btwice (a |per )?day\b|\btwice daily\b|\bbid\b/, "Twice daily"],
1070
+ [
1071
+ /\b(three times|3 times)( a| per)? day\b|\b(three times|3 times) daily\b|\btid\b/,
1072
+ "Three times daily"
1073
+ ],
1074
+ [
1075
+ /\b(four times|4 times)( a| per)? day\b|\b(four times|4 times) daily\b|\bqid\b/,
1076
+ "Four times daily"
1077
+ ],
1078
+ [/\bevery morning\b|\bqam\b/, "Every morning"],
1079
+ [/\b(at )?bedtime\b|\bqhs\b|\bat night\b/, "Every bedtime"],
1080
+ [/\bweekly\b|\bonce a week\b|\bevery week\b/, "Weekly"],
1081
+ [
1082
+ /\bonce (a |per )?day\b|\bonce daily\b|\bdaily\b|\bevery day\b|\bqd\b/,
1083
+ "Once daily"
1084
+ ]
1085
+ ];
1086
+ function parseSig(sig) {
1087
+ const lower = sig.toLowerCase();
1088
+ const route = SIG_ROUTES.find(([re]) => re.test(lower))?.[1];
1089
+ const frequency = SIG_FREQUENCIES.find(([re]) => re.test(lower))?.[1];
1090
+ const prn = /\bas needed\b|\bprn\b/.test(lower);
1091
+ return { route, frequency, prn };
1092
+ }
1093
+ function labelToMedicationFields(label) {
1094
+ const { strength, doseForm } = parseMedicationLabel(label);
1095
+ return {
1096
+ ...strength && { strength },
1097
+ ...doseForm && {
1098
+ doseForm,
1099
+ quantityUnit: FORM_TO_UNIT[doseForm] ?? doseForm
1100
+ }
1101
+ };
1102
+ }
1103
+ function lookupToMedicationFields(result) {
1104
+ return {
1105
+ name: result.label,
1106
+ code: {
1107
+ system: result.codetype,
1108
+ code: result.fullcode,
1109
+ display: result.label
1110
+ },
1111
+ ...labelToMedicationFields(result.label)
1112
+ };
1113
+ }
1114
+ function newId2() {
1115
+ return `med-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
1116
+ }
1117
+ function MedicationEditor({
1118
+ open,
1119
+ medication,
1120
+ codeLookup,
1121
+ onClose,
1122
+ onSave
1123
+ }) {
1124
+ const ambientCodeLookup = useCodeLookupConfig();
1125
+ const effectiveCodeLookup = codeLookup === false ? void 0 : codeLookup ?? ambientCodeLookup ?? void 0;
1126
+ const [draft, setDraft] = React3__namespace.useState(
1127
+ () => medication ?? {
1128
+ id: newId2(),
1129
+ name: "",
1130
+ status: "unreconciled"
1131
+ }
1132
+ );
1133
+ const bodyRef = React3__namespace.useRef(null);
1134
+ React3__namespace.useEffect(() => {
1135
+ const input = bodyRef.current?.querySelector("input");
1136
+ input?.focus();
1137
+ }, []);
1138
+ const patch = (p) => setDraft((prev) => ({ ...prev, ...p }));
1139
+ const handleCodeSelect = (result) => {
1140
+ patch(lookupToMedicationFields(result));
1141
+ };
1142
+ const handleSigChange = (sig) => {
1143
+ const { route, frequency, prn } = parseSig(sig);
1144
+ patch({ sig, route, frequency, prn: prn || void 0 });
1145
+ };
1146
+ const canSave = draft.name.trim().length > 0;
1147
+ if (!open) return null;
1148
+ return /* @__PURE__ */ jsxRuntime.jsxs(chunkKJPOFUF5_cjs.Modal, { open: true, onOpenChange: (o) => !o && onClose(), size: "lg", children: [
1149
+ /* @__PURE__ */ jsxRuntime.jsxs(chunkKJPOFUF5_cjs.ModalHeader, { children: [
1150
+ /* @__PURE__ */ jsxRuntime.jsx(chunkKJPOFUF5_cjs.ModalTitle, { children: medication ? "Correct Medication" : "Add Medication" }),
1151
+ /* @__PURE__ */ jsxRuntime.jsx(chunkKJPOFUF5_cjs.ModalClose, {})
1152
+ ] }),
1153
+ /* @__PURE__ */ jsxRuntime.jsx(chunkKJPOFUF5_cjs.ModalBody, { className: "space-y-5", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { ref: bodyRef, className: "contents", children: [
1154
+ /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "space-y-3", "aria-label": "Medication", children: [
1155
+ effectiveCodeLookup ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1.5", children: [
1156
+ /* @__PURE__ */ jsxRuntime.jsx(chunkUOOH356R_cjs.Label, { htmlFor: "med-search", children: "Medication" }),
1157
+ /* @__PURE__ */ jsxRuntime.jsx(
1158
+ effectiveCodeLookup.component,
1159
+ {
1160
+ indexUrl: effectiveCodeLookup.indexUrl,
1161
+ locale: effectiveCodeLookup.locale,
1162
+ domains: ["med"],
1163
+ bare: true,
1164
+ clearOnSelect: false,
1165
+ placeholder: "Search RxNorm / FDB \u2014 e.g. lisinopril",
1166
+ initialQuery: medication?.name || void 0,
1167
+ initialSearch: medication ? !medication.code : void 0,
1168
+ onSelect: handleCodeSelect,
1169
+ onFreeText: (text) => patch({ name: text, code: void 0 })
1170
+ }
1171
+ ),
1172
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-muted-foreground text-xs", children: draft.code ? `Coded: ${draft.code.system} ${draft.code.code}` : draft.name ? `Uncoded free text: "${draft.name}" \u2014 pick a result to code it` : "Pick a result to code the medication, or press Enter for free text" })
1173
+ ] }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1.5", children: [
1174
+ /* @__PURE__ */ jsxRuntime.jsx(chunkUOOH356R_cjs.Label, { htmlFor: "med-name", children: "Medication" }),
1175
+ /* @__PURE__ */ jsxRuntime.jsx(
1176
+ chunkMSRU3XBH_cjs.Input,
1177
+ {
1178
+ id: "med-name",
1179
+ value: draft.name,
1180
+ onChange: (e) => patch({ name: e.target.value })
1181
+ }
1182
+ )
1183
+ ] }),
1184
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-2 gap-3", children: [
1185
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1.5", children: [
1186
+ /* @__PURE__ */ jsxRuntime.jsx(chunkUOOH356R_cjs.Label, { htmlFor: "med-strength", children: "Strength" }),
1187
+ /* @__PURE__ */ jsxRuntime.jsx(
1188
+ chunkMSRU3XBH_cjs.Input,
1189
+ {
1190
+ id: "med-strength",
1191
+ value: draft.strength ?? "",
1192
+ onChange: (e) => patch({ strength: e.target.value })
1193
+ }
1194
+ )
1195
+ ] }),
1196
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1.5", children: [
1197
+ /* @__PURE__ */ jsxRuntime.jsx(chunkUOOH356R_cjs.Label, { htmlFor: "med-form", children: "Dose form" }),
1198
+ /* @__PURE__ */ jsxRuntime.jsx(
1199
+ chunkMSRU3XBH_cjs.Input,
1200
+ {
1201
+ id: "med-form",
1202
+ value: draft.doseForm ?? "",
1203
+ onChange: (e) => {
1204
+ const doseForm = e.target.value;
1205
+ const normalized = doseForm.toLowerCase().trim();
1206
+ patch({
1207
+ doseForm,
1208
+ quantityUnit: (FORM_TO_UNIT[normalized] ?? normalized) || void 0
1209
+ });
1210
+ }
1211
+ }
1212
+ )
1213
+ ] })
1214
+ ] })
1215
+ ] }),
1216
+ /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "space-y-3", "aria-label": "Dispensing", children: [
1217
+ /* @__PURE__ */ jsxRuntime.jsx("h4", { className: "text-muted-foreground text-xs font-semibold tracking-wide uppercase", children: "Dispensing" }),
1218
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-3 gap-3", children: [
1219
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1.5", children: [
1220
+ /* @__PURE__ */ jsxRuntime.jsxs(chunkUOOH356R_cjs.Label, { htmlFor: "med-qty", children: [
1221
+ "Quantity",
1222
+ draft.quantityUnit ? ` (${draft.quantityUnit}s)` : ""
1223
+ ] }),
1224
+ /* @__PURE__ */ jsxRuntime.jsx(
1225
+ chunkMSRU3XBH_cjs.Input,
1226
+ {
1227
+ id: "med-qty",
1228
+ inputMode: "decimal",
1229
+ value: draft.quantity ?? "",
1230
+ onChange: (e) => patch({ quantity: e.target.value })
1231
+ }
1232
+ )
1233
+ ] }),
1234
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1.5", children: [
1235
+ /* @__PURE__ */ jsxRuntime.jsx(chunkUOOH356R_cjs.Label, { htmlFor: "med-days", children: "Days supply" }),
1236
+ /* @__PURE__ */ jsxRuntime.jsx(
1237
+ chunkMSRU3XBH_cjs.Input,
1238
+ {
1239
+ id: "med-days",
1240
+ inputMode: "numeric",
1241
+ value: draft.daysSupply ?? "",
1242
+ onChange: (e) => patch({ daysSupply: e.target.value })
1243
+ }
1244
+ )
1245
+ ] }),
1246
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1.5", children: [
1247
+ /* @__PURE__ */ jsxRuntime.jsx(chunkUOOH356R_cjs.Label, { htmlFor: "med-refills", children: "Refills" }),
1248
+ /* @__PURE__ */ jsxRuntime.jsx(
1249
+ chunkMSRU3XBH_cjs.Input,
1250
+ {
1251
+ id: "med-refills",
1252
+ inputMode: "numeric",
1253
+ value: draft.refills ?? "",
1254
+ onChange: (e) => patch({ refills: e.target.value })
1255
+ }
1256
+ )
1257
+ ] })
1258
+ ] }),
1259
+ /* @__PURE__ */ jsxRuntime.jsxs(
1260
+ chunkXP6HELVG_cjs.RadioGroup,
1261
+ {
1262
+ name: "med-substitution",
1263
+ label: "Substitution",
1264
+ value: draft.substitution ?? "0",
1265
+ onValueChange: (v) => patch({ substitution: v }),
1266
+ orientation: "horizontal",
1267
+ size: "sm",
1268
+ children: [
1269
+ /* @__PURE__ */ jsxRuntime.jsx(chunkXP6HELVG_cjs.Radio, { value: "0", label: "Substitution permitted" }),
1270
+ /* @__PURE__ */ jsxRuntime.jsx(chunkXP6HELVG_cjs.Radio, { value: "1", label: "Dispense as written (DAW)" })
1271
+ ]
1272
+ }
1273
+ )
1274
+ ] }),
1275
+ /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "space-y-3", "aria-label": "Directions", children: [
1276
+ /* @__PURE__ */ jsxRuntime.jsx("h4", { className: "text-muted-foreground text-xs font-semibold tracking-wide uppercase", children: "Directions" }),
1277
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1.5", children: [
1278
+ /* @__PURE__ */ jsxRuntime.jsx(chunkUOOH356R_cjs.Label, { htmlFor: "med-sig", children: "Sig (patient directions)" }),
1279
+ /* @__PURE__ */ jsxRuntime.jsx(
1280
+ chunkU3ABLVYH_cjs.Textarea,
1281
+ {
1282
+ id: "med-sig",
1283
+ value: draft.sig ?? "",
1284
+ onChange: (e) => handleSigChange(e.target.value),
1285
+ rows: 2
1286
+ }
1287
+ ),
1288
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-muted-foreground text-xs", "aria-live": "polite", children: draft.route || draft.frequency || draft.prn ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1289
+ "Derived:",
1290
+ " ",
1291
+ [
1292
+ draft.route && `route ${draft.route}`,
1293
+ draft.frequency && draft.frequency.toLowerCase(),
1294
+ draft.prn && "PRN (as needed)"
1295
+ ].filter(Boolean).join(" \xB7 ")
1296
+ ] }) : "Route, frequency, and PRN are derived from the directions" })
1297
+ ] })
1298
+ ] }),
1299
+ /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "space-y-3", "aria-label": "Dates and context", children: [
1300
+ /* @__PURE__ */ jsxRuntime.jsx("h4", { className: "text-muted-foreground text-xs font-semibold tracking-wide uppercase", children: "Dates & context" }),
1301
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-2 gap-3", children: [
1302
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1.5", children: [
1303
+ /* @__PURE__ */ jsxRuntime.jsx(chunkUOOH356R_cjs.Label, { htmlFor: "med-start", children: "Start date" }),
1304
+ /* @__PURE__ */ jsxRuntime.jsx(
1305
+ chunkNINI4WVS_cjs.DateInput,
1306
+ {
1307
+ id: "med-start",
1308
+ value: draft.startDate ?? "",
1309
+ onChange: (v) => patch({ startDate: v })
1310
+ }
1311
+ )
1312
+ ] }),
1313
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1.5", children: [
1314
+ /* @__PURE__ */ jsxRuntime.jsx(chunkUOOH356R_cjs.Label, { htmlFor: "med-end", children: "End date" }),
1315
+ /* @__PURE__ */ jsxRuntime.jsx(
1316
+ chunkNINI4WVS_cjs.DateInput,
1317
+ {
1318
+ id: "med-end",
1319
+ value: draft.endDate ?? "",
1320
+ onChange: (v) => patch({ endDate: v })
1321
+ }
1322
+ )
1323
+ ] })
1324
+ ] }),
1325
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1.5", children: [
1326
+ /* @__PURE__ */ jsxRuntime.jsx(chunkUOOH356R_cjs.Label, { htmlFor: "med-indication", children: "Indication" }),
1327
+ /* @__PURE__ */ jsxRuntime.jsx(
1328
+ chunkMSRU3XBH_cjs.Input,
1329
+ {
1330
+ id: "med-indication",
1331
+ value: draft.indication ?? "",
1332
+ onChange: (e) => patch({ indication: e.target.value })
1333
+ }
1334
+ )
1335
+ ] }),
1336
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1.5", children: [
1337
+ /* @__PURE__ */ jsxRuntime.jsx(chunkUOOH356R_cjs.Label, { htmlFor: "med-pharmacy-notes", children: "Pharmacy notes" }),
1338
+ /* @__PURE__ */ jsxRuntime.jsx(
1339
+ chunkU3ABLVYH_cjs.Textarea,
1340
+ {
1341
+ id: "med-pharmacy-notes",
1342
+ value: draft.pharmacyNotes ?? "",
1343
+ onChange: (e) => patch({ pharmacyNotes: e.target.value }),
1344
+ rows: 2
1345
+ }
1346
+ )
1347
+ ] })
1348
+ ] })
1349
+ ] }) }),
1350
+ /* @__PURE__ */ jsxRuntime.jsxs(chunkKJPOFUF5_cjs.ModalFooter, { children: [
1351
+ /* @__PURE__ */ jsxRuntime.jsx(chunkA2QVQF54_cjs.Button, { variant: "secondary", onClick: onClose, children: "Cancel" }),
1352
+ /* @__PURE__ */ jsxRuntime.jsx(
1353
+ chunkA2QVQF54_cjs.Button,
1354
+ {
1355
+ onClick: () => {
1356
+ onSave({ ...draft, name: draft.name.trim() });
1357
+ onClose();
1358
+ },
1359
+ disabled: !canSave,
1360
+ children: "Save"
1361
+ }
1362
+ )
1363
+ ] })
1364
+ ] });
1365
+ }
1366
+ var MANAGED_ACTIONS = [
1367
+ "correct",
1368
+ "add-task",
1369
+ "note",
1370
+ "remove"
1371
+ ];
1372
+ function newId3() {
1373
+ return `med-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
1374
+ }
1375
+ function MedicationDialog({
1376
+ dialog,
1377
+ onClose,
1378
+ onSave
1379
+ }) {
1380
+ const [form, setForm] = React3__namespace.useState(
1381
+ () => dialog.kind === "note" ? { note: dialog.medication.note ?? "" } : { task: dialog.medication.task ?? "" }
1382
+ );
1383
+ const set = (key) => (e) => setForm((prev) => ({ ...prev, [key]: e.target.value }));
1384
+ const handleSave = () => {
1385
+ onSave(form);
1386
+ onClose();
1387
+ };
1388
+ return /* @__PURE__ */ jsxRuntime.jsxs(chunkKJPOFUF5_cjs.Modal, { open: true, onOpenChange: (open) => !open && onClose(), size: "md", children: [
1389
+ /* @__PURE__ */ jsxRuntime.jsxs(chunkKJPOFUF5_cjs.ModalHeader, { children: [
1390
+ /* @__PURE__ */ jsxRuntime.jsx(chunkKJPOFUF5_cjs.ModalTitle, { children: dialog.kind === "note" ? "Medication Notes" : "Add Task" }),
1391
+ /* @__PURE__ */ jsxRuntime.jsx(chunkKJPOFUF5_cjs.ModalClose, {})
1392
+ ] }),
1393
+ /* @__PURE__ */ jsxRuntime.jsxs(chunkKJPOFUF5_cjs.ModalBody, { className: "space-y-4", children: [
1394
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-muted-foreground text-sm", children: dialog.medication.name }),
1395
+ dialog.kind === "note" ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1.5", children: [
1396
+ /* @__PURE__ */ jsxRuntime.jsx(chunkUOOH356R_cjs.Label, { htmlFor: "med-note", children: "Note" }),
1397
+ /* @__PURE__ */ jsxRuntime.jsx(
1398
+ chunkU3ABLVYH_cjs.Textarea,
1399
+ {
1400
+ id: "med-note",
1401
+ value: form.note,
1402
+ onChange: set("note"),
1403
+ rows: 4
1404
+ }
1405
+ )
1406
+ ] }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1.5", children: [
1407
+ /* @__PURE__ */ jsxRuntime.jsx(chunkUOOH356R_cjs.Label, { htmlFor: "med-task", children: "Task" }),
1408
+ /* @__PURE__ */ jsxRuntime.jsx(
1409
+ chunkU3ABLVYH_cjs.Textarea,
1410
+ {
1411
+ id: "med-task",
1412
+ value: form.task,
1413
+ onChange: set("task"),
1414
+ rows: 3,
1415
+ placeholder: "Follow-up task for this medication"
1416
+ }
1417
+ )
1418
+ ] })
1419
+ ] }),
1420
+ /* @__PURE__ */ jsxRuntime.jsxs(chunkKJPOFUF5_cjs.ModalFooter, { children: [
1421
+ /* @__PURE__ */ jsxRuntime.jsx(chunkA2QVQF54_cjs.Button, { variant: "secondary", onClick: onClose, children: "Cancel" }),
1422
+ /* @__PURE__ */ jsxRuntime.jsx(chunkA2QVQF54_cjs.Button, { onClick: handleSave, children: "Save" })
1423
+ ] })
1424
+ ] });
1425
+ }
1426
+ function MedicationReconciliation({
1427
+ medications: controlledMedications,
1428
+ defaultMedications,
1429
+ onChange,
1430
+ title = "Presenting medications",
1431
+ quickAddOptions,
1432
+ actions = MANAGED_ACTIONS,
1433
+ onAction,
1434
+ codeLookup,
1435
+ inlineAddSearch = false,
1436
+ readOnly = false,
1437
+ reconciledMessage,
1438
+ emptyMessage,
1439
+ className,
1440
+ "data-testid": dataTestId
1441
+ }) {
1442
+ const isControlled = controlledMedications !== void 0;
1443
+ const [internal, setInternal] = React3__namespace.useState(
1444
+ defaultMedications ?? []
1445
+ );
1446
+ const medications = isControlled ? controlledMedications : internal;
1447
+ const ambientCodeLookup = useCodeLookupConfig();
1448
+ const effectiveCodeLookup = codeLookup === false ? void 0 : codeLookup ?? ambientCodeLookup ?? void 0;
1449
+ const [dialog, setDialog] = React3__namespace.useState(null);
1450
+ const commit = (next) => {
1451
+ if (!isControlled) setInternal(next);
1452
+ onChange?.(next);
1453
+ };
1454
+ const patchMedication = (id, patch) => {
1455
+ commit(medications.map((m) => m.id === id ? { ...m, ...patch } : m));
1456
+ };
1457
+ const moveMedication = (med, direction) => {
1458
+ const meds = [...medications];
1459
+ const group = meds.filter((m) => m.status === med.status);
1460
+ const groupIndex = group.findIndex((m) => m.id === med.id);
1461
+ const swapWith = group[groupIndex + direction];
1462
+ if (!swapWith) return;
1463
+ const i = meds.findIndex((m) => m.id === med.id);
1464
+ const j = meds.findIndex((m) => m.id === swapWith.id);
1465
+ [meds[i], meds[j]] = [meds[j], meds[i]];
1466
+ commit(meds);
1467
+ };
1468
+ const handleAction = (med, action) => {
1469
+ switch (action) {
1470
+ case "remove":
1471
+ commit(medications.filter((m) => m.id !== med.id));
1472
+ break;
1473
+ case "move-up":
1474
+ moveMedication(med, -1);
1475
+ break;
1476
+ case "move-down":
1477
+ moveMedication(med, 1);
1478
+ break;
1479
+ case "correct":
1480
+ case "note":
1481
+ case "add-task":
1482
+ setDialog({ kind: action, medication: med });
1483
+ break;
1484
+ default:
1485
+ onAction?.(med, action);
1486
+ break;
1487
+ }
1488
+ };
1489
+ const addMedication = (name, sig) => {
1490
+ commit([
1491
+ ...medications,
1492
+ { id: newId3(), name, sig: void 0, status: "unreconciled" }
1493
+ ]);
1494
+ };
1495
+ const handleDialogSave = (form) => {
1496
+ if (!dialog) return;
1497
+ switch (dialog.kind) {
1498
+ case "note":
1499
+ patchMedication(dialog.medication.id, {
1500
+ note: form.note.trim() || void 0
1501
+ });
1502
+ break;
1503
+ case "add-task":
1504
+ patchMedication(dialog.medication.id, {
1505
+ task: form.task.trim() || void 0
1506
+ });
1507
+ break;
1508
+ }
1509
+ };
1510
+ const editorOpen = dialog?.kind === "correct" || dialog?.kind === "add";
1511
+ const editorTarget = dialog?.kind === "correct" ? dialog.medication : void 0;
1512
+ const handleEditorSave = (med) => {
1513
+ if (dialog?.kind === "correct") {
1514
+ commit(medications.map((m) => m.id === med.id ? med : m));
1515
+ } else {
1516
+ commit([...medications, { ...med, status: "unreconciled" }]);
1517
+ }
1518
+ };
1519
+ const addSearch = inlineAddSearch && effectiveCodeLookup && !readOnly ? /* @__PURE__ */ jsxRuntime.jsx(
1520
+ effectiveCodeLookup.component,
1521
+ {
1522
+ indexUrl: effectiveCodeLookup.indexUrl,
1523
+ locale: effectiveCodeLookup.locale,
1524
+ domains: ["med"],
1525
+ bare: true,
1526
+ clearOnSelect: true,
1527
+ placeholder: "Search medications to add",
1528
+ onSelect: (result) => commit([
1529
+ ...medications,
1530
+ {
1531
+ id: newId3(),
1532
+ name: result.label,
1533
+ status: "unreconciled",
1534
+ ...lookupToMedicationFields(result)
1535
+ }
1536
+ ]),
1537
+ onFreeText: (text) => addMedication(text)
1538
+ }
1539
+ ) : void 0;
1540
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1541
+ /* @__PURE__ */ jsxRuntime.jsx(
1542
+ MedicationList,
1543
+ {
1544
+ medications,
1545
+ title,
1546
+ readOnly,
1547
+ actions,
1548
+ onStatusChange: (med, status) => patchMedication(med.id, { status }),
1549
+ onAction: handleAction,
1550
+ onReorder: (ids) => commit(
1551
+ [...medications].sort(
1552
+ (a, b) => ids.indexOf(a.id) - ids.indexOf(b.id)
1553
+ )
1554
+ ),
1555
+ quickAddOptions,
1556
+ onQuickAdd: (name) => addMedication(name),
1557
+ onAddOther: () => setDialog({ kind: "add" }),
1558
+ addSearch,
1559
+ reconciledMessage,
1560
+ emptyMessage,
1561
+ className,
1562
+ "data-testid": dataTestId
1563
+ }
1564
+ ),
1565
+ dialog && (dialog.kind === "note" || dialog.kind === "add-task") && /* @__PURE__ */ jsxRuntime.jsx(
1566
+ MedicationDialog,
1567
+ {
1568
+ dialog,
1569
+ onClose: () => setDialog(null),
1570
+ onSave: handleDialogSave
1571
+ },
1572
+ dialog.kind + dialog.medication.id
1573
+ ),
1574
+ editorOpen && /* @__PURE__ */ jsxRuntime.jsx(
1575
+ MedicationEditor,
1576
+ {
1577
+ open: true,
1578
+ medication: editorTarget,
1579
+ codeLookup: codeLookup === false ? false : effectiveCodeLookup,
1580
+ onClose: () => setDialog(null),
1581
+ onSave: handleEditorSave
1582
+ },
1583
+ editorTarget?.id ?? "add"
1584
+ )
1585
+ ] });
1586
+ }
1587
+
1588
+ exports.ALLERGY_TYPE_LABELS = ALLERGY_TYPE_LABELS;
1589
+ exports.AllergyList = AllergyList;
1590
+ exports.AllergyManager = AllergyManager;
1591
+ exports.CodeLookupProvider = CodeLookupProvider;
1592
+ exports.MEDICATION_STATUS_LABELS = MEDICATION_STATUS_LABELS;
1593
+ exports.MedicationEditor = MedicationEditor;
1594
+ exports.MedicationList = MedicationList;
1595
+ exports.MedicationReconciliation = MedicationReconciliation;
1596
+ exports.RowActionToolbar = RowActionToolbar;
1597
+ exports.RowIconButton = RowIconButton;
1598
+ exports.labelToMedicationFields = labelToMedicationFields;
1599
+ exports.lookupToMedicationFields = lookupToMedicationFields;
1600
+ exports.parseMedicationLabel = parseMedicationLabel;
1601
+ exports.parseSig = parseSig;
1602
+ exports.toolbarKeyNav = toolbarKeyNav;
1603
+ exports.useCodeLookupConfig = useCodeLookupConfig;
1604
+ //# sourceMappingURL=chunk-67CEEDAP.cjs.map
1605
+ //# sourceMappingURL=chunk-67CEEDAP.cjs.map