kitchen-simulator 6.0.3-react.18 → 7.0.0-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.
@@ -75,7 +75,6 @@ var LiteKitchenConfigurator = /*#__PURE__*/function (_Component) {
75
75
  isSaved: false,
76
76
  isLeaving: false
77
77
  };
78
- _this._catalogInitRequested = false;
79
78
  _this.openFloor = _this.openFloor.bind(_this);
80
79
  _this.openCabinet = _this.openCabinet.bind(_this);
81
80
  _this.openFinishing = _this.openFinishing.bind(_this);
@@ -299,10 +298,7 @@ var LiteKitchenConfigurator = /*#__PURE__*/function (_Component) {
299
298
  extractedState = _this$props.extractedState,
300
299
  projectActions = _this$props.projectActions;
301
300
  var catalogReady = extractedState === null || extractedState === void 0 || (_extractedState$getIn = extractedState.getIn) === null || _extractedState$getIn === void 0 ? void 0 : _extractedState$getIn.call(extractedState, ['catalog', 'ready']);
302
- if (!catalogReady && !this._catalogInitRequested) {
303
- this._catalogInitRequested = true;
304
- projectActions.initCatalog(catalog);
305
- }
301
+ if (!catalogReady) projectActions.initCatalog(catalog);
306
302
  }
307
303
  }, {
308
304
  key: "componentDidUpdate",
@@ -314,17 +310,12 @@ var LiteKitchenConfigurator = /*#__PURE__*/function (_Component) {
314
310
  projectActions = _this$props2.projectActions,
315
311
  catalog = _this$props2.catalog;
316
312
 
317
- // handle external event when it changes
318
- if (prevProps.externalEvent !== externalEvent && externalEvent) {
313
+ // same behavior: handle external event when it changes
314
+ if (prevProps.externalEvent !== externalEvent) {
319
315
  handleExternalEvent(this.props);
320
316
  }
321
317
  var catalogReady = extractedState === null || extractedState === void 0 || (_extractedState$getIn2 = extractedState.getIn) === null || _extractedState$getIn2 === void 0 ? void 0 : _extractedState$getIn2.call(extractedState, ['catalog', 'ready']);
322
- if (catalogReady) {
323
- this._catalogInitRequested = false; // allow re-init if state resets later
324
- } else if (!this._catalogInitRequested) {
325
- this._catalogInitRequested = true;
326
- projectActions.initCatalog(catalog);
327
- }
318
+ if (!catalogReady) projectActions.initCatalog(catalog);
328
319
  }
329
320
  }, {
330
321
  key: "isProjectEmpty",
@@ -347,20 +338,20 @@ var LiteKitchenConfigurator = /*#__PURE__*/function (_Component) {
347
338
  }
348
339
  var _viewer2D = extractedState.getIn(['viewer2D']);
349
340
  if (!_viewer2D || _viewer2D.size <= 0) return extractedState;
350
- var e = _viewer2D.get('e');
351
- var f = _viewer2D.get('f');
352
- if (e !== 0 || f !== 0) return extractedState;
353
- var viewerWidth = _viewer2D.get('viewerWidth');
354
- var viewerHeight = _viewer2D.get('viewerHeight');
355
- var SVGWidth = _viewer2D.get('SVGWidth');
356
- var SVGHeight = _viewer2D.get('SVGHeight');
357
- var cacheKey = "".concat(width, ":").concat(height, ":").concat(viewerWidth, ":").concat(viewerHeight, ":").concat(SVGWidth, ":").concat(SVGHeight);
341
+ var v = _viewer2D.toJS();
342
+
343
+ // Only do the "center viewer2D if e/f are zero" logic.
344
+ // No need to build keys from unrelated parts of state.
345
+ if (v.e !== 0 || v.f !== 0) return extractedState;
346
+
347
+ // Build a cache key ONLY for this viewer2D-centering computation.
348
+ var cacheKey = "".concat(width, ":").concat(height, ":").concat(v.viewerWidth, ":").concat(v.viewerHeight, ":").concat(v.SVGWidth, ":").concat(v.SVGHeight);
358
349
  if (this._cachedViewer2DKey === cacheKey && this._cachedExtractedState) {
359
350
  return this._cachedExtractedState;
360
351
  }
361
352
  var centeredViewer2D = _viewer2D.merge({
362
- e: viewerWidth / 2 - SVGWidth / 2,
363
- f: viewerHeight / 2 - SVGHeight / 2,
353
+ e: v.viewerWidth / 2 - v.SVGWidth / 2,
354
+ f: v.viewerHeight / 2 - v.SVGHeight / 2,
364
355
  a: 0.99,
365
356
  d: 0.99
366
357
  });
package/es/WorkSpace.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
2
2
  import _asyncToGenerator from "@babel/runtime/helpers/esm/asyncToGenerator";
3
3
  import _regeneratorRuntime from "@babel/runtime/regenerator";
4
- import React, { useState } from 'react';
4
+ import React, { useEffect, useState } from 'react';
5
5
  import { Map } from 'immutable';
6
6
  import { useResizeDetector } from 'react-resize-detector';
7
7
  import projectItemsCatalog from "./mocks/projectItemsCatalog.json";
@@ -62,6 +62,13 @@ function WorkSpace(props) {
62
62
  _useState2 = _slicedToArray(_useState, 2),
63
63
  externalEvent = _useState2[0],
64
64
  setExternalEvent = _useState2[1];
65
+ useEffect(function () {
66
+ setExternalEvent({
67
+ type: EXTERNAL_EVENT_LOAD_PROJECT,
68
+ // send request for sync scene data to 3DTool
69
+ payload: JSON.parse(mockProps.projectElement[0].project_data)
70
+ });
71
+ }, []);
65
72
  var offset = 5;
66
73
  return /*#__PURE__*/React.createElement("div", {
67
74
  className: "flex gap-4"
package/es/index.js CHANGED
@@ -5,71 +5,25 @@ 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
- import _toConsumableArray from "@babel/runtime/helpers/esm/toConsumableArray";
9
8
  function _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }
10
9
  function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }
11
10
  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; } } }; }
