@arcanejs/toolkit 3.1.1 → 4.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/README.md +1 -1
  2. package/dist/backend/components/base.d.mts +1 -1
  3. package/dist/backend/components/base.d.ts +1 -1
  4. package/dist/backend/components/base.js +2 -2
  5. package/dist/backend/components/base.mjs +1 -1
  6. package/dist/backend/components/button.d.mts +1 -1
  7. package/dist/backend/components/button.d.ts +1 -1
  8. package/dist/backend/components/button.js +3 -3
  9. package/dist/backend/components/button.mjs +2 -2
  10. package/dist/backend/components/group.d.mts +1 -1
  11. package/dist/backend/components/group.d.ts +1 -1
  12. package/dist/backend/components/group.js +3 -3
  13. package/dist/backend/components/group.mjs +2 -2
  14. package/dist/backend/components/label.d.mts +1 -1
  15. package/dist/backend/components/label.d.ts +1 -1
  16. package/dist/backend/components/label.js +3 -3
  17. package/dist/backend/components/label.mjs +2 -2
  18. package/dist/backend/components/rect.d.mts +1 -1
  19. package/dist/backend/components/rect.d.ts +1 -1
  20. package/dist/backend/components/rect.js +3 -3
  21. package/dist/backend/components/rect.mjs +2 -2
  22. package/dist/backend/components/slider-button.d.mts +1 -1
  23. package/dist/backend/components/slider-button.d.ts +1 -1
  24. package/dist/backend/components/slider-button.js +3 -3
  25. package/dist/backend/components/slider-button.mjs +2 -2
  26. package/dist/backend/components/switch.d.mts +1 -1
  27. package/dist/backend/components/switch.d.ts +1 -1
  28. package/dist/backend/components/switch.js +3 -3
  29. package/dist/backend/components/switch.mjs +2 -2
  30. package/dist/backend/components/tabs.d.mts +1 -1
  31. package/dist/backend/components/tabs.d.ts +1 -1
  32. package/dist/backend/components/tabs.js +3 -3
  33. package/dist/backend/components/tabs.mjs +2 -2
  34. package/dist/backend/components/text-input.d.mts +1 -1
  35. package/dist/backend/components/text-input.d.ts +1 -1
  36. package/dist/backend/components/text-input.js +3 -3
  37. package/dist/backend/components/text-input.mjs +2 -2
  38. package/dist/backend/components/timeline.d.mts +1 -1
  39. package/dist/backend/components/timeline.d.ts +1 -1
  40. package/dist/backend/components/timeline.js +3 -3
  41. package/dist/backend/components/timeline.mjs +2 -2
  42. package/dist/{chunk-DRQVYGTI.js → chunk-3GTEUTFT.js} +2 -2
  43. package/dist/{chunk-K37TZB75.mjs → chunk-3TXBS2UN.mjs} +1 -1
  44. package/dist/{chunk-DG75CS7F.js → chunk-4OCRZD4F.js} +7 -16
  45. package/dist/{chunk-VEZGD2PG.js → chunk-53EOA4UE.js} +3 -3
  46. package/dist/{chunk-N6IHYBZH.mjs → chunk-6ELB27LK.mjs} +1 -1
  47. package/dist/{chunk-6CWEURJP.js → chunk-6QWYIJLM.js} +2 -2
  48. package/dist/{chunk-O5ZW6JYG.js → chunk-7JIC2XBC.js} +4 -4
  49. package/dist/{chunk-5D7OSUZ6.mjs → chunk-E6FGU7DA.mjs} +1 -1
  50. package/dist/{chunk-RYR5I5FT.mjs → chunk-GONHNB6V.mjs} +33 -0
  51. package/dist/{chunk-4OZ22IQU.js → chunk-HTCWMJUA.js} +3 -3
  52. package/dist/{chunk-7TTY7CBH.mjs → chunk-KMEDXCBI.mjs} +1 -1
  53. package/dist/{chunk-W42AOMM6.mjs → chunk-LK6MGXYC.mjs} +5 -14
  54. package/dist/{chunk-CME7HZZK.js → chunk-NL3W4M7J.js} +3 -3
  55. package/dist/{chunk-NEQRLPXK.mjs → chunk-PG5EAV5X.mjs} +1 -1
  56. package/dist/{chunk-7OX2FB6C.js → chunk-QAH2OSHR.js} +2 -2
  57. package/dist/{chunk-JFZXSCGK.mjs → chunk-QB2WPBWV.mjs} +1 -1
  58. package/dist/{chunk-GMDJYFHD.js → chunk-U6FSQBQ3.js} +3 -3
  59. package/dist/{chunk-CUZSHFDP.mjs → chunk-UQWCTVMC.mjs} +1 -1
  60. package/dist/{chunk-YBBUC3QC.mjs → chunk-WDB3IMOP.mjs} +1 -1
  61. package/dist/{chunk-SGACFY53.js → chunk-WN3GXVUE.js} +35 -2
  62. package/dist/frontend/entrypoint.js +84 -31
  63. package/dist/frontend/entrypoint.js.map +3 -3
  64. package/dist/frontend/index.js +62 -19
  65. package/dist/frontend/index.mjs +62 -19
  66. package/dist/index.d.mts +1 -1
  67. package/dist/index.d.ts +1 -1
  68. package/dist/index.js +47 -14
  69. package/dist/index.mjs +43 -10
  70. package/dist/{toolkit-2w2SWHlT.d.ts → toolkit-C37sQAkD.d.ts} +23 -7
  71. package/dist/{toolkit-DB8G2TaA.d.mts → toolkit-CQMnQMOF.d.mts} +23 -7
  72. package/package.json +5 -5
