@broberg/bodymap 0.2.3 → 0.2.5

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/three.d.ts CHANGED
@@ -49,6 +49,28 @@ interface BodymapPalette {
49
49
  };
50
50
  /** Optional per-region base-colour overrides (region key → colour). */
51
51
  regions?: Record<string, string>;
52
+ /**
53
+ * Optional panel-chrome colours (the selection panel, labels, hint box) —
54
+ * NOT the body itself. All optional; anything omitted falls back to
55
+ * {@link defaultUi}. A palette that only themed the body was half a palette:
56
+ * a consumer passing brand colours still got hardcoded chrome. (F052.19)
57
+ */
58
+ ui?: BodymapUiColors;
59
+ }
60
+ /** Panel-chrome colours. Every default is WCAG-AA (>=4.5:1) on its own background. */
61
+ interface BodymapUiColors {
62
+ /** Primary text (headings, values). */
63
+ text?: string;
64
+ /** Secondary text — section labels, the empty-state hint. */
65
+ mutedText?: string;
66
+ /** Panel background. */
67
+ panelBg?: string;
68
+ /** Panel + control borders. */
69
+ border?: string;
70
+ /** Background behind the region-code badge. */
71
+ badgeBg?: string;
72
+ /** The destructive action (remove a marked region). */
73
+ danger?: string;
52
74
  }
53
75
  type BodyView = "front" | "back" | "left" | "right";
54
76
  /** Side in the serialized report — a midline region (no side) becomes "center". */
@@ -141,6 +163,10 @@ interface BodyMap3DProps {
141
163
  * shorter value on narrow viewports so the picker panel below the body stays visible
142
164
  * the moment a region is selected (no full-screen scroll). */
143
165
  canvasHeight?: string | number;
166
+ /** Show the clinical region-code badge (e.g. "HIP · right") in the panel header
167
+ * (default true). Set false for a patient/employee-facing flow where the code is
168
+ * internal jargon and the readable region name is enough. */
169
+ showRegionCode?: boolean;
144
170
  className?: string;
145
171
  }
146
172
  declare function BodyMap3D(props: BodyMap3DProps): react.JSX.Element;
package/dist/three.js CHANGED
@@ -58,6 +58,17 @@ function isSelectable(key, config = {}) {
58
58
  if (s?.visible === false) return false;
59
59
  return s?.selectable ?? true;
60
60
  }