12
11
  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; } }
13
12
  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; }
14
13
  import _regeneratorRuntime from "@babel/runtime/regenerator";
15
- // kitchen-simulator/index.js (or wherever renderKitchenSimulator lives)
16
14
  import React from 'react';
17
- import { createRoot } from 'react-dom/client';
18
- import LiteRenderer from "./LiteRenderer";
19
15
  import * as Three from 'three';
16
+ import LiteRenderer from "./LiteRenderer";
17
+ import { createRoot } from 'react-dom/client';
20
18
  var ROOT_KEY = '__kitchenSimulatorRoot__';
21
19
  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
- };
20
+ function nextFrame() {
21
+ return new Promise(function (resolve) {
22
+ return requestAnimationFrame(resolve);
23
+ });
70
24
  }
71
25
 
72
- // ---- Your URL rewrite + TextureLoader patch stays as you had it ----
26
+ // DIY-714 [Temp Fix] Rewrite API URLs
73
27
  var API_HOST_REGEX = /(https?:\/\/)?(api\.diydesignspace\.com|api\.addovisuals\.com|127\.0\.0\.1:4002)/;
74
28
  var API_HOST_REPLACEMENT = 'https://api-old.diydesignspace.com';
75
29
  function rewriteApiUrl(url) {
@@ -134,7 +88,7 @@ function installGltfTracker() {
134
88
  var s = typeof url === 'string' ? url : (_url$toString = url === null || url === void 0 || (_url$toString2 = url.toString) === null || _url$toString2 === void 0 ? void 0 : _url$toString2.call(url)) !== null && _url$toString !== void 0 ? _url$toString : '';
135
89
  var u = s.toLowerCase().split('?')[0]; // ignore cache params
136
90
  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');
137
- } catch (_unused2) {
91
+ } catch (_unused) {
138
92
  return false;
139
93
  }
140
94
  };