@@ -72,8 +72,14 @@ var Base = class {
72
72
  /** @hidden */
73
73
  handleMessage(_message, _connection) {
74
74
  }
75
+ /** @hidden */
76
+ handleCall(_call, _connection) {
77
+ return Promise.reject(new Error(`Component does not handle calls`));
78
+ }
75
79
  routeMessage(_idMap, _message, _connection) {
76
80
  }
81
+ routeCall(_idMap, _call, _connection, _callbacks) {
82
+ }
77
83
  };
78
84
  var BaseParent = class extends Base {
79
85
  /** @hidden */
@@ -134,6 +140,19 @@ var BaseParent = class extends Base {
134
140
  }
135
141
  }
136
142
  }
143
+ async routeCall(idMap, call, connection, callbacks) {
144
+ if (idMap.getId(this) === call.componentKey) {
145
+ this.handleCall(call, connection).then(callbacks.resolve).catch(callbacks.reject);
146
+ } else {
147
+ for (const c of this.children) {
148
+ if (idMap.getId(c) === call.componentKey) {
149
+ c.handleCall(call, connection).then(callbacks.resolve).catch(callbacks.reject);
150
+ } else {
151
+ c.routeCall(idMap, call, connection, callbacks);
152
+ }
153
+ }
154
+ }
155
+ }
137
156
  insertBefore(child, beforeChild) {
138
157
  const filteredChildren = this.children.filter((c) => c !== child);
139
158
  let match = filteredChildren.findIndex((c) => c === beforeChild);
@@ -177,6 +196,20 @@ var EventEmitter = class {
177
196
  )
178
197
  );
179
198
  };
199
+ /**
200
+ * Like {@link emit},
201
+ * but ensures only a single listener exists and returns its result.
202
+ */
203
+ call = async (type, ...args) => {
204
+ const result = await this.emit(type, ...args);
205
+ if (result.length > 1) {
206
+ throw new Error(`Multiple listeners for call: ${String(type)}`);
207
+ } else if (result[0]) {
208
+ return result[0];
209
+ } else {
210
+ throw new Error(`No listeners for call: ${String(type)}`);
211
+ }
212
+ };
180
213
  /**
181
214
  * Process prop changes to update listeners
182
215
  */
@@ -1,16 +1,16 @@
1
1
  "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } var _class;
2
2
 
3
3
 
4
- var _chunkSGACFY53js = require('./chunk-SGACFY53.js');
4
+ var _chunkWN3GXVUEjs = require('./chunk-WN3GXVUE.js');
5
5
 
6
6
  // src/backend/components/text-input.ts
7
7
  var _core = require('@arcanejs/protocol/core'); var proto = _interopRequireWildcard(_core);
8
8
  var DEFAULT_PROPS = {
9
9
  value: null
10
10
  };
