kitchen-simulator 6.0.2-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";
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; })(); }
9
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; } } }; }
10
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; } }
11
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; }
12
13
  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)
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) {
@@ -81,112 +35,415 @@ Three.TextureLoader.prototype.load = function (url, onLoad, onProgress, onError)
81
35
  return originalTextureLoad.call(this, newUrl, onLoad, onProgress, onError);
82
36
  };
83
37
 
84
- // ---- keep your installGltfTracker exactly as you have it ----
85
- // import / paste your installGltfTracker(debug) here
86
- // (omitted in this snippet for brevity)
38
+ /**
39
+ * Track 3D asset network activity (gltf/glb/bin/textures/hdr/etc)
40
+ * Ref-counted global install so multiple instances don't clobber each other.
41
+ */
42
+ function installGltfTracker() {
43
+ if (typeof window === 'undefined') {
44
+ var _subscribe = function _subscribe() {
45
+ return function () {};
46
+ };
47
+ return {
48
+ getInFlight: function getInFlight() {
49
+ return 0;
50
+ },
51
+ waitForIdle: function () {
52
+ var _waitForIdle = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee() {
53
+ return _regeneratorRuntime.wrap(function (_context) {
54
+ while (1) switch (_context.prev = _context.next) {
55
+ case 0:
56
+ return _context.abrupt("return", true);
57
+ case 1:
58
+ case "end":
59
+ return _context.stop();
60
+ }
61
+ }, _callee);
62
+ }));
63
+ function waitForIdle() {
64
+ return _waitForIdle.apply(this, arguments);
65
+ }
66
+ return waitForIdle;
67
+ }(),
68
+ uninstall: function uninstall() {},
69
+ subscribe: _subscribe
70
+ };
71
+ }
72
+ var GLOBAL_KEY = '__kitchenSimulatorGltfTracker__';
73
+ if (!window[GLOBAL_KEY]) {
74
+ window[GLOBAL_KEY] = {
75
+ refCount: 0,
76
+ inFlight: 0,
77
+ listeners: new Set(),
78
+ installed: false,
79
+ originalFetch: null,
80
+ originalOpen: null,
81
+ originalSend: null
82
+ };
83
+ }
84
+ var g = window[GLOBAL_KEY];
85
+ var is3dAssetUrl = function is3dAssetUrl(url) {
86
+ try {
87
+ var _url$toString, _url$toString2;
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 : '';
89
+ var u = s.toLowerCase().split('?')[0]; // ignore cache params
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');
91
+ } catch (_unused) {
92
+ return false;
93
+ }
94
+ };
95
+ var notify = function notify() {
96
+ var _iterator = _createForOfIteratorHelper(g.listeners),
97
+ _step;
98
+ try {
99
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
100
+ var fn = _step.value;
101
+ fn(g.inFlight);
102
+ }
103
+ } catch (err) {
104
+ _iterator.e(err);
105
+ } finally {
106
+ _iterator.f();
107
+ }
108
+ };
109
+ var subscribe = function subscribe(fn) {
110
+ g.listeners.add(fn);
111
+ fn(g.inFlight); // sync emit on subscribe
112
+ return function () {
113
+ return g.listeners["delete"](fn);
114
+ };
115
+ };
116
+ var installIfNeeded = function installIfNeeded() {
117
+ var _XHR$prototype, _XHR$prototype2;
118
+ if (g.installed) return;
119
+
120
+ // ---- XHR hook ----
121
+ var XHR = window.XMLHttpRequest;
122
+ if (XHR !== null && XHR !== void 0 && (_XHR$prototype = XHR.prototype) !== null && _XHR$prototype !== void 0 && _XHR$prototype.open && XHR !== null && XHR !== void 0 && (_XHR$prototype2 = XHR.prototype) !== null && _XHR$prototype2 !== void 0 && _XHR$prototype2.send) {
123
+ g.originalOpen = XHR.prototype.open;
124
+ g.originalSend = XHR.prototype.send;
125
+ XHR.prototype.open = function (method, url) {
126
+ var _g$originalOpen;
127
+ this.__is3dAssetRequest = is3dAssetUrl(url);
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];
130
+ }
131
+ return (_g$originalOpen = g.originalOpen).call.apply(_g$originalOpen, [this, method, url].concat(rest));
132
+ };
133
+ XHR.prototype.send = function () {
134
+ var _this = this;
135
+ if (this.__is3dAssetRequest) {
136
+ g.inFlight += 1;
137
+ notify();
138
+ var _done = function done() {
139
+ g.inFlight -= 1;
140
+ if (g.inFlight < 0) g.inFlight = 0;
141
+ notify();
142
+ _this.removeEventListener('loadend', _done);
143
+ _this.removeEventListener('error', _done);
144
+ _this.removeEventListener('abort', _done);
145
+ _this.removeEventListener('timeout', _done);
146
+ };
147
+ this.addEventListener('loadend', _done);
148
+ this.addEventListener('error', _done);
149
+ this.addEventListener('abort', _done);
150
+ this.addEventListener('timeout', _done);
151
+ }
152
+ for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
153
+ args[_key2] = arguments[_key2];
154
+ }
155
+ return g.originalSend.apply(this, args);
156
+ };
157
+ }
158
+
159
+ // ---- fetch hook ----
160
+ g.originalFetch = window.fetch;
161
+ if (typeof g.originalFetch === 'function') {
162
+ window.fetch = /*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee2() {
163
+ var _len3,
164
+ args,
165
+ _key3,
166
+ input,
167
+ init,
168
+ newUrl,
169
+ track,
170
+ _args2 = arguments;
171
+ return _regeneratorRuntime.wrap(function (_context2) {
172
+ while (1) switch (_context2.prev = _context2.next) {
173
+ case 0:
174
+ for (_len3 = _args2.length, args = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {
175
+ args[_key3] = _args2[_key3];
176
+ }
177
+ input = args[0], init = args[1]; // DIY-714 [Temp Fix] Rewrite API URLs
178
+ if (typeof input === 'string') {
179
+ input = rewriteApiUrl(input);
180
+ } else if (input instanceof Request) {
181
+ newUrl = rewriteApiUrl(input.url);
182
+ input = new Request(newUrl, input);
183
+ }
184
+ track = is3dAssetUrl(input);
185
+ if (track) {
186
+ _context2.next = 1;
187
+ break;
188
+ }
189
+ return _context2.abrupt("return", g.originalFetch.call(this, input, init));
190
+ case 1:
191
+ g.inFlight += 1;
192
+ notify();
193
+ _context2.prev = 2;
194
+ _context2.next = 3;
195
+ return g.originalFetch.call(this, input, init);
196
+ case 3:
197
+ return _context2.abrupt("return", _context2.sent);
198
+ case 4:
199
+ _context2.prev = 4;
200
+ g.inFlight -= 1;
201
+ if (g.inFlight < 0) g.inFlight = 0;
202
+ notify();
203
+ return _context2.finish(4);
204
+ case 5:
205
+ case "end":
206
+ return _context2.stop();
207
+ }
208
+ }, _callee2, this, [[2,, 4, 5]]);
209
+ }));
210
+ }
211
+ g.installed = true;
212
+ };
213
+
214
+ // “No grace” but stable: idle must remain idle for 2 RAF frames
215
+ function waitStableIdle2Frames() {
216
+ return _waitStableIdle2Frames.apply(this, arguments);
217
+ }
218
+ function _waitStableIdle2Frames() {
219
+ _waitStableIdle2Frames = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee5() {
220
+ return _regeneratorRuntime.wrap(function (_context5) {
221
+ while (1) switch (_context5.prev = _context5.next) {
222
+ case 0:
223
+ _context5.next = 1;
224
+ return nextFrame();
225
+ case 1:
226
+ if (!(g.inFlight !== 0)) {
227
+ _context5.next = 2;
228
+ break;
229
+ }
230
+ return _context5.abrupt("return", false);
231
+ case 2:
232
+ _context5.next = 3;
233
+ return nextFrame();
234
+ case 3:
235
+ return _context5.abrupt("return", g.inFlight === 0);
236
+ case 4:
237
+ case "end":
238
+ return _context5.stop();
239
+ }
240
+ }, _callee5);
241
+ }));
242
+ return _waitStableIdle2Frames.apply(this, arguments);
243
+ }
244
+ var waitForIdle = /*#__PURE__*/function () {
245
+ var _ref2 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee4() {
246
+ var _ref3,
247
+ _ref3$timeoutMs,
248
+ timeoutMs,
249
+ _args4 = arguments;
250
+ return _regeneratorRuntime.wrap(function (_context4) {
251
+ while (1) switch (_context4.prev = _context4.next) {
252
+ case 0:
253
+ _ref3 = _args4.length > 0 && _args4[0] !== undefined ? _args4[0] : {}, _ref3$timeoutMs = _ref3.timeoutMs, timeoutMs = _ref3$timeoutMs === void 0 ? 30000 : _ref3$timeoutMs;
254
+ _context4.next = 1;
255
+ return waitStableIdle2Frames();
256
+ case 1:
257
+ if (!_context4.sent) {
258
+ _context4.next = 2;
259
+ break;
260
+ }
261
+ return _context4.abrupt("return", true);
262
+ case 2:
263
+ return _context4.abrupt("return", new Promise(function (resolve, reject) {
264
+ var unsub = null;
265
+ var finished = false;
266
+ var finishOk = function finishOk() {
267
+ if (finished) return;
268
+ finished = true;
269
+ if (unsub) unsub();
270
+ clearTimeout(timer);
271
+ resolve(true);
272
+ };
273
+ var finishErr = function finishErr(err) {
274
+ if (finished) return;
275
+ finished = true;
276
+ if (unsub) unsub();
277
+ clearTimeout(timer);
278
+ reject(err);
279
+ };
87
280
 
281
+ // ✅ Real timeout no matter what happens with inFlight changes
282
+ var timer = setTimeout(function () {
283
+ finishErr(new Error('3D assets did not become idle within timeout'));
284
+ }, timeoutMs);
285
+ var onChange = /*#__PURE__*/function () {
286
+ var _ref4 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee3(count) {
287
+ var stable;
288
+ return _regeneratorRuntime.wrap(function (_context3) {
289
+ while (1) switch (_context3.prev = _context3.next) {
290
+ case 0:
291
+ if (!finished) {
292
+ _context3.next = 1;
293
+ break;
294
+ }
295
+ return _context3.abrupt("return");
296
+ case 1:
297
+ if (!(count !== 0)) {
298
+ _context3.next = 2;
299
+ break;
300
+ }
301
+ return _context3.abrupt("return");
302
+ case 2:
303
+ _context3.next = 3;
304
+ return waitStableIdle2Frames();
305
+ case 3:
306
+ stable = _context3.sent;
307
+ if (stable) finishOk();
308
+ // else keep waiting
309
+ case 4:
310
+ case "end":
311
+ return _context3.stop();
312
+ }
313
+ }, _callee3);
314
+ }));
315
+ return function onChange(_x) {
316
+ return _ref4.apply(this, arguments);
317
+ };
318
+ }();
319
+ unsub = subscribe(onChange);
320
+ }));
321
+ case 3:
322
+ case "end":
323
+ return _context4.stop();
324
+ }
325
+ }, _callee4);
326
+ }));
327
+ return function waitForIdle() {
328
+ return _ref2.apply(this, arguments);
329
+ };
330
+ }();
331
+ var uninstall = function uninstall() {
332
+ var _XHR$prototype3, _XHR$prototype4;
333
+ g.refCount -= 1;
334
+ if (g.refCount > 0) return;
335
+ var XHR = window.XMLHttpRequest;
336
+ if (XHR !== null && XHR !== void 0 && (_XHR$prototype3 = XHR.prototype) !== null && _XHR$prototype3 !== void 0 && _XHR$prototype3.open && g.originalOpen) XHR.prototype.open = g.originalOpen;
337
+ if (XHR !== null && XHR !== void 0 && (_XHR$prototype4 = XHR.prototype) !== null && _XHR$prototype4 !== void 0 && _XHR$prototype4.send && g.originalSend) XHR.prototype.send = g.originalSend;
338
+ if (typeof g.originalFetch === 'function') window.fetch = g.originalFetch;
339
+ g.listeners.clear();
340
+ g.inFlight = 0;
341
+ g.installed = false;
342
+ g.originalFetch = null;
343
+ g.originalOpen = null;
344
+ g.originalSend = null;
345
+ };
346
+ g.refCount += 1;
347
+ installIfNeeded();
348
+ return {
349
+ getInFlight: function getInFlight() {
350
+ return g.inFlight;
351
+ },
352
+ waitForIdle: waitForIdle,
353
+ uninstall: uninstall,
354
+ subscribe: subscribe
355
+ };
356
+ }
88
357
  export function renderKitchenSimulator(container) {
89
358
  var _props$framesPerEvent, _props$waitForGltfIdl, _props$gltfTimeoutMs;
90
359
  var props = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
91
360
  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
361
 
101
362
  // ✅ Reuse existing API
102
363
  if (container[API_KEY]) {
103
364
  var _container$API_KEY$__, _container$API_KEY;
104
- log('Reusing existing API; calling __render with new props');
105
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);
106
366
  return container[API_KEY];
107
367
  }
