@broberg/bodymap 0.4.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.d.cts CHANGED
@@ -216,6 +216,22 @@ interface BodyMap3DProps {
216
216
  * (default true). Set false for a patient/employee-facing flow where the code is
217
217
  * internal jargon and the readable region name is enough. */
218
218
  showRegionCode?: boolean;
219
+ /** Soften the colour transition between neighbouring regions (F052.21).
220
+ *
221
+ * DEFAULT FALSE, and the default is the accessible one (F052.23). The blend
222
+ * mixes the BODY colour into a marked region near its boundary — which on a
223
+ * SMALL mark is most of the mark. Measured on a phone with a consumer's
224
+ * palette and one knee marked: the mark's average contrast against the body
225
+ * fell from 4.71:1 to 3.59:1, i.e. below the WCAG AA threshold of 4.5:1, on a
226
+ * surface a public authority is legally required to meet.
227
+ *
228
+ * At the single strongest pixel the cost is small (5.12 → 4.78) — which is
229
+ * why a spot-check misses it and the AVERAGE is what a person sees.
230
+ *
231
+ * Turn it on when the marked areas are LARGE and you have no accessibility
232
+ * duty: the soft seam genuinely looks better there, and that is why it is
233
+ * still here rather than deleted. */
234
+ seam?: boolean;
219
235
  /** Fired after every pick with what ACTUALLY happened (F052.22): "select",
220
236
  * "clear" or "ignore". Wire it to a sound (`@broberg/soundkit`) or to native
221
237
  * haptics (Capacitor `Haptics.impact()` — the only route to a real buzz on an
package/dist/three.d.ts CHANGED
@@ -216,6 +216,22 @@ interface BodyMap3DProps {
216
216
  * (default true). Set false for a patient/employee-facing flow where the code is
217
217
  * internal jargon and the readable region name is enough. */
218
218
  showRegionCode?: boolean;
219
+ /** Soften the colour transition between neighbouring regions (F052.21).
220
+ *
221
+ * DEFAULT FALSE, and the default is the accessible one (F052.23). The blend
222
+ * mixes the BODY colour into a marked region near its boundary — which on a
223
+ * SMALL mark is most of the mark. Measured on a phone with a consumer's
224
+ * palette and one knee marked: the mark's average contrast against the body
225
+ * fell from 4.71:1 to 3.59:1, i.e. below the WCAG AA threshold of 4.5:1, on a
226
+ * surface a public authority is legally required to meet.
227
+ *
228
+ * At the single strongest pixel the cost is small (5.12 → 4.78) — which is
229
+ * why a spot-check misses it and the AVERAGE is what a person sees.
230
+ *
231
+ * Turn it on when the marked areas are LARGE and you have no accessibility
232
+ * duty: the soft seam genuinely looks better there, and that is why it is
233
+ * still here rather than deleted. */
234
+ seam?: boolean;
219
235
  /** Fired after every pick with what ACTUALLY happened (F052.22): "select",
220
236
  * "clear" or "ignore". Wire it to a sound (`@broberg/soundkit`) or to native
221
237
  * haptics (Capacitor `Haptics.impact()` — the only route to a real buzz on an
package/dist/three.js CHANGED
@@ -286,6 +286,7 @@ function BodyMap3D(props) {
286
286
  showRegionCode = true,
287
287
  onFeedback,
288
288
  haptics,
289
+ seam = false,
289
290
  className
290
291
  } = props;
291
292
  const chrome = uiColors(palette);
@@ -323,6 +324,8 @@ function BodyMap3D(props) {
323
324
  const pickRef = useRef(() => "ignore");
324
325
  const setReadyRef = useRef(setReady);
325
326
  setReadyRef.current = setReady;
327
+ const seamRef = useRef(seam);
328
+ seamRef.current = seam;
326
329
  const apiRef = useRef(null);
327
330
  useEffect(() => {
328
331
  if (!webglAvailable()) {
@@ -416,7 +419,7 @@ function BodyMap3D(props) {
416
419
  };
417
420
  for (let i = 0; i < vertexRegion.length; i++) {
418
421
  tmp.copy(col(vertexRegion[i]));
419
- const w = vertexBlend[i];
422
+ const w = seamRef.current ? vertexBlend[i] : 0;
420
423
  if (w > 0) {
421
424
  tmp2.copy(col(vertexNeighbour[i]));
422
425
  tmp.lerp(tmp2, w);
@@ -450,7 +453,7 @@ function BodyMap3D(props) {
450
453
  });
451
454
  if (bodyMesh) {
452
455
  const geo = bodyMesh.geometry;
453
- geo.computeVertexNormals();
456
+ if (!geo.getAttribute("normal")) geo.computeVertexNormals();
454
457
  const pos = geo.getAttribute("position");
455
458
  const n = pos.count;
456
459
  const cols = new Float32Array(n * 3);
@@ -587,7 +590,7 @@ function BodyMap3D(props) {
587
590
  }, []);
588
591
  useEffect(() => {
589
592
  apiRef.current?.refresh();
590
- }, [selected, report, palette]);
593
+ }, [selected, report, palette, seam]);
591
594
  const sexInited = useRef(false);
592
595
  useEffect(() => {
593
596
  if (!sexInited.current) {