kitchen-simulator 6.0.1-react.18 → 6.0.2-react.18

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.
Files changed (2) hide show
  1. package/es/index.js +346 -365
  2. package/package.json +1 -1
package/es/index.js CHANGED
@@ -5,344 +5,334 @@ import _possibleConstructorReturn from "@babel/runtime/helpers/esm/possibleConst
5
5
  import _getPrototypeOf from "@babel/runtime/helpers/esm/getPrototypeOf";
6
6
  import _inherits from "@babel/runtime/helpers/esm/inherits";
7
7
  import _asyncToGenerator from "@babel/runtime/helpers/esm/asyncToGenerator";
8
- function _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }
9
- function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }
8
+ import _toConsumableArray from "@babel/runtime/helpers/esm/toConsumableArray";
10
9
  function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t["return"] || t["return"](); } finally { if (u) throw o; } } }; }
11
10
  function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
12
11
  function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
13
12
  import _regeneratorRuntime from "@babel/runtime/regenerator";
13
+ function _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }
14
+ function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }
15
+ // kitchen-simulator/index.js (or wherever renderKitchenSimulator lives)
14
16
  import React from 'react';
15
- import * as Three from 'three';
16
- import LiteRenderer from "./LiteRenderer";
17
17
  import { createRoot } from 'react-dom/client';
18
+ import LiteRenderer from "./LiteRenderer";
19
+ import * as Three from 'three';
18
20
  var ROOT_KEY = '__kitchenSimulatorRoot__';
19
21
  var API_KEY = '__kitchenSimulatorApi__';
22
+ function makeLogger(getEnabled) {
23
+ var prefix = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '[kitchen-simulator]';
24
+ var now = function now() {
25
+ return (typeof performance !== 'undefined' && performance.now ? performance.now() : Date.now()).toFixed(1);
26
+ };
27
+ var safe = function safe(v) {
28
+ try {
29
+ if (v == null) return v;
30
+ if (typeof v === 'string') return v;
31
+ if (typeof v === 'number' || typeof v === 'boolean') return v;
32
+ return JSON.stringify(v, function (k, val) {
33
+ if (k === 'children' || k === 'parent') return '[omitted]';
34
+ if (typeof val === 'function') return '[fn]';
35
+ return val;
36
+ });
37
+ } catch (_unused) {
38
+ return '[unserializable]';
39
+ }
40
+ };
41
+ var log = function log() {
42
+ var _console;
43
+ if (!getEnabled()) return;
44
+ for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
45
+ args[_key] = arguments[_key];
46
+ }
47
+ (_console = console).log.apply(_console, ["".concat(prefix, " ").concat(now(), "ms")].concat(_toConsumableArray(args.map(safe))));
48
+ };
49
+ var warn = function warn() {
50
+ var _console2;
51
+ if (!getEnabled()) return;
52
+ for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
53
+ args[_key2] = arguments[_key2];
54
+ }
55
+ (_console2 = console).warn.apply(_console2, ["".concat(prefix, " ").concat(now(), "ms")].concat(_toConsumableArray(args.map(safe))));
56
+ };
57
+ var error = function error() {
58
+ var _console3;
59
+ if (!getEnabled()) return;
60
+ for (var _len3 = arguments.length, args = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {
61
+ args[_key3] = arguments[_key3];
62
+ }
63
+ (_console3 = console).error.apply(_console3, ["".concat(prefix, " ").concat(now(), "ms")].concat(_toConsumableArray(args.map(safe))));
64
+ };
65
+ return {
66
+ log: log,
67
+ warn: warn,
68
+ error: error
69
+ };
70
+ }
20
71
 
21
- // ---------------- URL rewrite (keep if needed) ----------------
72
+ // ---- Your URL rewrite + TextureLoader patch stays as you had it ----
22
73
  var API_HOST_REGEX = /(https?:\/\/)?(api\.diydesignspace\.com|api\.addovisuals\.com|127\.0\.0\.1:4002)/;
23
74
  var API_HOST_REPLACEMENT = 'https://api-old.diydesignspace.com';
24
75
  function rewriteApiUrl(url) {
25
76
  return typeof url === 'string' ? url.replace(API_HOST_REGEX, API_HOST_REPLACEMENT) : url;
26
77
  }
