partforge 0.111.0 → 0.111.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "partforge",
3
- "version": "0.111.0",
3
+ "version": "0.111.1",
4
4
  "description": "Turn a declarative part definition into a parametric-CAD web app (three.js + Manifold/Replicad). Requires a Vite-based consumer.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -84,7 +84,15 @@ export function createAnnotateMode(viewer, { stage, getContext, onSend, createCa
84
84
  let hoverProbe = null; // hand tool: what's under the pointer right now (no gesture)
85
85
  const modeListeners = new Set();
86
86
  const toolListeners = new Set();
87
- const notifyMode = () => { for (const cb of [...modeListeners]) cb(); };
87
+ // Every listener hears every transition: the host application registers its
88
+ // relay AFTER mount.js's own listeners, so a throw in one of ours must not
89
+ // end the loop before the host is told — and must never escape setEnabled,
90
+ // which send() calls after the ink is already discarded.
91
+ const notifyMode = () => {
92
+ for (const cb of [...modeListeners]) {
93
+ try { cb(); } catch (err) { console.error("mode listener failed", err); }
94
+ }
95
+ };
88
96
  const notifyTool = () => { for (const cb of [...toolListeners]) cb(); };
89
97
 
90
98
  const rectOf = () => canvas.element.getBoundingClientRect();
@@ -54,7 +54,15 @@ export function createMeasureMode(viewer, { part, getContext, revealParams, getP
54
54
  const pinListeners = new Set();
55
55
  const notifyPins = () => { for (const cb of [...pinListeners]) cb(); };
56
56
  const modeListeners = new Set();
57
- const notifyMode = () => { for (const cb of [...modeListeners]) cb(); };
57
+ // Every listener hears every transition: the host application registers its
58
+ // relay AFTER mount.js's own listeners, so a throw in one of ours must not
59
+ // end the loop before the host is told — and must never escape setEnabled,
60
+ // which send() calls after the ink is already discarded.
61
+ const notifyMode = () => {
62
+ for (const cb of [...modeListeners]) {
63
+ try { cb(); } catch (err) { console.error("mode listener failed", err); }
64
+ }
65
+ };
58
66
 
59
67
  let enabled = false;
60
68
  let units = "mm"; // display only; values stay mm internally
@@ -11,8 +11,14 @@ export function attachHoverLabels(
11
11
  viewer,
12
12
  { part, schedule = (cb) => requestAnimationFrame(cb), tooltip } = {},
13
13
  ) {
14
- // Hover is a mouse idiom — skip entirely on touch-only devices.
15
- if (globalThis.matchMedia && !matchMedia("(hover: hover)").matches) return { detach: () => {} };
14
+ // Hover is a mouse idiom — skip entirely on touch-only devices. The stub
15
+ // still answers the WHOLE interface: mount.js calls setSuppressed from the
16
+ // measure and annotate mode-change listeners without asking which device it
17
+ // is on, and a missing method there threw inside notifyMode on every phone —
18
+ // aborting the listener loop before the host application's own relay ran.
19
+ if (globalThis.matchMedia && !matchMedia("(hover: hover)").matches) {
20
+ return { setSuppressed: () => {}, detach: () => {} };
21
+ }
16
22
 
17
23
  const ownsTooltip = !tooltip;
18
24
  const tooltipPresenter = tooltip ?? createTooltipPresenter();