@ai-matrx/summon 0.1.1 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/react.cjs CHANGED
@@ -25,6 +25,7 @@ __export(react_exports, {
25
25
  DEFAULT_IMPORT_TIMEOUT_MS: () => DEFAULT_IMPORT_TIMEOUT_MS,
26
26
  DEFAULT_KEEP_ALIVE_LIMIT: () => DEFAULT_KEEP_ALIVE_LIMIT,
27
27
  DEFAULT_STALL_WARN_MS: () => DEFAULT_STALL_WARN_MS,
28
+ MISSING_RENDER_ERROR: () => MISSING_RENDER_ERROR,
28
29
  OverlayErrorBoundary: () => OverlayErrorBoundary,
29
30
  OverlayErrorFallback: () => OverlayErrorFallback,
30
31
  OverlayLoadingFallback: () => OverlayLoadingFallback,
@@ -310,7 +311,7 @@ function SummonProvider({
310
311
  }
311
312
 
312
313
  // src/react/defineOverlay.tsx
313
- var import_react9 = require("react");
314
+ var import_react10 = require("react");
314
315
  var import_summon7 = require("@ai-matrx/summon");
315
316
  var import_summon8 = require("@ai-matrx/summon");
316
317
 
@@ -348,7 +349,7 @@ function emitOverlayEvent(channelId, type, payload) {
348
349
  }
349
350
 
350
351
  // src/react/instanceBody.tsx
351
- var import_react8 = require("react");
352
+ var import_react9 = require("react");
352
353
 
353
354
  // src/react/OverlayErrorBoundary.tsx
354
355
  var import_react6 = require("react");
@@ -433,6 +434,26 @@ function useOverlayState(name, initial) {
433
434
  return [value, setValue];
434
435
  }
435
436
 
437
+ // src/react/hostRenders.ts
438
+ var import_react8 = require("react");
439
+ var HostRendersContext = (0, import_react8.createContext)(null);
440
+ var MISSING_RENDER_ERROR = "OverlayRenderMissingError";
441
+ var missing = /* @__PURE__ */ new Map();
442
+ function missingRenderLoader(overlayId) {
443
+ let loader = missing.get(overlayId);
444
+ if (!loader) {
445
+ const message = `Overlay "${overlayId}" is open but has no render module: its definition has no \`render\` and <SummonHost renders> has no "${overlayId}" entry.`;
446
+ loader = () => {
447
+ if (process.env.NODE_ENV !== "production") console.error(`[summon] ${message}`);
448
+ const error = new Error(message);
449
+ error.name = MISSING_RENDER_ERROR;
450
+ return Promise.reject(error);
451
+ };
452
+ missing.set(overlayId, loader);
453
+ }
454
+ return loader;
455
+ }
456
+
436
457
  // src/react/instanceBody.tsx
437
458
  var import_jsx_runtime4 = require("react/jsx-runtime");
438
459
  function LazyRender({ overlayId, instanceId, data, hidden, close, render, attemptRef }) {
@@ -442,14 +463,17 @@ function LazyRender({ overlayId, instanceId, data, hidden, close, render, attemp
442
463
  const Render = entry.Component;
443
464
  return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Render, { overlayId, instanceId, data, isOpen: true, close, hidden });
444
465
  }
445
- function createInstanceBody(overlayId, label, render, parse, refusable) {
466
+ function createInstanceBody(overlayId, label, ownRender, parse, refusable) {
446
467
  function OverlayInstanceBody({ instanceId, instanceKey, data, hidden, close }) {
447
468
  const config = useSummonConfig();
448
469
  const ports = useSummonPorts();
449
- const attemptRef = (0, import_react8.useRef)(0);
450
- const parsed = (0, import_react8.useMemo)(() => parse(data), [data]);
470
+ const hostRenders = (0, import_react9.useContext)(HostRendersContext);
471
+ const hostRender = ownRender ? void 0 : hostRenders?.[overlayId];
472
+ const render = ownRender ?? hostRender ?? missingRenderLoader(overlayId);
473
+ const attemptRef = (0, import_react9.useRef)(0);
474
+ const parsed = (0, import_react9.useMemo)(() => parse(data), [data]);
451
475
  const refused = refusable && parsed === null;
452
- (0, import_react8.useEffect)(() => {
476
+ (0, import_react9.useEffect)(() => {
453
477
  if (!refused) return;
454
478
  if (process.env.NODE_ENV !== "production") {
455
479
  ports.notify.warn(`Overlay "${overlayId}" was opened with data its parse() refused; closing it.`, {
@@ -458,7 +482,7 @@ function createInstanceBody(overlayId, label, render, parse, refusable) {
458
482
  }
459
483
  close();
460
484
  }, [refused, ports, instanceKey, close]);
461
- const instance = (0, import_react8.useMemo)(
485
+ const instance = (0, import_react9.useMemo)(
462
486
  () => ({ overlayId, instanceId, instanceKey, close, hidden, rawData: data }),
463
487
  [instanceId, instanceKey, close, hidden, data]
464
488
  );
@@ -476,7 +500,7 @@ function createInstanceBody(overlayId, label, render, parse, refusable) {
476
500
  extras: config.errorReportExtras,
477
501
  onRetry: () => config.loaders.retry(overlayId, render, attemptRef.current),
478
502
  onClose: close,
479
- children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react8.Suspense, { fallback: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(config.loadingFallback, { overlayId, label }), children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
503
+ children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react9.Suspense, { fallback: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(config.loadingFallback, { overlayId, label }), children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
480
504
  LazyRender,
481
505
  {
482
506
  overlayId,
@@ -493,7 +517,7 @@ function createInstanceBody(overlayId, label, render, parse, refusable) {
493
517
  return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(OverlayInstanceContext.Provider, { value: instance, children: config.renderWrapper ? config.renderWrapper(body, context) : body });
494
518
  }
495
519
  OverlayInstanceBody.displayName = `Overlay(${overlayId})`;
496
- return (0, import_react8.memo)(OverlayInstanceBody);
520
+ return (0, import_react9.memo)(OverlayInstanceBody);
497
521
  }
498
522
 
499
523
  // src/react/defineOverlay.tsx
@@ -525,19 +549,19 @@ function defineOverlay() {
525
549
  const meta = spec;
526
550
  function useSummon() {
527
551
  const dispatch = useSummonDispatch();
528
- return (0, import_react9.useCallback)((options) => openWith(dispatch, id, multi, options), [dispatch]);
552
+ return (0, import_react10.useCallback)((options) => openWith(dispatch, id, multi, options), [dispatch]);
529
553
  }
530
554
  function useIsOpen(instanceId = import_summon7.DEFAULT_INSTANCE_ID) {
531
555
  return useSummonSelector((state) => (0, import_summon8.selectIsOverlayOpen)(state, id, instanceId));
532
556
  }
533
557
  function useClose() {
534
558
  const dispatch = useSummonDispatch();
535
- return (0, import_react9.useCallback)((instanceId) => dispatchClose(dispatch, id, instanceId ?? import_summon7.DEFAULT_INSTANCE_ID), [dispatch]);
559
+ return (0, import_react10.useCallback)((instanceId) => dispatchClose(dispatch, id, instanceId ?? import_summon7.DEFAULT_INSTANCE_ID), [dispatch]);
536
560
  }
537
561
  function useEmit() {
538
562
  const instance = useOptionalOverlayInstance();
539
563
  const channelId = instance?.overlayId === id ? instance.rawData?.[CALLBACK_GROUP_KEY] : void 0;
540
- return (0, import_react9.useCallback)(
564
+ return (0, import_react10.useCallback)(
541
565
  (event, payload) => {
542
566
  if (typeof channelId === "string") emitOverlayEvent(channelId, event, payload);
543
567
  },
@@ -546,12 +570,12 @@ function defineOverlay() {
546
570
  }
547
571
  function Controller(props) {
548
572
  const dispatch = useSummonDispatch();
549
- const [ownInstanceId] = (0, import_react9.useState)(() => multi ? newInstanceId(id) : import_summon7.DEFAULT_INSTANCE_ID);
573
+ const [ownInstanceId] = (0, import_react10.useState)(() => multi ? newInstanceId(id) : import_summon7.DEFAULT_INSTANCE_ID);
550
574
  const instanceId = props.instanceId ?? ownInstanceId;
551
- const handlersRef = (0, import_react9.useRef)(props.handlers);
575
+ const handlersRef = (0, import_react10.useRef)(props.handlers);
552
576
  handlersRef.current = props.handlers;
553
577
  const hasHandlers = props.handlers !== void 0;
554
- const data = (0, import_react9.useMemo)(() => {
578
+ const data = (0, import_react10.useMemo)(() => {
555
579
  const out = {};
556
580
  for (const [key, value] of Object.entries(props)) {
557
581
  if (key !== "instanceId" && key !== "handlers") out[key] = value;
@@ -559,9 +583,9 @@ function defineOverlay() {
559
583
  return out;
560
584
  }, [props]);
561
585
  const signature = dataSignature(data);
562
- const dataRef = (0, import_react9.useRef)(data);
586
+ const dataRef = (0, import_react10.useRef)(data);
563
587
  dataRef.current = data;
564
- (0, import_react9.useEffect)(() => {
588
+ (0, import_react10.useEffect)(() => {
565
589
  const key = (0, import_summon7.instanceKey)(id, instanceId);
566
590
  const open = { ...dataRef.current };
567
591
  if (hasHandlers) open[CALLBACK_GROUP_KEY] = openOverlayEventChannel(key, () => handlersRef.current);
@@ -589,7 +613,7 @@ function defineOverlay() {
589
613
  }
590
614
 
591
615
  // src/react/SummonHost.tsx
592
- var import_react10 = require("react");
616
+ var import_react11 = require("react");
593
617
  var import_summon9 = require("@ai-matrx/summon");
594
618
  var import_summon10 = require("@ai-matrx/summon");
595
619
  var import_summon11 = require("@ai-matrx/summon");
@@ -612,7 +636,7 @@ var NO_RETAINED = /* @__PURE__ */ new Map();
612
636
  function useCloseOnNavigation() {
613
637
  const ports = useSummonPorts();
614
638
  const dispatch = useSummonDispatch();
615
- (0, import_react10.useEffect)(() => {
639
+ (0, import_react11.useEffect)(() => {
616
640
  const router = ports.router;
617
641
  let previous = router.pathname();
618
642
  return router.subscribe(() => {
@@ -624,19 +648,19 @@ function useCloseOnNavigation() {
624
648
  });
625
649
  }, [ports, dispatch]);
626
650
  }
627
- var InstanceSlot = (0, import_react10.memo)(function InstanceSlot2({ definition, instanceId, data, hidden }) {
651
+ var InstanceSlot = (0, import_react11.memo)(function InstanceSlot2({ definition, instanceId, data, hidden }) {
628
652
  const dispatch = useSummonDispatch();
629
- const close = (0, import_react10.useCallback)(() => dispatchClose(dispatch, definition.id, instanceId), [dispatch, definition.id, instanceId]);
653
+ const close = (0, import_react11.useCallback)(() => dispatchClose(dispatch, definition.id, instanceId), [dispatch, definition.id, instanceId]);
630
654
  const Body = definition.Body;
631
655
  return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Body, { instanceId, instanceKey: (0, import_summon12.instanceKey)(definition.id, instanceId), data, hidden, close });
632
656
  });
633
- var DefinitionSlot = (0, import_react10.memo)(function DefinitionSlot2({ definition }) {
657
+ var DefinitionSlot = (0, import_react11.memo)(function DefinitionSlot2({ definition }) {
634
658
  const { keepAlive } = useSummonConfig();
635
659
  const dispatch = useSummonDispatch();
636
660
  const open = useSummonSelector((state) => (0, import_summon11.selectOpenInstances)(state, definition.id), sameInstances);
637
661
  const keepHidden = definition.keepAlive === "hidden";
638
- const [retained, setRetained] = (0, import_react10.useState)(NO_RETAINED);
639
- const [previousOpen, setPreviousOpen] = (0, import_react10.useState)(open);
662
+ const [retained, setRetained] = (0, import_react11.useState)(NO_RETAINED);
663
+ const [previousOpen, setPreviousOpen] = (0, import_react11.useState)(open);
640
664
  if (previousOpen !== open) {
641
665
  setPreviousOpen(open);
642
666
  if (keepHidden) {
@@ -649,8 +673,8 @@ var DefinitionSlot = (0, import_react10.memo)(function DefinitionSlot2({ definit
649
673
  setRetained(next);
650
674
  }
651
675
  }
652
- const registered = (0, import_react10.useRef)(/* @__PURE__ */ new Set());
653
- (0, import_react10.useEffect)(() => {
676
+ const registered = (0, import_react11.useRef)(/* @__PURE__ */ new Set());
677
+ (0, import_react11.useEffect)(() => {
654
678
  const seen = registered.current;
655
679
  for (const instanceId of retained.keys()) {
656
680
  if (seen.has(instanceId)) continue;
@@ -673,7 +697,7 @@ var DefinitionSlot = (0, import_react10.memo)(function DefinitionSlot2({ definit
673
697
  keepAlive.release((0, import_summon12.instanceKey)(definition.id, instanceId));
674
698
  }
675
699
  }, [retained, keepAlive, definition.id, dispatch]);
676
- (0, import_react10.useEffect)(() => {
700
+ (0, import_react11.useEffect)(() => {
677
701
  const seen = registered.current;
678
702
  return () => {
679
703
  for (const instanceId of seen) {
@@ -689,30 +713,30 @@ var DefinitionSlot = (0, import_react10.memo)(function DefinitionSlot2({ definit
689
713
  for (const instance of open) {
690
714
  const node = /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(InstanceSlot, { definition, instanceId: instance.instanceId, data: asRawData(instance.data), hidden: false }, instance.instanceId);
691
715
  nodes.push(
692
- keepHidden ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react10.Activity, { mode: "visible", children: node }, instance.instanceId) : node
716
+ keepHidden ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react11.Activity, { mode: "visible", children: node }, instance.instanceId) : node
693
717
  );
694
718
  }
695
719
  if (keepHidden) {
696
720
  for (const [instanceId, data] of retained) {
697
721
  nodes.push(
698
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react10.Activity, { mode: "hidden", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(InstanceSlot, { definition, instanceId, data, hidden: true }, instanceId) }, instanceId)
722
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react11.Activity, { mode: "hidden", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(InstanceSlot, { definition, instanceId, data, hidden: true }, instanceId) }, instanceId)
699
723
  );
700
724
  }
701
725
  }
702
726
  return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_jsx_runtime5.Fragment, { children: nodes });
703
727
  });
704
- function SummonHost({ definitions }) {
705
- const registeredFor = (0, import_react10.useRef)(null);
728
+ function SummonHost({ definitions, renders }) {
729
+ const registeredFor = (0, import_react11.useRef)(null);
706
730
  if (registeredFor.current !== definitions) {
707
731
  (0, import_summon10.registerOverlayMeta)(definitions.map((definition) => definition.meta));
708
732
  registeredFor.current = definitions;
709
733
  }
710
734
  useCloseOnNavigation();
711
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_jsx_runtime5.Fragment, { children: definitions.map((definition) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(DefinitionSlot, { definition }, definition.id)) });
735
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(HostRendersContext.Provider, { value: renders ?? null, children: definitions.map((definition) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(DefinitionSlot, { definition }, definition.id)) });
712
736
  }
713
737
 
714
738
  // src/react/hooks.ts
715
- var import_react11 = require("react");
739
+ var import_react12 = require("react");
716
740
  var import_summon13 = require("@ai-matrx/summon");
717
741
  var import_summon14 = require("@ai-matrx/summon");
718
742
  var import_summon15 = require("@ai-matrx/summon");
@@ -721,7 +745,7 @@ function useIsOverlayOpen(overlayId, instanceId = import_summon15.DEFAULT_INSTAN
721
745
  }
722
746
  function useOpenOverlay(overlayId) {
723
747
  const dispatch = useSummonDispatch();
724
- return (0, import_react11.useCallback)(
748
+ return (0, import_react12.useCallback)(
725
749
  (options) => {
726
750
  const multi = (0, import_summon13.getOverlayMeta)(overlayId)?.instance === "multi";
727
751
  const instanceId = options?.instanceId ?? (multi ? newInstanceId(overlayId) : import_summon15.DEFAULT_INSTANCE_ID);
@@ -733,6 +757,6 @@ function useOpenOverlay(overlayId) {
733
757
  }
734
758
  function useCloseOverlay(overlayId, instanceId = import_summon15.DEFAULT_INSTANCE_ID) {
735
759
  const dispatch = useSummonDispatch();
736
- return (0, import_react11.useCallback)(() => dispatchClose(dispatch, overlayId, instanceId), [dispatch, overlayId, instanceId]);
760
+ return (0, import_react12.useCallback)(() => dispatchClose(dispatch, overlayId, instanceId), [dispatch, overlayId, instanceId]);
737
761
  }
738
762
  //# sourceMappingURL=react.cjs.map