27
-
28
- // texture rewrite
29
78
  var originalTextureLoad = Three.TextureLoader.prototype.load;
30
79
  Three.TextureLoader.prototype.load = function (url, onLoad, onProgress, onError) {
31
- return originalTextureLoad.call(this, rewriteApiUrl(url), onLoad, onProgress, onError);
80
+ var newUrl = rewriteApiUrl(url);
81
+ return originalTextureLoad.call(this, newUrl, onLoad, onProgress, onError);
32
82
  };
33
83
 
34
- // ---------------- minimal gltf tracker (same idea, but smaller) ----------------
35
- function installGltfTracker() {
36
- if (typeof window === 'undefined') {
37
- return {
38
- getInFlight: function getInFlight() {
39
- return 0;
40
- },
41
- subscribe: function subscribe() {
42
- return function () {};
43
- },
44
- waitForIdle: function () {
45
- var _waitForIdle = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee() {
46
- return _regeneratorRuntime.wrap(function (_context) {
47
- while (1) switch (_context.prev = _context.next) {
48
- case 0:
49
- return _context.abrupt("return", true);
50
- case 1:
51
- case "end":
52
- return _context.stop();
53
- }
54
- }, _callee);
55
- }));
56
- function waitForIdle() {
57
- return _waitForIdle.apply(this, arguments);
58
- }
59
- return waitForIdle;
60
- }(),
61
- uninstall: function uninstall() {}
62
- };
84
+ // ---- keep your installGltfTracker exactly as you have it ----
85
+ // import / paste your installGltfTracker(debug) here
86
+ // (omitted in this snippet for brevity)
87
+
88
+ export function renderKitchenSimulator(container) {
89
+ var _props$framesPerEvent, _props$waitForGltfIdl, _props$gltfTimeoutMs;
90
+ var props = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
91
+ if (!container) throw new Error('renderKitchenSimulator: container is required');
92
+ var DEBUG_KEY = '__kitchenSimulatorDebug__';
93
+ var debugEnabled = !!props.debug || typeof window !== 'undefined' && !!window[DEBUG_KEY];
94
+ var _makeLogger = makeLogger(function () {
95
+ return debugEnabled;
96
+ }),
97
+ log = _makeLogger.log,
98
+ warn = _makeLogger.warn,
99
+ error = _makeLogger.error;
100
+
101
+ // ✅ Reuse existing API
102
+ if (container[API_KEY]) {
103
+ var _container$API_KEY$__, _container$API_KEY;
104
+ log('Reusing existing API; calling __render with new props');
105
+ (_container$API_KEY$__ = (_container$API_KEY = container[API_KEY]).__render) === null || _container$API_KEY$__ === void 0 || _container$API_KEY$__.call(_container$API_KEY, props);
106
+ return container[API_KEY];
63
107
  }
64
- var KEY = '__kitchenSimulatorGltfTracker__';
65
- if (!window[KEY]) {
66
- window[KEY] = {
67
- refCount: 0,
68
- inFlight: 0,
69
- listeners: new Set(),
70
- installed: false,
71
- originalFetch: null
72
- };
108
+
109
+ // Root
110
+ var root = container[ROOT_KEY];
111
+ if (!root) {
112
+ root = createRoot(container);
113
+ container[ROOT_KEY] = root;
114
+ log('Created new React root');
73
115
  }
74
- var g = window[KEY];
75
- var is3dAssetUrl = function is3dAssetUrl(url) {
76
- var _ref, _url$url, _url$toString;
77
- var s = typeof url === 'string' ? url : (_ref = (_url$url = url === null || url === void 0 ? void 0 : url.url) !== null && _url$url !== void 0 ? _url$url : url === null || url === void 0 || (_url$toString = url.toString) === null || _url$toString === void 0 ? void 0 : _url$toString.call(url)) !== null && _ref !== void 0 ? _ref : '';
78
- var u = String(s).toLowerCase().split('?')[0];
79
- return u.endsWith('.gltf') || u.endsWith('.glb') || u.endsWith('.bin') || u.endsWith('.ktx2') || u.endsWith('.hdr') || u.endsWith('.exr') || u.endsWith('.png') || u.endsWith('.jpg') || u.endsWith('.jpeg') || u.endsWith('.webp');
80
- };
81
- var notify = function notify() {
82
- var _iterator = _createForOfIteratorHelper(g.listeners),
83
- _step;
84
- try {
85
- for (_iterator.s(); !(_step = _iterator.n()).done;) {
86
- var fn = _step.value;
87
- fn(g.inFlight);
88
- }
89
- } catch (err) {
90
- _iterator.e(err);
91
- } finally {
92
- _iterator.f();
93
- }
94
- };
95
- var subscribe = function subscribe(fn) {
96
- g.listeners.add(fn);
97
- fn(g.inFlight);
98
- return function () {
99
- return g.listeners["delete"](fn);
100
- };
101
- };
102
- var nextFrame = function nextFrame() {
103
- return new Promise(function (r) {
104
- return requestAnimationFrame(r);
116
+ var setExternalEventFn = null;
117
+ var destroyed = false;
118
+ var queue = [];
119
+ var pendingMarkers = new Set();
120
+ var MARKER = Symbol('marker');
121
+
122
+ // ✅ keep your tracker
123
+ var gltfTracker = installGltfTracker(debugEnabled);
124
+ var defaultFramesPerEvent = (_props$framesPerEvent = props.framesPerEvent) !== null && _props$framesPerEvent !== void 0 ? _props$framesPerEvent : 1;
125
+ var waitForAssets = (_props$waitForGltfIdl = props.waitForGltfIdleAfterEachEvent) !== null && _props$waitForGltfIdl !== void 0 ? _props$waitForGltfIdl : true;
126
+ var defaultTimeout = (_props$gltfTimeoutMs = props.gltfTimeoutMs) !== null && _props$gltfTimeoutMs !== void 0 ? _props$gltfTimeoutMs : 30000;
127
+ var draining = false;
128
+
129
+ // ---- Ready gate: mounted & setExternalEventFn installed ----
130
+ var readyResolve = null;
131
+ var readyReject = null;
132
+ var readyPromise = new Promise(function (res, rej) {
133
+ readyResolve = res;
134
+ readyReject = rej;
135
+ });
136
+
137
+ // ---- Catalog-ready gate (NEW) ----
138
+ var catalogReadyResolve = null;
139
+ var catalogReadyPromise = new Promise(function (res) {
140
+ catalogReadyResolve = res;
141
+ });
142
+ var catalogReady = false;
143
+ function nextFrame() {
144
+ return new Promise(function (resolve) {
145
+ return requestAnimationFrame(resolve);
105
146
  });
106
- };
107
- function waitStableIdle2Frames() {
108
- return _waitStableIdle2Frames.apply(this, arguments);
109
147
  }
110
- function _waitStableIdle2Frames() {
111
- _waitStableIdle2Frames = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee5() {
112
- return _regeneratorRuntime.wrap(function (_context5) {
113
- while (1) switch (_context5.prev = _context5.next) {
148
+ function settle(_x) {
149
+ return _settle.apply(this, arguments);
150
+ }
151
+ function _settle() {
152
+ _settle = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee3(ev) {
153
+ var _ev$framesPerEvent, _ev$waitForGltfIdleAf, _ev$gltfTimeoutMs;
154
+ var frames, shouldWait, timeoutMs, i;
155
+ return _regeneratorRuntime.wrap(function (_context3) {
156
+ while (1) switch (_context3.prev = _context3.next) {
114
157
  case 0:
115
- _context5.next = 1;
116
- return nextFrame();
158
+ frames = (_ev$framesPerEvent = ev === null || ev === void 0 ? void 0 : ev.framesPerEvent) !== null && _ev$framesPerEvent !== void 0 ? _ev$framesPerEvent : defaultFramesPerEvent;
159
+ shouldWait = (_ev$waitForGltfIdleAf = ev === null || ev === void 0 ? void 0 : ev.waitForGltfIdleAfterEachEvent) !== null && _ev$waitForGltfIdleAf !== void 0 ? _ev$waitForGltfIdleAf : waitForAssets;
160
+ timeoutMs = (_ev$gltfTimeoutMs = ev === null || ev === void 0 ? void 0 : ev.gltfTimeoutMs) !== null && _ev$gltfTimeoutMs !== void 0 ? _ev$gltfTimeoutMs : defaultTimeout; // RAF frames
161
+ i = 0;
117
162
  case 1:
118
- if (!(g.inFlight !== 0)) {
119
- _context5.next = 2;
163
+ if (!(i < frames)) {
164
+ _context3.next = 3;
120
165
  break;
121
166
  }
122
- return _context5.abrupt("return", false);
123
- case 2:
124
- _context5.next = 3;
167
+ _context3.next = 2;
125
168
  return nextFrame();
169
+ case 2:
170
+ i++;
171
+ _context3.next = 1;
172
+ break;
126
173
  case 3:
127
- return _context5.abrupt("return", g.inFlight === 0);
174
+ if (!shouldWait) {
175
+ _context3.next = 4;
176
+ break;
177
+ }
178
+ _context3.next = 4;
179
+ return gltfTracker.waitForIdle({
180
+ timeoutMs: timeoutMs
181
+ });
128
182
  case 4:
183
+ _context3.next = 5;
184
+ return nextFrame();
185
+ case 5:
129
186
  case "end":
130
- return _context5.stop();
187
+ return _context3.stop();
131
188
  }
132
- }, _callee5);
189
+ }, _callee3);
133
190
  }));
134
- return _waitStableIdle2Frames.apply(this, arguments);
191
+ return _settle.apply(this, arguments);
135
192
  }
136
- var waitForIdle = /*#__PURE__*/function () {
137
- var _ref2 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee3() {
138
- var _ref3,
139
- _ref3$timeoutMs,
140
- timeoutMs,
141
- _args3 = arguments;
142
- return _regeneratorRuntime.wrap(function (_context3) {
143
- while (1) switch (_context3.prev = _context3.next) {
193
+ function drain() {
194
+ return _drain.apply(this, arguments);
195
+ }
196
+ function _drain() {
197
+ _drain = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee4() {
198
+ var item, _err$message, _t;
199
+ return _regeneratorRuntime.wrap(function (_context4) {
200
+ while (1) switch (_context4.prev = _context4.next) {
144
201
  case 0:
145
- _ref3 = _args3.length > 0 && _args3[0] !== undefined ? _args3[0] : {}, _ref3$timeoutMs = _ref3.timeoutMs, timeoutMs = _ref3$timeoutMs === void 0 ? 30000 : _ref3$timeoutMs;
146
- _context3.next = 1;
147
- return waitStableIdle2Frames();
148
- case 1:
149
- if (!_context3.sent) {
150
- _context3.next = 2;
202
+ if (!(draining || destroyed)) {
203
+ _context4.next = 1;
151
204
  break;
152
205
  }
153
- return _context3.abrupt("return", true);
154
- case 2:
155
- return _context3.abrupt("return", new Promise(function (resolve, reject) {
156
- var done = false;
157
- var timer = setTimeout(function () {
158
- if (done) return;
159
- done = true;
160
- unsub === null || unsub === void 0 || unsub();
161
- reject(new Error('3D assets did not become idle within timeout'));
162
- }, timeoutMs);
163
- var unsub = subscribe(/*#__PURE__*/function () {
164
- var _ref4 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee2(count) {
165
- var stable;
166
- return _regeneratorRuntime.wrap(function (_context2) {
167
- while (1) switch (_context2.prev = _context2.next) {
168
- case 0:
169
- if (!done) {
170
- _context2.next = 1;
171
- break;
172
- }
173
- return _context2.abrupt("return");
174
- case 1:
175
- if (!(count !== 0)) {
176
- _context2.next = 2;
177
- break;
178
- }
179
- return _context2.abrupt("return");
180
- case 2:
181
- _context2.next = 3;
182
- return waitStableIdle2Frames();
183
- case 3:
184
- stable = _context2.sent;
185
- if (stable) {
186
- done = true;
187
- clearTimeout(timer);
188
- unsub();
189
- resolve(true);
190
- }
191
- case 4:
192
- case "end":
193
- return _context2.stop();
194
- }
195
- }, _callee2);
196
- }));
197
- return function (_x) {
198
- return _ref4.apply(this, arguments);
199
- };
200
- }());
201
- }));
206
+ return _context4.abrupt("return");
207
+ case 1:
208
+ draining = true;
209
+ _context4.prev = 2;
210
+ _context4.next = 3;
211
+ return readyPromise;
202
212
  case 3:
213
+ if (!(!destroyed && queue.length)) {
214
+ _context4.next = 10;
215
+ break;
216
+ }
217
+ if (setExternalEventFn) {
218
+ _context4.next = 5;
219
+ break;
220
+ }
221
+ _context4.next = 4;
222
+ return nextFrame();
223
+ case 4:
224
+ return _context4.abrupt("continue", 3);
225
+ case 5:
226
+ item = queue.shift();
227
+ if (!(item && item.__marker === MARKER)) {
228
+ _context4.next = 6;
229
+ break;
230
+ }
231
+ pendingMarkers["delete"](item.token);
232
+ return _context4.abrupt("continue", 3);
233
+ case 6:
234
+ _context4.prev = 6;
235
+ setExternalEventFn(item);
236
+ _context4.next = 7;
237
+ return settle(item);
238
+ case 7:
239
+ _context4.next = 9;
240
+ break;
241
+ case 8:
242
+ _context4.prev = 8;
243
+ _t = _context4["catch"](6);
244
+ error('drain:event failed', {
245
+ err: (_err$message = _t === null || _t === void 0 ? void 0 : _t.message) !== null && _err$message !== void 0 ? _err$message : _t,
246
+ type: item === null || item === void 0 ? void 0 : item.type
247
+ });
248
+ case 9:
249
+ _context4.next = 3;
250
+ break;
251
+ case 10:
252
+ _context4.prev = 10;
253
+ draining = false;
254
+ return _context4.finish(10);
255
+ case 11:
203
256
  case "end":
204
- return _context3.stop();
257
+ return _context4.stop();
205
258
  }
206
- }, _callee3);
259
+ }, _callee4, null, [[2,, 10, 11], [6, 8]]);
207
260
  }));
208
- return function waitForIdle() {
209
- return _ref2.apply(this, arguments);
210
- };
211
- }();
212
- var installIfNeeded = function installIfNeeded() {
213
- if (g.installed) return;
214
- g.originalFetch = window.fetch;
215
- if (typeof g.originalFetch === 'function') {
216
- window.fetch = /*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee4() {
217
- var _len,
218
- args,
219
- _key,
220
- input,
221
- init,
222
- track,
223
- _args4 = arguments;
224
- return _regeneratorRuntime.wrap(function (_context4) {
225
- while (1) switch (_context4.prev = _context4.next) {
226
- case 0:
227
- for (_len = _args4.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
228
- args[_key] = _args4[_key];
229
- }
230
- input = args[0], init = args[1]; // rewrite
231
- if (typeof input === 'string') input = rewriteApiUrl(input);else if (input instanceof Request) input = new Request(rewriteApiUrl(input.url), input);
232
- track = is3dAssetUrl(input);
233
- if (track) {
234
- _context4.next = 1;
235
- break;
236
- }
237
- return _context4.abrupt("return", g.originalFetch.call(this, input, init));
238
- case 1:
239
- g.inFlight += 1;
240
- notify();
241
- _context4.prev = 2;
242
- _context4.next = 3;
243
- return g.originalFetch.call(this, input, init);
244
- case 3:
245
- return _context4.abrupt("return", _context4.sent);
246
- case 4:
247
- _context4.prev = 4;
248
- g.inFlight -= 1;
249
- if (g.inFlight < 0) g.inFlight = 0;
250
- notify();
251
- return _context4.finish(4);
252
- case 5:
253
- case "end":
254
- return _context4.stop();
255
- }
256
- }, _callee4, this, [[2,, 4, 5]]);
257
- }));
258
- }
259
- g.installed = true;
260
- };
261
- var uninstall = function uninstall() {
262
- g.refCount -= 1;
263
- if (g.refCount > 0) return;
264
- if (typeof g.originalFetch === 'function') window.fetch = g.originalFetch;
265
- g.listeners.clear();
266
- g.inFlight = 0;
267
- g.installed = false;
268
- g.originalFetch = null;
269
- };
270
- g.refCount += 1;
271
- installIfNeeded();
272
- return {
273
- getInFlight: function getInFlight() {
274
- return g.inFlight;
275
- },
276
- subscribe: subscribe,
277
- waitForIdle: waitForIdle,
278
- uninstall: uninstall
279
- };
280
- }
281
-
282
- // ---------------- simple render + simple API ----------------
283
- export function renderKitchenSimulator(container) {
284
- var props = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
285
- if (!container) throw new Error('renderKitchenSimulator: container is required');
286
-
287
- // reuse API if already mounted
288
- if (container[API_KEY]) {
289
- container[API_KEY].__render(props);
290
- return container[API_KEY];
261
+ return _drain.apply(this, arguments);
291
262
  }
292
-
293
- // reuse root
294
- var root = container[ROOT_KEY];
295
- if (!root) {
296
- root = createRoot(container);
297
- container[ROOT_KEY] = root;
298
- }
299
- var gltfTracker = installGltfTracker();
300
- var destroyed = false;
301
- var setExternalEvent = null;
302
-
303
- // mounted gate (first-event safety)
304
- var mountedResolve;
305
- var mounted = new Promise(function (res) {
306
- return mountedResolve = res;
307
- });
308
- var nextFrame = function nextFrame() {
309
- return new Promise(function (r) {
310
- return requestAnimationFrame(r);
311
- });
312
- };
313
263
  var Wrapper = /*#__PURE__*/function (_React$Component) {
314
264
  function Wrapper(p) {
315
265
  var _this;
316
266
  _classCallCheck(this, Wrapper);
317
267
  _this = _callSuper(this, Wrapper, [p]);
318
268
  _this.state = {
319
- externalEvent: null
269
+ externalEvent: p.externalEvent || null
320
270
  };
271
+ _this._mounted = false;
321
272
  return _this;
322
273
  }
323
274
  _inherits(Wrapper, _React$Component);
324
275
  return _createClass(Wrapper, [{
325
276
  key: "componentDidMount",
326
277
  value: function componentDidMount() {
327
- var _this2 = this,
328
- _mountedResolve;
329
- setExternalEvent = function setExternalEvent(ev) {
330
- return _this2.setState({
331
- externalEvent: ev
278
+ var _this2 = this;
279
+ this._mounted = true;
280
+ log('Wrapper mounted -> ready');
281
+ setExternalEventFn = function setExternalEventFn(newEvent) {
282
+ if (!_this2._mounted) return;
283
+ _this2.setState({
284
+ externalEvent: newEvent
332
285
  });
333
286
  };
334
- (_mountedResolve = mountedResolve) === null || _mountedResolve === void 0 || _mountedResolve();
335
- mountedResolve = null;
287
+ if (readyResolve) {
288
+ readyResolve(true);
289
+ readyResolve = null;
290
+ }
336
291
  }
337
292
  }, {
338
293
  key: "componentWillUnmount",
339
294
  value: function componentWillUnmount() {
340
- setExternalEvent = null;
295
+ this._mounted = false;
296
+ setExternalEventFn = null;
297
+ if (readyReject) {
298
+ readyReject(new Error('Wrapper unmounted before ready'));
299
+ readyReject = null;
300
+ }
341
301
  }
342
302
  }, {
343
303
  key: "render",
344
304
  value: function render() {
305
+ var userOnInternalEvent = this.props.onInternalEvent;
306
+
307
+ // ✅ Wrap internal event to detect catalog readiness
308
+ var onInternalEventWrapped = /*#__PURE__*/function () {
309
+ var _ref = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee(evt, callback) {
310
+ return _regeneratorRuntime.wrap(function (_context) {
311
+ while (1) switch (_context.prev = _context.next) {
312
+ case 0:
313
+ // IMPORTANT: first time we see INTERNAL_EVENT_ITEMS_CATALOG,
314
+ // it means catalog init path ran and tool is requesting items.
315
+ if (!catalogReady && (evt === null || evt === void 0 ? void 0 : evt.type) === 'INTERNAL_EVENT_ITEMS_CATALOG') {
316
+ catalogReady = true;
317
+ if (catalogReadyResolve) {
318
+ catalogReadyResolve(true);
319
+ catalogReadyResolve = null;
320
+ }
321
+ log('Catalog is ready (observed INTERNAL_EVENT_ITEMS_CATALOG)');
322
+ }
323
+ return _context.abrupt("return", userOnInternalEvent === null || userOnInternalEvent === void 0 ? void 0 : userOnInternalEvent(evt, callback));
324
+ case 1:
325
+ case "end":
326
+ return _context.stop();
327
+ }
328
+ }, _callee);
329
+ }));
330
+ return function onInternalEventWrapped(_x2, _x3) {
331
+ return _ref.apply(this, arguments);
332
+ };
333
+ }();
345
334
  return /*#__PURE__*/React.createElement(LiteRenderer, _extends({}, this.props, {
335
+ onInternalEvent: onInternalEventWrapped,
346
336
  externalEvent: this.state.externalEvent
347
337
  }));
348
338
  }
@@ -352,106 +342,97 @@ export function renderKitchenSimulator(container) {
352
342
  __render: function __render(nextProps) {
353
343
  root.render(/*#__PURE__*/React.createElement(Wrapper, nextProps));
354
344
  },
355
- // subscribe to gltf inFlight
356
- subscribeGltfInFlight: function subscribeGltfInFlight(cb) {
357
- return gltfTracker.subscribe(cb);
345
+ // Host can await mount
346
+ whenReady: function whenReady() {
347
+ return readyPromise;
348
+ },
349
+ // ✅ Host can await catalog init (NEW)
350
+ whenCatalogReady: function whenCatalogReady() {
351
+ return catalogReadyPromise;
358
352
  },
359
353
  getGltfInFlight: function getGltfInFlight() {
360
354
  return gltfTracker.getInFlight();
361
355
  },
362
- // VERY SIMPLE batch sender
363
- sendExternalEvents: function sendExternalEvents(events) {
364
- var _arguments = arguments;
365
- return _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee6() {
366
- var opts, _opts$framesPerEvent, framesPerEvent, _opts$heavyPredicate, heavyPredicate, _opts$gltfTimeoutMs, gltfTimeoutMs, list, _iterator2, _step2, ev, i, isHeavy, _t;
367
- return _regeneratorRuntime.wrap(function (_context6) {
368
- while (1) switch (_context6.prev = _context6.next) {
369
- case 0:
370
- opts = _arguments.length > 1 && _arguments[1] !== undefined ? _arguments[1] : {};
371
- _opts$framesPerEvent = opts.framesPerEvent, framesPerEvent = _opts$framesPerEvent === void 0 ? 2 : _opts$framesPerEvent, _opts$heavyPredicate = opts.heavyPredicate, heavyPredicate = _opts$heavyPredicate === void 0 ? function (ev) {
372
- var _ev$type;
373
- return /ADD_ITEM|LOAD_PROJECT|REPLACE|CHANGE_DOORSTYLE|SET_FINISHING|SET_MOLDING|ADD_ROOM_SHAPE/.test((_ev$type = ev === null || ev === void 0 ? void 0 : ev.type) !== null && _ev$type !== void 0 ? _ev$type : '');
374
- } : _opts$heavyPredicate, _opts$gltfTimeoutMs = opts.gltfTimeoutMs, gltfTimeoutMs = _opts$gltfTimeoutMs === void 0 ? 30000 : _opts$gltfTimeoutMs;
375
- list = Array.isArray(events) ? events : [events]; // ensure mounted before first event
376
- _context6.next = 1;
377
- return mounted;
378
- case 1:
379
- if (!(destroyed || !setExternalEvent)) {
380
- _context6.next = 2;
381
- break;
382
- }
383
- return _context6.abrupt("return", false);
384
- case 2:
385
- _iterator2 = _createForOfIteratorHelper(list);
386
- _context6.prev = 3;
387
- _iterator2.s();
388
- case 4:
389
- if ((_step2 = _iterator2.n()).done) {
390
- _context6.next = 11;
391
- break;
392
- }
393
- ev = _step2.value;
394
- if (!destroyed) {
395
- _context6.next = 5;
396
- break;
397
- }
398
- return _context6.abrupt("return", false);
399
- case 5:
400
- // push event
401
- setExternalEvent(ev);
402
-
403
- // allow react/redux to process
404
- i = 0;
405
- case 6:
406
- if (!(i < framesPerEvent)) {
407
- _context6.next = 8;
408
- break;
409
- }
410
- _context6.next = 7;
411
- return nextFrame();
412
- case 7:
413
- i++;
414
- _context6.next = 6;
415
- break;
416
- case 8:
417
- // optional gltf wait only for heavy events
418
- isHeavy = !!heavyPredicate(ev);
419
- if (!isHeavy) {
420
- _context6.next = 9;
421
- break;
356
+ subscribeGltfInFlight: function subscribeGltfInFlight(cb) {
357
+ return gltfTracker.subscribe(cb);
358
+ },
359
+ sendExternalEvents: function sendExternalEvents(eventOrEvents) {
360
+ var _ref2 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
361
+ _ref2$timeoutMs = _ref2.timeoutMs,
362
+ timeoutMs = _ref2$timeoutMs === void 0 ? 60000 : _ref2$timeoutMs;
363
+ var events = Array.isArray(eventOrEvents) ? eventOrEvents : [eventOrEvents];
364
+ var token = Symbol('batch');
365
+ var _iterator = _createForOfIteratorHelper(events),
366
+ _step;
367
+ try {
368
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
369
+ var e = _step.value;
370
+ queue.push(e);
371
+ }
372
+ } catch (err) {
373
+ _iterator.e(err);
374
+ } finally {
375
+ _iterator.f();
376
+ }
377
+ pendingMarkers.add(token);
378
+ queue.push({
379
+ __marker: MARKER,
380
+ token: token
381
+ });
382
+ drain();
383
+ return new Promise(function (resolve) {
384
+ var start = Date.now();
385
+ var check = /*#__PURE__*/function () {
386
+ var _ref3 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee2() {
387
+ return _regeneratorRuntime.wrap(function (_context2) {
388
+ while (1) switch (_context2.prev = _context2.next) {
389
+ case 0:
390
+ if (destroyed) {
391
+ _context2.next = 4;
392
+ break;
393
+ }
394
+ if (pendingMarkers.has(token)) {
395
+ _context2.next = 1;
396
+ break;
397
+ }
398
+ resolve(true);
399
+ return _context2.abrupt("return");
400
+ case 1:
401
+ if (!(Date.now() - start > timeoutMs)) {
402
+ _context2.next = 2;
403
+ break;
404
+ }
405
+ error('sendExternalEvents timed out', {
406
+ timeoutMs: timeoutMs
407
+ });
408
+ pendingMarkers["delete"](token); // fail-open
409
+ resolve(false);
410
+ return _context2.abrupt("return");
411
+ case 2:
412
+ _context2.next = 3;
413
+ return nextFrame();
414
+ case 3:
415
+ _context2.next = 0;
416
+ break;
417
+ case 4:
418
+ resolve(false);
419
+ case 5:
420
+ case "end":
421
+ return _context2.stop();
422
422
  }
423
- _context6.next = 9;
424
- return gltfTracker.waitForIdle({
425
- timeoutMs: gltfTimeoutMs
426
- });
427
- case 9:
428
- _context6.next = 10;
429
- return nextFrame();
430
- case 10:
431
- _context6.next = 4;
432
- break;
433
- case 11:
434
- _context6.next = 13;
435
- break;
436
- case 12:
437
- _context6.prev = 12;
438
- _t = _context6["catch"](3);
439
- _iterator2.e(_t);
440
- case 13:
441
- _context6.prev = 13;
442
- _iterator2.f();
443
- return _context6.finish(13);
444
- case 14:
445
- return _context6.abrupt("return", true);
446
- case 15:
447
- case "end":
448
- return _context6.stop();
449
- }
450
- }, _callee6, null, [[3, 12, 13, 14]]);
451
- }))();
423
+ }, _callee2);
424
+ }));
425
+ return function check() {
426
+ return _ref3.apply(this, arguments);
427
+ };
428
+ }();
429
+ check();
430
+ });
452
431
  },
453
432
  unmount: function unmount() {
454
433
  destroyed = true;
434
+ queue.length = 0;
435
+ pendingMarkers.clear();
455
436
  gltfTracker.uninstall();
456
437
  root.unmount();
457
438
  container[ROOT_KEY] = null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kitchen-simulator",
3
- "version": "6.0.1-react.18",
3
+ "version": "6.0.2-react.18",
4
4
  "description": "It is a kitchen simulator (self-contained micro-frontend).",
5
5
  "license": "MIT",
6
6
  "module": "es/index.js",