@matterfact/embed 0.12.0 → 0.15.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 (42) hide show
  1. package/README.md +41 -0
  2. package/dist/{chunk-M5TS546Z.js → chunk-C7DXO37G.js} +2 -2
  3. package/dist/{chunk-ZXMJWCQV.js → chunk-JLJG3MDX.js} +57 -35
  4. package/dist/chunk-JLJG3MDX.js.map +1 -0
  5. package/dist/chunk-QZCUQZJK.js +3 -0
  6. package/dist/chunk-QZCUQZJK.js.map +7 -0
  7. package/dist/{chunk-C4XGE6BO.js → chunk-S6OT47DL.js} +56 -34
  8. package/dist/chunk-S6OT47DL.js.map +1 -0
  9. package/dist/{chunk-WAUSVV7Y.js → chunk-UA4Y2O64.js} +2 -2
  10. package/dist/{context-4LP3EDXL.js → context-DAXACLSP.js} +3 -3
  11. package/dist/{context-4LP3EDXL.js.map → context-DAXACLSP.js.map} +1 -1
  12. package/dist/{context-ZSPDZWIB.js → context-IJK345PN.js} +2 -2
  13. package/dist/embed.js +1 -1
  14. package/dist/embed.js.map +3 -3
  15. package/dist/index.cjs +82 -32
  16. package/dist/index.cjs.map +1 -1
  17. package/dist/index.d.cts +73 -2
  18. package/dist/index.d.ts +73 -2
  19. package/dist/index.js +29 -1
  20. package/dist/index.js.map +1 -1
  21. package/dist/react.cjs +281 -55
  22. package/dist/react.cjs.map +1 -1
  23. package/dist/react.d.cts +168 -12
  24. package/dist/react.d.ts +168 -12
  25. package/dist/react.js +221 -19
  26. package/dist/react.js.map +1 -1
  27. package/dist/{snapshot-OR5SVEUD.js → snapshot-EVBNVVCT.js} +2 -2
  28. package/dist/{snapshot-X6FPP3HF.js → snapshot-P5SVKSPB.js} +3 -3
  29. package/dist/{snapshot-X6FPP3HF.js.map → snapshot-P5SVKSPB.js.map} +1 -1
  30. package/examples/embed-demo/.env.example +9 -0
  31. package/examples/embed-demo/README.md +66 -12
  32. package/examples/embed-demo/src/App.tsx +56 -12
  33. package/examples/embed-demo/src/config.ts +8 -0
  34. package/package.json +1 -1
  35. package/dist/chunk-C4XGE6BO.js.map +0 -1
  36. package/dist/chunk-SR4ZNUAN.js +0 -3
  37. package/dist/chunk-SR4ZNUAN.js.map +0 -7
  38. package/dist/chunk-ZXMJWCQV.js.map +0 -1
  39. /package/dist/{chunk-M5TS546Z.js.map → chunk-C7DXO37G.js.map} +0 -0
  40. /package/dist/{chunk-WAUSVV7Y.js.map → chunk-UA4Y2O64.js.map} +0 -0
  41. /package/dist/{context-ZSPDZWIB.js.map → context-IJK345PN.js.map} +0 -0
  42. /package/dist/{snapshot-OR5SVEUD.js.map → snapshot-EVBNVVCT.js.map} +0 -0
package/dist/react.js CHANGED
@@ -2,7 +2,7 @@
2
2
  "use client";
3
3
 
4
4
  // src/react.tsx
5
- import { useEffect, useRef } from "react";
5
+ import { useEffect as useEffect2, useRef } from "react";
6
6
 
7
7
  // src/protocol.ts
8
8
  var PROTOCOL_VERSION = 3;
@@ -613,6 +613,13 @@ var EmbedHost = class {
613
613
  case "widget.chat":
614
614
  this.emit({ type: "chat", phase: msg.phase, chatId: msg.chatId });
615
615
  break;
616
+ case "widget.artifactParams":
617
+ this.emit({
618
+ type: "artifactParams",
619
+ params: msg.params,
620
+ source: msg.source
621
+ });
622
+ break;
616
623
  }
617
624
  }
