@broberg/bodymap 0.9.0 → 0.10.0

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/README.md CHANGED
@@ -382,6 +382,34 @@ is invisible on a desktop monitor and obvious on a phone.
382
382
 
383
383
  3D only — the 2D renderer has no canvas and no fullscreen, so it ignores it.
384
384
 
385
+ ### `hint` — turn the help note off, or move it (0.10.0)
386
+
387
+ ```tsx
388
+ <BodyMap3D hint={false} /> // don't show it
389
+ <BodyMap3D hint={{ text: "…", placement: "stage-bottom" }} /> // yours, pinned in the stage
390
+ ```
391
+
392
+ **`hint={false}` is the "do not show this" that did not exist.** `ui.hoverHint`
393
+ only ever changed the *text*, and setting it to `""` produced an empty bordered
394
+ box — worse than the sentence. `ui.hoverHint` still works and is not deprecated;
395
+ `hint.text` is simply the newer way to say the same thing.
396
+
397
+ **`placement: "stage-bottom"` fixes a real clipping bug rather than moving it.**
398
+ The note sits in normal flow in the panel column. In fullscreen the canvas takes
399
+ the full height, that column wraps beneath it, and the note lands past the bottom
400
+ edge — measured on a real iPhone at **858–912 in an 852px window**, entirely
401
+ offscreen. `stage-bottom` pins it inside the fullscreen surface, clear of the home
402
+ indicator. Outside fullscreen it stays where it was, because there the flow
403
+ position is right.
404
+
405
+ You cannot make that call in CSS without knowing our internal structure, which is
406
+ why the prop exists.
407
+
408
+ ⚠️ **The default text changed in 0.10.0.** It said *"Hover to highlight"* —
409
+ describing an interaction that does not exist on a touchscreen, on a component
410
+ whose primary surface is a phone. Now *"Drag to rotate · tap a body part to mark
411
+ pain."*
412
+
385
413
  ### `ui.accent` — the controls read your palette now (0.9.0)
386
414
 
387
415
  Until 0.9.0 the buttons carried their colours inline, so a consumer palette
package/dist/three.cjs CHANGED
@@ -234,8 +234,8 @@ var LABELS_EN = {
234
234
  zoomOut: "Zoom out",
235
235
  zoomReset: "Reset zoom"
236
236
  };
237
- var UI_DA = { male: "Mand", female: "Kvinde", hoverHint: "Hover for at fremh\xE6ve \xB7 klik en kropsdel for at markere smerte.", expand: "Vis stor", collapse: "Luk stor visning" };
238
- var UI_EN = { male: "Male", female: "Female", hoverHint: "Hover to highlight \xB7 tap a body part to mark pain.", expand: "Expand", collapse: "Close" };
237
+ var UI_DA = { male: "Mand", female: "Kvinde", hoverHint: "Tr\xE6k for at dreje \xB7 tryk en kropsdel for at markere smerte.", expand: "Vis stor", collapse: "Luk stor visning" };
238
+ var UI_EN = { male: "Male", female: "Female", hoverHint: "Drag to rotate \xB7 tap a body part to mark pain.", expand: "Expand", collapse: "Close" };
239
239
  var ANCHORS = {
240
240
  head: [0, 1.79, 0.02],
241
241
  neck: [0, 1.57, 0],
@@ -342,6 +342,7 @@ function BodyMap3D(props) {
342
342
  onFeedback,
343
343
  haptics,
344
344
  seam = false,
345
+ hint,
345
346
  fullscreen: fullscreenProp,
346
347
  onFullscreenChange,
347
348
  showFullscreenButton = true,
@@ -701,7 +702,9 @@ function BodyMap3D(props) {
701
702
  const region = selected ? REGIONS.find((r) => r.key === selected) : null;
702
703
  const current = selected ? pointOf(selected) : void 0;
703
704
  const anySelectable = REGIONS.some((r) => isSelectable(r.key, config ?? {}));
704
- const showEmptyHint = anySelectable || ui?.hoverHint !== void 0;
705
+ const showEmptyHint = hint === false ? false : anySelectable || ui?.hoverHint !== void 0;
706
+ const hintText = (hint ? hint.text : void 0) ?? UI.hoverHint;
707
+ const hintAtStage = isFullscreen && !!hint && hint.placement === "stage-bottom";
705
708
  return /* @__PURE__ */ jsxRuntime.jsxs(
706
709
  "div",
707
710
  {
@@ -817,8 +820,33 @@ function BodyMap3D(props) {
817
820
  /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: 11, fontWeight: 700, letterSpacing: ".06em", textTransform: "uppercase", color: chrome.mutedText, marginBottom: 7 }, children: L.quality }),
818
821
  /* @__PURE__ */ jsxRuntime.jsx("div", { style: { display: "flex", flexWrap: "wrap", gap: 6, marginBottom: 14 }, children: PAIN_TYPES.map((t) => /* @__PURE__ */ jsxRuntime.jsx("button", { "data-testid": `bodymap3d-type-${t}`, onClick: () => setPain(region.key, current?.intensity ?? 5, t), style: { ...btn(chrome), borderRadius: 999, padding: "6px 12px", background: current?.type === t ? chrome.text : chrome.panelBg, color: current?.type === t ? chrome.panelBg : chrome.mutedText }, children: L.qualities[t] ?? t }, t)) }),
819
822
  current && /* @__PURE__ */ jsxRuntime.jsx("button", { "data-testid": "bodymap3d-remove", onClick: () => removePain(region.key), style: { ...btn(chrome), color: chrome.danger, borderColor: chrome.dangerBorder }, children: L.remove })
820
- ] }) : showEmptyHint ? /* @__PURE__ */ jsxRuntime.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 })
821
- ] })
823
+ ] }) : showEmptyHint && !hintAtStage ? /* @__PURE__ */ jsxRuntime.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: hintText }) : null })
824
+ ] }),
825
+ showEmptyHint && hintAtStage && /* F052.31 — pinned INSIDE the fullscreen surface, not in the column that
826
+ wraps beneath a full-height canvas. That wrap is what put the note at
827
+ 858-912 in an 852px window on a real iPhone: entirely offscreen, and
828
+ it reads as a bug in the consumer's app rather than in ours.
829
+ The bottom inset clears the home indicator, exactly as the exit
830
+ control's does (F052.27). */
831
+ /* @__PURE__ */ jsxRuntime.jsx(
832
+ "div",
833
+ {
834
+ "data-testid": "bodymap3d-empty",
835
+ "data-placement": "stage-bottom",
836
+ style: {
837
+ flex: "0 0 auto",
838
+ marginTop: 12,
839
+ marginBottom: "env(safe-area-inset-bottom)",
840
+ border: `1px solid ${chrome.border}`,
841
+ borderRadius: 14,
842
+ padding: 16,
843
+ background: chrome.panelBg,
844
+ color: chrome.mutedText,
845
+ fontSize: 13.5
846
+ },
847
+ children: hintText
848
+ }
849
+ )
822
850
  ]
823
851
  }
824
852
  );