@eka-care/medical-records-ui 1.0.6 → 1.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -27,11 +27,6 @@ interface SdkProviderProps {
27
27
  config: SdkConfig;
28
28
  bid?: string;
29
29
  patientId?: string;
30
- /**
31
- * Document-type definitions from the host's onboarding config
32
- * (`mr_document_type`). Drives the code → display-name labels shown across
33
- * the feature; the SDK's static map is the fallback when a code is absent.
34
- */
35
30
  documentTypes?: DocumentTypeConfig[];
36
31
  children: ReactNode;
37
32
  }
@@ -234,6 +229,7 @@ interface SdkContextValue {
234
229
  ready: boolean;
235
230
  labelOf: DocumentTypeLabelResolver;
236
231
  documentTypes: DocumentTypeConfig[];
232
+ environment?: string;
237
233
  }
238
234
 
239
235
  declare function useSdk(): SdkContextValue;
@@ -246,7 +242,6 @@ declare function logoutMedicalRecords(bid?: string): Promise<void>;
246
242
  interface RecordsViewProps {
247
243
  className?: string;
248
244
  onUpload?: () => void;
249
- allowUpload?: boolean;
250
245
  onCopyToNote?: (text: string, anchor?: {
251
246
  x: number;
252
247
  y: number;
@@ -259,7 +254,7 @@ interface RecordsViewProps {
259
254
  onRemoveAttachment?: (documentId: string) => void | Promise<void>;
260
255
  onToast?: (message: string, type?: 'error' | 'success') => void;
261
256
  }
262
- declare function RecordsView({ className, onUpload, allowUpload, onCopyToNote, attachedIds, onAttachManyToContext, onRemoveAttachment, onToast, }: RecordsViewProps): react.JSX.Element;
257
+ declare function RecordsView({ className, onUpload, onCopyToNote, attachedIds, onAttachManyToContext, onRemoveAttachment, onToast, }: RecordsViewProps): react.JSX.Element;
263
258
 
264
259
  interface RecordsConnectionActions {
265
260
  refresh: () => Promise<void>;
package/dist/index.d.ts CHANGED
@@ -27,11 +27,6 @@ interface SdkProviderProps {
27
27
  config: SdkConfig;
28
28
  bid?: string;
29
29
  patientId?: string;
30
- /**
31
- * Document-type definitions from the host's onboarding config
32
- * (`mr_document_type`). Drives the code → display-name labels shown across
33
- * the feature; the SDK's static map is the fallback when a code is absent.
34
- */
35
30
  documentTypes?: DocumentTypeConfig[];
36
31
  children: ReactNode;
37
32
  }
@@ -234,6 +229,7 @@ interface SdkContextValue {
234
229
  ready: boolean;
235
230
  labelOf: DocumentTypeLabelResolver;
236
231
  documentTypes: DocumentTypeConfig[];
232
+ environment?: string;
237
233
  }
238
234
 
239
235
  declare function useSdk(): SdkContextValue;
@@ -246,7 +242,6 @@ declare function logoutMedicalRecords(bid?: string): Promise<void>;
246
242
  interface RecordsViewProps {
247
243
  className?: string;
248
244
  onUpload?: () => void;
249
- allowUpload?: boolean;
250
245
  onCopyToNote?: (text: string, anchor?: {
251
246
  x: number;
252
247
  y: number;
@@ -259,7 +254,7 @@ interface RecordsViewProps {
259
254
  onRemoveAttachment?: (documentId: string) => void | Promise<void>;
260
255
  onToast?: (message: string, type?: 'error' | 'success') => void;
261
256
  }
262
- declare function RecordsView({ className, onUpload, allowUpload, onCopyToNote, attachedIds, onAttachManyToContext, onRemoveAttachment, onToast, }: RecordsViewProps): react.JSX.Element;
257
+ declare function RecordsView({ className, onUpload, onCopyToNote, attachedIds, onAttachManyToContext, onRemoveAttachment, onToast, }: RecordsViewProps): react.JSX.Element;
263
258
 
264
259
  interface RecordsConnectionActions {
265
260
  refresh: () => Promise<void>;
package/dist/index.js CHANGED
@@ -528,8 +528,8 @@ function SdkProviderInner({ config, bid, patientId, documentTypes, children }) {
528
528
  [documentTypes]
529
529
  );
530
530
  const value = _react.useMemo.call(void 0,
531
- () => ({ bid, patientId, store, ready: true, labelOf, documentTypes: docTypes }),
532
- [bid, patientId, store, labelOf, docTypes]
531
+ () => ({ bid, patientId, store, ready: true, labelOf, documentTypes: docTypes, environment: config.environment }),
532
+ [bid, patientId, store, labelOf, docTypes, config.environment]
533
533
  );
534
534
  return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SdkContext.Provider, { value, children });
535
535
  }
@@ -1513,6 +1513,26 @@ function useLogout() {
1513
1513
  }, []);
1514
1514
  }
1515
1515
 
1516
+ // src/connection/useDenialList.ts
1517
+
1518
+ var HUB_URLS = {
1519
+ prod: "https://hub.eka.care",
1520
+ dev: "https://hub.dev.eka.care"
1521
+ };
1522
+ function useDenialList(environment) {
1523
+ const [denialList, setDenialList] = _react.useState.call(void 0, []);
1524
+ _react.useEffect.call(void 0, () => {
1525
+ const hubUrl = _nullishCoalesce(HUB_URLS[_nullishCoalesce(environment, () => ( "prod"))], () => ( HUB_URLS.prod));
1526
+ const url = `${hubUrl}/onboarding/5/configuration/?config_keys=denial_list&format=json`;
1527
+ fetch(url).then((res) => res.json()).then((data) => {
1528
+ const list = _optionalChain([data, 'optionalAccess', _36 => _36.denial_list]);
1529
+ if (Array.isArray(list)) setDenialList(list);
1530
+ }).catch(() => {
1531
+ });
1532
+ }, [environment]);
1533
+ return denialList;
1534
+ }
1535
+
1516
1536
  // src/stores/selectors/recordsSelectors.ts
1517
1537
 
1518
1538
 
@@ -1530,7 +1550,7 @@ function useRecordsStatus(store) {
1530
1550
  return _zustand.useStore.call(void 0, store, (s) => s.records.status);
1531
1551
  }
1532
1552
  function useThumbnailUrl(store, id) {
1533
- return _zustand.useStore.call(void 0, store, (s) => _nullishCoalesce(_optionalChain([s, 'access', _36 => _36.records, 'access', _37 => _37.byId, 'access', _38 => _38[id], 'optionalAccess', _39 => _39.thumbnailUrl]), () => ( null)));
1553
+ return _zustand.useStore.call(void 0, store, (s) => _nullishCoalesce(_optionalChain([s, 'access', _37 => _37.records, 'access', _38 => _38.byId, 'access', _39 => _39[id], 'optionalAccess', _40 => _40.thumbnailUrl]), () => ( null)));
1534
1554
  }
1535
1555
  function useIsSelected(store, id) {
1536
1556
  return _zustand.useStore.call(void 0, store, (s) => s.selection.recordIds.has(id));
@@ -1674,7 +1694,7 @@ function FilterPopover({ onClose }) {
1674
1694
  const ids = _zustand.useStore.call(void 0, store, (s) => s.records.ids);
1675
1695
  const typeOptions = _react.useMemo.call(void 0, () => {
1676
1696
  const seen = /* @__PURE__ */ new Set();
1677
- return ids.map((id) => _optionalChain([byId, 'access', _40 => _40[id], 'optionalAccess', _41 => _41.typeCode])).filter((code) => !!code && !seen.has(code) && !!seen.add(code)).map((code) => ({ value: code, label: labelOf(code) }));
1697
+ return ids.map((id) => _optionalChain([byId, 'access', _41 => _41[id], 'optionalAccess', _42 => _42.typeCode])).filter((code) => !!code && !seen.has(code) && !!seen.add(code)).map((code) => ({ value: code, label: labelOf(code) }));
1678
1698
  }, [ids, byId, labelOf]);
1679
1699
  const [docType, setDocType] = _react.useState.call(void 0, _nullishCoalesce(filters.type, () => ( "")));
1680
1700
  const [docPreset, setDocPreset] = _react.useState.call(void 0, filters.documentDatePreset);
@@ -1849,7 +1869,7 @@ function RecordsToolbar({
1849
1869
  if (!filterOpen) return;
1850
1870
  const onDown = (e) => {
1851
1871
  const t = e.target;
1852
- if (_optionalChain([t, 'access', _42 => _42.closest, 'optionalCall', _43 => _43("[data-mr-portal]")])) return;
1872
+ if (_optionalChain([t, 'access', _43 => _43.closest, 'optionalCall', _44 => _44("[data-mr-portal]")])) return;
1853
1873
  if (filterRef.current && !filterRef.current.contains(t)) setFilterOpen(false);
1854
1874
  };
1855
1875
  document.addEventListener("mousedown", onDown);
@@ -1865,7 +1885,7 @@ function RecordsToolbar({
1865
1885
  if (isRefreshing) return;
1866
1886
  setIsRefreshing(true);
1867
1887
  try {
1868
- await _optionalChain([onRefresh, 'optionalCall', _44 => _44()]);
1888
+ await _optionalChain([onRefresh, 'optionalCall', _45 => _45()]);
1869
1889
  } finally {
1870
1890
  setIsRefreshing(false);
1871
1891
  }
@@ -1891,7 +1911,7 @@ function RecordsToolbar({
1891
1911
  store.getState().filters.setType(id === ALL ? null : id);
1892
1912
  };
1893
1913
  const scrollBy = (delta) => {
1894
- _optionalChain([scrollRef, 'access', _45 => _45.current, 'optionalAccess', _46 => _46.scrollBy, 'call', _47 => _47({ left: delta, behavior: "smooth" })]);
1914
+ _optionalChain([scrollRef, 'access', _46 => _46.current, 'optionalAccess', _47 => _47.scrollBy, 'call', _48 => _48({ left: delta, behavior: "smooth" })]);
1895
1915
  };
1896
1916
  return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "mr-records-toolbar", children: [
1897
1917
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "mr-toolbar-filter", ref: filterRef, children: [
@@ -1904,7 +1924,7 @@ function RecordsToolbar({
1904
1924
  "aria-expanded": filterOpen,
1905
1925
  onClick: () => {
1906
1926
  setFilterOpen((o) => !o);
1907
- _optionalChain([onFilter, 'optionalCall', _48 => _48()]);
1927
+ _optionalChain([onFilter, 'optionalCall', _49 => _49()]);
1908
1928
  },
1909
1929
  children: [
1910
1930
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _lucidereact.Filter, { size: 16, "aria-hidden": true, color: "var(--mr-primary)" }),
@@ -1931,7 +1951,7 @@ function RecordsToolbar({
1931
1951
  {
1932
1952
  id: ALL,
1933
1953
  label: "All Records",
1934
- count: _optionalChain([filteredIds, 'optionalAccess', _49 => _49.length]),
1954
+ count: _optionalChain([filteredIds, 'optionalAccess', _50 => _50.length]),
1935
1955
  active: activeType == null,
1936
1956
  onSelect: selectType
1937
1957
  }
@@ -2174,8 +2194,8 @@ function CasePicker({ selected, onChange, mode = "dropdown" }) {
2174
2194
  }
2175
2195
  const onDown = (e) => {
2176
2196
  const t = e.target;
2177
- if (_optionalChain([fieldRef, 'access', _50 => _50.current, 'optionalAccess', _51 => _51.contains, 'call', _52 => _52(t)]) || _optionalChain([menuRef, 'access', _53 => _53.current, 'optionalAccess', _54 => _54.contains, 'call', _55 => _55(t)])) return;
2178
- if (_optionalChain([t, 'access', _56 => _56.closest, 'optionalCall', _57 => _57("[data-mr-portal]")])) return;
2197
+ if (_optionalChain([fieldRef, 'access', _51 => _51.current, 'optionalAccess', _52 => _52.contains, 'call', _53 => _53(t)]) || _optionalChain([menuRef, 'access', _54 => _54.current, 'optionalAccess', _55 => _55.contains, 'call', _56 => _56(t)])) return;
2198
+ if (_optionalChain([t, 'access', _57 => _57.closest, 'optionalCall', _58 => _58("[data-mr-portal]")])) return;
2179
2199
  setMenuPos(null);
2180
2200
  };
2181
2201
  const onResize = () => setMenuPos(null);
@@ -2262,7 +2282,7 @@ function CasePicker({ selected, onChange, mode = "dropdown" }) {
2262
2282
  ) : (
2263
2283
  // List mode — show cases + footer button
2264
2284
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
2265
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "ul", { className: "mr-case-picker__list", children: filtered.length === 0 ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "li", { className: "mr-case-picker__empty", children: "No cases found" }) : filtered.map((c) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "li", { children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
2285
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "ul", { className: "mr-case-picker__list", children: filtered.length === 0 ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "li", { className: "mr-case-picker__empty text-center", children: "No cases found" }) : filtered.map((c) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "li", { children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
2266
2286
  "button",
2267
2287
  {
2268
2288
  type: "button",
@@ -2346,7 +2366,7 @@ function CasePicker({ selected, onChange, mode = "dropdown" }) {
2346
2366
  onClick: () => open ? setMenuPos(null) : place(),
2347
2367
  children: [
2348
2368
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _lucidereact.Search, { size: 14, "aria-hidden": true, className: "mr-case-picker__field-icon" }),
2349
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: selectedCase ? "mr-case-picker__field-value" : "mr-case-picker__field-placeholder", children: _nullishCoalesce(_optionalChain([selectedCase, 'optionalAccess', _58 => _58.name]), () => ( "Search or select case\u2026")) }),
2369
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: selectedCase ? "mr-case-picker__field-value" : "mr-case-picker__field-placeholder", children: _nullishCoalesce(_optionalChain([selectedCase, 'optionalAccess', _59 => _59.name]), () => ( "Search or select case\u2026")) }),
2350
2370
  selected ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _lucidereact.X, { size: 14, "aria-hidden": true, className: "mr-case-picker__field-icon", onClick: (e) => {
2351
2371
  e.stopPropagation();
2352
2372
  onChange(null);
@@ -2562,7 +2582,7 @@ var TagChip = _react.memo.call(void 0, function TagChip2({ label, removable, onR
2562
2582
  "aria-label": `Remove ${label}`,
2563
2583
  onClick: (e) => {
2564
2584
  e.stopPropagation();
2565
- _optionalChain([onRemove, 'optionalCall', _59 => _59()]);
2585
+ _optionalChain([onRemove, 'optionalCall', _60 => _60()]);
2566
2586
  },
2567
2587
  children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _lucidereact.X, { size: 12, "aria-hidden": true })
2568
2588
  }
@@ -2601,7 +2621,7 @@ var Thumbnail = _react.memo.call(void 0, function Thumbnail2({ url, size, alt })
2601
2621
  bitmapRef.current = null;
2602
2622
  } else {
2603
2623
  const ctx2d = canvas.getContext("2d");
2604
- _optionalChain([ctx2d, 'optionalAccess', _60 => _60.drawImage, 'call', _61 => _61(bitmap, 0, 0)]);
2624
+ _optionalChain([ctx2d, 'optionalAccess', _61 => _61.drawImage, 'call', _62 => _62(bitmap, 0, 0)]);
2605
2625
  bitmap.close();
2606
2626
  bitmapRef.current = null;
2607
2627
  }
@@ -2630,8 +2650,8 @@ var Thumbnail = _react.memo.call(void 0, function Thumbnail2({ url, size, alt })
2630
2650
  }
2631
2651
  const dpr = typeof window === "undefined" ? 1 : window.devicePixelRatio || 1;
2632
2652
  const box = wrapRef.current;
2633
- const boxW = size || _optionalChain([box, 'optionalAccess', _62 => _62.clientWidth]) || probe.width;
2634
- const boxH = size || _optionalChain([box, 'optionalAccess', _63 => _63.clientHeight]) || probe.height;
2653
+ const boxW = size || _optionalChain([box, 'optionalAccess', _63 => _63.clientWidth]) || probe.width;
2654
+ const boxH = size || _optionalChain([box, 'optionalAccess', _64 => _64.clientHeight]) || probe.height;
2635
2655
  const boxRatio = boxW > 0 && boxH > 0 ? boxW / boxH : probe.width / probe.height;
2636
2656
  const srcRatio = probe.width / probe.height;
2637
2657
  let sw = probe.width;
@@ -2666,7 +2686,7 @@ var Thumbnail = _react.memo.call(void 0, function Thumbnail2({ url, size, alt })
2666
2686
  return () => {
2667
2687
  cancelled = true;
2668
2688
  controller.abort();
2669
- _optionalChain([bitmapRef, 'access', _64 => _64.current, 'optionalAccess', _65 => _65.close, 'call', _66 => _66()]);
2689
+ _optionalChain([bitmapRef, 'access', _65 => _65.current, 'optionalAccess', _66 => _66.close, 'call', _67 => _67()]);
2670
2690
  bitmapRef.current = null;
2671
2691
  };
2672
2692
  }, [url, size]);
@@ -2756,8 +2776,8 @@ function OverflowMenu({ items, "aria-label": ariaLabel = "More options" }) {
2756
2776
  if (!open) return;
2757
2777
  const onDown = (e) => {
2758
2778
  const node = e.target;
2759
- if (_optionalChain([triggerRef, 'access', _67 => _67.current, 'optionalAccess', _68 => _68.contains, 'call', _69 => _69(node)]) || _optionalChain([menuRef, 'access', _70 => _70.current, 'optionalAccess', _71 => _71.contains, 'call', _72 => _72(node)])) return;
2760
- if (_optionalChain([node, 'access', _73 => _73.closest, 'optionalCall', _74 => _74("[data-mr-portal]")])) return;
2779
+ if (_optionalChain([triggerRef, 'access', _68 => _68.current, 'optionalAccess', _69 => _69.contains, 'call', _70 => _70(node)]) || _optionalChain([menuRef, 'access', _71 => _71.current, 'optionalAccess', _72 => _72.contains, 'call', _73 => _73(node)])) return;
2780
+ if (_optionalChain([node, 'access', _74 => _74.closest, 'optionalCall', _75 => _75("[data-mr-portal]")])) return;
2761
2781
  close();
2762
2782
  };
2763
2783
  const onKey = (e) => {
@@ -2800,7 +2820,7 @@ function OverflowMenu({ items, "aria-label": ariaLabel = "More options" }) {
2800
2820
  "data-mr-portal": true,
2801
2821
  style: { top: coords.top, bottom: coords.bottom, right: coords.right },
2802
2822
  onClick: (e) => e.stopPropagation(),
2803
- children: _optionalChain([activeItem, 'optionalAccess', _75 => _75.subPanel]) ? /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "mr-overflow-subpanel", children: [
2823
+ children: _optionalChain([activeItem, 'optionalAccess', _76 => _76.subPanel]) ? /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "mr-overflow-subpanel", children: [
2804
2824
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "mr-overflow-subpanel__back", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
2805
2825
  "button",
2806
2826
  {
@@ -2825,7 +2845,7 @@ function OverflowMenu({ items, "aria-label": ariaLabel = "More options" }) {
2825
2845
  if (item.subPanel) {
2826
2846
  setActiveSubPanel(item.key);
2827
2847
  } else if (item.onSelect) {
2828
- const triggerRect = _nullishCoalesce(_optionalChain([triggerRef, 'access', _76 => _76.current, 'optionalAccess', _77 => _77.getBoundingClientRect, 'call', _78 => _78()]), () => ( new DOMRect()));
2848
+ const triggerRect = _nullishCoalesce(_optionalChain([triggerRef, 'access', _77 => _77.current, 'optionalAccess', _78 => _78.getBoundingClientRect, 'call', _79 => _79()]), () => ( new DOMRect()));
2829
2849
  close();
2830
2850
  item.onSelect(triggerRect);
2831
2851
  }
@@ -2953,8 +2973,8 @@ function AddToContextSubPanel({
2953
2973
  }
2954
2974
  const onDown = (e) => {
2955
2975
  const t = e.target;
2956
- if (_optionalChain([fieldRef, 'access', _79 => _79.current, 'optionalAccess', _80 => _80.contains, 'call', _81 => _81(t)]) || _optionalChain([dropRef, 'access', _82 => _82.current, 'optionalAccess', _83 => _83.contains, 'call', _84 => _84(t)])) return;
2957
- if (_optionalChain([t, 'access', _85 => _85.closest, 'optionalCall', _86 => _86("[data-mr-portal]")])) return;
2976
+ if (_optionalChain([fieldRef, 'access', _80 => _80.current, 'optionalAccess', _81 => _81.contains, 'call', _82 => _82(t)]) || _optionalChain([dropRef, 'access', _83 => _83.current, 'optionalAccess', _84 => _84.contains, 'call', _85 => _85(t)])) return;
2977
+ if (_optionalChain([t, 'access', _86 => _86.closest, 'optionalCall', _87 => _87("[data-mr-portal]")])) return;
2958
2978
  setDropPos(null);
2959
2979
  };
2960
2980
  document.addEventListener("mousedown", onDown);
@@ -2964,10 +2984,10 @@ function AddToContextSubPanel({
2964
2984
  if (!selected) return;
2965
2985
  try {
2966
2986
  await editRecord(recordId, { cases: [selected] });
2967
- _optionalChain([onToast, 'optionalCall', _87 => _87(`Moved to ${_nullishCoalesce(_optionalChain([selectedCase, 'optionalAccess', _88 => _88.name]), () => ( "care context"))}`, "success")]);
2987
+ _optionalChain([onToast, 'optionalCall', _88 => _88(`Moved to ${_nullishCoalesce(_optionalChain([selectedCase, 'optionalAccess', _89 => _89.name]), () => ( "care context"))}`, "success")]);
2968
2988
  onClose();
2969
2989
  } catch (e4) {
2970
- _optionalChain([onToast, 'optionalCall', _89 => _89("Failed to add to care context", "error")]);
2990
+ _optionalChain([onToast, 'optionalCall', _90 => _90("Failed to add to care context", "error")]);
2971
2991
  }
2972
2992
  };
2973
2993
  const handleCreate = async () => {
@@ -2978,10 +2998,10 @@ function AddToContextSubPanel({
2978
2998
  const occurred_at = newDate ? Math.floor((/* @__PURE__ */ new Date(newDate + "T00:00:00")).getTime() / 1e3) : void 0;
2979
2999
  const id = await createCase({ display_name: name, type: newType, occurred_at });
2980
3000
  await editRecord(recordId, { cases: [id] });
2981
- _optionalChain([onToast, 'optionalCall', _90 => _90(`Created and added to "${name}"`, "success")]);
3001
+ _optionalChain([onToast, 'optionalCall', _91 => _91(`Created and added to "${name}"`, "success")]);
2982
3002
  onClose();
2983
3003
  } catch (e5) {
2984
- _optionalChain([onToast, 'optionalCall', _91 => _91("Failed to create care context", "error")]);
3004
+ _optionalChain([onToast, 'optionalCall', _92 => _92("Failed to create care context", "error")]);
2985
3005
  } finally {
2986
3006
  setSaving(false);
2987
3007
  }
@@ -2997,7 +3017,7 @@ function AddToContextSubPanel({
2997
3017
  className: `mr-ctx-subpanel__field${dropOpen ? " mr-ctx-subpanel__field--open" : ""}`,
2998
3018
  onClick: () => dropOpen ? setDropPos(null) : openDrop(),
2999
3019
  children: [
3000
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: selectedCase ? "mr-ctx-subpanel__field-value" : "mr-ctx-subpanel__field-placeholder", children: _nullishCoalesce(_optionalChain([selectedCase, 'optionalAccess', _92 => _92.name]), () => ( "Search or select")) }),
3020
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: selectedCase ? "mr-ctx-subpanel__field-value" : "mr-ctx-subpanel__field-placeholder", children: _nullishCoalesce(_optionalChain([selectedCase, 'optionalAccess', _93 => _93.name]), () => ( "Search or select")) }),
3001
3021
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _lucidereact.ChevronsUpDown, { size: 16, "aria-hidden": true, className: "mr-ctx-subpanel__field-chevron" })
3002
3022
  ]
3003
3023
  }
@@ -3041,7 +3061,7 @@ function AddToContextSubPanel({
3041
3061
  }
3042
3062
  )
3043
3063
  ] }),
3044
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "ul", { className: "mr-ctx-subpanel__list", children: filtered.length === 0 ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "li", { className: "mr-ctx-subpanel__empty", children: "No cases found" }) : filtered.map((c) => {
3064
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "ul", { className: "mr-ctx-subpanel__list", children: filtered.length === 0 ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "li", { className: "mr-ctx-subpanel__empty text-center", children: "No cases found" }) : filtered.map((c) => {
3045
3065
  const isCurrent = linkedCaseIds.includes(c.id);
3046
3066
  return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "li", { children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
3047
3067
  "button",
@@ -3355,8 +3375,8 @@ function useRecordItem({ id, selectionMode, maxSelectable }) {
3355
3375
  const thumbnailUrl = useThumbnailUrl2(id);
3356
3376
  const pendingSelected = useIsSelected2(id);
3357
3377
  const pendingCount = _zustand.useStore.call(void 0, store, (s) => s.selection.recordIds.size);
3358
- const attachedCount = _nullishCoalesce(_optionalChain([attachedIds, 'optionalAccess', _93 => _93.size]), () => ( 0));
3359
- const attached = _nullishCoalesce(_optionalChain([attachedIds, 'optionalAccess', _94 => _94.has, 'call', _95 => _95(id)]), () => ( false));
3378
+ const attachedCount = _nullishCoalesce(_optionalChain([attachedIds, 'optionalAccess', _94 => _94.size]), () => ( 0));
3379
+ const attached = _nullishCoalesce(_optionalChain([attachedIds, 'optionalAccess', _95 => _95.has, 'call', _96 => _96(id)]), () => ( false));
3360
3380
  const checked = pendingSelected || attached;
3361
3381
  const attachDisabled = attachedCount >= maxSelectable && !attached;
3362
3382
  const selectDisabled = attachedCount + pendingCount >= maxSelectable && !checked;
@@ -3367,14 +3387,14 @@ function useRecordItem({ id, selectionMode, maxSelectable }) {
3367
3387
  );
3368
3388
  const handleSelect = _react.useCallback.call(void 0, () => {
3369
3389
  if (attached) {
3370
- void _optionalChain([onRemoveAttachment, 'optionalCall', _96 => _96(id)]);
3390
+ void _optionalChain([onRemoveAttachment, 'optionalCall', _97 => _97(id)]);
3371
3391
  } else {
3372
3392
  store.getState().selection.toggleRecord(id, pendingLimit);
3373
3393
  }
3374
3394
  }, [store, id, pendingLimit, attached, onRemoveAttachment]);
3375
3395
  const handleAddToContext = _react.useCallback.call(void 0, () => {
3376
3396
  if (attached) {
3377
- void _optionalChain([onRemoveAttachment, 'optionalCall', _97 => _97(id)]);
3397
+ void _optionalChain([onRemoveAttachment, 'optionalCall', _98 => _98(id)]);
3378
3398
  } else {
3379
3399
  const r = store.getState().records.byId[id];
3380
3400
  if (r && onAttachToContext) void onAttachToContext([{ documentId: id, name: r.title }]);
@@ -3404,7 +3424,7 @@ function useRecordItem({ id, selectionMode, maxSelectable }) {
3404
3424
  [store, id, bid, patientId, onCopyToNote]
3405
3425
  );
3406
3426
  const handleDelete = _react.useCallback.call(void 0, () => {
3407
- _optionalChain([onRequestDelete, 'optionalCall', _98 => _98(id)]);
3427
+ _optionalChain([onRequestDelete, 'optionalCall', _99 => _99(id)]);
3408
3428
  }, [onRequestDelete, id]);
3409
3429
  if (!record) return null;
3410
3430
  return {
@@ -3609,7 +3629,7 @@ function RecordsGrid({
3609
3629
  const headerRefs = _react.useRef.call(void 0, /* @__PURE__ */ new Map());
3610
3630
  _react.useEffect.call(void 0, () => {
3611
3631
  if (!scrollToKey) return;
3612
- _optionalChain([headerRefs, 'access', _99 => _99.current, 'access', _100 => _100.get, 'call', _101 => _101(scrollToKey), 'optionalAccess', _102 => _102.scrollIntoView, 'call', _103 => _103({ behavior: "smooth", block: "start" })]);
3632
+ _optionalChain([headerRefs, 'access', _100 => _100.current, 'access', _101 => _101.get, 'call', _102 => _102(scrollToKey), 'optionalAccess', _103 => _103.scrollIntoView, 'call', _104 => _104({ behavior: "smooth", block: "start" })]);
3613
3633
  }, [scrollToKey]);
3614
3634
  return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "mr-records-grid", children: sections.map((section, i) => {
3615
3635
  const showMonth = showMonths && (i === 0 || sections[i - 1].monthKey !== section.monthKey);
@@ -3910,12 +3930,12 @@ function RecordPreview({ recordId, onBack }) {
3910
3930
  const { attachedIds, onAttachToContext, onRemoveAttachment, onCopyToNote } = useRecordsActions();
3911
3931
  const [smartOpen, setSmartOpen] = _react.useState.call(void 0, true);
3912
3932
  if (!record) return null;
3913
- const attached = _nullishCoalesce(_optionalChain([attachedIds, 'optionalAccess', _104 => _104.has, 'call', _105 => _105(recordId)]), () => ( false));
3914
- const attachFull = !attached && (_nullishCoalesce(_optionalChain([attachedIds, 'optionalAccess', _106 => _106.size]), () => ( 0))) >= MAX_CONTEXT_ATTACHMENTS;
3933
+ const attached = _nullishCoalesce(_optionalChain([attachedIds, 'optionalAccess', _105 => _105.has, 'call', _106 => _106(recordId)]), () => ( false));
3934
+ const attachFull = !attached && (_nullishCoalesce(_optionalChain([attachedIds, 'optionalAccess', _107 => _107.size]), () => ( 0))) >= MAX_CONTEXT_ATTACHMENTS;
3915
3935
  const handleAttach = () => {
3916
3936
  if (attachFull) return;
3917
- if (attached) void _optionalChain([onRemoveAttachment, 'optionalCall', _107 => _107(recordId)]);
3918
- else void _optionalChain([onAttachToContext, 'optionalCall', _108 => _108([{ documentId: recordId, name: record.title }])]);
3937
+ if (attached) void _optionalChain([onRemoveAttachment, 'optionalCall', _108 => _108(recordId)]);
3938
+ else void _optionalChain([onAttachToContext, 'optionalCall', _109 => _109([{ documentId: recordId, name: record.title }])]);
3919
3939
  };
3920
3940
  return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "mr-record-preview", children: [
3921
3941
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "header", { className: "mr-record-preview__header", children: [
@@ -3943,13 +3963,13 @@ function RecordPreview({ recordId, onBack }) {
3943
3963
  children: "Show smart report"
3944
3964
  }
3945
3965
  ),
3946
- _optionalChain([record, 'access', _109 => _109.fileType, 'optionalAccess', _110 => _110.toUpperCase, 'call', _111 => _111()]) === "HTML" && onCopyToNote && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
3966
+ _optionalChain([record, 'access', _110 => _110.fileType, 'optionalAccess', _111 => _111.toUpperCase, 'call', _112 => _112()]) === "HTML" && onCopyToNote && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
3947
3967
  "button",
3948
3968
  {
3949
3969
  type: "button",
3950
3970
  className: "mr-record-preview__copy-btn",
3951
3971
  onClick: async (e) => {
3952
- const url = _optionalChain([preview, 'access', _112 => _112.files, 'access', _113 => _113[0], 'optionalAccess', _114 => _114.url]);
3972
+ const url = _optionalChain([preview, 'access', _113 => _113.files, 'access', _114 => _114[0], 'optionalAccess', _115 => _115.url]);
3953
3973
  if (!url) return;
3954
3974
  const res = await fetch(url);
3955
3975
  const html = await res.text();
@@ -3996,7 +4016,7 @@ function RecordPreview({ recordId, onBack }) {
3996
4016
  {
3997
4017
  files: preview.files,
3998
4018
  title: record.title,
3999
- isHtml: _optionalChain([record, 'access', _115 => _115.fileType, 'optionalAccess', _116 => _116.toUpperCase, 'call', _117 => _117()]) === "HTML"
4019
+ isHtml: _optionalChain([record, 'access', _116 => _116.fileType, 'optionalAccess', _117 => _117.toUpperCase, 'call', _118 => _118()]) === "HTML"
4000
4020
  }
4001
4021
  ) }),
4002
4022
  preview.hasSmartReport && smartOpen && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
@@ -4068,7 +4088,7 @@ function UploadModal({ onUpload, onError, onSuccess, onClose }) {
4068
4088
  }));
4069
4089
  onClose();
4070
4090
  void onUpload(items).then(() => {
4071
- _optionalChain([onSuccess, 'optionalCall', _118 => _118(items.length > 1 ? `${items.length} records uploaded` : "Record uploaded")]);
4091
+ _optionalChain([onSuccess, 'optionalCall', _119 => _119(items.length > 1 ? `${items.length} records uploaded` : "Record uploaded")]);
4072
4092
  }).catch((e) => {
4073
4093
  onError(e instanceof Error ? e.message : "Upload failed. Please try again.");
4074
4094
  });
@@ -4076,7 +4096,7 @@ function UploadModal({ onUpload, onError, onSuccess, onClose }) {
4076
4096
  const onDrop = (e) => {
4077
4097
  e.preventDefault();
4078
4098
  setDragging(false);
4079
- if (_optionalChain([e, 'access', _119 => _119.dataTransfer, 'access', _120 => _120.files, 'optionalAccess', _121 => _121.length])) addFiles(e.dataTransfer.files);
4099
+ if (_optionalChain([e, 'access', _120 => _120.dataTransfer, 'access', _121 => _121.files, 'optionalAccess', _122 => _122.length])) addFiles(e.dataTransfer.files);
4080
4100
  };
4081
4101
  return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "mr-upload-modal", role: "presentation", onClick: onClose, children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
4082
4102
  "div",
@@ -4102,7 +4122,7 @@ function UploadModal({ onUpload, onError, onSuccess, onClose }) {
4102
4122
  ] }),
4103
4123
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "button", { type: "button", className: "mr-upload-modal__close", "aria-label": "Close", onClick: onClose, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _lucidereact.X, { size: 18, "aria-hidden": true }) })
4104
4124
  ] }),
4105
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "button", { type: "button", className: "mr-upload-dropzone", onClick: () => _optionalChain([inputRef, 'access', _122 => _122.current, 'optionalAccess', _123 => _123.click, 'call', _124 => _124()]), children: [
4125
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "button", { type: "button", className: "mr-upload-dropzone", onClick: () => _optionalChain([inputRef, 'access', _123 => _123.current, 'optionalAccess', _124 => _124.click, 'call', _125 => _125()]), children: [
4106
4126
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "mr-upload-dropzone__icon", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _lucidereact.Upload, { size: 20, "aria-hidden": true }) }),
4107
4127
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "mr-upload-dropzone__title", children: "Drop files here or click to browse" }),
4108
4128
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "mr-upload-dropzone__hint", children: "PDF, JPG, PNG \xB7 up to 25 MB each \xB7 multiple files supported" })
@@ -4243,7 +4263,7 @@ function useRecordSections(tab, ids) {
4243
4263
  return caseIds.map((caseId) => {
4244
4264
  const c = casesById[caseId];
4245
4265
  if (!c) return null;
4246
- const recordIds = ids.filter((id) => _optionalChain([byId, 'access', _125 => _125[id], 'optionalAccess', _126 => _126.cases, 'access', _127 => _127.includes, 'call', _128 => _128(caseId)]));
4266
+ const recordIds = ids.filter((id) => _optionalChain([byId, 'access', _126 => _126[id], 'optionalAccess', _127 => _127.cases, 'access', _128 => _128.includes, 'call', _129 => _129(caseId)]));
4247
4267
  const type = (_nullishCoalesce(c.typeCode, () => ( ""))).toUpperCase();
4248
4268
  return {
4249
4269
  key: caseId,
@@ -4320,14 +4340,15 @@ function useSectionPages(tab, sections, page) {
4320
4340
  // src/views/RecordsView/useRecordsView.ts
4321
4341
  function useRecordsView({
4322
4342
  onUpload,
4323
- allowUpload = true,
4324
4343
  onCopyToNote,
4325
4344
  attachedIds,
4326
4345
  onAttachManyToContext,
4327
4346
  onRemoveAttachment,
4328
4347
  onToast
4329
4348
  }) {
4330
- const { store, labelOf } = useSdk();
4349
+ const { store, labelOf, environment } = useSdk();
4350
+ const denialList = useDenialList(environment);
4351
+ const allowUpload = !denialList.includes("UPLOAD_MEDICAL_RECORDS");
4331
4352
  const { refresh, sourceRefreshedAt, deleteRecord } = useRecordsConnection();
4332
4353
  const { upload } = useUploadConnection();
4333
4354
  const status = useRecordsStatus2();
@@ -4405,7 +4426,7 @@ function useRecordsView({
4405
4426
  if (records.length && onAttachManyToContext) void onAttachManyToContext(records);
4406
4427
  }, [store, onAttachManyToContext]);
4407
4428
  const openUpload = _react.useCallback.call(void 0, () => {
4408
- _optionalChain([onUpload, 'optionalCall', _129 => _129()]);
4429
+ _optionalChain([onUpload, 'optionalCall', _130 => _130()]);
4409
4430
  setUploadOpen(true);
4410
4431
  }, [onUpload]);
4411
4432
  const requestDelete = _react.useCallback.call(void 0, (id) => setDeleteTargetId(id), []);
@@ -4418,11 +4439,11 @@ function useRecordsView({
4418
4439
  setDeleting(true);
4419
4440
  try {
4420
4441
  await deleteRecord(deleteTargetId);
4421
- _optionalChain([onToast, 'optionalCall', _130 => _130(`${_nullishCoalesce(_optionalChain([target, 'optionalAccess', _131 => _131.title]), () => ( "Record"))} deleted`, "success")]);
4442
+ _optionalChain([onToast, 'optionalCall', _131 => _131(`${_nullishCoalesce(_optionalChain([target, 'optionalAccess', _132 => _132.title]), () => ( "Record"))} deleted`, "success")]);
4422
4443
  setDeleteTargetId(null);
4423
4444
  } catch (e) {
4424
4445
  const msg = e instanceof Error ? e.message : "Delete failed";
4425
- _optionalChain([onToast, 'optionalCall', _132 => _132(`Could not delete record. ${msg}`, "error")]);
4446
+ _optionalChain([onToast, 'optionalCall', _133 => _133(`Could not delete record. ${msg}`, "error")]);
4426
4447
  } finally {
4427
4448
  setDeleting(false);
4428
4449
  }
@@ -4499,7 +4520,6 @@ var MAX_CONTEXT_ATTACHMENTS = 1;
4499
4520
  function RecordsView({
4500
4521
  className,
4501
4522
  onUpload,
4502
- allowUpload = true,
4503
4523
  onCopyToNote,
4504
4524
  attachedIds,
4505
4525
  onAttachManyToContext,
@@ -4533,6 +4553,7 @@ function RecordsView({
4533
4553
  refresh,
4534
4554
  sourceRefreshedAt,
4535
4555
  actions,
4556
+ allowUpload,
4536
4557
  handleTabChange,
4537
4558
  handleSelectSection,
4538
4559
  handleToggleSelectionMode,
@@ -4544,7 +4565,6 @@ function RecordsView({
4544
4565
  setPage
4545
4566
  } = useRecordsView({
4546
4567
  onUpload,
4547
- allowUpload,
4548
4568
  onCopyToNote,
4549
4569
  attachedIds,
4550
4570
  onAttachManyToContext,
@@ -4561,8 +4581,8 @@ function RecordsView({
4561
4581
  UploadModal,
4562
4582
  {
4563
4583
  onUpload: upload,
4564
- onError: (msg) => _optionalChain([onToast, 'optionalCall', _133 => _133(msg, "error")]),
4565
- onSuccess: (msg) => _optionalChain([onToast, 'optionalCall', _134 => _134(msg, "success")]),
4584
+ onError: (msg) => _optionalChain([onToast, 'optionalCall', _134 => _134(msg, "error")]),
4585
+ onSuccess: (msg) => _optionalChain([onToast, 'optionalCall', _135 => _135(msg, "success")]),
4566
4586
  onClose: () => setUploadOpen(false)
4567
4587
  }
4568
4588
  )
@@ -4656,8 +4676,8 @@ function RecordsView({
4656
4676
  UploadModal,
4657
4677
  {
4658
4678
  onUpload: upload,
4659
- onError: (msg) => _optionalChain([onToast, 'optionalCall', _135 => _135(msg, "error")]),
4660
- onSuccess: (msg) => _optionalChain([onToast, 'optionalCall', _136 => _136(msg, "success")]),
4679
+ onError: (msg) => _optionalChain([onToast, 'optionalCall', _136 => _136(msg, "error")]),
4680
+ onSuccess: (msg) => _optionalChain([onToast, 'optionalCall', _137 => _137(msg, "success")]),
4661
4681
  onClose: () => setUploadOpen(false)
4662
4682
  }
4663
4683
  )