@@ -171,8 +125,8 @@ function installGltfTracker() {
171
125
  XHR.prototype.open = function (method, url) {
172
126
  var _g$originalOpen;
173
127
  this.__is3dAssetRequest = is3dAssetUrl(url);
174
- for (var _len4 = arguments.length, rest = new Array(_len4 > 2 ? _len4 - 2 : 0), _key4 = 2; _key4 < _len4; _key4++) {
175
- rest[_key4 - 2] = arguments[_key4];
128
+ for (var _len = arguments.length, rest = new Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) {
129
+ rest[_key - 2] = arguments[_key];
176
130
  }
177
131
  return (_g$originalOpen = g.originalOpen).call.apply(_g$originalOpen, [this, method, url].concat(rest));
178
132
  };
@@ -195,8 +149,8 @@ function installGltfTracker() {
195
149
  this.addEventListener('abort', _done);
196
150
  this.addEventListener('timeout', _done);
197
151
  }
198
- for (var _len5 = arguments.length, args = new Array(_len5), _key5 = 0; _key5 < _len5; _key5++) {
199
- args[_key5] = arguments[_key5];
152
+ for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
153
+ args[_key2] = arguments[_key2];
200
154
  }
201
155
  return g.originalSend.apply(this, args);
202
156
  };
@@ -206,9 +160,9 @@ function installGltfTracker() {
206
160
  g.originalFetch = window.fetch;
207
161
  if (typeof g.originalFetch === 'function') {
208
162
  window.fetch = /*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee2() {
209
- var _len6,
163
+ var _len3,
210
164
  args,
211
- _key6,
165
+ _key3,
212
166
  input,
213
167
  init,
214
168
  newUrl,
@@ -217,8 +171,8 @@ function installGltfTracker() {
217
171
  return _regeneratorRuntime.wrap(function (_context2) {
218
172
  while (1) switch (_context2.prev = _context2.next) {
219
173
  case 0:
220
- for (_len6 = _args2.length, args = new Array(_len6), _key6 = 0; _key6 < _len6; _key6++) {
221
- args[_key6] = _args2[_key6];
174
+ for (_len3 = _args2.length, args = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {
175
+ args[_key3] = _args2[_key3];
222
176
  }
223
177
  input = args[0], init = args[1]; // DIY-714 [Temp Fix] Rewrite API URLs
224
178
  if (typeof input === 'string') {
@@ -404,104 +358,92 @@ export function renderKitchenSimulator(container) {
404
358
  var _props$framesPerEvent, _props$waitForGltfIdl, _props$gltfTimeoutMs;
405
359
  var props = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
406
360
  if (!container) throw new Error('renderKitchenSimulator: container is required');
407
- var DEBUG_KEY = '__kitchenSimulatorDebug__';
408
- var debugEnabled = !!props.debug || typeof window !== 'undefined' && !!window[DEBUG_KEY];
409
- var _makeLogger = makeLogger(function () {
410
- return debugEnabled;
411
- }),
412
- log = _makeLogger.log,
413
- warn = _makeLogger.warn,
414
- error = _makeLogger.error;
415
361
 
416
362
  // ✅ Reuse existing API
417
363
  if (container[API_KEY]) {
418
364
  var _container$API_KEY$__, _container$API_KEY;
419
- log('Reusing existing API; calling __render with new props');
420
365
  (_container$API_KEY$__ = (_container$API_KEY = container[API_KEY]).__render) === null || _container$API_KEY$__ === void 0 || _container$API_KEY$__.call(_container$API_KEY, props);
421
366
  return container[API_KEY];
422
367
  }
423
368
 
424
- // ✅ Root
369
+ // ✅ Reuse root
425
370
  var root = container[ROOT_KEY];
426
371
  if (!root) {
427
372
  root = createRoot(container);
428
373
  container[ROOT_KEY] = root;
429
- log('Created new React root');
430
374
  }
431
375
  var setExternalEventFn = null;
432
376
  var destroyed = false;
433
377
  var queue = [];
434
378
  var pendingMarkers = new Set();
435
379
  var MARKER = Symbol('marker');
380
+ var gltfTracker = installGltfTracker();
436
381
 
437
- // keep your tracker
438
- var gltfTracker = installGltfTracker(debugEnabled);
382
+ // FAST defaults (safe)
439
383
  var defaultFramesPerEvent = (_props$framesPerEvent = props.framesPerEvent) !== null && _props$framesPerEvent !== void 0 ? _props$framesPerEvent : 1;
440
384
  var waitForAssets = (_props$waitForGltfIdl = props.waitForGltfIdleAfterEachEvent) !== null && _props$waitForGltfIdl !== void 0 ? _props$waitForGltfIdl : true;
441
385
  var defaultTimeout = (_props$gltfTimeoutMs = props.gltfTimeoutMs) !== null && _props$gltfTimeoutMs !== void 0 ? _props$gltfTimeoutMs : 30000;
442
- var draining = false;
443
386
 
444
- // ---- Ready gate: mounted & setExternalEventFn installed ----
445
- var readyResolve = null;
446
- var readyReject = null;
447
- var readyPromise = new Promise(function (res, rej) {
448
- readyResolve = res;
449
- readyReject = rej;
450
- });
387
+ // If you want ultra-fast UI responsiveness, you can disable waiting per-event
388
+ // and only wait on “important” events, see comment in settle() below.
451
389
 
452
- // ---- Catalog-ready gate (NEW) ----
453
- var catalogReadyResolve = null;
454
- var catalogReadyPromise = new Promise(function (res) {
455
- catalogReadyResolve = res;
456
- });
457
- var catalogReady = false;
458
- function nextFrame() {
459
- return new Promise(function (resolve) {
460
- return requestAnimationFrame(resolve);
461
- });
390
+ var draining = false;
391
+ function isSyncScene(ev) {
392
+ var _ev$payload;
393
+ return (ev === null || ev === void 0 ? void 0 : ev.type) === 'EXTERNAL_EVENT_SYNC_SCENE' || (ev === null || ev === void 0 || (_ev$payload = ev.payload) === null || _ev$payload === void 0 ? void 0 : _ev$payload.mode) === 'sync-scene' || (ev === null || ev === void 0 ? void 0 : ev.__sync) === true;
462
394
  }
463
395
  function settle(_x2) {
464
396
  return _settle.apply(this, arguments);
465
397
  }
466
398
  function _settle() {
467
- _settle = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee8(ev) {
468
- var _ev$framesPerEvent, _ev$waitForGltfIdleAf, _ev$gltfTimeoutMs;
469
- var frames, shouldWait, timeoutMs, i;
470
- return _regeneratorRuntime.wrap(function (_context8) {
471
- while (1) switch (_context8.prev = _context8.next) {
399
+ _settle = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee7(ev) {
400
+ var _ev$framesPerEvent, _ev$waitForGltfIdleAf;
401
+ var frames, i, shouldWait, _ev$gltfTimeoutMs, timeoutMs;
402
+ return _regeneratorRuntime.wrap(function (_context7) {
403
+ while (1) switch (_context7.prev = _context7.next) {
472
404
  case 0:
473
- frames = (_ev$framesPerEvent = ev === null || ev === void 0 ? void 0 : ev.framesPerEvent) !== null && _ev$framesPerEvent !== void 0 ? _ev$framesPerEvent : defaultFramesPerEvent;
474
- shouldWait = (_ev$waitForGltfIdleAf = ev === null || ev === void 0 ? void 0 : ev.waitForGltfIdleAfterEachEvent) !== null && _ev$waitForGltfIdleAf !== void 0 ? _ev$waitForGltfIdleAf : waitForAssets;
475
- timeoutMs = (_ev$gltfTimeoutMs = ev === null || ev === void 0 ? void 0 : ev.gltfTimeoutMs) !== null && _ev$gltfTimeoutMs !== void 0 ? _ev$gltfTimeoutMs : defaultTimeout; // RAF frames
405
+ frames = (_ev$framesPerEvent = ev === null || ev === void 0 ? void 0 : ev.framesPerEvent) !== null && _ev$framesPerEvent !== void 0 ? _ev$framesPerEvent : defaultFramesPerEvent; // (1) allow react/reducers to run (fixes “must zoom to see updates”)
476
406
  i = 0;
477
407
  case 1:
478
408
  if (!(i < frames)) {
479
- _context8.next = 3;
409
+ _context7.next = 3;
480
410
  break;
481
411
  }
482
- _context8.next = 2;
412
+ _context7.next = 2;
483
413
  return nextFrame();
484
414
  case 2:
485
- i++;
486
- _context8.next = 1;
415
+ i += 1;
416
+ _context7.next = 1;
487
417
  break;
488
418
  case 3:
419
+ // (2) optionally wait for assets
420
+ // fastest safe approach: keep ON for events that add/replace/load models
421
+ // You can override per-event via ev.waitForGltfIdleAfterEachEvent = false
422
+ shouldWait = (_ev$waitForGltfIdleAf = ev === null || ev === void 0 ? void 0 : ev.waitForGltfIdleAfterEachEvent) !== null && _ev$waitForGltfIdleAf !== void 0 ? _ev$waitForGltfIdleAf : waitForAssets;
489
423
  if (!shouldWait) {
490
- _context8.next = 4;
424
+ _context7.next = 4;
491
425
  break;
492
426
  }
493
- _context8.next = 4;
427
+ timeoutMs = (_ev$gltfTimeoutMs = ev === null || ev === void 0 ? void 0 : ev.gltfTimeoutMs) !== null && _ev$gltfTimeoutMs !== void 0 ? _ev$gltfTimeoutMs : defaultTimeout;
428
+ _context7.next = 4;
494
429
  return gltfTracker.waitForIdle({
495
430
  timeoutMs: timeoutMs
496
431
  });
497
432
  case 4:
498
- _context8.next = 5;
433
+ _context7.next = 5;
499
434
  return nextFrame();
500
435
  case 5:
436
+ if (!isSyncScene(ev)) {
437
+ _context7.next = 6;
438
+ break;
439
+ }
440
+ _context7.next = 6;
441
+ return nextFrame();
442
+ case 6:
501
443
  case "end":
502
- return _context8.stop();
444
+ return _context7.stop();
503
445
  }
504
- }, _callee8);
446
+ }, _callee7);
505
447
  }));
506
448
  return _settle.apply(this, arguments);
507
449
  }
@@ -509,69 +451,66 @@ export function renderKitchenSimulator(container) {
509
451
  return _drain.apply(this, arguments);
510
452
  }
511
453
  function _drain() {
512
- _drain = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee9() {
513
- var item, _err$message, _t;
514
- return _regeneratorRuntime.wrap(function (_context9) {
515
- while (1) switch (_context9.prev = _context9.next) {
454
+ _drain = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee8() {
455
+ var item, _t;
456
+ return _regeneratorRuntime.wrap(function (_context8) {
457
+ while (1) switch (_context8.prev = _context8.next) {
516
458
  case 0:
517
459
  if (!(draining || destroyed)) {
518
- _context9.next = 1;
460
+ _context8.next = 1;
519
461
  break;
520
462
  }
521
- return _context9.abrupt("return");
463
+ return _context8.abrupt("return");
522
464
  case 1:
523
465
  draining = true;
524
- _context9.prev = 2;
525
- _context9.next = 3;
526
- return readyPromise;
466
+ _context8.prev = 2;
527
467
  case 3:
528
468
  if (!(!destroyed && queue.length)) {
529
- _context9.next = 10;
469
+ _context8.next = 10;
530
470
  break;
531
471
  }
532
472
  if (setExternalEventFn) {
533
- _context9.next = 5;
473
+ _context8.next = 5;
534
474
  break;
535
475
  }
536
- _context9.next = 4;
476
+ _context8.next = 4;
537
477
  return nextFrame();
538
478
  case 4:
539
- return _context9.abrupt("continue", 3);
479
+ return _context8.abrupt("continue", 3);
540
480
  case 5:
541
481
  item = queue.shift();
542
482
  if (!(item && item.__marker === MARKER)) {
543
- _context9.next = 6;
483
+ _context8.next = 6;
544
484
  break;
545
485
  }
546
486
  pendingMarkers["delete"](item.token);
547
- return _context9.abrupt("continue", 3);
487
+ return _context8.abrupt("continue", 3);
548
488
  case 6:
549
- _context9.prev = 6;
489
+ _context8.prev = 6;
550
490
  setExternalEventFn(item);
551
- _context9.next = 7;
491
+ _context8.next = 7;
552
492
  return settle(item);
553
493
  case 7:
554
- _context9.next = 9;
494
+ _context8.next = 9;
555
495
  break;
556
496
  case 8:
557
- _context9.prev = 8;
558
- _t = _context9["catch"](6);
559
- error('drain:event failed', {
560
- err: (_err$message = _t === null || _t === void 0 ? void 0 : _t.message) !== null && _err$message !== void 0 ? _err$message : _t,
561
- type: item === null || item === void 0 ? void 0 : item.type
562
- });
497
+ _context8.prev = 8;
498
+ _t = _context8["catch"](6);
499
+ console.error('[kitchen-simulator] event failed:', item, _t);
500
+ // IMPORTANT: continue so we can eventually consume the marker
501
+ // Optionally you can decide to clear remaining queue here.
563
502
  case 9:
564
- _context9.next = 3;
503
+ _context8.next = 3;
565
504
  break;
566
505
  case 10:
567
- _context9.prev = 10;
506
+ _context8.prev = 10;
568
507
  draining = false;
569
- return _context9.finish(10);
508
+ return _context8.finish(10);
570
509
  case 11:
571
510
  case "end":
572
- return _context9.stop();
511
+ return _context8.stop();
573
512
  }
574
- }, _callee9, null, [[2,, 10, 11], [6, 8]]);
513
+ }, _callee8, null, [[2,, 10, 11], [6, 8]]);
575
514
  }));
576
515
  return _drain.apply(this, arguments);
577
516
  }
@@ -592,62 +531,23 @@ export function renderKitchenSimulator(container) {
592
531
  value: function componentDidMount() {
593
532
  var _this3 = this;
594
533
  this._mounted = true;
595
- log('Wrapper mounted -> ready');
596
534
  setExternalEventFn = function setExternalEventFn(newEvent) {
597
535
  if (!_this3._mounted) return;
598
536
  _this3.setState({
599
537
  externalEvent: newEvent
600
538
  });
601
539
  };
602
- if (readyResolve) {
603
- readyResolve(true);
604
- readyResolve = null;
605
- }
606
540
  }
607
541
  }, {
608
542
  key: "componentWillUnmount",
609
543
  value: function componentWillUnmount() {
610
544
  this._mounted = false;
611
545
  setExternalEventFn = null;
612
- if (readyReject) {
613
- readyReject(new Error('Wrapper unmounted before ready'));
614
- readyReject = null;
615
- }
616
546
  }
617
547
  }, {
618
548
  key: "render",
619
549
  value: function render() {
620
- var userOnInternalEvent = this.props.onInternalEvent;
621
-
622
- // ✅ Wrap internal event to detect catalog readiness
623
- var onInternalEventWrapped = /*#__PURE__*/function () {
624
- var _ref5 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee6(evt, callback) {
625
- return _regeneratorRuntime.wrap(function (_context6) {
626
- while (1) switch (_context6.prev = _context6.next) {
627
- case 0:
628
- // IMPORTANT: first time we see INTERNAL_EVENT_ITEMS_CATALOG,
629
- // it means catalog init path ran and tool is requesting items.
630
- if (!catalogReady && (evt === null || evt === void 0 ? void 0 : evt.type) === 'INTERNAL_EVENT_ITEMS_CATALOG') {
631
- catalogReady = true;
632
- if (catalogReadyResolve) {
633
- catalogReadyResolve(true);
634
- catalogReadyResolve = null;
635
- }
636
- log('Catalog is ready (observed INTERNAL_EVENT_ITEMS_CATALOG)');
637
- }
638
- return _context6.abrupt("return", userOnInternalEvent === null || userOnInternalEvent === void 0 ? void 0 : userOnInternalEvent(evt, callback));
639
- case 1:
640
- case "end":
641
- return _context6.stop();
642
- }
643
- }, _callee6);
644
- }));
645
- return function onInternalEventWrapped(_x3, _x4) {
646
- return _ref5.apply(this, arguments);
647
- };
648
- }();
649
550
  return /*#__PURE__*/React.createElement(LiteRenderer, _extends({}, this.props, {
650
- onInternalEvent: onInternalEventWrapped,
651
551
  externalEvent: this.state.externalEvent
652
552
  }));
653
553
  }