618
625
  /**
@@ -739,7 +746,7 @@ var EmbedHost = class {
739
746
  }
740
747
  }
741
748
  loadContext() {
742
- this.context ?? (this.context = import("./context-ZSPDZWIB.js").then((m) => {
749
+ this.context ?? (this.context = import("./context-IJK345PN.js").then((m) => {
743
750
  m.start(
744
751
  this.send,
745
752
  this.config.origin,
@@ -758,6 +765,23 @@ var EmbedHost = class {
758
765
  this.queue = [];
759
766
  for (const m of pending) this.send(m);
760
767
  }
768
+ /**
769
+ * Push artifact param values into the widget — a PARTIAL patch; only the named
770
+ * params change. Buffered like every other host→widget message until the widget
771
+ * says it's listening.
772
+ *
773
+ * Explicit and deliberate, so it applies even to a param whose page-context binding
774
+ * the viewer has overridden (spec §7.3).
775
+ */
776
+ setArtifactParams(params) {
777
+ if (params == null || typeof params !== "object" || Array.isArray(params)) {
778
+ console.error(
779
+ "[matterfact] setArtifactParams expects an object of param values"
780
+ );
781
+ return;
782
+ }
783
+ this.send({ type: "host.artifactParams", params });
784
+ }
761
785
  /** Tear down: stop listening and remove the host element. For the React wrapper's
762
786
  * unmount — the vanilla `<script>` loader lives for the page's lifetime and never
763
787
  * calls this. */
@@ -775,12 +799,70 @@ var EmbedHost = class {
775
799
  function mount(config) {
776
800
  const host = new EmbedHost(config);
777
801
  host.mount();
802
+ window.matterfact = {
803
+ ...window.matterfact ?? {},
804
+ setArtifactParams: (params) => host.setArtifactParams(params)
805
+ };
778
806
  return host;
779
807
  }
780
808
 
781
- // src/react.tsx
809
+ // src/react-context.tsx
810
+ import { createContext, useContext, useEffect, useMemo } from "react";
782
811
  import { jsx } from "react/jsx-runtime";
783
812
  var DEFAULT_ORIGIN = "https://app.matterfact.com";
813
+ var MatterfactAuthContext = createContext(null);
814
+ function useMatterfactConfig() {
815
+ return useContext(MatterfactAuthContext);
816
+ }
817
+ function MatterfactAuthProvider({
818
+ publishableKey,
819
+ widgetOrigin,
820
+ getAuthToken,
821
+ theme,
822
+ onEvent,
823
+ children
824
+ }) {
825
+ const resolvedWidgetOrigin = widgetOrigin || DEFAULT_ORIGIN;
826
+ const value = useMemo(
827
+ () => ({
828
+ publishableKey,
829
+ widgetOrigin: resolvedWidgetOrigin,
830
+ getAuthToken,
831
+ theme: theme || "auto",
832
+ onEvent
833
+ }),
834
+ [publishableKey, resolvedWidgetOrigin, getAuthToken, theme, onEvent]
835
+ );
836
+ useEffect(() => {
837
+ if (typeof window === "undefined" || !getAuthToken) return;
838
+ let inflight = null;
839
+ const onMessage = (e) => {
840
+ if (e.origin !== resolvedWidgetOrigin) return;
841
+ if (!e.data || e.data.type !== "mf.hostAuth.request") return;
842
+ const source = e.source;
843
+ if (!source) return;
844
+ try {
845
+ inflight = inflight ?? Promise.resolve(getAuthToken()).catch(() => null);
846
+ } catch {
847
+ return;
848
+ }
849
+ const p = inflight;
850
+ void p.then((token) => {
851
+ if (p === inflight) inflight = null;
852
+ if (typeof token === "string" && token) {
853
+ source.postMessage({ type: "mf.hostAuth.grant", token }, resolvedWidgetOrigin);
854
+ }
855
+ });
856
+ };
857
+ window.addEventListener("message", onMessage);
858
+ return () => window.removeEventListener("message", onMessage);
859
+ }, [getAuthToken, resolvedWidgetOrigin]);
860
+ return /* @__PURE__ */ jsx(MatterfactAuthContext.Provider, { value, children });
861
+ }
862
+
863
+ // src/react.tsx
864
+ import { jsx as jsx2 } from "react/jsx-runtime";
865
+ var DEFAULT_ORIGIN2 = "https://app.matterfact.com";
784
866
  function writeActionsGlobal(actions) {
785
867
  if (typeof window === "undefined") return;
786
868
  const w = window;
@@ -824,11 +906,11 @@ function toolDescriptorKey(artifacts, resolve, tools) {
824
906
  });
825
907
  }
