@mieweb/ui 0.11.0-dev.29 → 0.11.0-dev.30

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