@broberg/bodymap 0.3.0 → 0.5.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/dist/three.cjs CHANGED
@@ -84,6 +84,25 @@ function isSelectable(key, config = {}) {
84
84
  if (s?.visible === false) return false;
85
85
  return s?.selectable ?? true;
86
86
  }
87
+ var VIBRATION_PATTERNS = {
88
+ select: [12],
89
+ clear: [8, 40, 8],
90
+ ignore: []
91
+ };
92
+ function requestVibration(pattern, nav = globalThis.navigator) {
93
+ if (pattern.length === 0) return "skipped";
94
+ if (typeof nav?.vibrate !== "function") return "unsupported";
95
+ try {
96
+ return nav.vibrate([...pattern]) ? "requested" : "declined";
97
+ } catch {
98
+ return "declined";
99
+ }
100
+ }
101
+ function emitFeedback(outcome, region, opts = {}) {
102
+ opts.onFeedback?.({ outcome, region });
103
+ if (opts.haptics === false) return "skipped";
104
+ return requestVibration(VIBRATION_PATTERNS[outcome], opts.nav);
105
+ }
87
106
  var defaultUi = {
88
107
  text: "#1e293b",
89
108
  mutedText: "#475569",
@@ -287,6 +306,9 @@ function BodyMap3D(props) {
287
306
  autoRotate = true,
288
307
  canvasHeight = "60vh",
289
308
  showRegionCode = true,
309
+ onFeedback,
310
+ haptics,
311
+ seam = false,
290
312
  className
291
313
  } = props;
292
314
  const chrome = uiColors(palette);
@@ -324,6 +346,8 @@ function BodyMap3D(props) {
324
346
  const pickRef = react.useRef(() => "ignore");
325
347
  const setReadyRef = react.useRef(setReady);
326
348
  setReadyRef.current = setReady;
349
+ const seamRef = react.useRef(seam);
350
+ seamRef.current = seam;
327
351
  const apiRef = react.useRef(null);
328
352
  react.useEffect(() => {
329
353
  if (!webglAvailable()) {
@@ -417,7 +441,7 @@ function BodyMap3D(props) {
417
441
  };
418
442
  for (let i = 0; i < vertexRegion.length; i++) {
419
443
  tmp.copy(col(vertexRegion[i]));
420
- const w = vertexBlend[i];
444
+ const w = seamRef.current ? vertexBlend[i] : 0;
421
445
  if (w > 0) {
422
446
  tmp2.copy(col(vertexNeighbour[i]));
423
447
  tmp.lerp(tmp2, w);
@@ -451,7 +475,7 @@ function BodyMap3D(props) {
451
475
  });
452
476
  if (bodyMesh) {
453
477
  const geo = bodyMesh.geometry;
454
- geo.computeVertexNormals();
478
+ if (!geo.getAttribute("normal")) geo.computeVertexNormals();
455
479
  const pos = geo.getAttribute("position");
456
480
  const n = pos.count;
457
481
  const cols = new Float32Array(n * 3);
@@ -588,7 +612,7 @@ function BodyMap3D(props) {
588
612
  }, []);
589
613
  react.useEffect(() => {
590
614
  apiRef.current?.refresh();
591
- }, [selected, report, palette]);
615
+ }, [selected, report, palette, seam]);
592
616
  const sexInited = react.useRef(false);
593
617
  react.useEffect(() => {
594
618
  if (!sexInited.current) {
@@ -607,6 +631,7 @@ function BodyMap3D(props) {
607
631
  };
608
632
  pickRef.current = (k) => {
609
633
  const what = decidePick(k, reportRef.current, configRef.current ?? {});
634
+ emitFeedback(what, k, { onFeedback, haptics });
610
635
  if (what === "clear") removePain(k);
611
636
  else if (what === "select") setSelected(k);
612
637
  return what;