@mieweb/ui 0.11.0-dev.33 → 0.11.0-dev.34

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 (88) hide show
  1. package/dist/{chunk-PJN4HM2X.cjs → chunk-3O3Q3DX7.cjs} +21 -21
  2. package/dist/{chunk-PJN4HM2X.cjs.map → chunk-3O3Q3DX7.cjs.map} +1 -1
  3. package/dist/{chunk-M42FTWY2.cjs → chunk-46RYJYN2.cjs} +6 -6
  4. package/dist/{chunk-M42FTWY2.cjs.map → chunk-46RYJYN2.cjs.map} +1 -1
  5. package/dist/{chunk-JMAZ2GKT.js → chunk-4GSFVD5V.js} +3 -3
  6. package/dist/{chunk-JMAZ2GKT.js.map → chunk-4GSFVD5V.js.map} +1 -1
  7. package/dist/{chunk-2R3ILG4Y.cjs → chunk-4M2KE4O5.cjs} +7 -7
  8. package/dist/{chunk-2R3ILG4Y.cjs.map → chunk-4M2KE4O5.cjs.map} +1 -1
  9. package/dist/{chunk-NAQMIFUF.js → chunk-4SUEBKTY.js} +3 -3
  10. package/dist/{chunk-NAQMIFUF.js.map → chunk-4SUEBKTY.js.map} +1 -1
  11. package/dist/{chunk-X6HEWIYP.cjs → chunk-6O6EYKOG.cjs} +130 -874
  12. package/dist/chunk-6O6EYKOG.cjs.map +1 -0
  13. package/dist/{chunk-ZNYBLM4O.cjs → chunk-DXNVQQYN.cjs} +4 -4
  14. package/dist/{chunk-ZNYBLM4O.cjs.map → chunk-DXNVQQYN.cjs.map} +1 -1
  15. package/dist/{chunk-WEGKY2LY.js → chunk-EWPNM6OO.js} +5 -3
  16. package/dist/chunk-EWPNM6OO.js.map +1 -0
  17. package/dist/{chunk-IBEQ54XW.js → chunk-EX7Q5545.js} +4 -4
  18. package/dist/{chunk-IBEQ54XW.js.map → chunk-EX7Q5545.js.map} +1 -1
  19. package/dist/{chunk-VV2U36T6.cjs → chunk-MZR634HI.cjs} +9 -9
  20. package/dist/{chunk-VV2U36T6.cjs.map → chunk-MZR634HI.cjs.map} +1 -1
  21. package/dist/{chunk-JCO62XMU.cjs → chunk-NCPDUJKJ.cjs} +43 -26
  22. package/dist/chunk-NCPDUJKJ.cjs.map +1 -0
  23. package/dist/{chunk-PYAK7XXD.js → chunk-NW6D6AFL.js} +80 -819
  24. package/dist/chunk-NW6D6AFL.js.map +1 -0
  25. package/dist/{chunk-ZPPMEUGR.cjs → chunk-PGJLW2NO.cjs} +7 -7
  26. package/dist/{chunk-ZPPMEUGR.cjs.map → chunk-PGJLW2NO.cjs.map} +1 -1
  27. package/dist/{chunk-ZFJJMDV3.js → chunk-RTADGBBN.js} +3 -3
  28. package/dist/{chunk-ZFJJMDV3.js.map → chunk-RTADGBBN.js.map} +1 -1
  29. package/dist/{chunk-LJ4CCM3V.cjs → chunk-S2CJ57BX.cjs} +5 -3
  30. package/dist/chunk-S2CJ57BX.cjs.map +1 -0
  31. package/dist/{chunk-KSQQBFDQ.js → chunk-SPGP252Q.js} +43 -26
  32. package/dist/chunk-SPGP252Q.js.map +1 -0
  33. package/dist/{chunk-67SD6VPF.cjs → chunk-SVC7NPQ6.cjs} +6 -6
  34. package/dist/{chunk-67SD6VPF.cjs.map → chunk-SVC7NPQ6.cjs.map} +1 -1
  35. package/dist/{chunk-TWQSMUE6.js → chunk-VMEVLBI3.js} +46 -38
  36. package/dist/chunk-VMEVLBI3.js.map +1 -0
  37. package/dist/{chunk-QNJEDBIN.js → chunk-X5HLVACK.js} +4 -4
  38. package/dist/{chunk-QNJEDBIN.js.map → chunk-X5HLVACK.js.map} +1 -1
  39. package/dist/{chunk-LC3JL2HB.cjs → chunk-XEHD2HA5.cjs} +46 -38
  40. package/dist/chunk-XEHD2HA5.cjs.map +1 -0
  41. package/dist/{chunk-R3MJKY63.js → chunk-YGSPIDE4.js} +3 -3
  42. package/dist/{chunk-R3MJKY63.js.map → chunk-YGSPIDE4.js.map} +1 -1
  43. package/dist/{chunk-7LKTIZLR.js → chunk-YR45POH2.js} +3 -3
  44. package/dist/{chunk-7LKTIZLR.js.map → chunk-YR45POH2.js.map} +1 -1
  45. package/dist/components/AlertDialog/index.cjs +6 -6
  46. package/dist/components/AlertDialog/index.js +2 -2
  47. package/dist/components/EmailEditor/index.cjs +12 -12
  48. package/dist/components/EmailEditor/index.js +3 -3
  49. package/dist/components/KeyboardShortcutsOverlay/index.cjs +4 -4
  50. package/dist/components/KeyboardShortcutsOverlay/index.js +2 -2
  51. package/dist/components/MediaEditor/index.cjs +7 -7
  52. package/dist/components/MediaEditor/index.js +2 -2
  53. package/dist/components/MediaFeed/index.cjs +3 -3
  54. package/dist/components/MediaFeed/index.js +2 -2
  55. package/dist/components/Modal/index.cjs +9 -9
  56. package/dist/components/Modal/index.js +1 -1
  57. package/dist/components/RichTextEditor/index.cjs +4 -4
  58. package/dist/components/RichTextEditor/index.js +1 -1
  59. package/dist/components/SuperChat/index.cjs +3 -3
  60. package/dist/components/SuperChat/index.js +2 -2
  61. package/dist/components/Textarea/index.cjs +5 -5
  62. package/dist/components/Textarea/index.js +2 -2
  63. package/dist/esheet.cjs +462 -1233
  64. package/dist/esheet.cjs.map +1 -1
  65. package/dist/esheet.d.cts +2 -2
  66. package/dist/esheet.d.ts +2 -2
  67. package/dist/esheet.js +375 -1146
  68. package/dist/esheet.js.map +1 -1
  69. package/dist/index.cjs +1011 -239
  70. package/dist/index.cjs.map +1 -1
  71. package/dist/index.d.cts +6 -2
  72. package/dist/index.d.ts +6 -2
  73. package/dist/index.js +804 -17
  74. package/dist/index.js.map +1 -1
  75. package/dist/{model-NPW2JMHZ.cjs → model-EFXX5JZN.cjs} +18 -18
  76. package/dist/{model-NPW2JMHZ.cjs.map → model-EFXX5JZN.cjs.map} +1 -1
  77. package/dist/{model-SG5H3TCJ.js → model-TAARSYDY.js} +4 -4
  78. package/dist/{model-SG5H3TCJ.js.map → model-TAARSYDY.js.map} +1 -1
  79. package/dist/styles.css +1 -1
  80. package/package.json +1 -1
  81. package/dist/chunk-JCO62XMU.cjs.map +0 -1
  82. package/dist/chunk-KSQQBFDQ.js.map +0 -1
  83. package/dist/chunk-LC3JL2HB.cjs.map +0 -1
  84. package/dist/chunk-LJ4CCM3V.cjs.map +0 -1
  85. package/dist/chunk-PYAK7XXD.js.map +0 -1
  86. package/dist/chunk-TWQSMUE6.js.map +0 -1
  87. package/dist/chunk-WEGKY2LY.js.map +0 -1
  88. package/dist/chunk-X6HEWIYP.cjs.map +0 -1
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var chunkLC3JL2HB_cjs = require('./chunk-LC3JL2HB.cjs');
3
+ var chunkXEHD2HA5_cjs = require('./chunk-XEHD2HA5.cjs');
4
4
  var chunkS5RVSXDV_cjs = require('./chunk-S5RVSXDV.cjs');
5
5
  var React = require('react');
6
6
  var lucideReact = require('lucide-react');
@@ -81,7 +81,7 @@ function KeyboardShortcutsOverlay({
81
81
  ] });
82
82
  const footer = hint === null ? null : hint ?? defaultHint;