11
- var TextInput = (_class = class extends _chunkSGACFY53js.Base {
11
+ var TextInput = (_class = class extends _chunkWN3GXVUEjs.Base {
12
12
  /** @hidden */
13
- __init() {this.events = new (0, _chunkSGACFY53js.EventEmitter)()}
13
+ __init() {this.events = new (0, _chunkWN3GXVUEjs.EventEmitter)()}
14
14
  constructor(props) {
15
15
  super(DEFAULT_PROPS, props, {
16
16
  onPropsUpdated: (oldProps) => this.events.processPropChanges(
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  BaseParent
3
- } from "./chunk-RYR5I5FT.mjs";
3
+ } from "./chunk-GONHNB6V.mjs";
4
4
 
5
5
  // src/backend/components/tabs.ts
6
6
  var Tab = class extends BaseParent {
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  Base,
3
3
  EventEmitter
4
- } from "./chunk-RYR5I5FT.mjs";
4
+ } from "./chunk-GONHNB6V.mjs";
5
5
 
6
6
  // src/backend/components/button.ts
7
7
  import * as proto from "@arcanejs/protocol/core";
@@ -56,20 +56,11 @@ var Button = class extends Base {
56
56
  };
57
57
  };
58
58
  /** @hidden */
59
- handleMessage = (message, connection) => {
60
- if (proto.isCoreComponentMessage(message, "button")) {
61
- this.events.emit("click", connection).then(() => {
62
- if (this.props.error) {
63
- this.updateProps({
64
- error: null
65
- });
66
- }
67
- }).catch((e) => {
68
- this.updateProps({
69
- error: `${e}`
70
- });
71
- });
59
+ handleCall = (call, connection) => {
60
+ if (proto.isCoreComponentCall(call, "press")) {
61
+ return this.events.emit("click", connection).then(() => true);
72
62
  }
63
+ throw new Error(`Unhandled call action: ${call.action}`);
73
64
  };
74
65
  };
75
66
 
@@ -1,7 +1,7 @@
1
1
  "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } } var _class;
2
2
 
3
3
 
4
- var _chunkSGACFY53js = require('./chunk-SGACFY53.js');
4
+ var _chunkWN3GXVUEjs = require('./chunk-WN3GXVUE.js');
5
5
 
6
6
  // src/backend/components/slider-button.ts
7
7
  var _core = require('@arcanejs/protocol/core'); var proto = _interopRequireWildcard(_core);
@@ -10,9 +10,9 @@ var DEFAULT_PROPS = {
10
10
  max: 255,
11
11
  step: 5
12
12
  };
13
- var SliderButton = (_class = class extends _chunkSGACFY53js.Base {
13
+ var SliderButton = (_class = class extends _chunkWN3GXVUEjs.Base {
14
14
  /** @hidden */
15
- __init() {this.events = new (0, _chunkSGACFY53js.EventEmitter)()}
15
+ __init() {this.events = new (0, _chunkWN3GXVUEjs.EventEmitter)()}
16
16
  /**
17
17
  * Manually manage the state of the slider,
18
18
  * to support both controlled and uncontrolled inputs.
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  Base,
3
3
  EventEmitter
4
- } from "./chunk-RYR5I5FT.mjs";
4
+ } from "./chunk-GONHNB6V.mjs";
5
5
 
6
6
  // src/backend/components/switch.ts
7
7
  import * as proto from "@arcanejs/protocol/core";
@@ -1,12 +1,12 @@
1
1
  "use strict";Object.defineProperty(exports, "__esModule", {value: true});
2
2
 
3
- var _chunkSGACFY53js = require('./chunk-SGACFY53.js');
3
+ var _chunkWN3GXVUEjs = require('./chunk-WN3GXVUE.js');
4
4
 
5
5
  // src/backend/components/rect.ts
6
6
  var DEFAULT_PROPS = {
7
7
  color: "rgba(0, 0, 0, 0)"
8
8
  };
9
- var Rect = class extends _chunkSGACFY53js.Base {
9
+ var Rect = class extends _chunkWN3GXVUEjs.Base {
10
10
  constructor(props) {
11
11
  super(DEFAULT_PROPS, props);
12
12
  }
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  Base,
3
3
  EventEmitter
4
- } from "./chunk-RYR5I5FT.mjs";
4
+ } from "./chunk-GONHNB6V.mjs";
5
5
 
6
6
  // src/backend/components/slider-button.ts
7
7
  import * as proto from "@arcanejs/protocol/core";
@@ -1,9 +1,9 @@
1
1
  "use strict";Object.defineProperty(exports, "__esModule", {value: true}); var _class; var _class2;
2
2
 
3
- var _chunkSGACFY53js = require('./chunk-SGACFY53.js');
3
+ var _chunkWN3GXVUEjs = require('./chunk-WN3GXVUE.js');
4
4
 
5
5
  // src/backend/components/tabs.ts
6
- var Tab = (_class = class extends _chunkSGACFY53js.BaseParent {constructor(...args) { super(...args); _class.prototype.__init.call(this);_class.prototype.__init2.call(this); }
6
+ var Tab = (_class = class extends _chunkWN3GXVUEjs.BaseParent {constructor(...args) { super(...args); _class.prototype.__init.call(this);_class.prototype.__init2.call(this); }
7
7
  __init() {this.validateChildren = (children) => {
8
8
  if (children.length > 1) {
9
9
  throw new Error("Tab can only have one child");
@@ -18,7 +18,7 @@ var Tab = (_class = class extends _chunkSGACFY53js.BaseParent {constructor(...ar
18
18
  child: this.getChildren().slice(0, 1).map((c) => c.getProtoInfo(idMap))[0]
19
19
  })}
20
20
  }, _class);
21
- var Tabs = (_class2 = class extends _chunkSGACFY53js.BaseParent {
21
+ var Tabs = (_class2 = class extends _chunkWN3GXVUEjs.BaseParent {
22
22
  __init3() {this.validateChildren = (children) => {
23
23
  for (const child of children) {
24
24
  if (!(child instanceof Tab)) {
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  Base
3
- } from "./chunk-RYR5I5FT.mjs";
3
+ } from "./chunk-GONHNB6V.mjs";
4
4
 
5
5
  // src/backend/components/label.ts
6
6
  var Label = class extends Base {
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  Base,
3
3
  EventEmitter
4
- } from "./chunk-RYR5I5FT.mjs";
4
+ } from "./chunk-GONHNB6V.mjs";
5
5
 
6
6
  // src/backend/components/text-input.ts
7
7
  import * as proto from "@arcanejs/protocol/core";
@@ -72,8 +72,14 @@ var Base = (_class = class {
72
72
  /** @hidden */
73
73
  handleMessage(_message, _connection) {
74
74
  }
75
+ /** @hidden */
76
+ handleCall(_call, _connection) {
77
+ return Promise.reject(new Error(`Component does not handle calls`));
78
+ }
75
79
  routeMessage(_idMap, _message, _connection) {
76
80
  }
81
+ routeCall(_idMap, _call, _connection, _callbacks) {
82
+ }
77
83
  }, _class);
78
84
  var BaseParent = (_class2 = class extends Base {constructor(...args2) { super(...args2); _class2.prototype.__init7.call(this);_class2.prototype.__init8.call(this);_class2.prototype.__init9.call(this);_class2.prototype.__init10.call(this);_class2.prototype.__init11.call(this);_class2.prototype.__init12.call(this); }
79
85
  /** @hidden */
@@ -134,6 +140,19 @@ var BaseParent = (_class2 = class extends Base {constructor(...args2) { super(..
134
140
  }
135
141
  }
136
142
  }
143
+ async routeCall(idMap, call, connection, callbacks) {
144
+ if (idMap.getId(this) === call.componentKey) {
145
+ this.handleCall(call, connection).then(callbacks.resolve).catch(callbacks.reject);
146
+ } else {
147
+ for (const c of this.children) {
148
+ if (idMap.getId(c) === call.componentKey) {
149
+ c.handleCall(call, connection).then(callbacks.resolve).catch(callbacks.reject);
150
+ } else {
151
+ c.routeCall(idMap, call, connection, callbacks);
152
+ }
153
+ }
154
+ }
155
+ }
137
156
  insertBefore(child, beforeChild) {
138
157
  const filteredChildren = this.children.filter((c) => c !== child);
139
158
  let match = filteredChildren.findIndex((c) => c === beforeChild);
@@ -151,7 +170,7 @@ var BaseParent = (_class2 = class extends Base {constructor(...args2) { super(..
151
170
  this.updateTree();
152
171
  }
153
172
  }, _class2);
154
- var EventEmitter = (_class3 = class {constructor() { _class3.prototype.__init13.call(this);_class3.prototype.__init14.call(this);_class3.prototype.__init15.call(this);_class3.prototype.__init16.call(this);_class3.prototype.__init17.call(this); }
173
+ var EventEmitter = (_class3 = class {constructor() { _class3.prototype.__init13.call(this);_class3.prototype.__init14.call(this);_class3.prototype.__init15.call(this);_class3.prototype.__init16.call(this);_class3.prototype.__init17.call(this);_class3.prototype.__init18.call(this); }
155
174
  __init13() {this.listeners = /* @__PURE__ */ new Map()}
156
175
  __init14() {this.addListener = (type, listener) => {
157
176
  let set = this.listeners.get(type);
@@ -177,10 +196,24 @@ var EventEmitter = (_class3 = class {constructor() { _class3.prototype.__init13.
177
196
  )
178
197
  );
179
198
  }}
199
+ /**
200
+ * Like {@link emit},
201
+ * but ensures only a single listener exists and returns its result.
202
+ */
203
+ __init17() {this.call = async (type, ...args) => {
204
+ const result = await this.emit(type, ...args);
205
+ if (result.length > 1) {
206
+ throw new Error(`Multiple listeners for call: ${String(type)}`);
207
+ } else if (result[0]) {
208
+ return result[0];
209
+ } else {
210
+ throw new Error(`No listeners for call: ${String(type)}`);
211
+ }
212
+ }}
180
213
  /**
181
214
  * Process prop changes to update listeners
182
215
  */
183
- __init17() {this.processPropChanges = (mapping, oldProps, newProps) => {
216
+ __init18() {this.processPropChanges = (mapping, oldProps, newProps) => {
184
217
  for (const key of Object.keys(mapping)) {
185
218
  const prev = oldProps[key];
186
219
  const next = newProps[key];
@@ -26202,6 +26202,7 @@ body {
26202
26202
  })
26203
26203
  );
26204
26204
  var TOUCH_INDICATOR_CLASS = "touch-indicator";
26205
+ var LOADING_CLASS = "loading";
26205
26206
  var TOUCHING_CLASS = "touching";
26206
26207
  var ERROR_CLASS = "error";
26207
26208
  var ButtonContents = dt.div`
@@ -26218,22 +26219,31 @@ body {
26218
26219
  padding: 0 4px;
26219
26220
  `;
26220
26221
  var Button = (props) => {
26221
- const { sendMessage } = import_react4.default.useContext(StageContext);
26222
- const { touching, handlers } = usePressable(
26223
- () => sendMessage?.({
26224
- type: "component-message",
26225
- namespace: "core",
26226
- componentKey: props.info.key,
26227
- component: "button"
26228
- })
26229
- );
26230
- const { state } = props.info;
26222
+ const { call } = import_react4.default.useContext(StageContext);
26223
+ const [localState, setLocalState] = import_react4.default.useState(null);
26224
+ const state = localState ?? props.info.state;
26225
+ const { touching, handlers } = usePressable(async () => {
26226
+ try {
26227
+ if (!call) return;
26228
+ setLocalState({ state: "loading" });
26229
+ await call?.({
26230
+ type: "component-call",
26231
+ namespace: "core",
26232
+ componentKey: props.info.key,
26233
+ action: "press"
26234
+ });
26235
+ setLocalState(null);
26236
+ } catch (e) {
26237
+ setLocalState({ state: "error", error: `${e}` });
26238
+ }
26239
+ });
26231
26240
  return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
26232
26241
  "div",
26233
26242
  {
26234
26243
  className: calculateClass(
26235
26244
  props.className,
26236
- touching || state.state === "pressed" ? TOUCHING_CLASS : null,
26245
+ (touching || state.state === "pressed") && TOUCHING_CLASS,
26246
+ state.state === "loading" && LOADING_CLASS,
26237
26247
  state.state === "error" && ERROR_CLASS
26238
26248
  ),
26239
26249
  ...handlers,
@@ -26264,7 +26274,7 @@ body {
26264
26274
  border-color: ${(p2) => p2.theme.colorRed};
26265
26275
  }
26266
26276
 
26267
- &.${TOUCHING_CLASS} {
26277
+ &.${TOUCHING_CLASS}, &.${LOADING_CLASS} {
26268
26278
  ${buttonStateNormalActive}
26269
26279
 
26270
26280
  .${TOUCH_INDICATOR_CLASS} {
@@ -27469,6 +27479,10 @@ body {
27469
27479
  );
27470
27480
  const socket = (0, import_react15.useRef)(null);
27471
27481
  const uuid = (0, import_react15.useRef)(null);
27482
+ const calls = (0, import_react15.useRef)({
27483
+ nextId: 1,
27484
+ calls: /* @__PURE__ */ new Map()
27485
+ });
27472
27486
  const preparedRenderers = (0, import_react15.useMemo)(() => {
27473
27487
  const prepared = {};
27474
27488
  for (const renderer of renderers) {
@@ -27486,10 +27500,36 @@ body {
27486
27500
  },
27487
27501
  [preparedRenderers]
27488
27502
  );
27489
- (0, import_react15.useEffect)(() => {
27490
- initializeWebsocket();
27503
+ const handleMessage = (0, import_react15.useCallback)((msg) => {
27504
+ switch (msg.type) {
27505
+ case "metadata":
27506
+ uuid.current = msg.connectionUuid;
27507
+ return;
27508
+ case "tree-full":
27509
+ setRoot(msg.root);
27510
+ return;
27511
+ case "tree-diff":
27512
+ setRoot((prevRoot) => patchJson(prevRoot, msg.diff));
27513
+ return;
27514
+ case "call-response": {
27515
+ const call2 = calls.current.calls.get(msg.requestId);
27516
+ if (call2) {
27517
+ calls.current.calls.delete(msg.requestId);
27518
+ if (msg.success) {
27519
+ call2.resolve(msg.returnValue);
27520
+ } else {
27521
+ call2.reject(msg.errorMessage);
27522
+ }
27523
+ } else {
27524
+ console.warn(
27525
+ `Received response for unknown call request ID ${msg.requestId}`
27526
+ );
27527
+ }
27528
+ return;
27529
+ }
27530
+ }
27491
27531
  }, []);
27492
- const initializeWebsocket = async () => {
27532
+ const initializeWebsocket = (0, import_react15.useCallback)(async () => {
27493
27533
  console.log("initializing websocket");
27494
27534
  const wsUrl = new URL(window.location.href);
27495
27535
  wsUrl.protocol = wsUrl.protocol === "https:" ? "wss:" : "ws:";
@@ -27513,29 +27553,42 @@ body {
27513
27553
  };
27514
27554
  });
27515
27555
  return ws;
27516
- };
27517
- const sendMessage = async (msg) => {
27556
+ }, []);
27557
+ const sendMessage = (0, import_react15.useCallback)(async (msg) => {
27518
27558
  (await (socket.current || initializeWebsocket())).send(JSON.stringify(msg));
27519
- };
27520
- const handleMessage = (msg) => {
27521
- switch (msg.type) {
27522
- case "metadata":
27523
- uuid.current = msg.connectionUuid;
27524
- return;
27525
- case "tree-full":
27526
- setRoot(msg.root);
27527
- return;
27528
- case "tree-diff":
27529
- setRoot((prevRoot) => patchJson(prevRoot, msg.diff));
27530
- return;
27531
- }
27532
- };
27559
+ }, []);
27560
+ const call = (0, import_react15.useCallback)(
27561
+ async (msg) => {
27562
+ const requestId = calls.current.nextId++;
27563
+ const sendMsg = {
27564
+ ...msg,
27565
+ requestId
27566
+ };
27567
+ const promise = new Promise(
27568
+ (resolve, reject) => {
27569
+ calls.current.calls.set(requestId, {
27570
+ resolve,
27571
+ reject
27572
+ });
27573
+ (socket.current || initializeWebsocket()).then(
27574
+ (s2) => s2.send(JSON.stringify(sendMsg))
27575
+ );
27576
+ }
27577
+ );
27578
+ return promise;
27579
+ },
27580
+ []
27581
+ );
27582
+ (0, import_react15.useEffect)(() => {
27583
+ initializeWebsocket();
27584
+ }, [initializeWebsocket]);
27533
27585
  return /* @__PURE__ */ import_react15.default.createElement(
27534
27586
  StageContext.Provider,
27535
27587
  {
27536
27588
  value: {
27537
27589
  sendMessage,
27538
27590
  renderComponent,
27591
+ call,
27539
27592
  get connectionUuid() {
27540
27593
  if (!uuid.current) {
27541
27594
  throw new Error("Unexpected missing UUID");