108
368
 
109
- // ✅ Root
369
+ // ✅ Reuse root
110
370
  var root = container[ROOT_KEY];
111
371
  if (!root) {
112
372
  root = createRoot(container);
113
373
  container[ROOT_KEY] = root;
114
- log('Created new React root');
115
374
  }
116
375
  var setExternalEventFn = null;
117
376
  var destroyed = false;
118
377
  var queue = [];
119
378
  var pendingMarkers = new Set();
120
379
  var MARKER = Symbol('marker');
380
+ var gltfTracker = installGltfTracker();
121
381
 
122
- // keep your tracker
123
- var gltfTracker = installGltfTracker(debugEnabled);
382
+ // FAST defaults (safe)
124
383
  var defaultFramesPerEvent = (_props$framesPerEvent = props.framesPerEvent) !== null && _props$framesPerEvent !== void 0 ? _props$framesPerEvent : 1;
125
384
  var waitForAssets = (_props$waitForGltfIdl = props.waitForGltfIdleAfterEachEvent) !== null && _props$waitForGltfIdl !== void 0 ? _props$waitForGltfIdl : true;
126
385
  var defaultTimeout = (_props$gltfTimeoutMs = props.gltfTimeoutMs) !== null && _props$gltfTimeoutMs !== void 0 ? _props$gltfTimeoutMs : 30000;