61
+ var defaultUi = {
62
+ text: "#1e293b",
63
+ mutedText: "#475569",
64
+ panelBg: "#fff",
65
+ border: "#e2e8f0",
66
+ badgeBg: "#f1f5f9",
67
+ danger: "#dc2626"
68
+ };
69
+ function uiColors(palette) {
70
+ return { ...defaultUi, ...palette?.ui ?? {} };
71
+ }
61
72
  var defaultPalette = {
62
73
  body: "#d2d7de",
63
74
  hover: "#8fd0cd",
@@ -238,8 +249,10 @@ function BodyMap3D(props) {
238
249
  onSexChange,
239
250
  autoRotate = true,
240
251
  canvasHeight = "60vh",
252
+ showRegionCode = true,
241
253
  className
242
254
  } = props;
255
+ const chrome = uiColors(palette);
243
256
  const L = mergeLabels(locale, labels);
244
257
  const UI = { ...locale === "en" ? UI_EN : UI_DA, ...ui };
245
258
  const nameOf = (key) => L.regions[key] ?? getRegion(key)?.label ?? key;
@@ -539,20 +552,20 @@ function BodyMap3D(props) {
539
552
  ready && /* @__PURE__ */ jsx("span", { "data-testid": "bodymap3d-ready", style: { position: "absolute", width: 1, height: 1, opacity: 0, pointerEvents: "none" } }),
540
553
  /* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: 18, alignItems: "flex-start", flexWrap: "wrap" }, children: [
541
554
  unsupported ? /* @__PURE__ */ jsx("div", { "data-testid": "bodymap3d-unsupported", style: { flex: "1 1 520px", minWidth: 320, height: canvasH, borderRadius: 16, background: "#0e1424", color: "#cbd5e1", display: "flex", alignItems: "center", justifyContent: "center", padding: 24, textAlign: "center", fontSize: 14 }, children: "3D kr\xE6ver WebGL, som ikke er tilg\xE6ngeligt her." }) : /* @__PURE__ */ jsx("div", { ref: mountRef, "data-testid": "bodymap3d-canvas", style: { flex: "1 1 520px", height: canvasH, minWidth: 320, borderRadius: 16, overflow: "hidden", background: "#0e1424", touchAction: "none" } }),
542
- /* @__PURE__ */ jsx("div", { style: { flex: "1 1 300px", minWidth: 260 }, children: region ? /* @__PURE__ */ jsxs("div", { style: { border: "1px solid #e2e8f0", borderRadius: 14, padding: 16, background: "#fff" }, children: [
555
+ /* @__PURE__ */ jsx("div", { style: { flex: "1 1 300px", minWidth: 260 }, children: region ? /* @__PURE__ */ jsxs("div", { style: { border: `1px solid ${chrome.border}`, borderRadius: 14, padding: 16, background: chrome.panelBg }, children: [
543
556
  /* @__PURE__ */ jsxs("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 12 }, children: [
544
557
  /* @__PURE__ */ jsx("b", { style: { fontSize: 16 }, children: nameOf(region.key) }),
545
- /* @__PURE__ */ jsxs("span", { style: { font: "11px ui-monospace, monospace", color: "#64748b", background: "#f1f5f9", borderRadius: 6, padding: "2px 7px" }, children: [
558
+ showRegionCode && /* @__PURE__ */ jsxs("span", { "data-testid": "bodymap3d-region-code", style: { font: "11px ui-monospace, monospace", color: chrome.mutedText, background: chrome.badgeBg, borderRadius: 6, padding: "2px 7px" }, children: [
546
559
  region.code,
547
560
  region.side ? " \xB7 " + region.side : ""
548
561
  ] })
549
562
  ] }),
550
- /* @__PURE__ */ jsx("div", { style: { fontSize: 11, fontWeight: 700, letterSpacing: ".06em", textTransform: "uppercase", color: "#94a3b8", marginBottom: 7 }, children: L.intensity }),
563
+ /* @__PURE__ */ jsx("div", { style: { fontSize: 11, fontWeight: 700, letterSpacing: ".06em", textTransform: "uppercase", color: chrome.mutedText, marginBottom: 7 }, children: L.intensity }),
551
564
  /* @__PURE__ */ jsx("div", { style: { display: "flex", flexWrap: "wrap", gap: 4, marginBottom: 12 }, children: Array.from({ length: 11 }, (_, i) => /* @__PURE__ */ jsx("button", { "data-testid": `bodymap3d-intensity-${i}`, onClick: () => setPain(region.key, i, current?.type), style: { ...btn, display: "inline-flex", alignItems: "center", justifyContent: "center", minWidth: 30, height: 30, padding: 0, background: current?.intensity === i ? "#0e8f8a" : "#fff", color: current?.intensity === i ? "#fff" : "#1e293b" }, children: i }, i)) }),
552
- /* @__PURE__ */ jsx("div", { style: { fontSize: 11, fontWeight: 700, letterSpacing: ".06em", textTransform: "uppercase", color: "#94a3b8", marginBottom: 7 }, children: L.quality }),
565
+ /* @__PURE__ */ jsx("div", { style: { fontSize: 11, fontWeight: 700, letterSpacing: ".06em", textTransform: "uppercase", color: chrome.mutedText, marginBottom: 7 }, children: L.quality }),
553
566
  /* @__PURE__ */ jsx("div", { style: { display: "flex", flexWrap: "wrap", gap: 6, marginBottom: 14 }, children: PAIN_TYPES.map((t) => /* @__PURE__ */ jsx("button", { "data-testid": `bodymap3d-type-${t}`, onClick: () => setPain(region.key, current?.intensity ?? 5, t), style: { ...btn, borderRadius: 999, padding: "6px 12px", background: current?.type === t ? "#1e293b" : "#fff", color: current?.type === t ? "#fff" : "#64748b" }, children: L.qualities[t] ?? t }, t)) }),
554
- current && /* @__PURE__ */ jsx("button", { "data-testid": "bodymap3d-remove", onClick: () => removePain(region.key), style: { ...btn, color: "#ef4444", borderColor: "#f6c9c9" }, children: L.remove })
555
- ] }) : showEmptyHint ? /* @__PURE__ */ jsx("div", { "data-testid": "bodymap3d-empty", style: { border: "1px solid #e2e8f0", borderRadius: 14, padding: 16, background: "#fff", color: "#94a3b8", fontSize: 13.5 }, children: UI.hoverHint }) : null })
567
+ current && /* @__PURE__ */ jsx("button", { "data-testid": "bodymap3d-remove", onClick: () => removePain(region.key), style: { ...btn, color: chrome.danger, borderColor: "#f6c9c9" }, children: L.remove })
568
+ ] }) : showEmptyHint ? /* @__PURE__ */ jsx("div", { "data-testid": "bodymap3d-empty", style: { border: `1px solid ${chrome.border}`, borderRadius: 14, padding: 16, background: chrome.panelBg, color: chrome.mutedText, fontSize: 13.5 }, children: UI.hoverHint }) : null })
556
569
  ] })
557
570
  ] });
558
571
  }