826
908
  function MatterfactAgent({
827
- publishableKey,
828
- widgetOrigin,
909
+ publishableKey: publishableKeyProp,
910
+ widgetOrigin: widgetOriginProp,
829
911
  surface = "",
830
- theme = "auto",
831
- getAuthToken,
912
+ theme: themeProp,
913
+ getAuthToken: getAuthTokenProp,
832
914
  getPageContext,
833
915
  inline = false,
834
916
  className,
@@ -843,6 +925,16 @@ function MatterfactAgent({
843
925
  onToolEvent,
844
926
  onEvent
845
927
  }) {
928
+ const ctx = useMatterfactConfig();
929
+ const publishableKey = publishableKeyProp ?? ctx?.publishableKey;
930
+ if (!publishableKey) {
931
+ throw new Error(
932
+ "MatterfactAgent requires publishableKey (as a prop or via MatterfactAuthProvider)"
933
+ );
934
+ }
935
+ const widgetOrigin = widgetOriginProp ?? ctx?.widgetOrigin ?? DEFAULT_ORIGIN2;
936
+ const getAuthToken = getAuthTokenProp ?? ctx?.getAuthToken;
937
+ const theme = themeProp ?? ctx?.theme ?? "auto";
846
938
  const authRef = useRef(getAuthToken);
847
939
  authRef.current = getAuthToken;
848
940
  const pageContextRef = useRef(getPageContext);
@@ -852,21 +944,22 @@ function MatterfactAgent({
852
944
  const actionsKey = JSON.stringify(actions ?? null);
853
945
  const slot = useRef(null);
854
946
  const sitemapKey = JSON.stringify(sitemap ?? null);
855
- useEffect(() => {
947
+ useEffect2(() => {
856
948
  writeSitemapGlobal(sitemap);
857
949
  }, [sitemapKey]);
858
- useEffect(() => {
950
+ useEffect2(() => {
859
951
  writeToolGlobals(artifacts, resolve, tools, onToolEvent, onEvent);
860
952
  });
861
953
  const toolsKey = toolDescriptorKey(artifacts, resolve, tools);
862
- useEffect(() => {
954
+ useEffect2(() => {
863
955
  if (typeof window === "undefined") return;
864
956
  if (inline && !slot.current) return;
865
957
  writeActionsGlobal(actionsRef.current);
866
958
  writeToolGlobals(artifacts, resolve, tools, onToolEvent, onEvent);
867
959
  const config = {
868
960
  publishableKey,
869
- origin: widgetOrigin || DEFAULT_ORIGIN,
961
+ // Already fully resolved above (prop ?? context ?? DEFAULT_ORIGIN).
962
+ origin: widgetOrigin,
870
963
  theme,
871
964
  surface,
872
965
  // Always present; a null return (no getAuthToken supplied) makes the core fall
@@ -908,7 +1001,7 @@ function MatterfactAgent({
908
1001
  // eslint-disable-next-line react-hooks/exhaustive-deps
909
1002
  ]);
910
1003
  if (!inline) return null;
911
- return /* @__PURE__ */ jsx(
1004
+ return /* @__PURE__ */ jsx2(
912
1005
  "div",
913
1006
  {
914
1007
  ref: slot,
@@ -919,29 +1012,138 @@ function MatterfactAgent({
919
1012
  }
920
1013
  var DEFAULT_ARTIFACT_ORIGIN = "https://app.matterfact.com";
921
1014
  function MatterfactArtifact({
1015
+ name: nameProp,
922
1016
  slug,
923
1017
  owner,
924
1018
  token,
925
- widgetOrigin,
926
- theme = "auto",
1019
+ widgetOrigin: widgetOriginProp,
1020
+ theme: themeProp,
927
1021
  className,
928
1022
  style
929
1023
  }) {
930
- const origin = widgetOrigin || DEFAULT_ARTIFACT_ORIGIN;
931
- const src = `${origin}/embed/artifacts/${encodeURIComponent(slug)}?owner=${encodeURIComponent(owner)}&t=${encodeURIComponent(token)}&theme=${theme}`;
932
- return /* @__PURE__ */ jsx(
1024
+ const ctx = useMatterfactConfig();
1025
+ const artifactName = nameProp ?? slug;
1026
+ if (!artifactName) {
1027
+ throw new Error(
1028
+ "MatterfactArtifact requires name (or its deprecated alias, slug)"
1029
+ );
1030
+ }
1031
+ const origin = widgetOriginProp ?? ctx?.widgetOrigin ?? DEFAULT_ARTIFACT_ORIGIN;
1032
+ const theme = themeProp ?? ctx?.theme ?? "auto";
1033
+ let src;
1034
+ if (token) {
1035
+ src = `${origin}/embed/artifacts/${encodeURIComponent(artifactName)}?owner=${encodeURIComponent(owner)}&t=${encodeURIComponent(token)}&theme=${theme}`;
1036
+ } else if (ctx) {
1037
+ const hostOrigin = typeof window === "undefined" ? "" : window.location.origin;
1038
+ src = `${origin}/embed/artifacts/${encodeURIComponent(artifactName)}?owner=${encodeURIComponent(owner)}&k=${encodeURIComponent(ctx.publishableKey)}&o=${encodeURIComponent(hostOrigin)}&theme=${theme}`;
1039
+ } else {
1040
+ return /* @__PURE__ */ jsx2(
1041
+ "div",
1042
+ {
1043
+ className,
1044
+ style: {
1045
+ width: "100%",
1046
+ height: 600,
1047
+ display: "flex",
1048
+ alignItems: "center",
1049
+ justifyContent: "center",
1050
+ textAlign: "center",
1051
+ ...style
1052
+ },
1053
+ children: /* @__PURE__ */ jsx2("p", { children: "This embedded artifact link is incomplete." })
1054
+ }
1055
+ );
1056
+ }
1057
+ return /* @__PURE__ */ jsx2(
933
1058
  "iframe",
934
1059
  {
935
1060
  src,
936
- title: `matterfact artifact ${slug}`,
1061
+ title: `matterfact artifact ${artifactName}`,
937
1062
  className,
938
1063
  style: { width: "100%", height: 600, border: 0, ...style },
939
1064
  sandbox: "allow-scripts allow-same-origin allow-forms allow-popups allow-popups-to-escape-sandbox allow-downloads"
940
1065
  }
941
1066
  );
942
1067
  }
1068
+ var DEFAULT_DOC_ORIGIN = "https://app.matterfact.com";
1069
+ function diffDocParams(params, sent) {
1070
+ const changed = {};
1071
+ for (const [key, value] of Object.entries(params)) {
1072
+ if (value === void 0) continue;
1073
+ const snapshot = JSON.stringify(value);
1074
+ if (sent.get(key) === snapshot) continue;
1075
+ changed[key] = value;
1076
+ sent.set(key, snapshot);
1077
+ }
1078
+ return changed;
1079
+ }
1080
+ function MatterfactDoc({
1081
+ docKey,
1082
+ ticker = "",
1083
+ version = "latest",
1084
+ theme: themeProp,
1085
+ params,
1086
+ className,
1087
+ style
1088
+ }) {
1089
+ const ctx = useMatterfactConfig();
1090
+ const iframeRef = useRef(null);
1091
+ const sentParamsRef = useRef(/* @__PURE__ */ new Map());
1092
+ const origin = ctx?.widgetOrigin ?? DEFAULT_DOC_ORIGIN;
1093
+ const paramsKey = JSON.stringify(params ?? null);
1094
+ const pushParams = (force) => {
1095
+ if (!params) return;
1096
+ const win = iframeRef.current?.contentWindow;
1097
+ if (!win) return;
1098
+ if (force) sentParamsRef.current.clear();
1099
+ const changed = diffDocParams(params, sentParamsRef.current);
1100
+ if (Object.keys(changed).length === 0) return;
1101
+ win.postMessage({ type: "host.docParams", params: changed }, origin);
1102
+ };
1103
+ useEffect2(() => {
1104
+ pushParams(false);
1105
+ }, [paramsKey]);
1106
+ if (!docKey) {
1107
+ throw new Error("MatterfactDoc requires docKey");
1108
+ }
1109
+ if (!ctx || !ctx.publishableKey) {
1110
+ return /* @__PURE__ */ jsx2(
1111
+ "div",
1112
+ {
1113
+ className,
1114
+ style: {
1115
+ width: "100%",
1116
+ height: 600,
1117
+ display: "flex",
1118
+ alignItems: "center",
1119
+ justifyContent: "center",
1120
+ textAlign: "center",
1121
+ ...style
1122
+ },
1123
+ children: /* @__PURE__ */ jsx2("p", { children: "This embedded document link is incomplete." })
1124
+ }
1125
+ );
1126
+ }
1127
+ const theme = themeProp ?? ctx.theme ?? "auto";
1128
+ const hostOrigin = typeof window === "undefined" ? "" : window.location.origin;
1129
+ const src = `${origin}/embed/document?k=${encodeURIComponent(ctx.publishableKey)}&o=${encodeURIComponent(hostOrigin)}&key=${encodeURIComponent(docKey)}&ticker=${encodeURIComponent(ticker)}&version=${encodeURIComponent(version)}&theme=${theme}`;
1130
+ return /* @__PURE__ */ jsx2(
1131
+ "iframe",
1132
+ {
1133
+ ref: iframeRef,
1134
+ src,
1135
+ title: `matterfact document ${docKey}`,
1136
+ className,
1137
+ style: { width: "100%", height: 600, border: 0, ...style },
1138
+ sandbox: "allow-scripts allow-same-origin allow-forms allow-popups allow-popups-to-escape-sandbox allow-downloads",
1139
+ onLoad: () => pushParams(true)
1140
+ }
1141
+ );
1142
+ }
943
1143
  export {
944
1144
  MatterfactAgent,
945
- MatterfactArtifact
1145
+ MatterfactArtifact,
1146
+ MatterfactAuthProvider,
1147
+ MatterfactDoc
946
1148
  };
947
1149
  //# sourceMappingURL=react.js.map