127
- var draining = false;
128
386
 
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
- });
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.
136
389
 
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);
146
- });
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;
147
394
  }
148
- function settle(_x) {
395
+ function settle(_x2) {
149
396
  return _settle.apply(this, arguments);
150
397
  }
151
398
  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) {
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) {
157
404
  case 0:
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
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”)
161
406
  i = 0;
162
407
  case 1:
163
408
  if (!(i < frames)) {
164
- _context3.next = 3;
409
+ _context7.next = 3;
165
410
  break;
166
411
  }
167
- _context3.next = 2;
412
+ _context7.next = 2;
168
413
  return nextFrame();
169
414
  case 2:
170
- i++;
171
- _context3.next = 1;
415
+ i += 1;
416
+ _context7.next = 1;
172
417
  break;
173
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;
174
423
  if (!shouldWait) {
175
- _context3.next = 4;
424
+ _context7.next = 4;
176
425
  break;
177
426
  }
178
- _context3.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;
179
429
  return gltfTracker.waitForIdle({
180
430
  timeoutMs: timeoutMs
181
431
  });
182
432
  case 4:
183
- _context3.next = 5;
433
+ _context7.next = 5;
184
434
  return nextFrame();
185
435
  case 5:
436
+ if (!isSyncScene(ev)) {
437
+ _context7.next = 6;
438
+ break;
439
+ }
440
+ _context7.next = 6;
441
+ return nextFrame();
442
+ case 6:
186
443
  case "end":