@@ -657,26 +557,36 @@ export function renderKitchenSimulator(container) {
657
557
  __render: function __render(nextProps) {
658
558
  root.render(/*#__PURE__*/React.createElement(Wrapper, nextProps));
659
559
  },
660
- // ✅ Host can await mount
661
- whenReady: function whenReady() {
662
- return readyPromise;
663
- },
664
- // ✅ Host can await catalog init (NEW)
665
- whenCatalogReady: function whenCatalogReady() {
666
- return catalogReadyPromise;
667
- },
560
+ // ✅ host can query current inFlight
668
561
  getGltfInFlight: function getGltfInFlight() {
669
562
  return gltfTracker.getInFlight();
670
563
  },
564
+ // ✅ host can subscribe to inFlight changes (loader)
671
565
  subscribeGltfInFlight: function subscribeGltfInFlight(cb) {
672
566
  return gltfTracker.subscribe(cb);
673
567
  },
568
+ setExternalEventImmediate: function setExternalEventImmediate(event) {
569
+ // If Wrapper is mounted, bypass queue/drain and push straight into state
570
+ if (setExternalEventFn) {
571
+ try {
572
+ setExternalEventFn(event);
573
+ return true; // applied immediately
574
+ } catch (e) {
575
+ console.error('[kitchen-simulator] setExternalEventImmediate failed', e);
576
+ // fall through to queue
577
+ }
578
+ }
579
+
580
+ // Wrapper not ready yet: make it the NEXT thing processed
581
+ queue.unshift(event);
582
+ drain();
583
+ return false; // queued (not immediate)
584
+ },
674
585
  sendExternalEvents: function sendExternalEvents(eventOrEvents) {
675
- var _ref6 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
676
- _ref6$timeoutMs = _ref6.timeoutMs,
677
- timeoutMs = _ref6$timeoutMs === void 0 ? 60000 : _ref6$timeoutMs;
586
+ var _ref5 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
587
+ _ref5$timeoutMs = _ref5.timeoutMs,
588
+ timeoutMs = _ref5$timeoutMs === void 0 ? 60000 : _ref5$timeoutMs;
678
589
  var events = Array.isArray(eventOrEvents) ? eventOrEvents : [eventOrEvents];
679
- var token = Symbol('batch');
680
590
  var _iterator2 = _createForOfIteratorHelper(events),
681
591
  _step2;
682
592
  try {
@@ -689,69 +599,82 @@ export function renderKitchenSimulator(container) {
689
599
  } finally {
690
600
  _iterator2.f();
691
601
  }
602
+ var token = Symbol('batch');
692
603
  pendingMarkers.add(token);
693
604
  queue.push({
694
605
  __marker: MARKER,
695
606
  token: token
696
607
  });
697
608
  drain();
609
+
610
+ // resolve when marker cleared
698
611
  return new Promise(function (resolve) {
699
612
  var start = Date.now();
700
613
  var check = /*#__PURE__*/function () {
701
- var _ref7 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee7() {
702
- return _regeneratorRuntime.wrap(function (_context7) {
703
- while (1) switch (_context7.prev = _context7.next) {
614
+ var _ref6 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee6() {
615
+ return _regeneratorRuntime.wrap(function (_context6) {
616
+ while (1) switch (_context6.prev = _context6.next) {
704
617
  case 0:
705
618
  if (destroyed) {
706
- _context7.next = 4;
619
+ _context6.next = 4;
707
620
  break;
708
621
  }
709
622
  if (pendingMarkers.has(token)) {
710
- _context7.next = 1;
623
+ _context6.next = 1;
711
624
  break;
712
625
  }
713
626
  resolve(true);
714
- return _context7.abrupt("return");
627
+ return _context6.abrupt("return");
715
628
  case 1:
716
629
  if (!(Date.now() - start > timeoutMs)) {
717
- _context7.next = 2;
630
+ _context6.next = 2;
718
631
  break;
719
632
  }
720
- error('sendExternalEvents timed out', {
721
- timeoutMs: timeoutMs
722
- });
633
+ console.error('[kitchen-simulator] sendExternalEvents timed out');
723
634
  pendingMarkers["delete"](token); // fail-open
724
635
  resolve(false);
725
- return _context7.abrupt("return");
636
+ return _context6.abrupt("return");
726
637
  case 2:
727
- _context7.next = 3;
638
+ _context6.next = 3;
728
639
  return nextFrame();
729
640
  case 3:
730
- _context7.next = 0;
641
+ _context6.next = 0;
731
642
  break;
732
643
  case 4:
733
644
  resolve(false);
734
645
  case 5:
735
646
  case "end":
736
- return _context7.stop();
647
+ return _context6.stop();
737
648
  }
738
- }, _callee7);
649
+ }, _callee6);
739
650
  }));
740
651
  return function check() {
741
- return _ref7.apply(this, arguments);
652
+ return _ref6.apply(this, arguments);
742
653
  };
743
654
  }();
744
655
  check();
745
656
  });
746
657
  },
747
- unmount: function unmount() {
748
- destroyed = true;
658
+ updateExternalEvent: function updateExternalEvent(e) {
659
+ return api.sendExternalEvents(e);
660
+ },
661
+ clearQueue: function clearQueue() {
749
662
  queue.length = 0;
750
663
  pendingMarkers.clear();
664
+ },
665
+ unmount: function unmount() {
666
+ destroyed = true;
667
+ api.clearQueue();
751
668
  gltfTracker.uninstall();
752
- root.unmount();
753
- container[ROOT_KEY] = null;
754
- container[API_KEY] = null;
669
+ var doUnmount = function doUnmount() {
670
+ try {
671
+ root.unmount();
672
+ } finally {
673
+ container[ROOT_KEY] = null;
674
+ container[API_KEY] = null;
675
+ }
676
+ };
677
+ if (typeof queueMicrotask === 'function') queueMicrotask(doUnmount);else setTimeout(doUnmount, 0);
755
678
  }
756
679
  };
757
680
  api.__render(props);
@@ -23,6 +23,9 @@ export default function (state, action) {
23
23
  case UPDATE_POPUP_OPEN:
24
24
  return Item.updatePopupOpen(state, action.value).updatedState;
25
25
  case SELECT_ITEM:
26
+ state = state.merge({
27
+ sceneHistory: history.historyPush(state.sceneHistory, state.scene)
28
+ });
26
29
  return Item.select(state, action.layerID, action.itemID).updatedState;
27
30
  case SELECT_TOOL_DRAWING_ITEM:
28
31
  state = state.merge({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kitchen-simulator",
3
- "version": "6.0.3-react.18",
3
+ "version": "7.0.0-react-18",
4
4
  "description": "It is a kitchen simulator (self-contained micro-frontend).",
5
5
  "license": "MIT",
6
6
  "module": "es/index.js",