@matterfact/embed 0.13.0 → 0.16.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.
- package/README.md +37 -2
- package/dist/react.cjs +275 -28
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +164 -11
- package/dist/react.d.ts +164 -11
- package/dist/react.js +264 -19
- package/dist/react.js.map +1 -1
- package/examples/embed-demo/.env.example +9 -0
- package/examples/embed-demo/README.md +66 -12
- package/examples/embed-demo/src/App.tsx +56 -12
- package/examples/embed-demo/src/config.ts +8 -0
- package/package.json +1 -1
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 { useCallback, useEffect as useEffect2, useRef } from "react";
|
|
6
6
|
|
|
7
7
|
// src/protocol.ts
|
|
8
8
|
var PROTOCOL_VERSION = 3;
|
|
@@ -806,9 +806,63 @@ function mount(config) {
|
|
|
806
806
|
return host;
|
|
807
807
|
}
|
|
808
808
|
|
|
809
|
-
// src/react.tsx
|
|
809
|
+
// src/react-context.tsx
|
|
810
|
+
import { createContext, useContext, useEffect, useMemo } from "react";
|
|
810
811
|
import { jsx } from "react/jsx-runtime";
|
|
811
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";
|
|
812
866
|
function writeActionsGlobal(actions) {
|
|
813
867
|
if (typeof window === "undefined") return;
|
|
814
868
|
const w = window;
|
|
@@ -852,11 +906,11 @@ function toolDescriptorKey(artifacts, resolve, tools) {
|
|
|
852
906
|
});
|
|
853
907
|
}
|
|
854
908
|
function MatterfactAgent({
|
|
855
|
-
publishableKey,
|
|
856
|
-
widgetOrigin,
|
|
909
|
+
publishableKey: publishableKeyProp,
|
|
910
|
+
widgetOrigin: widgetOriginProp,
|
|
857
911
|
surface = "",
|
|
858
|
-
theme
|
|
859
|
-
getAuthToken,
|
|
912
|
+
theme: themeProp,
|
|
913
|
+
getAuthToken: getAuthTokenProp,
|
|
860
914
|
getPageContext,
|
|
861
915
|
inline = false,
|
|
862
916
|
className,
|
|
@@ -871,6 +925,16 @@ function MatterfactAgent({
|
|
|
871
925
|
onToolEvent,
|
|
872
926
|
onEvent
|
|
873
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";
|
|
874
938
|
const authRef = useRef(getAuthToken);
|
|
875
939
|
authRef.current = getAuthToken;
|
|
876
940
|
const pageContextRef = useRef(getPageContext);
|
|
@@ -880,21 +944,22 @@ function MatterfactAgent({
|
|
|
880
944
|
const actionsKey = JSON.stringify(actions ?? null);
|
|
881
945
|
const slot = useRef(null);
|
|
882
946
|
const sitemapKey = JSON.stringify(sitemap ?? null);
|
|
883
|
-
|
|
947
|
+
useEffect2(() => {
|
|
884
948
|
writeSitemapGlobal(sitemap);
|
|
885
949
|
}, [sitemapKey]);
|
|
886
|
-
|
|
950
|
+
useEffect2(() => {
|
|
887
951
|
writeToolGlobals(artifacts, resolve, tools, onToolEvent, onEvent);
|
|
888
952
|
});
|
|
889
953
|
const toolsKey = toolDescriptorKey(artifacts, resolve, tools);
|
|
890
|
-
|
|
954
|
+
useEffect2(() => {
|
|
891
955
|
if (typeof window === "undefined") return;
|
|
892
956
|
if (inline && !slot.current) return;
|
|
893
957
|
writeActionsGlobal(actionsRef.current);
|
|
894
958
|
writeToolGlobals(artifacts, resolve, tools, onToolEvent, onEvent);
|
|
895
959
|
const config = {
|
|
896
960
|
publishableKey,
|
|
897
|
-
|
|
961
|
+
// Already fully resolved above (prop ?? context ?? DEFAULT_ORIGIN).
|
|
962
|
+
origin: widgetOrigin,
|
|
898
963
|
theme,
|
|
899
964
|
surface,
|
|
900
965
|
// Always present; a null return (no getAuthToken supplied) makes the core fall
|
|
@@ -936,7 +1001,7 @@ function MatterfactAgent({
|
|
|
936
1001
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
937
1002
|
]);
|
|
938
1003
|
if (!inline) return null;
|
|
939
|
-
return /* @__PURE__ */
|
|
1004
|
+
return /* @__PURE__ */ jsx2(
|
|
940
1005
|
"div",
|
|
941
1006
|
{
|
|
942
1007
|
ref: slot,
|
|
@@ -946,30 +1011,210 @@ function MatterfactAgent({
|
|
|
946
1011
|
);
|
|
947
1012
|
}
|
|
948
1013
|
var DEFAULT_ARTIFACT_ORIGIN = "https://app.matterfact.com";
|
|
1014
|
+
function snapshot(params) {
|
|
1015
|
+
const out = /* @__PURE__ */ new Map();
|
|
1016
|
+
for (const [key, value] of Object.entries(params ?? {})) {
|
|
1017
|
+
out.set(key, JSON.stringify(value ?? null));
|
|
1018
|
+
}
|
|
1019
|
+
return out;
|
|
1020
|
+
}
|
|
949
1021
|
function MatterfactArtifact({
|
|
1022
|
+
name: nameProp,
|
|
950
1023
|
slug,
|
|
951
1024
|
owner,
|
|
952
1025
|
token,
|
|
953
|
-
widgetOrigin,
|
|
954
|
-
theme
|
|
1026
|
+
widgetOrigin: widgetOriginProp,
|
|
1027
|
+
theme: themeProp,
|
|
955
1028
|
className,
|
|
956
|
-
style
|
|
1029
|
+
style,
|
|
1030
|
+
params,
|
|
1031
|
+
onParamsChange
|
|
957
1032
|
}) {
|
|
958
|
-
const
|
|
959
|
-
const
|
|
960
|
-
|
|
1033
|
+
const ctx = useMatterfactConfig();
|
|
1034
|
+
const artifactName = nameProp ?? slug;
|
|
1035
|
+
if (!artifactName) {
|
|
1036
|
+
throw new Error(
|
|
1037
|
+
"MatterfactArtifact requires name (or its deprecated alias, slug)"
|
|
1038
|
+
);
|
|
1039
|
+
}
|
|
1040
|
+
const origin = widgetOriginProp ?? ctx?.widgetOrigin ?? DEFAULT_ARTIFACT_ORIGIN;
|
|
1041
|
+
const theme = themeProp ?? ctx?.theme ?? "auto";
|
|
1042
|
+
const frame = useRef(null);
|
|
1043
|
+
const changeRef = useRef(onParamsChange);
|
|
1044
|
+
changeRef.current = onParamsChange;
|
|
1045
|
+
const paramsRef = useRef(params);
|
|
1046
|
+
paramsRef.current = params;
|
|
1047
|
+
const posted = useRef(/* @__PURE__ */ new Map());
|
|
1048
|
+
const post = useCallback(
|
|
1049
|
+
(values) => {
|
|
1050
|
+
if (Object.keys(values).length === 0) return;
|
|
1051
|
+
frame.current?.contentWindow?.postMessage(
|
|
1052
|
+
{ type: "host.artifactParams", params: values },
|
|
1053
|
+
origin
|
|
1054
|
+
);
|
|
1055
|
+
},
|
|
1056
|
+
[origin]
|
|
1057
|
+
);
|
|
1058
|
+
const postAll = useCallback(() => {
|
|
1059
|
+
posted.current = snapshot(paramsRef.current);
|
|
1060
|
+
post({ ...paramsRef.current });
|
|
1061
|
+
}, [post]);
|
|
1062
|
+
const onLoad = useCallback(() => postAll(), [postAll]);
|
|
1063
|
+
useEffect2(() => {
|
|
1064
|
+
if (typeof window === "undefined") return;
|
|
1065
|
+
const onMessage = (event) => {
|
|
1066
|
+
if (!frame.current || event.source !== frame.current.contentWindow) return;
|
|
1067
|
+
const data = event.data;
|
|
1068
|
+
if (!data || typeof data !== "object") return;
|
|
1069
|
+
if (data.type === "widget.artifactReady") {
|
|
1070
|
+
postAll();
|
|
1071
|
+
return;
|
|
1072
|
+
}
|
|
1073
|
+
if (data.type === "widget.artifactParams" && data.params) {
|
|
1074
|
+
const source = data.source === "context" ? "context" : "user";
|
|
1075
|
+
try {
|
|
1076
|
+
changeRef.current?.(data.params, source);
|
|
1077
|
+
} catch {
|
|
1078
|
+
}
|
|
1079
|
+
}
|
|
1080
|
+
};
|
|
1081
|
+
window.addEventListener("message", onMessage);
|
|
1082
|
+
return () => window.removeEventListener("message", onMessage);
|
|
1083
|
+
}, [postAll]);
|
|
1084
|
+
const paramsKey = JSON.stringify(params ?? null);
|
|
1085
|
+
const settled = useRef(false);
|
|
1086
|
+
useEffect2(() => {
|
|
1087
|
+
const next = snapshot(paramsRef.current);
|
|
1088
|
+
if (!settled.current) {
|
|
1089
|
+
settled.current = true;
|
|
1090
|
+
posted.current = next;
|
|
1091
|
+
return;
|
|
1092
|
+
}
|
|
1093
|
+
const changed = {};
|
|
1094
|
+
for (const [key, json] of next) {
|
|
1095
|
+
if (posted.current.get(key) !== json) {
|
|
1096
|
+
changed[key] = paramsRef.current[key];
|
|
1097
|
+
}
|
|
1098
|
+
}
|
|
1099
|
+
posted.current = next;
|
|
1100
|
+
post(changed);
|
|
1101
|
+
}, [paramsKey, post]);
|
|
1102
|
+
let src;
|
|
1103
|
+
if (token) {
|
|
1104
|
+
src = `${origin}/embed/artifacts/${encodeURIComponent(artifactName)}?owner=${encodeURIComponent(owner)}&t=${encodeURIComponent(token)}&theme=${theme}`;
|
|
1105
|
+
} else if (ctx) {
|
|
1106
|
+
const hostOrigin = typeof window === "undefined" ? "" : window.location.origin;
|
|
1107
|
+
src = `${origin}/embed/artifacts/${encodeURIComponent(artifactName)}?owner=${encodeURIComponent(owner)}&k=${encodeURIComponent(ctx.publishableKey)}&o=${encodeURIComponent(hostOrigin)}&theme=${theme}`;
|
|
1108
|
+
} else {
|
|
1109
|
+
return /* @__PURE__ */ jsx2(
|
|
1110
|
+
"div",
|
|
1111
|
+
{
|
|
1112
|
+
className,
|
|
1113
|
+
style: {
|
|
1114
|
+
width: "100%",
|
|
1115
|
+
height: 600,
|
|
1116
|
+
display: "flex",
|
|
1117
|
+
alignItems: "center",
|
|
1118
|
+
justifyContent: "center",
|
|
1119
|
+
textAlign: "center",
|
|
1120
|
+
...style
|
|
1121
|
+
},
|
|
1122
|
+
children: /* @__PURE__ */ jsx2("p", { children: "This embedded artifact link is incomplete." })
|
|
1123
|
+
}
|
|
1124
|
+
);
|
|
1125
|
+
}
|
|
1126
|
+
return /* @__PURE__ */ jsx2(
|
|
961
1127
|
"iframe",
|
|
962
1128
|
{
|
|
1129
|
+
ref: frame,
|
|
963
1130
|
src,
|
|
964
|
-
|
|
1131
|
+
onLoad,
|
|
1132
|
+
title: `matterfact artifact ${artifactName}`,
|
|
965
1133
|
className,
|
|
966
1134
|
style: { width: "100%", height: 600, border: 0, ...style },
|
|
967
1135
|
sandbox: "allow-scripts allow-same-origin allow-forms allow-popups allow-popups-to-escape-sandbox allow-downloads"
|
|
968
1136
|
}
|
|
969
1137
|
);
|
|
970
1138
|
}
|
|
1139
|
+
var DEFAULT_DOC_ORIGIN = "https://app.matterfact.com";
|
|
1140
|
+
function diffDocParams(params, sent) {
|
|
1141
|
+
const changed = {};
|
|
1142
|
+
for (const [key, value] of Object.entries(params)) {
|
|
1143
|
+
if (value === void 0) continue;
|
|
1144
|
+
const snapshot2 = JSON.stringify(value);
|
|
1145
|
+
if (sent.get(key) === snapshot2) continue;
|
|
1146
|
+
changed[key] = value;
|
|
1147
|
+
sent.set(key, snapshot2);
|
|
1148
|
+
}
|
|
1149
|
+
return changed;
|
|
1150
|
+
}
|
|
1151
|
+
function MatterfactDoc({
|
|
1152
|
+
docKey,
|
|
1153
|
+
ticker = "",
|
|
1154
|
+
version = "latest",
|
|
1155
|
+
theme: themeProp,
|
|
1156
|
+
params,
|
|
1157
|
+
className,
|
|
1158
|
+
style
|
|
1159
|
+
}) {
|
|
1160
|
+
const ctx = useMatterfactConfig();
|
|
1161
|
+
const iframeRef = useRef(null);
|
|
1162
|
+
const sentParamsRef = useRef(/* @__PURE__ */ new Map());
|
|
1163
|
+
const origin = ctx?.widgetOrigin ?? DEFAULT_DOC_ORIGIN;
|
|
1164
|
+
const paramsKey = JSON.stringify(params ?? null);
|
|
1165
|
+
const pushParams = (force) => {
|
|
1166
|
+
if (!params) return;
|
|
1167
|
+
const win = iframeRef.current?.contentWindow;
|
|
1168
|
+
if (!win) return;
|
|
1169
|
+
if (force) sentParamsRef.current.clear();
|
|
1170
|
+
const changed = diffDocParams(params, sentParamsRef.current);
|
|
1171
|
+
if (Object.keys(changed).length === 0) return;
|
|
1172
|
+
win.postMessage({ type: "host.docParams", params: changed }, origin);
|
|
1173
|
+
};
|
|
1174
|
+
useEffect2(() => {
|
|
1175
|
+
pushParams(false);
|
|
1176
|
+
}, [paramsKey]);
|
|
1177
|
+
if (!docKey) {
|
|
1178
|
+
throw new Error("MatterfactDoc requires docKey");
|
|
1179
|
+
}
|
|
1180
|
+
if (!ctx || !ctx.publishableKey) {
|
|
1181
|
+
return /* @__PURE__ */ jsx2(
|
|
1182
|
+
"div",
|
|
1183
|
+
{
|
|
1184
|
+
className,
|
|
1185
|
+
style: {
|
|
1186
|
+
width: "100%",
|
|
1187
|
+
height: 600,
|
|
1188
|
+
display: "flex",
|
|
1189
|
+
alignItems: "center",
|
|
1190
|
+
justifyContent: "center",
|
|
1191
|
+
textAlign: "center",
|
|
1192
|
+
...style
|
|
1193
|
+
},
|
|
1194
|
+
children: /* @__PURE__ */ jsx2("p", { children: "This embedded document link is incomplete." })
|
|
1195
|
+
}
|
|
1196
|
+
);
|
|
1197
|
+
}
|
|
1198
|
+
const theme = themeProp ?? ctx.theme ?? "auto";
|
|
1199
|
+
const hostOrigin = typeof window === "undefined" ? "" : window.location.origin;
|
|
1200
|
+
const src = `${origin}/embed/document?k=${encodeURIComponent(ctx.publishableKey)}&o=${encodeURIComponent(hostOrigin)}&key=${encodeURIComponent(docKey)}&ticker=${encodeURIComponent(ticker)}&version=${encodeURIComponent(version)}&theme=${theme}`;
|
|
1201
|
+
return /* @__PURE__ */ jsx2(
|
|
1202
|
+
"iframe",
|
|
1203
|
+
{
|
|
1204
|
+
ref: iframeRef,
|
|
1205
|
+
src,
|
|
1206
|
+
title: `matterfact document ${docKey}`,
|
|
1207
|
+
className,
|
|
1208
|
+
style: { width: "100%", height: 600, border: 0, ...style },
|
|
1209
|
+
sandbox: "allow-scripts allow-same-origin allow-forms allow-popups allow-popups-to-escape-sandbox allow-downloads",
|
|
1210
|
+
onLoad: () => pushParams(true)
|
|
1211
|
+
}
|
|
1212
|
+
);
|
|
1213
|
+
}
|
|
971
1214
|
export {
|
|
972
1215
|
MatterfactAgent,
|
|
973
|
-
MatterfactArtifact
|
|
1216
|
+
MatterfactArtifact,
|
|
1217
|
+
MatterfactAuthProvider,
|
|
1218
|
+
MatterfactDoc
|
|
974
1219
|
};
|
|
975
1220
|
//# sourceMappingURL=react.js.map
|