187
- return _context3.stop();
444
+ return _context7.stop();
188
445
  }
189
- }, _callee3);
446
+ }, _callee7);
190
447
  }));
191
448
  return _settle.apply(this, arguments);
192
449
  }
@@ -194,145 +451,103 @@ export function renderKitchenSimulator(container) {
194
451
  return _drain.apply(this, arguments);
195
452
  }
196
453
  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) {
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) {
201
458
  case 0:
202
459
  if (!(draining || destroyed)) {
203
- _context4.next = 1;
460
+ _context8.next = 1;
204
461
  break;
205
462
  }
206
- return _context4.abrupt("return");
463
+ return _context8.abrupt("return");
207
464
  case 1:
208
465
  draining = true;
209
- _context4.prev = 2;
210
- _context4.next = 3;
211
- return readyPromise;
466
+ _context8.prev = 2;
212
467
  case 3:
213
468
  if (!(!destroyed && queue.length)) {
214
- _context4.next = 10;
469
+ _context8.next = 10;
215
470
  break;
216
471
  }
217
472
  if (setExternalEventFn) {
218
- _context4.next = 5;
473
+ _context8.next = 5;
219
474
  break;
220
475
  }
221
- _context4.next = 4;
476
+ _context8.next = 4;
222
477
  return nextFrame();
223
478
  case 4:
224
- return _context4.abrupt("continue", 3);
479
+ return _context8.abrupt("continue", 3);
225
480
  case 5:
226
481
  item = queue.shift();
227
482
  if (!(item && item.__marker === MARKER)) {
228
- _context4.next = 6;
483
+ _context8.next = 6;
229
484
  break;
230
485
  }
231
486
  pendingMarkers["delete"](item.token);
232
- return _context4.abrupt("continue", 3);
487
+ return _context8.abrupt("continue", 3);
233
488
  case 6:
234
- _context4.prev = 6;
489
+ _context8.prev = 6;
235
490
  setExternalEventFn(item);
236
- _context4.next = 7;
491
+ _context8.next = 7;
237
492
  return settle(item);
238
493
  case 7:
239
- _context4.next = 9;
494
+ _context8.next = 9;
240
495
  break;
241
496
  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
- });
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.
248
502
  case 9:
249
- _context4.next = 3;
503
+ _context8.next = 3;
250
504
  break;
251
505
  case 10:
252
- _context4.prev = 10;
506
+ _context8.prev = 10;
253
507
  draining = false;
254
- return _context4.finish(10);
508
+ return _context8.finish(10);
255
509
  case 11:
256
510
  case "end":
257
- return _context4.stop();
511
+ return _context8.stop();
258
512
  }
259
- }, _callee4, null, [[2,, 10, 11], [6, 8]]);
513
+ }, _callee8, null, [[2,, 10, 11], [6, 8]]);
260
514
  }));
261
515
  return _drain.apply(this, arguments);
262
516
  }
263
517
  var Wrapper = /*#__PURE__*/function (_React$Component) {
264
518
  function Wrapper(p) {
265
- var _this;
519
+ var _this2;
266
520
  _classCallCheck(this, Wrapper);
267
- _this = _callSuper(this, Wrapper, [p]);
268
- _this.state = {
521
+ _this2 = _callSuper(this, Wrapper, [p]);
522
+ _this2.state = {
269
523
  externalEvent: p.externalEvent || null
270
524
  };
271
- _this._mounted = false;
272
- return _this;
525
+ _this2._mounted = false;
526
+ return _this2;
273
527
  }
274
528
  _inherits(Wrapper, _React$Component);
275
529
  return _createClass(Wrapper, [{
276
530
  key: "componentDidMount",
277
531
  value: function componentDidMount() {
278
- var _this2 = this;
532
+ var _this3 = this;
279
533
  this._mounted = true;
280
- log('Wrapper mounted -> ready');
281
534
  setExternalEventFn = function setExternalEventFn(newEvent) {
282
- if (!_this2._mounted) return;
283
- _this2.setState({
535
+ if (!_this3._mounted) return;
536
+ _this3.setState({
284
537
  externalEvent: newEvent
285
538
  });
286
539
  };
287
- if (readyResolve) {
288
- readyResolve(true);
289
- readyResolve = null;
290
- }
291
540
  }
292
541
  }, {
293
542
  key: "componentWillUnmount",
294
543
  value: function componentWillUnmount() {
295
544
  this._mounted = false;
296
545
  setExternalEventFn = null;
297
- if (readyReject) {
298
- readyReject(new Error('Wrapper unmounted before ready'));
299
- readyReject = null;
300
- }
301
546
  }
302
547
  }, {
303
548
  key: "render",
304
549
  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
- }();
334
550
  return /*#__PURE__*/React.createElement(LiteRenderer, _extends({}, this.props, {
335
- onInternalEvent: onInternalEventWrapped,
336
551
  externalEvent: this.state.externalEvent
337
552
  }));
338
553
  }
@@ -342,101 +557,124 @@ export function renderKitchenSimulator(container) {
342
557
  __render: function __render(nextProps) {
343
558
  root.render(/*#__PURE__*/React.createElement(Wrapper, nextProps));
344
559
  },
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;
352
- },
560
+ // ✅ host can query current inFlight
353
561
  getGltfInFlight: function getGltfInFlight() {
354
562
  return gltfTracker.getInFlight();
355
563
  },
564
+ // ✅ host can subscribe to inFlight changes (loader)
356
565
  subscribeGltfInFlight: function subscribeGltfInFlight(cb) {
357
566
  return gltfTracker.subscribe(cb);
358
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
+ },
359
585
  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;
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;
363
589
  var events = Array.isArray(eventOrEvents) ? eventOrEvents : [eventOrEvents];
364
- var token = Symbol('batch');
365
- var _iterator = _createForOfIteratorHelper(events),
366
- _step;
590
+ var _iterator2 = _createForOfIteratorHelper(events),
591
+ _step2;
367
592
  try {
368
- for (_iterator.s(); !(_step = _iterator.n()).done;) {
369
- var e = _step.value;
593
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
594
+ var e = _step2.value;
370
595
  queue.push(e);
371
596
  }
372
597
  } catch (err) {
373
- _iterator.e(err);
598
+ _iterator2.e(err);
374
599
  } finally {
375
- _iterator.f();
600
+ _iterator2.f();
376
601
  }
602
+ var token = Symbol('batch');
377
603
  pendingMarkers.add(token);
378
604
  queue.push({
379
605
  __marker: MARKER,
380
606
  token: token
381
607
  });
382
608
  drain();
609
+
610
+ // resolve when marker cleared
383
611
  return new Promise(function (resolve) {
384
612
  var start = Date.now();
385
613
  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) {
614
+ var _ref6 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee6() {
615
+ return _regeneratorRuntime.wrap(function (_context6) {
616
+ while (1) switch (_context6.prev = _context6.next) {
389
617
  case 0:
390
618
  if (destroyed) {
391
- _context2.next = 4;
619
+ _context6.next = 4;
392
620
  break;
393
621
  }
394
622
  if (pendingMarkers.has(token)) {
395
- _context2.next = 1;
623
+ _context6.next = 1;
396
624
  break;
397
625
  }
398
626
  resolve(true);
399
- return _context2.abrupt("return");
627
+ return _context6.abrupt("return");
400
628
  case 1:
401
629
  if (!(Date.now() - start > timeoutMs)) {
402
- _context2.next = 2;
630
+ _context6.next = 2;
403
631
  break;
404
632
  }
405
- error('sendExternalEvents timed out', {
406
- timeoutMs: timeoutMs
407
- });
633
+ console.error('[kitchen-simulator] sendExternalEvents timed out');
408
634
  pendingMarkers["delete"](token); // fail-open
409
635
  resolve(false);
410
- return _context2.abrupt("return");
636
+ return _context6.abrupt("return");
411
637
  case 2:
412
- _context2.next = 3;
638
+ _context6.next = 3;
413
639
  return nextFrame();
414
640
  case 3:
415
- _context2.next = 0;
641
+ _context6.next = 0;
416
642
  break;
417
643
  case 4:
418
644
  resolve(false);
419
645
  case 5:
420
646
  case "end":
421
- return _context2.stop();
647
+ return _context6.stop();
422
648
  }
423
- }, _callee2);
649
+ }, _callee6);
424
650
  }));
425
651
  return function check() {
426
- return _ref3.apply(this, arguments);
652
+ return _ref6.apply(this, arguments);
427
653
  };
428
654
  }();
429
655
  check();
430
656
  });
431
657
  },
432
- unmount: function unmount() {
433
- destroyed = true;
658
+ updateExternalEvent: function updateExternalEvent(e) {
659
+ return api.sendExternalEvents(e);
660
+ },
661
+ clearQueue: function clearQueue() {
434
662
  queue.length = 0;
435
663
  pendingMarkers.clear();
664
+ },
665
+ unmount: function unmount() {
666
+ destroyed = true;
667
+ api.clearQueue();
436
668
  gltfTracker.uninstall();
437
- root.unmount();
438
- container[ROOT_KEY] = null;
439
- 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);
440
678
  }
441
679
  };
442
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.2-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",