@broberg/bodymap 0.10.0 → 0.12.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 +17 -0
- package/dist/three.cjs +34 -6
- package/dist/three.cjs.map +1 -1
- package/dist/three.d.cts +71 -1
- package/dist/three.d.ts +71 -1
- package/dist/three.js +31 -7
- package/dist/three.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -382,6 +382,23 @@ 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
|
+
### A slow tap is still a tap (0.11.0)
|
|
386
|
+
|
|
387
|
+
Until 0.11.0 a press held longer than **450 ms** was discarded — silently. No
|
|
388
|
+
pick, no clear, no `onFeedback`, no repaint.
|
|
389
|
+
|
|
390
|
+
Distance already separates a tap from a drag: a drag moves. The time ceiling did
|
|
391
|
+
not help with that; what it did was rule that a **slow** press is not a tap. And a
|
|
392
|
+
slow press is exactly what a **careful** tap is — aiming at a small body part on a
|
|
393
|
+
phone, at a mark you are trying to hit again, takes longer than a casual poke.
|
|
394
|
+
|
|
395
|
+
The owner reported it twice, as *"the remove button is gone"* and as *"the sound
|
|
396
|
+
doesn't work"*. Both were the same swallowed tap, and each was explained away
|
|
397
|
+
separately. **A tap that is silently discarded is indistinguishable from a broken
|
|
398
|
+
component.**
|
|
399
|
+
|
|
400
|
+
`isTap(dx, dy)` is exported if you need the same rule.
|
|
401
|
+
|
|
385
402
|
### `hint` — turn the help note off, or move it (0.10.0)
|
|
386
403
|
|
|
387
404
|
```tsx
|
package/dist/three.cjs
CHANGED
|
@@ -282,6 +282,10 @@ function seamBlend(nearestSq, secondSq) {
|
|
|
282
282
|
function seamWeight(seamEnabled, blend) {
|
|
283
283
|
return seamEnabled ? blend : 0;
|
|
284
284
|
}
|
|
285
|
+
function isTap(dx, dy, maxDistance = TAP_MAX_DISTANCE) {
|
|
286
|
+
return Math.hypot(dx, dy) <= maxDistance;
|
|
287
|
+
}
|
|
288
|
+
var TAP_MAX_DISTANCE = 6;
|
|
285
289
|
function ensureNormals(geo) {
|
|
286
290
|
if (geo.getAttribute("normal")) return false;
|
|
287
291
|
geo.computeVertexNormals();
|
|
@@ -307,6 +311,12 @@ function webglAvailable() {
|
|
|
307
311
|
return false;
|
|
308
312
|
}
|
|
309
313
|
}
|
|
314
|
+
var INTENSITY_SIZE = 46;
|
|
315
|
+
function shouldShowHint(opts) {
|
|
316
|
+
if (opts.openRegion) return false;
|
|
317
|
+
if (opts.hint === false) return false;
|
|
318
|
+
return opts.anySelectable || opts.hasExplicitHoverHint;
|
|
319
|
+
}
|
|
310
320
|
var btn = (c) => ({
|
|
311
321
|
font: "inherit",
|
|
312
322
|
cursor: "pointer",
|
|
@@ -595,12 +605,11 @@ function BodyMap3D(props) {
|
|
|
595
605
|
}
|
|
596
606
|
return best;
|
|
597
607
|
};
|
|
598
|
-
let downX = 0, downY = 0
|
|
608
|
+
let downX = 0, downY = 0;
|
|
599
609
|
const canvas = renderer.domElement;
|
|
600
610
|
const onDown = (e) => {
|
|
601
611
|
downX = e.clientX;
|
|
602
612
|
downY = e.clientY;
|
|
603
|
-
downT = Date.now();
|
|
604
613
|
};
|
|
605
614
|
const onMove = (e) => {
|
|
606
615
|
if ((e.buttons || 0) !== 0) return;
|
|
@@ -612,7 +621,7 @@ function BodyMap3D(props) {
|
|
|
612
621
|
renderFrame();
|
|
613
622
|
};
|
|
614
623
|
const onUp = (e) => {
|
|
615
|
-
if (
|
|
624
|
+
if (!isTap(e.clientX - downX, e.clientY - downY)) return;
|
|
616
625
|
const k = pick(e.clientX, e.clientY);
|
|
617
626
|
if (!k) return;
|
|
618
627
|
const outcome = pickRef.current(k);
|
|
@@ -702,7 +711,12 @@ function BodyMap3D(props) {
|
|
|
702
711
|
const region = selected ? REGIONS.find((r) => r.key === selected) : null;
|
|
703
712
|
const current = selected ? pointOf(selected) : void 0;
|
|
704
713
|
const anySelectable = REGIONS.some((r) => isSelectable(r.key, config ?? {}));
|
|
705
|
-
const showEmptyHint =
|
|
714
|
+
const showEmptyHint = shouldShowHint({
|
|
715
|
+
openRegion: selected,
|
|
716
|
+
hint,
|
|
717
|
+
anySelectable,
|
|
718
|
+
hasExplicitHoverHint: ui?.hoverHint !== void 0
|
|
719
|
+
});
|
|
706
720
|
const hintText = (hint ? hint.text : void 0) ?? UI.hoverHint;
|
|
707
721
|
const hintAtStage = isFullscreen && !!hint && hint.placement === "stage-bottom";
|
|
708
722
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -810,13 +824,23 @@ function BodyMap3D(props) {
|
|
|
810
824
|
"data-testid": "bodymap3d-close",
|
|
811
825
|
"aria-label": L.close,
|
|
812
826
|
onClick: () => setSelected(null),
|
|
813
|
-
style: { ...btn(chrome), width:
|
|
827
|
+
style: { ...btn(chrome), width: 40, height: 40, minWidth: 40, padding: 0, borderRadius: "50%", fontSize: 20, lineHeight: 1, color: chrome.mutedText, borderColor: chrome.border, background: chrome.panelBg },
|
|
814
828
|
children: "\xD7"
|
|
815
829
|
}
|
|
816
830
|
)
|
|
817
831
|
] }),
|
|
818
832
|
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: 11, fontWeight: 700, letterSpacing: ".06em", textTransform: "uppercase", color: chrome.mutedText, marginBottom: 7 }, children: L.intensity }),
|
|
819
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { display: "flex", flexWrap: "wrap", gap: 4, marginBottom: 12 }, children: Array.from({ length: 11 }, (_, i) =>
|
|
833
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { display: "flex", flexWrap: "wrap", gap: 4, marginBottom: 12 }, children: Array.from({ length: 11 }, (_, i) => (
|
|
834
|
+
/* F052.34 — CIRCLES, and all eleven the same size.
|
|
835
|
+
Dimensioned by «10», the widest label: sizing by the average
|
|
836
|
+
would make the two-digit one an ellipse among circles, which
|
|
837
|
+
is worse than eleven rounded squares because the odd one out
|
|
838
|
+
becomes a different SHAPE rather than slightly wider.
|
|
839
|
+
46px is the SIBLING's touch size, not a new number: the 2D
|
|
840
|
+
renderer already used it and this one was on 30px, under the
|
|
841
|
+
>=44px floor F052.8 set. See INTENSITY_SIZE. */
|
|
842
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { "data-testid": `bodymap3d-intensity-${i}`, onClick: () => setPain(region.key, i, current?.type), style: { ...btn(chrome), display: "inline-flex", alignItems: "center", justifyContent: "center", width: INTENSITY_SIZE, height: INTENSITY_SIZE, minWidth: INTENSITY_SIZE, padding: 0, borderRadius: "50%", background: current?.intensity === i ? chrome.accent : chrome.panelBg, color: current?.intensity === i ? chrome.accentText : chrome.text }, children: i }, i)
|
|
843
|
+
)) }),
|
|
820
844
|
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: 11, fontWeight: 700, letterSpacing: ".06em", textTransform: "uppercase", color: chrome.mutedText, marginBottom: 7 }, children: L.quality }),
|
|
821
845
|
/* @__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)) }),
|
|
822
846
|
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 })
|
|
@@ -853,9 +877,13 @@ function BodyMap3D(props) {
|
|
|
853
877
|
}
|
|
854
878
|
|
|
855
879
|
exports.BodyMap3D = BodyMap3D;
|
|
880
|
+
exports.INTENSITY_SIZE = INTENSITY_SIZE;
|
|
881
|
+
exports.TAP_MAX_DISTANCE = TAP_MAX_DISTANCE;
|
|
856
882
|
exports.ensureNormals = ensureNormals;
|
|
883
|
+
exports.isTap = isTap;
|
|
857
884
|
exports.seamBlend = seamBlend;
|
|
858
885
|
exports.seamWeight = seamWeight;
|
|
859
886
|
exports.serializeReport = serializeReport;
|
|
887
|
+
exports.shouldShowHint = shouldShowHint;
|
|
860
888
|
//# sourceMappingURL=three.cjs.map
|
|
861
889
|
//# sourceMappingURL=three.cjs.map
|