83
83
  return /* @__PURE__ */ jsxRuntime.jsxs(
84
- chunkLC3JL2HB_cjs.Modal,
84
+ chunkXEHD2HA5_cjs.Modal,
85
85
  {
86
86
  open,
87
87
  onOpenChange: (o) => {
@@ -90,14 +90,14 @@ function KeyboardShortcutsOverlay({
90
90
  size: "sm",
91
91
  "aria-label": title,
92
92
  children: [
93
- /* @__PURE__ */ jsxRuntime.jsxs(chunkLC3JL2HB_cjs.ModalHeader, { children: [
94
- /* @__PURE__ */ jsxRuntime.jsxs(chunkLC3JL2HB_cjs.ModalTitle, { className: "flex items-center gap-2 text-sm", children: [
93
+ /* @__PURE__ */ jsxRuntime.jsxs(chunkXEHD2HA5_cjs.ModalHeader, { children: [
94
+ /* @__PURE__ */ jsxRuntime.jsxs(chunkXEHD2HA5_cjs.ModalTitle, { className: "flex items-center gap-2 text-sm", children: [
95
95
  /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Keyboard, { "aria-hidden": "true", className: "text-primary-500 h-4 w-4" }),
96
96
  title
97
97
  ] }),
98
- /* @__PURE__ */ jsxRuntime.jsx(chunkLC3JL2HB_cjs.ModalClose, {})
98
+ /* @__PURE__ */ jsxRuntime.jsx(chunkXEHD2HA5_cjs.ModalClose, {})
99
99
  ] }),
100
- /* @__PURE__ */ jsxRuntime.jsxs(chunkLC3JL2HB_cjs.ModalBody, { className: "flex flex-col gap-4", children: [
100
+ /* @__PURE__ */ jsxRuntime.jsxs(chunkXEHD2HA5_cjs.ModalBody, { className: "flex flex-col gap-4", children: [
101
101
  shortcuts && /* @__PURE__ */ jsxRuntime.jsx(
102
102
  ShortcutList,
103
103
  {
@@ -116,7 +116,7 @@ function KeyboardShortcutsOverlay({
116
116
  )
117
117
  ] }, group.title))
118
118
  ] }),
119
- footer && /* @__PURE__ */ jsxRuntime.jsx(chunkLC3JL2HB_cjs.ModalFooter, { className: "text-muted-foreground justify-center text-[11px]", children: /* @__PURE__ */ jsxRuntime.jsx("span", { children: footer }) })
119
+ footer && /* @__PURE__ */ jsxRuntime.jsx(chunkXEHD2HA5_cjs.ModalFooter, { className: "text-muted-foreground justify-center text-[11px]", children: /* @__PURE__ */ jsxRuntime.jsx("span", { children: footer }) })
120
120
  ]
121
121
  }
122
122
  );
@@ -124,5 +124,5 @@ function KeyboardShortcutsOverlay({
124
124
 
125
125
  exports.Kbd = Kbd;
126
126
  exports.KeyboardShortcutsOverlay = KeyboardShortcutsOverlay;
127
- //# sourceMappingURL=chunk-VV2U36T6.cjs.map
128
- //# sourceMappingURL=chunk-VV2U36T6.cjs.map
127
+ //# sourceMappingURL=chunk-MZR634HI.cjs.map
128
+ //# sourceMappingURL=chunk-MZR634HI.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/components/KeyboardShortcutsOverlay/KeyboardShortcutsOverlay.tsx"],"names":["React","Kbd","jsx","cn","jsxs","Fragment","Modal","ModalHeader","ModalTitle","Keyboard","ModalClose","ModalBody","ModalFooter"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqBO,IAAM,GAAA,GAAYA,4BAAkC,SAASC,IAAAA,CAClE,EAAE,SAAA,EAAW,GAAG,KAAA,EAAM,EACtB,GAAA,EACA;AACA,EAAA,uBACEC,cAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,GAAA;AAAA,MACA,SAAA,EAAWC,oBAAA;AAAA,QACT,2FAAA;AAAA,QACA;AAAA,OACF;AAAA,MACC,GAAG;AAAA;AAAA,GACN;AAEJ,CAAC;AA+BD,SAAS,IAAA,CAAK;AAAA,EACZ,IAAA;AAAA,EACA;AACF,CAAA,EAGG;AACD,EAAA,MAAM,IAAA,GAAO,MAAM,OAAA,CAAQ,IAAI,IAAI,IAAA,GAAO,IAAA,CAAK,MAAM,KAAK,CAAA;AAC1D,EAAA,uBACED,cAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,kCAAA,EACb,QAAA,EAAA,IAAA,CAAK,GAAA,CAAI,CAAC,CAAA,EAAG,CAAA,qBACZE,eAAA,CAAOJ,gBAAA,CAAA,QAAA,EAAN,EACC,QAAA,EAAA;AAAA,oBAAAE,cAAA,CAAC,OAAK,QAAA,EAAA,CAAA,EAAE,CAAA;AAAA,IACP,CAAA,GAAI,KAAK,MAAA,GAAS,CAAA,mCAChB,MAAA,EAAA,EAAK,SAAA,EAAU,wCACb,QAAA,EAAA,iBAAA,EACH;AAAA,GAAA,EAAA,EALiB,GAAG,CAAC,CAAA,CAAA,EAAI,CAAC,CAAA,CAO9B,CACD,CAAA,EACH,CAAA;AAEJ;AAEA,SAAS,YAAA,CAAa;AAAA,EACpB,SAAA;AAAA,EACA;AACF,CAAA,EAGG;AACD,EAAA,sCACG,IAAA,EAAA,EAAG,SAAA,EAAU,qCACX,QAAA,EAAA,SAAA,CAAU,GAAA,CAAI,CAAC,CAAA,qBACdE,eAAA;AAAA,IAAC,IAAA;AAAA,IAAA;AAAA,MAEC,SAAA,EAAU,iEAAA;AAAA,MAEV,QAAA,EAAA;AAAA,wBAAAF,cAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,SAAA,EAAW,QAAA,EAAA,CAAA,CAAE,WAAA,EAAY,CAAA;AAAA,wBACzCA,cAAA,CAAC,IAAA,EAAA,EAAK,IAAA,EAAM,CAAA,CAAE,MAAM,iBAAA,EAAsC;AAAA;AAAA,KAAA;AAAA,IAJrD,GAAG,CAAA,CAAE,WAAW,IAAI,MAAA,CAAO,CAAA,CAAE,IAAI,CAAC,CAAA;AAAA,GAM1C,CAAA,EACH,CAAA;AAEJ;AAyBO,SAAS,wBAAA,CAAyB;AAAA,EACvC,IAAA;AAAA,EACA,OAAA;AAAA,EACA,SAAA;AAAA,EACA,MAAA;AAAA,EACA,KAAA,GAAQ,oBAAA;AAAA,EACR,IAAA;AAAA,EACA,iBAAA,GAAoB;AACtB,CAAA,EAAkC;AAChC,EAAA,MAAM,WAAA,mBACJE,eAAA,CAAAC,mBAAAA,EAAA,EAAE,QAAA,EAAA;AAAA,IAAA,QAAA;AAAA,oBACMH,cAAA,CAAC,OAAI,QAAA,EAAA,GAAA,EAAC,CAAA;AAAA,IAAM;AAAA,GAAA,EACpB,CAAA;AAEF,EAAA,MAAM,MAAA,GAAS,IAAA,KAAS,IAAA,GAAO,IAAA,GAAQ,IAAA,IAAQ,WAAA;AAE/C,EAAA,uBACEE,eAAA;AAAA,IAACE,uBAAA;AAAA,IAAA;AAAA,MACC,IAAA;AAAA,MACA,YAAA,EAAc,CAAC,CAAA,KAAM;AACnB,QAAA,IAAI,CAAC,GAAG,OAAA,EAAQ;AAAA,MAClB,CAAA;AAAA,MACA,IAAA,EAAK,IAAA;AAAA,MACL,YAAA,EAAY,KAAA;AAAA,MAEZ,QAAA,EAAA;AAAA,wBAAAF,eAAA,CAACG,6BAAA,EAAA,EACC,QAAA,EAAA;AAAA,0BAAAH,eAAA,CAACI,4BAAA,EAAA,EAAW,WAAU,iCAAA,EACpB,QAAA,EAAA;AAAA,4BAAAN,cAAA,CAACO,oBAAA,EAAA,EAAS,aAAA,EAAY,MAAA,EAAO,SAAA,EAAU,0BAAA,EAA2B,CAAA;AAAA,YACjE;AAAA,WAAA,EACH,CAAA;AAAA,yCACCC,4BAAA,EAAA,EAAW;AAAA,SAAA,EACd,CAAA;AAAA,wBACAN,eAAA,CAACO,2BAAA,EAAA,EAAU,SAAA,EAAU,qBAAA,EAClB,QAAA,EAAA;AAAA,UAAA,SAAA,oBACCT,cAAA;AAAA,YAAC,YAAA;AAAA,YAAA;AAAA,cACC,SAAA;AAAA,cACA;AAAA;AAAA,WACF;AAAA,UAED,QAAQ,GAAA,CAAI,CAAC,0BACZE,eAAA,CAAC,KAAA,EAAA,EAAsB,WAAU,qBAAA,EAC/B,QAAA,EAAA;AAAA,4BAAAF,cAAA,CAAC,IAAA,EAAA,EAAG,SAAA,EAAU,qEAAA,EACX,QAAA,EAAA,KAAA,CAAM,KAAA,EACT,CAAA;AAAA,4BACAA,cAAA;AAAA,cAAC,YAAA;AAAA,cAAA;AAAA,gBACC,WAAW,KAAA,CAAM,SAAA;AAAA,gBACjB;AAAA;AAAA;AACF,WAAA,EAAA,EAPQ,KAAA,CAAM,KAQhB,CACD;AAAA,SAAA,EACH,CAAA;AAAA,QACC,MAAA,mCACEU,6BAAA,EAAA,EAAY,SAAA,EAAU,oDACrB,QAAA,kBAAAV,cAAA,CAAC,MAAA,EAAA,EAAM,kBAAO,CAAA,EAChB;AAAA;AAAA;AAAA,GAEJ;AAEJ","file":"chunk-VV2U36T6.cjs","sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { Keyboard } from 'lucide-react';\nimport { cn } from '../../utils/cn';\nimport {\n Modal,\n ModalHeader,\n ModalTitle,\n ModalClose,\n ModalBody,\n ModalFooter,\n} from '../Modal';\n\n// =============================================================================\n// Kbd\n// =============================================================================\n\nexport type KbdProps = React.HTMLAttributes<HTMLElement>;\n\n/** A keyboard-key chip: `<Kbd>⌘K</Kbd>`. */\nexport const Kbd = React.forwardRef<HTMLElement, KbdProps>(function Kbd(\n { className, ...props },\n ref\n) {\n return (\n <kbd\n ref={ref}\n className={cn(\n 'border-border bg-muted text-foreground rounded border px-1.5 py-0.5 font-mono text-[11px]',\n className\n )}\n {...props}\n />\n );\n});\n\n// =============================================================================\n// KeyboardShortcutsOverlay\n// =============================================================================\n\nexport interface ShortcutDef {\n /** Key or alternatives — `\"j\"`, `[\"j\", \"↓\"]`, `\"⌘K\"`. */\n keys: string | string[];\n description: string;\n}\n\nexport interface ShortcutGroup {\n title: string;\n shortcuts: ShortcutDef[];\n}\n\nexport interface KeyboardShortcutsOverlayProps {\n open: boolean;\n onClose: () => void;\n /** Flat list of shortcuts, or use `groups` for sectioned help. */\n shortcuts?: ShortcutDef[];\n /** Sectioned shortcuts with group headings. */\n groups?: ShortcutGroup[];\n title?: string;\n /** Footer hint. Pass `null` to hide it. */\n hint?: React.ReactNode | null;\n /** Joins key alternatives (default \"or\"), overridable for i18n. */\n alternativesLabel?: string;\n}\n\nfunction Keys({\n keys,\n alternativesLabel,\n}: {\n keys: string | string[];\n alternativesLabel: string;\n}) {\n const list = Array.isArray(keys) ? keys : keys.split(' / ');\n return (\n <span className=\"flex shrink-0 items-center gap-1\">\n {list.map((k, i) => (\n <React.Fragment key={`${k}-${i}`}>\n <Kbd>{k}</Kbd>\n {i < list.length - 1 && (\n <span className=\"text-muted-foreground mx-0.5 text-xs\">\n {alternativesLabel}\n </span>\n )}\n </React.Fragment>\n ))}\n </span>\n );\n}\n\nfunction ShortcutList({\n shortcuts,\n alternativesLabel,\n}: {\n shortcuts: ShortcutDef[];\n alternativesLabel: string;\n}) {\n return (\n <ul className=\"flex list-none flex-col gap-2 p-0\">\n {shortcuts.map((s) => (\n <li\n key={`${s.description}-${String(s.keys)}`}\n className=\"text-foreground flex items-center justify-between gap-4 text-sm\"\n >\n <span className=\"min-w-0\">{s.description}</span>\n <Keys keys={s.keys} alternativesLabel={alternativesLabel} />\n </li>\n ))}\n </ul>\n );\n}\n\n/**\n * The `?` keyboard-shortcuts help dialog: a list of shortcut rows\n * (optionally grouped) with `Kbd` chips for each key. Pairs with the\n * `useKeyboardShortcut` hook, which handles the binding — this component\n * only renders the help.\n *\n * @example\n * ```tsx\n * const [open, setOpen] = useState(false);\n * useKeyboardShortcut('?', () => setOpen((v) => !v), {\n * modifiers: { shift: true },\n * });\n *\n * <KeyboardShortcutsOverlay\n * open={open}\n * onClose={() => setOpen(false)}\n * shortcuts={[\n * { keys: ['j', '↓'], description: 'Next record' },\n * { keys: '⌘K', description: 'Command palette' },\n * ]}\n * />\n * ```\n */\nexport function KeyboardShortcutsOverlay({\n open,\n onClose,\n shortcuts,\n groups,\n title = 'Keyboard shortcuts',\n hint,\n alternativesLabel = 'or',\n}: KeyboardShortcutsOverlayProps) {\n const defaultHint = (\n <>\n Press <Kbd>?</Kbd> anytime to toggle this help\n </>\n );\n const footer = hint === null ? null : (hint ?? defaultHint);\n\n return (\n <Modal\n open={open}\n onOpenChange={(o) => {\n if (!o) onClose();\n }}\n size=\"sm\"\n aria-label={title}\n >\n <ModalHeader>\n <ModalTitle className=\"flex items-center gap-2 text-sm\">\n <Keyboard aria-hidden=\"true\" className=\"text-primary-500 h-4 w-4\" />\n {title}\n </ModalTitle>\n <ModalClose />\n </ModalHeader>\n <ModalBody className=\"flex flex-col gap-4\">\n {shortcuts && (\n <ShortcutList\n shortcuts={shortcuts}\n alternativesLabel={alternativesLabel}\n />\n )}\n {groups?.map((group) => (\n <div key={group.title} className=\"flex flex-col gap-2\">\n <h3 className=\"text-muted-foreground text-xs font-semibold tracking-wide uppercase\">\n {group.title}\n </h3>\n <ShortcutList\n shortcuts={group.shortcuts}\n alternativesLabel={alternativesLabel}\n />\n </div>\n ))}\n </ModalBody>\n {footer && (\n <ModalFooter className=\"text-muted-foreground justify-center text-[11px]\">\n <span>{footer}</span>\n </ModalFooter>\n )}\n </Modal>\n );\n}\n"]}
1
+ {"version":3,"sources":["../src/components/KeyboardShortcutsOverlay/KeyboardShortcutsOverlay.tsx"],"names":["React","Kbd","jsx","cn","jsxs","Fragment","Modal","ModalHeader","ModalTitle","Keyboard","ModalClose","ModalBody","ModalFooter"],"mappings":"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","file":"chunk-MZR634HI.cjs","sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { Keyboard } from 'lucide-react';\nimport { cn } from '../../utils/cn';\nimport {\n Modal,\n ModalHeader,\n ModalTitle,\n ModalClose,\n ModalBody,\n ModalFooter,\n} from '../Modal';\n\n// =============================================================================\n// Kbd\n// =============================================================================\n\nexport type KbdProps = React.HTMLAttributes<HTMLElement>;\n\n/** A keyboard-key chip: `<Kbd>⌘K</Kbd>`. */\nexport const Kbd = React.forwardRef<HTMLElement, KbdProps>(function Kbd(\n { className, ...props },\n ref\n) {\n return (\n <kbd\n ref={ref}\n className={cn(\n 'border-border bg-muted text-foreground rounded border px-1.5 py-0.5 font-mono text-[11px]',\n className\n )}\n {...props}\n />\n );\n});\n\n// =============================================================================\n// KeyboardShortcutsOverlay\n// =============================================================================\n\nexport interface ShortcutDef {\n /** Key or alternatives — `\"j\"`, `[\"j\", \"↓\"]`, `\"⌘K\"`. */\n keys: string | string[];\n description: string;\n}\n\nexport interface ShortcutGroup {\n title: string;\n shortcuts: ShortcutDef[];\n}\n\nexport interface KeyboardShortcutsOverlayProps {\n open: boolean;\n onClose: () => void;\n /** Flat list of shortcuts, or use `groups` for sectioned help. */\n shortcuts?: ShortcutDef[];\n /** Sectioned shortcuts with group headings. */\n groups?: ShortcutGroup[];\n title?: string;\n /** Footer hint. Pass `null` to hide it. */\n hint?: React.ReactNode | null;\n /** Joins key alternatives (default \"or\"), overridable for i18n. */\n alternativesLabel?: string;\n}\n\nfunction Keys({\n keys,\n alternativesLabel,\n}: {\n keys: string | string[];\n alternativesLabel: string;\n}) {\n const list = Array.isArray(keys) ? keys : keys.split(' / ');\n return (\n <span className=\"flex shrink-0 items-center gap-1\">\n {list.map((k, i) => (\n <React.Fragment key={`${k}-${i}`}>\n <Kbd>{k}</Kbd>\n {i < list.length - 1 && (\n <span className=\"text-muted-foreground mx-0.5 text-xs\">\n {alternativesLabel}\n </span>\n )}\n </React.Fragment>\n ))}\n </span>\n );\n}\n\nfunction ShortcutList({\n shortcuts,\n alternativesLabel,\n}: {\n shortcuts: ShortcutDef[];\n alternativesLabel: string;\n}) {\n return (\n <ul className=\"flex list-none flex-col gap-2 p-0\">\n {shortcuts.map((s) => (\n <li\n key={`${s.description}-${String(s.keys)}`}\n className=\"text-foreground flex items-center justify-between gap-4 text-sm\"\n >\n <span className=\"min-w-0\">{s.description}</span>\n <Keys keys={s.keys} alternativesLabel={alternativesLabel} />\n </li>\n ))}\n </ul>\n );\n}\n\n/**\n * The `?` keyboard-shortcuts help dialog: a list of shortcut rows\n * (optionally grouped) with `Kbd` chips for each key. Pairs with the\n * `useKeyboardShortcut` hook, which handles the binding — this component\n * only renders the help.\n *\n * @example\n * ```tsx\n * const [open, setOpen] = useState(false);\n * useKeyboardShortcut('?', () => setOpen((v) => !v), {\n * modifiers: { shift: true },\n * });\n *\n * <KeyboardShortcutsOverlay\n * open={open}\n * onClose={() => setOpen(false)}\n * shortcuts={[\n * { keys: ['j', '↓'], description: 'Next record' },\n * { keys: '⌘K', description: 'Command palette' },\n * ]}\n * />\n * ```\n */\nexport function KeyboardShortcutsOverlay({\n open,\n onClose,\n shortcuts,\n groups,\n title = 'Keyboard shortcuts',\n hint,\n alternativesLabel = 'or',\n}: KeyboardShortcutsOverlayProps) {\n const defaultHint = (\n <>\n Press <Kbd>?</Kbd> anytime to toggle this help\n </>\n );\n const footer = hint === null ? null : (hint ?? defaultHint);\n\n return (\n <Modal\n open={open}\n onOpenChange={(o) => {\n if (!o) onClose();\n }}\n size=\"sm\"\n aria-label={title}\n >\n <ModalHeader>\n <ModalTitle className=\"flex items-center gap-2 text-sm\">\n <Keyboard aria-hidden=\"true\" className=\"text-primary-500 h-4 w-4\" />\n {title}\n </ModalTitle>\n <ModalClose />\n </ModalHeader>\n <ModalBody className=\"flex flex-col gap-4\">\n {shortcuts && (\n <ShortcutList\n shortcuts={shortcuts}\n alternativesLabel={alternativesLabel}\n />\n )}\n {groups?.map((group) => (\n <div key={group.title} className=\"flex flex-col gap-2\">\n <h3 className=\"text-muted-foreground text-xs font-semibold tracking-wide uppercase\">\n {group.title}\n </h3>\n <ShortcutList\n shortcuts={group.shortcuts}\n alternativesLabel={alternativesLabel}\n />\n </div>\n ))}\n </ModalBody>\n {footer && (\n <ModalFooter className=\"text-muted-foreground justify-center text-[11px]\">\n <span>{footer}</span>\n </ModalFooter>\n )}\n </Modal>\n );\n}\n"]}
@@ -492,6 +492,8 @@ var ProblemList = React__namespace.forwardRef(
492
492
  title = "Problem list",
493
493
  onAction,
494
494
  onAddProblem,
495
+ addSearch,
496
+ onAdd,
495
497
  onReorder,
496
498
  actions = DEFAULT_ACTIONS,
497
499
  inlineActions = false,
@@ -609,35 +611,50 @@ var ProblemList = React__namespace.forwardRef(
609
611
  concern.concernId
610
612
  )) }) : /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-muted-foreground mt-2 text-sm", children: m(emptyMessage) })
611
613
  ] }, key)),
612
- !readOnly && onAddProblem && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5", children: [
613
- /* @__PURE__ */ jsxRuntime.jsx(
614
- "input",
615
- {
616
- type: "text",
617
- "data-slot": "input",
618
- value: draft,
619
- onChange: (e) => setDraft(e.target.value),
620
- onKeyDown: (e) => {
621
- if (e.key === "Enter") submitDraft();
622
- },
623
- placeholder: m("Add problem (name is enough)\u2026"),
624
- "aria-label": m("Add problem"),
625
- className: chunkS5RVSXDV_cjs.cn(
626
- "border-border bg-background text-foreground placeholder:text-muted-foreground",
627
- "h-8 flex-1 rounded-md border px-2.5 text-sm",
628
- "focus:ring-ring focus:ring-2 focus:outline-none"
629
- )
630
- }
631
- ),
632
- /* @__PURE__ */ jsxRuntime.jsx(
614
+ !readOnly && (addSearch || onAddProblem || onAdd) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
615
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground text-xs font-semibold tracking-wide uppercase", children: m("Add problem") }),
616
+ addSearch,
617
+ onAddProblem && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5", children: [
618
+ /* @__PURE__ */ jsxRuntime.jsx(
619
+ "input",
620
+ {
621
+ type: "text",
622
+ "data-slot": "input",
623
+ value: draft,
624
+ onChange: (e) => setDraft(e.target.value),
625
+ onKeyDown: (e) => {
626
+ if (e.key === "Enter") submitDraft();
627
+ },
628
+ placeholder: m("Add problem (name is enough)\u2026"),
629
+ "aria-label": m("Add problem"),
630
+ className: chunkS5RVSXDV_cjs.cn(
631
+ "border-border bg-background text-foreground placeholder:text-muted-foreground",
632
+ "h-8 flex-1 rounded-md border px-2.5 text-sm",
633
+ "focus:ring-ring focus:ring-2 focus:outline-none"
634
+ )
635
+ }
636
+ ),
637
+ /* @__PURE__ */ jsxRuntime.jsx(
638
+ chunkFSARTLUE_cjs.Button,
639
+ {
640
+ variant: "outline",
641
+ size: "sm",
642
+ onClick: submitDraft,
643
+ disabled: !draft.trim(),
644
+ leftIcon: /* @__PURE__ */ jsxRuntime.jsx(chunkL7L5S2HO_cjs.Plus, { size: 12 }),
645
+ className: "h-8",
646
+ children: m("Add")
647
+ }
648
+ )
649
+ ] }),
650
+ onAdd && /* @__PURE__ */ jsxRuntime.jsx(
633
651
  chunkFSARTLUE_cjs.Button,
634
652
  {
635
653
  variant: "outline",
636
654
  size: "sm",
637
- onClick: submitDraft,
638
- disabled: !draft.trim(),
655
+ onClick: onAdd,
639
656
  leftIcon: /* @__PURE__ */ jsxRuntime.jsx(chunkL7L5S2HO_cjs.Plus, { size: 12 }),
640
- className: "h-8",
657
+ className: "h-auto rounded-full px-2.5 py-1 text-xs",
641
658
  children: m("Add")
642
659
  }
643
660
  )
@@ -662,5 +679,5 @@ exports.concernGroupKey = concernGroupKey;
662
679
  exports.concernHistoryContent = concernHistoryContent;
663
680
  exports.currentAssertion = currentAssertion;
664
681
  exports.toolbarKeyNav = toolbarKeyNav;
665
- //# sourceMappingURL=chunk-JCO62XMU.cjs.map
666
- //# sourceMappingURL=chunk-JCO62XMU.cjs.map
682
+ //# sourceMappingURL=chunk-NCPDUJKJ.cjs.map
683
+ //# sourceMappingURL=chunk-NCPDUJKJ.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/RowActionToolbar/RowActionToolbar.tsx","../src/components/ProblemList/ProblemList.tsx"],"names":["isRtl","cn","jsx","Tooltip","Button","ExternalLink","StickyNote","Pencil","RefreshCw","CheckCircle","Link","Trash2","ChevronUp","ChevronDown","useMessages","jsxs","Fragment","Badge","HelpCircle","React","dragIndicatorClasses","GripVertical","History","useLiveAnnouncement","useDragReorder","Card","CardHeader","CardContent","Plus"],"mappings":"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","file":"chunk-NCPDUJKJ.cjs","sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { isRtl } from '../../hooks/useDirection';\nimport { cn } from '../../utils/cn';\nimport { Button } from '../Button';\nimport { Tooltip } from '../Tooltip';\n\n/**\n * Toolbar / group arrow-key navigation (WAI-ARIA toolbar pattern).\n * Attach to a container's onKeyDown: ←/→ move focus between enabled\n * buttons, Home/End jump to first/last. Horizontal arrows follow the\n * visual direction, so they invert under RTL.\n */\nexport function toolbarKeyNav(e: React.KeyboardEvent<HTMLElement>) {\n if (e.altKey || e.ctrlKey || e.metaKey) return;\n if (!['ArrowLeft', 'ArrowRight', 'Home', 'End'].includes(e.key)) return;\n const buttons = Array.from(\n e.currentTarget.querySelectorAll<HTMLButtonElement>(\n 'button:not([disabled])'\n )\n );\n const i = buttons.indexOf(document.activeElement as HTMLButtonElement);\n if (i === -1 || buttons.length === 0) return;\n e.preventDefault();\n e.stopPropagation();\n let key = e.key;\n if (isRtl(e.currentTarget)) {\n if (key === 'ArrowRight') key = 'ArrowLeft';\n else if (key === 'ArrowLeft') key = 'ArrowRight';\n }\n const next =\n key === 'ArrowLeft'\n ? (i - 1 + buttons.length) % buttons.length\n : key === 'ArrowRight'\n ? (i + 1) % buttons.length\n : key === 'Home'\n ? 0\n : buttons.length - 1;\n buttons[next]?.focus();\n}\n\n// Alignment of the floating (fine-pointer) overlay within the row.\nconst ALIGN = {\n /** Vertically centered on the row's right edge (single-line rows). */\n center:\n 'pointer-fine:top-1/2 pointer-fine:end-0 pointer-fine:-translate-y-1/2',\n /** Pinned near the row's top-right corner (multi-line rows). */\n top: 'pointer-fine:top-1.5 pointer-fine:end-1.5',\n} as const;\n\n// Which hover scope reveals the toolbar. Rows nested inside another `group`\n// (e.g. order rows inside an assessed problem) use a named group so hovering\n// the outer block doesn't reveal every nested toolbar. `grid` keys off the\n// datavis (NITRO) table row (`.wcdv-tr`) for toolbars rendered into grid\n// cells via `formatCell`.\nconst REVEAL = {\n row: cn(\n 'group-hover:pointer-events-auto group-hover:opacity-100',\n 'group-focus-within:pointer-events-auto group-focus-within:opacity-100',\n 'group-focus:pointer-events-auto group-focus:opacity-100'\n ),\n order: cn(\n 'group-hover/order:pointer-events-auto group-hover/order:opacity-100',\n 'group-focus-within/order:pointer-events-auto group-focus-within/order:opacity-100',\n 'group-focus/order:pointer-events-auto group-focus/order:opacity-100'\n ),\n grid: cn(\n '[.wcdv-tr:hover_&]:pointer-events-auto [.wcdv-tr:hover_&]:opacity-100',\n '[.wcdv-tr:focus-within_&]:pointer-events-auto [.wcdv-tr:focus-within_&]:opacity-100'\n ),\n} as const;\n\nexport interface RowActionToolbarProps {\n /** Accessible name, e.g. `Actions for penicillin`. */\n label: string;\n /** Overlay alignment on fine-pointer devices. @default 'center' */\n align?: keyof typeof ALIGN;\n /**\n * Hover scope for the reveal. Use `'order'` when the row is a\n * `group/order` nested inside another `group`; use `'grid'` inside a\n * datavis (NITRO) grid cell — the toolbar then stays in flow (the cell\n * reserves its space) and reveals when the `.wcdv-tr` row is hovered.\n * @default 'row'\n */\n group?: keyof typeof REVEAL;\n /**\n * `'hover'` floats the toolbar over the row on fine-pointer devices and\n * reveals it on hover/focus; `'always'` keeps it in flow at the end of the\n * row and always visible on every pointer type.\n * @default 'hover'\n */\n reveal?: 'hover' | 'always';\n className?: string;\n children: React.ReactNode;\n}\n\n/**\n * Per-row action toolbar for clinical lists.\n *\n * On hover-capable (fine pointer) devices it floats over the row's right\n * edge as a card-styled overlay, hidden until the row is hovered or\n * keyboard-focused. Touch devices can't hover, so the toolbar stays in\n * flow at the end of the row (`ms-auto`) and is always visible.\n *\n * Implements WAI-ARIA toolbar arrow-key navigation. The parent row must be\n * `relative` and carry the matching `group` (or `group/order`) class.\n */\nexport function RowActionToolbar({\n label,\n align = 'center',\n group = 'row',\n reveal = 'hover',\n className,\n children,\n}: RowActionToolbarProps) {\n return (\n <div\n role=\"toolbar\"\n aria-label={label}\n onKeyDown={toolbarKeyNav}\n className={cn(\n 'z-10 ms-auto flex items-center gap-0.5',\n reveal === 'hover' && [\n 'transition-opacity',\n // Inside a grid cell the column already reserves the space, so the\n // toolbar stays in flow — no absolute overlay. It keeps the card\n // chrome, though: pair with a `sticky end-0` actions column and it\n // floats over scrolled-under content at the grid's right edge.\n group !== 'grid' && [\n 'pointer-fine:absolute',\n ALIGN[align],\n 'pointer-fine:bg-card pointer-fine:border-border pointer-fine:rounded-md pointer-fine:border pointer-fine:p-0.5 pointer-fine:shadow-sm',\n ],\n group === 'grid' &&\n 'bg-card border-border rounded-md border p-0.5 shadow-sm',\n 'pointer-fine:pointer-events-none pointer-fine:opacity-0',\n REVEAL[group],\n 'focus-within:pointer-events-auto focus-within:opacity-100',\n ],\n className\n )}\n >\n {children}\n </div>\n );\n}\n\nexport interface RowIconButtonProps {\n label: string;\n icon: React.ComponentType<{ size?: number | string }>;\n onClick: () => void;\n /** Toggle-button state (renders `aria-pressed` + tinted background). */\n active?: boolean;\n /** Disclosure state and the id of the controlled region. */\n expanded?: boolean;\n controls?: string;\n /** `md` = 32px button / 16px icon; `sm` = 28px / 14px. @default 'md' */\n size?: 'md' | 'sm';\n}\n\n/** Tooltip-labeled ghost icon button for `RowActionToolbar`. */\nexport function RowIconButton({\n label,\n icon: Icon,\n onClick,\n active,\n expanded,\n controls,\n size = 'md',\n}: RowIconButtonProps) {\n return (\n <Tooltip content={label}>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n aria-label={label}\n aria-pressed={active}\n aria-expanded={expanded}\n aria-controls={controls}\n onClick={(e) => {\n e.stopPropagation();\n onClick();\n }}\n className={cn(\n size === 'sm' ? 'h-7 w-7' : 'h-8 w-8',\n 'shrink-0',\n (active || expanded) &&\n 'bg-primary-50 text-primary-700 dark:bg-primary-950 dark:text-primary-400'\n )}\n >\n <Icon size={size === 'sm' ? 14 : 16} />\n </Button>\n </Tooltip>\n );\n}\n","'use client';\n\nimport { useMessages, type MessageTranslator } from '../../utils/messages';\n\nimport * as React from 'react';\nimport { cn } from '../../utils/cn';\nimport { Badge } from '../Badge/Badge';\nimport { Button } from '../Button';\nimport { Tooltip } from '../Tooltip';\nimport { Card, CardHeader, CardContent } from '../Card/Card';\nimport {\n PencilIcon,\n RefreshIcon,\n CheckCircleIcon,\n LinkIcon,\n ExternalLinkIcon,\n ChevronDownIcon,\n ChevronUpIcon,\n PlusIcon,\n HistoryIcon,\n HelpCircleIcon,\n GripVerticalIcon,\n StickyNoteIcon,\n TrashIcon,\n} from '../Icons';\nimport {\n useDragReorder,\n dragIndicatorClasses,\n type UseDragReorderReturn,\n} from '../../hooks/useDragReorder';\nimport { RowActionToolbar, RowIconButton } from '../RowActionToolbar';\nimport { useLiveAnnouncement } from '../../hooks/useLiveAnnouncement';\n\n// =============================================================================\n// Types — shared condition (concern/assertion) model\n// =============================================================================\n\n/** A single coding on a condition assertion (ICD-10 / ICD-11 / SNOMED). */\nexport interface ConditionCoding {\n /** Coding system, e.g. 'ICD-10-CM', 'ICD-11', 'SNOMED' */\n system: 'ICD-10-CM' | 'ICD-11' | 'SNOMED' | string;\n code: string;\n display?: string;\n /** Which coding is authoritative for this assertion */\n primary?: boolean;\n /** Provenance when derived via a crosswalk (e.g. SNOMED→ICD-10 map) */\n mappedFrom?: string;\n}\n\n/** Longitudinal status of the concern (the stable problem thread). */\nexport type ConcernStatus =\n | 'active'\n | 'recurrence'\n | 'relapse'\n | 'inactive'\n | 'remission'\n | 'resolved';\n\n/** FHIR-aligned verification status of an assertion. */\nexport type VerificationStatus =\n | 'unconfirmed'\n | 'provisional'\n | 'differential'\n | 'confirmed'\n | 'refuted'\n | 'entered-in-error';\n\n/** Why an assertion superseded its predecessor. */\nexport type AssertionChangeType =\n | 'refinement'\n | 'revision'\n | 'progression'\n | 'reattribution';\n\n// ---- Uncertainty (mirrors §4 of the design doc) ----\n\n/** Three-state flag for an optional field: confident / uncertain / explicitly unknown. */\nexport interface FieldUncertainty {\n /** false = explicitly unknown (\"asked; patient doesn't know\") — distinct from untouched */\n known: boolean;\n /** Why the value is absent (~ FHIR data-absent-reason) */\n reason?: 'asked-unknown' | 'not-asked' | 'masked' | 'unavailable';\n /** Softness of a value that IS present */\n confidence?: 'low' | 'medium' | 'high';\n note?: string;\n}\n\n/** Condition fields that can carry per-field uncertainty. */\nexport type UncertainConditionField =\n | 'coding'\n | 'onset'\n | 'severity'\n | 'laterality'\n | 'bodySite';\n\n/** First-class uncertainty block for a condition assertion. */\nexport interface Uncertainty {\n overall?: 'confirmed' | 'low' | 'medium' | 'high';\n fields?: Partial<Record<UncertainConditionField, FieldUncertainty>>;\n}\n\n/** A time-stamped, coded characterization of a concern. */\nexport interface ConditionAssertion {\n id: string;\n /** Display date the assertion was made, e.g. \"2023-06-14\" */\n date: string;\n /** Free-text condition name — the only hard-required clinical field */\n text: string;\n coding?: ConditionCoding[];\n verificationStatus: VerificationStatus;\n /** How this assertion relates to the one it supersedes */\n changeType?: AssertionChangeType;\n /** Id of the assertion this one supersedes */\n supersedes?: string;\n severity?: 'mild' | 'moderate' | 'severe';\n /** Onset — exact date and/or fuzzy human string (\"since her twenties\") */\n onset?: { date?: string; fuzzy?: string };\n /** First-class uncertainty (§4 of the design doc) */\n uncertainty?: Uncertainty;\n note?: string;\n}\n\n/** Relationship between two concerns. */\nexport interface ConcernRelationship {\n type:\n | 'caused-by'\n | 'evolved-from'\n | 'differential-sibling'\n | 'complication-of';\n /** concernId of the related concern */\n concernId: string;\n /** Display name of the related concern */\n display?: string;\n}\n\n/** A quick, dated progress note about a concern — lighter than an assertion. */\nexport interface ConditionObservation {\n id: string;\n /** Display date, e.g. \"2026-07-03\" */\n date: string;\n text: string;\n author?: string;\n}\n\n/**\n * A stable problem thread. The concernId is the durable identity that orders\n * and encounters reference; assertions carry the evolving codes.\n */\nexport interface ConditionConcern {\n concernId: string;\n clinicalStatus: ConcernStatus;\n /** Ordered oldest → newest; the last non-refuted assertion is current */\n assertions: ConditionAssertion[];\n /** Quick progress notes over time (newest last) */\n observations?: ConditionObservation[];\n relationships?: ConcernRelationship[];\n /** Where the concern came from */\n source?:\n | 'ehrProblemList'\n | 'patientReported'\n | 'manuallyAdded'\n | 'claimsHistory';\n}\n\n/** Row actions on a concern. */\nexport type ProblemListAction =\n | 'open'\n | 'observe'\n | 'refine'\n | 'revise'\n | 'resolve'\n | 'relate'\n | 'remove'\n | 'move-up'\n | 'move-down';\n\nexport interface ProblemListProps extends Omit<\n React.HTMLAttributes<HTMLDivElement>,\n 'className' | 'title'\n> {\n /** Patient-level concerns (controlled) */\n concerns: ConditionConcern[];\n /** Header title (pass null to hide) */\n title?: string | null;\n /** Called when a row action is clicked */\n onAction?: (concern: ConditionConcern, action: ProblemListAction) => void;\n /** Called when a new problem is added via the capture-first input */\n onAddProblem?: (text: string) => void;\n /** Inline coded add search (e.g. a CodeLookup) rendered in the add section */\n addSearch?: React.ReactNode;\n /** Called when the \"Add\" pill is clicked (omit to hide; opens the host's detailed editor) */\n onAdd?: () => void;\n /**\n * Called with the full ordered list of concernIds after a move — via drag\n * and drop, the move buttons, or Alt+Arrow keys. Enables reordering. The\n * component renders concerns in props order — persist the ids wherever the\n * encounter/patient object lives and feed them back in.\n */\n onReorder?: (concernIds: string[]) => void;\n /** Which row actions to show (default: all except 'remove') */\n actions?: ProblemListAction[];\n /** Show row actions in flow, always visible, instead of the hover-reveal overlay */\n inlineActions?: boolean;\n /** Hide all action buttons (display only) */\n readOnly?: boolean;\n /** Message shown when there are no concerns */\n emptyMessage?: string;\n /** Additional CSS classes */\n className?: string;\n /** Test ID for testing */\n 'data-testid'?: string;\n}\n\n// =============================================================================\n// Constants\n// =============================================================================\n\nconst GROUP_ORDER: { key: string; label: string; statuses: ConcernStatus[] }[] =\n [\n {\n key: 'active',\n label: 'Active',\n statuses: ['active', 'recurrence', 'relapse'],\n },\n { key: 'inactive', label: 'Inactive', statuses: ['inactive', 'remission'] },\n { key: 'resolved', label: 'Resolved', statuses: ['resolved'] },\n ];\n\n/**\n * Grouping key for a concern. Unconfirmed concerns (current assertion not yet\n * verified) live in their own group, separate from Active / Resolved.\n */\nexport function concernGroupKey(concern: ConditionConcern): string {\n if (currentAssertion(concern)?.verificationStatus === 'unconfirmed') {\n return 'unconfirmed';\n }\n return (\n GROUP_ORDER.find((g) => g.statuses.includes(concern.clinicalStatus))?.key ??\n 'active'\n );\n}\n\nexport const CONCERN_STATUS_LABELS: Record<ConcernStatus, string> = {\n active: 'Active',\n recurrence: 'Recurrence',\n relapse: 'Relapse',\n inactive: 'Inactive',\n remission: 'Remission',\n resolved: 'Resolved',\n};\n\nexport const CHANGE_TYPE_LABELS: Record<AssertionChangeType, string> = {\n refinement: 'Refined',\n revision: 'Revised',\n progression: 'Progressed',\n reattribution: 'Re-attributed',\n};\n\nconst DEFAULT_ACTIONS: ProblemListAction[] = [\n 'open',\n 'observe',\n 'refine',\n 'revise',\n 'resolve',\n 'relate',\n 'move-up',\n 'move-down',\n];\n\nconst ACTION_META: Record<\n ProblemListAction,\n { label: string; icon: React.ComponentType<{ size?: number | string }> }\n> = {\n open: { label: 'Open', icon: ExternalLinkIcon },\n observe: { label: 'Add observation (progress note)', icon: StickyNoteIcon },\n refine: { label: 'Refine (more specific)', icon: PencilIcon },\n revise: { label: 'Revise (prior was wrong)', icon: RefreshIcon },\n resolve: { label: 'Resolve', icon: CheckCircleIcon },\n relate: { label: 'Relate to another problem', icon: LinkIcon },\n remove: { label: 'Delete', icon: TrashIcon },\n 'move-up': { label: 'Move up (Alt+↑)', icon: ChevronUpIcon },\n 'move-down': { label: 'Move down (Alt+↓)', icon: ChevronDownIcon },\n};\n\nconst VERIFICATION_BADGE: Record<\n VerificationStatus,\n {\n label: string;\n variant: 'default' | 'secondary' | 'success' | 'warning' | 'outline';\n }\n> = {\n unconfirmed: { label: 'Unconfirmed', variant: 'outline' },\n provisional: { label: 'Provisional', variant: 'warning' },\n differential: { label: 'Differential', variant: 'warning' },\n confirmed: { label: 'Confirmed', variant: 'success' },\n refuted: { label: 'Refuted', variant: 'secondary' },\n 'entered-in-error': { label: 'Entered in error', variant: 'secondary' },\n};\n\n// =============================================================================\n// Helpers\n// =============================================================================\n\n/** The current (last non-refuted, non-error) assertion of a concern. */\nexport function currentAssertion(\n concern: ConditionConcern\n): ConditionAssertion | undefined {\n for (let i = concern.assertions.length - 1; i >= 0; i--) {\n const a = concern.assertions[i];\n if (\n a.verificationStatus !== 'refuted' &&\n a.verificationStatus !== 'entered-in-error'\n ) {\n return a;\n }\n }\n return concern.assertions[concern.assertions.length - 1];\n}\n\nconst UNCERTAIN_FIELD_LABELS: Record<UncertainConditionField, string> = {\n coding: 'Coding',\n onset: 'Onset',\n severity: 'Severity',\n laterality: 'Laterality',\n bodySite: 'Body site',\n};\n\nfunction describeFieldUncertainty(\n field: UncertainConditionField,\n f: FieldUncertainty,\n m: MessageTranslator\n): string {\n const label = UNCERTAIN_FIELD_LABELS[field];\n if (!f.known) {\n const reason =\n f.reason === 'asked-unknown'\n ? 'asked — unknown'\n : (f.reason ?? 'unknown').replace(/-/g, ' ');\n return `${m(label)}: ${m(reason)}${f.note ? ` (${f.note})` : ''}`;\n }\n return `${m(label)}: ${m('{confidence} confidence', {\n confidence: m(f.confidence ?? 'uncertain'),\n })}${f.note ? ` (${f.note})` : ''}`;\n}\n\n// =============================================================================\n// Sub-components\n// =============================================================================\n\n/**\n * Parenthetical coding display. Clinicians don't need chip noise: inline we\n * show only ICD-10/ICD-11 codes, unlabeled (the code format is obvious), and\n * SNOMED stays out of the way. The full coding background — every system,\n * display name, and crosswalk provenance — lives in the tooltip.\n */\nexport function CodingChips({ coding }: { coding?: ConditionCoding[] }) {\n const m = useMessages();\n if (!coding?.length) return null;\n const icd = coding.filter((c) => c.system.startsWith('ICD'));\n const inline = icd.length > 0 ? icd : coding.filter((c) => c.primary);\n const label = inline.map((c) => c.code).join(', ');\n return (\n <Tooltip\n content={\n <span className=\"flex flex-col gap-0.5\">\n {coding.map((c) => (\n <span key={`${c.system}:${c.code}`}>\n {c.system} {c.code}\n {c.display ? ` — ${c.display}` : ''}\n {c.primary ? m(' · primary') : ''}\n {c.mappedFrom\n ? m(' · mapped from {source}', { source: c.mappedFrom })\n : ''}\n </span>\n ))}\n </span>\n }\n >\n {/* focusable so the coding provenance is reachable by keyboard */}\n <span\n // eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex\n tabIndex={0}\n className=\"text-muted-foreground focus-visible:ring-ring rounded text-xs whitespace-nowrap focus-visible:ring-2 focus-visible:outline-none\"\n >\n ({label || m('coded')})\n </span>\n </Tooltip>\n );\n}\n\n/**\n * Full concern background for a hover/long-press tooltip: assertion history,\n * coding background, and recent observations.\n */\nexport function concernHistoryContent(\n concern: ConditionConcern,\n m: MessageTranslator = (message) => message\n): React.ReactNode {\n return (\n <span className=\"flex max-w-xs flex-col gap-1\">\n <span className=\"font-semibold\">{m('History')}</span>\n {[...concern.assertions].reverse().map((a) => (\n <span key={a.id}>\n {a.date} — {a.text}\n {a.changeType\n ? ` (${m(CHANGE_TYPE_LABELS[a.changeType]).toLocaleLowerCase()})`\n : ''}\n {a.verificationStatus === 'refuted'\n ? ` — ${m('Refuted').toLocaleLowerCase()}`\n : ''}\n </span>\n ))}\n {concern.observations && concern.observations.length > 0 && (\n <>\n <span className=\"mt-1 font-semibold\">{m('Observations')}</span>\n {[...concern.observations]\n .reverse()\n .slice(0, 3)\n .map((o) => (\n <span key={o.id}>\n {o.date} — {o.text}\n </span>\n ))}\n </>\n )}\n {(currentAssertion(concern)?.coding?.length ?? 0) > 0 && (\n <>\n <span className=\"mt-1 font-semibold\">{m('Coding')}</span>\n {currentAssertion(concern)!.coding!.map((c) => (\n <span key={`${c.system}:${c.code}`}>\n {c.system} {c.code}\n {c.display ? ` — ${c.display}` : ''}\n </span>\n ))}\n </>\n )}\n </span>\n );\n}\n\n/** Badge summarizing an assertion's uncertainty block (§4 of the design doc). */\nexport function UncertaintyBadge({\n uncertainty,\n}: {\n uncertainty?: Uncertainty;\n}) {\n const m = useMessages();\n if (!uncertainty) return null;\n const fieldEntries = Object.entries(uncertainty.fields ?? {}) as Array<\n [UncertainConditionField, FieldUncertainty]\n >;\n const overall =\n uncertainty.overall && uncertainty.overall !== 'confirmed'\n ? uncertainty.overall\n : null;\n if (!overall && fieldEntries.length === 0) return null;\n const lines = [\n ...(overall\n ? [m('Overall certainty: {certainty}', { certainty: m(overall) })]\n : []),\n ...fieldEntries.map(([field, f]) => describeFieldUncertainty(field, f, m)),\n ];\n return (\n <Tooltip content={lines.join(' · ')}>\n <Badge variant=\"warning\" size=\"sm\" className=\"gap-1\">\n <HelpCircleIcon size={10} />\n {overall\n ? m('{certainty} certainty', { certainty: m(overall) })\n : m('{count} uncertain', { count: fieldEntries.length })}\n </Badge>\n </Tooltip>\n );\n}\n\nfunction AssertionTimeline({ concern }: { concern: ConditionConcern }) {\n const m = useMessages();\n const items = [...concern.assertions].reverse(); // newest first\n return (\n <ol\n aria-label={m('Assertion history')}\n className=\"border-border ms-1.5 mt-2 space-y-2 border-s ps-4\"\n >\n {items.map((a) => {\n const refuted =\n a.verificationStatus === 'refuted' ||\n a.verificationStatus === 'entered-in-error';\n const verification = VERIFICATION_BADGE[a.verificationStatus];\n return (\n <li key={a.id} className=\"relative text-sm\">\n <span\n aria-hidden\n className=\"bg-border absolute -start-5 top-1.5 h-2 w-2 rounded-full\"\n />\n <span className=\"flex flex-wrap items-center gap-x-2 gap-y-1\">\n <span className=\"text-muted-foreground text-xs tabular-nums\">\n {a.date}\n </span>\n <span\n className={cn(\n 'text-foreground font-medium',\n refuted && 'text-muted-foreground line-through'\n )}\n >\n {a.text}\n </span>\n {a.changeType && (\n <Badge variant=\"secondary\" size=\"sm\">\n {m(CHANGE_TYPE_LABELS[a.changeType])}\n </Badge>\n )}\n <Badge variant={verification.variant} size=\"sm\">\n {m(verification.label)}\n </Badge>\n <UncertaintyBadge uncertainty={a.uncertainty} />\n <CodingChips coding={a.coding} />\n </span>\n {a.note && (\n <p className=\"text-muted-foreground mt-0.5 text-xs\">{a.note}</p>\n )}\n </li>\n );\n })}\n </ol>\n );\n}\n\nfunction ConcernRow({\n concern,\n actions,\n inlineActions,\n readOnly,\n canReorder,\n drag,\n onAction,\n}: {\n concern: ConditionConcern;\n actions: ProblemListAction[];\n inlineActions: boolean;\n readOnly: boolean;\n canReorder: boolean;\n drag: UseDragReorderReturn;\n onAction?: (concern: ConditionConcern, action: ProblemListAction) => void;\n}) {\n const m = useMessages();\n const [expanded, setExpanded] = React.useState(false);\n const current = currentAssertion(concern);\n const hasHistory = concern.assertions.length > 1;\n\n const visibleActions = actions.filter(\n (a) => canReorder || (a !== 'move-up' && a !== 'move-down')\n );\n\n const handleRowKeyDown = (e: React.KeyboardEvent<HTMLElement>) => {\n if (e.target !== e.currentTarget) return;\n if (e.altKey && (e.key === 'ArrowUp' || e.key === 'ArrowDown')) {\n if (!canReorder) return;\n e.preventDefault();\n onAction?.(concern, e.key === 'ArrowUp' ? 'move-up' : 'move-down');\n } else if (e.key === 'ArrowUp' || e.key === 'ArrowDown') {\n // Roving focus between rows\n e.preventDefault();\n const list = e.currentTarget.closest('ul');\n if (!list) return;\n const rows = Array.from(\n list.querySelectorAll<HTMLElement>('li[data-concern-id]')\n );\n const i = rows.indexOf(e.currentTarget as HTMLElement);\n rows[\n e.key === 'ArrowUp'\n ? Math.max(0, i - 1)\n : Math.min(rows.length - 1, i + 1)\n ]?.focus();\n } else if ((e.key === 'Enter' || e.key === ' ') && hasHistory) {\n e.preventDefault();\n setExpanded((v) => !v);\n }\n };\n\n if (!current) return null;\n\n return (\n // Roving-focus row (WAI-ARIA listbox-like keyboard pattern): the row is a\n // legitimate focus stop so ↑/↓ navigate rows, Enter toggles history, and\n // Alt+↑/↓ reorders — required for 508 keyboard operability.\n /* eslint-disable jsx-a11y/no-noninteractive-element-interactions, jsx-a11y/no-noninteractive-tabindex */\n <li\n data-slot=\"clinical-list-row\"\n data-concern-id={concern.concernId}\n tabIndex={0}\n onKeyDown={handleRowKeyDown}\n {...drag.rowProps(concern.concernId)}\n aria-label={[\n `${current.text}.`,\n hasHistory ? m('Press Enter to toggle history.') : '',\n canReorder ? m('Alt plus arrow keys to reorder.') : '',\n ]\n .filter(Boolean)\n .join(' ')}\n className={cn(\n 'group border-border/60 relative border-b px-1 py-2',\n 'focus-visible:ring-ring focus-visible:ring-2 focus-visible:outline-none',\n drag.enabled && 'cursor-grab active:cursor-grabbing',\n dragIndicatorClasses(drag, concern.concernId)\n )}\n >\n {/* eslint-enable jsx-a11y/no-noninteractive-element-interactions, jsx-a11y/no-noninteractive-tabindex */}\n <div className=\"flex min-h-9 flex-wrap items-center gap-x-2 gap-y-1\">\n {drag.enabled ? (\n <GripVerticalIcon\n size={14}\n aria-hidden\n className=\"text-muted-foreground/50 shrink-0\"\n />\n ) : (\n <span className=\"text-muted-foreground/60 select-none\">•</span>\n )}\n {/* Hover (or long-press on touch) the name for the complete background:\n assertion history, observations, and coding provenance. */}\n <Tooltip content={concernHistoryContent(concern, m)}>\n <span className=\"text-foreground font-medium\">{current.text}</span>\n </Tooltip>\n <CodingChips coding={current.coding} />\n {/* 'unconfirmed' is conveyed by the Unconfirmed group header */}\n {current.verificationStatus !== 'confirmed' &&\n current.verificationStatus !== 'unconfirmed' && (\n <Badge\n variant={VERIFICATION_BADGE[current.verificationStatus].variant}\n size=\"sm\"\n >\n {m(VERIFICATION_BADGE[current.verificationStatus].label)}\n </Badge>\n )}\n <UncertaintyBadge uncertainty={current.uncertainty} />\n {concern.relationships?.map((r) => (\n <Badge key={`${r.type}:${r.concernId}`} variant=\"outline\" size=\"sm\">\n <LinkIcon size={10} className=\"me-1\" />\n {m(r.type.replace(/-/g, ' '))}\n {r.display ? `: ${r.display}` : ''}\n </Badge>\n ))}\n {hasHistory && (\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={() => setExpanded((v) => !v)}\n aria-expanded={expanded}\n leftIcon={<HistoryIcon size={12} />}\n rightIcon={\n expanded ? (\n <ChevronUpIcon size={12} />\n ) : (\n <ChevronDownIcon size={12} />\n )\n }\n className=\"text-muted-foreground h-auto px-1.5 py-0.5 text-xs\"\n >\n {m('{count} assertions', { count: concern.assertions.length })}\n </Button>\n )}\n\n {!readOnly && (\n <RowActionToolbar\n label={m('Actions for {name}', { name: current.text })}\n align=\"top\"\n reveal={inlineActions ? 'always' : 'hover'}\n >\n {visibleActions.map((action) => (\n <RowIconButton\n key={action}\n label={m(ACTION_META[action].label)}\n icon={ACTION_META[action].icon}\n onClick={() => onAction?.(concern, action)}\n />\n ))}\n </RowActionToolbar>\n )}\n </div>\n\n {expanded && (\n <>\n <AssertionTimeline concern={concern} />\n {concern.observations && concern.observations.length > 0 && (\n <div className=\"ms-1.5 mt-2 ps-4\">\n <h5 className=\"text-muted-foreground text-xs font-semibold tracking-wide uppercase\">\n {m('Observations')}\n </h5>\n <ol aria-label={m('Observations')} className=\"mt-1 space-y-1\">\n {[...concern.observations].reverse().map((o) => (\n <li key={o.id} className=\"flex flex-wrap gap-x-2 text-sm\">\n <span className=\"text-muted-foreground text-xs tabular-nums\">\n {o.date}\n </span>\n <span className=\"text-foreground\">{o.text}</span>\n {o.author && (\n <span className=\"text-muted-foreground text-xs\">\n — {o.author}\n </span>\n )}\n </li>\n ))}\n </ol>\n </div>\n )}\n </>\n )}\n </li>\n );\n}\n\n// =============================================================================\n// ProblemList\n// =============================================================================\n\n/**\n * Patient-level problem list built on the concern/assertion model: each row is\n * a stable ConditionConcern whose coded characterization evolves through an\n * assertion history (refinement / revision / progression). Rows expand to show\n * the assertion timeline; refuted assertions render struck-through.\n *\n * Controlled component: concerns come in via props; every user interaction is\n * reported through callbacks.\n *\n * @example\n * ```tsx\n * <ProblemList\n * concerns={concerns}\n * onAction={(concern, action) => handleAction(concern, action)}\n * onAddProblem={(text) => addConcern(text)}\n * />\n * ```\n */\nexport const ProblemList = React.forwardRef<HTMLDivElement, ProblemListProps>(\n (\n {\n concerns,\n title = 'Problem list',\n onAction,\n onAddProblem,\n addSearch,\n onAdd,\n onReorder,\n actions = DEFAULT_ACTIONS,\n inlineActions = false,\n readOnly = false,\n emptyMessage = 'No problems recorded.',\n className,\n 'data-testid': dataTestId,\n ...props\n },\n ref\n ) => {\n const m = useMessages();\n const [draft, setDraft] = React.useState('');\n // clears-then-sets so repeated identical messages re-announce\n const [announcement, setAnnouncement] = useLiveAnnouncement();\n\n const submitDraft = () => {\n const text = draft.trim();\n if (!text) return;\n onAddProblem?.(text);\n setDraft('');\n };\n\n /** Swap with the adjacent concern in the same group, then report the full order. */\n const moveConcern = React.useCallback(\n (concern: ConditionConcern, dir: -1 | 1) => {\n if (!onReorder || readOnly) return;\n const groupKey = concernGroupKey(concern);\n const ids = concerns.map((c) => c.concernId);\n const from = ids.indexOf(concern.concernId);\n // nearest neighbor in the same group\n let to = from + dir;\n while (\n to >= 0 &&\n to < concerns.length &&\n concernGroupKey(concerns[to]) !== groupKey\n ) {\n to += dir;\n }\n if (to < 0 || to >= concerns.length) return;\n [ids[from], ids[to]] = [ids[to], ids[from]];\n const current = currentAssertion(concern);\n setAnnouncement(\n m(dir === -1 ? '{name} moved up' : '{name} moved down', {\n name: current?.text ?? concern.concernId,\n })\n );\n onReorder(ids);\n },\n [concerns, onReorder, readOnly, setAnnouncement, m]\n );\n\n const handleAction = React.useCallback(\n (concern: ConditionConcern, action: ProblemListAction) => {\n if (action === 'move-up') moveConcern(concern, -1);\n else if (action === 'move-down') moveConcern(concern, 1);\n else onAction?.(concern, action);\n },\n [moveConcern, onAction]\n );\n\n // Drag & drop reordering, restricted to the same group (a cross-group\n // drop would silently imply a status change). Precomputed map — dragover\n // fires too frequently for a linear concern scan per event.\n const groupById = React.useMemo(\n () =>\n new Map(\n concerns.map((c) => [c.concernId, concernGroupKey(c)] as const)\n ),\n [concerns]\n );\n const groupOf = React.useCallback(\n (id: string) => groupById.get(id),\n [groupById]\n );\n const drag = useDragReorder({\n ids: concerns.map((c) => c.concernId),\n onReorder:\n readOnly || !onReorder\n ? undefined\n : (newIds) => {\n // announce pointer drops too, not just keyboard moves\n setAnnouncement(m('Problem list reordered'));\n onReorder(newIds);\n },\n canDropOn: (dragged, target) => groupOf(dragged) === groupOf(target),\n });\n\n // Unconfirmed concerns get their own list, ahead of Active / Resolved.\n const groups = [\n {\n key: 'unconfirmed',\n label: 'Unconfirmed',\n items: concerns.filter((c) => concernGroupKey(c) === 'unconfirmed'),\n },\n ...GROUP_ORDER.map(({ key, label }) => ({\n key,\n label,\n items: concerns.filter((c) => concernGroupKey(c) === key),\n })),\n // Active stays visible as the empty state only when nothing is recorded\n // at all — an empty Active section next to populated groups would\n // misleadingly read \"No problems recorded\".\n ].filter(\n (g) => g.items.length > 0 || (g.key === 'active' && concerns.length === 0)\n );\n\n return (\n <Card\n ref={ref}\n padding=\"none\"\n className={cn('w-full', className)}\n data-testid={dataTestId}\n {...props}\n >\n {title !== null && (\n <CardHeader className=\"border-border bg-muted/50 border-b px-4 py-3\">\n <h3 className=\"text-foreground text-sm font-semibold tracking-wide uppercase\">\n {m(title)}\n </h3>\n </CardHeader>\n )}\n\n <CardContent className=\"space-y-6 px-4 py-4\">\n {groups.map(({ key, label, items }) => (\n <section key={key} aria-label={m(label)}>\n <h4\n data-slot=\"clinical-list-heading\"\n className=\"border-border text-foreground border-b pb-1 text-sm font-semibold tracking-wide uppercase\"\n >\n {m(label)}\n </h4>\n {items.length > 0 ? (\n <ul className=\"mt-1\">\n {items.map((concern) => (\n <ConcernRow\n key={concern.concernId}\n concern={concern}\n actions={actions}\n inlineActions={inlineActions}\n readOnly={readOnly}\n canReorder={drag.enabled}\n drag={drag}\n onAction={handleAction}\n />\n ))}\n </ul>\n ) : (\n <p className=\"text-muted-foreground mt-2 text-sm\">\n {m(emptyMessage)}\n </p>\n )}\n </section>\n ))}\n\n {!readOnly && (addSearch || onAddProblem || onAdd) && (\n <div className=\"space-y-2\">\n <span className=\"text-muted-foreground text-xs font-semibold tracking-wide uppercase\">\n {m('Add problem')}\n </span>\n {addSearch}\n {onAddProblem && (\n <div className=\"flex items-center gap-1.5\">\n <input\n type=\"text\"\n data-slot=\"input\"\n value={draft}\n onChange={(e) => setDraft(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === 'Enter') submitDraft();\n }}\n placeholder={m('Add problem (name is enough)…')}\n aria-label={m('Add problem')}\n className={cn(\n 'border-border bg-background text-foreground placeholder:text-muted-foreground',\n 'h-8 flex-1 rounded-md border px-2.5 text-sm',\n 'focus:ring-ring focus:ring-2 focus:outline-none'\n )}\n />\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={submitDraft}\n disabled={!draft.trim()}\n leftIcon={<PlusIcon size={12} />}\n className=\"h-8\"\n >\n {m('Add')}\n </Button>\n </div>\n )}\n {onAdd && (\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={onAdd}\n leftIcon={<PlusIcon size={12} />}\n className=\"h-auto rounded-full px-2.5 py-1 text-xs\"\n >\n {m('Add')}\n </Button>\n )}\n </div>\n )}\n </CardContent>\n\n {/* Reorder announcements for screen readers */}\n <div aria-live=\"polite\" className=\"sr-only\">\n {announcement}\n </div>\n </Card>\n );\n }\n);\n\nProblemList.displayName = 'ProblemList';\n\nexport default ProblemList;\n"]}