@broberg/bodymap 0.2.0 → 0.2.2

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.cts CHANGED
@@ -131,6 +131,10 @@ interface BodyMap3DProps {
131
131
  ui?: Partial<BodyMap3DUiLabels>;
132
132
  defaultSex?: BodyMap3DSex;
133
133
  onSexChange?: (sex: BodyMap3DSex) => void;
134
+ /** Controlled body type — when set, the parent owns it (e.g. from the user's profile); `onSexChange` still fires. */
135
+ sex?: BodyMap3DSex;
136
+ /** Show the Male/Female toggle (default true). Set false when `sex` comes from a profile and the picker would just be noise. */
137
+ showSexToggle?: boolean;
134
138
  /** Slowly auto-rotate until the user interacts (default true). */
135
139
  autoRotate?: boolean;
136
140
  className?: string;
package/dist/three.d.ts CHANGED
@@ -131,6 +131,10 @@ interface BodyMap3DProps {
131
131
  ui?: Partial<BodyMap3DUiLabels>;
132
132
  defaultSex?: BodyMap3DSex;
133
133
  onSexChange?: (sex: BodyMap3DSex) => void;
134
+ /** Controlled body type — when set, the parent owns it (e.g. from the user's profile); `onSexChange` still fires. */
135
+ sex?: BodyMap3DSex;
136
+ /** Show the Male/Female toggle (default true). Set false when `sex` comes from a profile and the picker would just be noise. */
137
+ showSexToggle?: boolean;
134
138
  /** Slowly auto-rotate until the user interacts (default true). */
135
139
  autoRotate?: boolean;
136
140
  className?: string;
package/dist/three.js CHANGED
@@ -233,6 +233,8 @@ function BodyMap3D(props) {
233
233
  labels,
234
234
  ui,
235
235
  defaultSex = "male",
236
+ sex: sexProp,
237
+ showSexToggle = true,
236
238
  onSexChange,
237
239
  autoRotate = true,
238
240
  className
@@ -244,7 +246,8 @@ function BodyMap3D(props) {
244
246
  const loadedRef = useRef(null);
245
247
  const [unsupported, setUnsupported] = useState(false);
246
248
  const [ready, setReady] = useState(false);
247
- const [sex, setSex] = useState(defaultSex);
249
+ const [internalSex, setInternalSex] = useState(defaultSex);
250
+ const sex = sexProp ?? internalSex;
248
251
  const [selected, setSelected] = useState(null);
249
252
  const [internal, setInternal] = useState(defaultValue ?? []);
250
253
  const report = value ?? internal;
@@ -262,6 +265,8 @@ function BodyMap3D(props) {
262
265
  configRef.current = config;
263
266
  const modelsRef = useRef(models);
264
267
  modelsRef.current = models;
268
+ const sexRef = useRef(sex);
269
+ sexRef.current = sex;
265
270
  const setSelectedRef = useRef(setSelected);
266
271
  setSelectedRef.current = setSelected;
267
272
  const setReadyRef = useRef(setReady);
@@ -407,7 +412,7 @@ function BodyMap3D(props) {
407
412
  }
408
413
  });
409
414
  };
410
- loadModel(defaultSex);
415
+ loadModel(sexRef.current);
411
416
  apiRef.current = {
412
417
  setSex: (s) => {
413
418
  loadedRef.current?.removeAttribute("data-loaded");
@@ -499,7 +504,12 @@ function BodyMap3D(props) {
499
504
  useEffect(() => {
500
505
  apiRef.current?.refresh();
501
506
  }, [selected, report, palette]);
507
+ const sexInited = useRef(false);
502
508
  useEffect(() => {
509
+ if (!sexInited.current) {
510
+ sexInited.current = true;
511
+ return;
512
+ }
503
513
  apiRef.current?.setSex(sex);
504
514
  }, [sex]);
505
515
  const pointOf = (k) => report.find((p) => p.region === k);
@@ -511,13 +521,15 @@ function BodyMap3D(props) {
511
521
  setSelected(null);
512
522
  };
513
523
  const changeSex = (s) => {
514
- setSex(s);
524
+ if (sexProp === void 0) setInternalSex(s);
515
525
  onSexChange?.(s);
516
526
  };
517
527
  const region = selected ? REGIONS.find((r) => r.key === selected) : null;
518
528
  const current = selected ? pointOf(selected) : void 0;
529
+ const anySelectable = REGIONS.some((r) => isSelectable(r.key, config ?? {}));
530
+ const showEmptyHint = anySelectable || ui?.hoverHint !== void 0;
519
531
  return /* @__PURE__ */ jsxs("div", { "data-testid": "bodymap3d-root", className, style: { fontFamily: "system-ui, sans-serif", color: "#1e293b" }, children: [
520
- /* @__PURE__ */ jsx("div", { style: { display: "flex", gap: 16, flexWrap: "wrap", marginBottom: 12, fontSize: 13 }, children: /* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: 6, alignItems: "center" }, children: [
532
+ showSexToggle && /* @__PURE__ */ jsx("div", { style: { display: "flex", gap: 16, flexWrap: "wrap", marginBottom: 12, fontSize: 13 }, children: /* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: 6, alignItems: "center" }, children: [
521
533
  /* @__PURE__ */ jsx("button", { "data-testid": "bodymap3d-sex-male", onClick: () => changeSex("male"), style: seg(sex === "male"), children: UI.male }),
522
534
  /* @__PURE__ */ jsx("button", { "data-testid": "bodymap3d-sex-female", onClick: () => changeSex("female"), style: seg(sex === "female"), children: UI.female })
523
535
  ] }) }),
@@ -538,7 +550,7 @@ function BodyMap3D(props) {
538
550
  /* @__PURE__ */ jsx("div", { style: { fontSize: 11, fontWeight: 700, letterSpacing: ".06em", textTransform: "uppercase", color: "#94a3b8", marginBottom: 7 }, children: L.quality }),
539
551
  /* @__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)) }),
540
552
  current && /* @__PURE__ */ jsx("button", { "data-testid": "bodymap3d-remove", onClick: () => removePain(region.key), style: { ...btn, color: "#ef4444", borderColor: "#f6c9c9" }, children: L.remove })
541
- ] }) : /* @__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 }) })
553
+ ] }) : 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 })
542
554
  ] })
543
555
  ] });
544
556
  }