@matterfact/embed 0.15.0 → 0.17.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 +62 -2
- package/dist/chunk-QVNE5FQV.js +2 -0
- package/dist/chunk-QVNE5FQV.js.map +7 -0
- package/dist/deeplink-IBFUWANV.js +104 -0
- package/dist/deeplink-IBFUWANV.js.map +1 -0
- package/dist/deeplink-QW3VRPOY.js +101 -0
- package/dist/deeplink-QW3VRPOY.js.map +1 -0
- package/dist/embed.js +1 -1
- package/dist/embed.js.map +3 -3
- package/dist/index.cjs +131 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +35 -1
- package/dist/index.d.ts +35 -1
- package/dist/index.js +23 -3
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +214 -14
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +44 -8
- package/dist/react.d.ts +44 -8
- package/dist/react.js +102 -11
- package/dist/react.js.map +1 -1
- package/examples/embed-demo/src/App.tsx +6 -0
- package/package.json +1 -1
package/dist/react.cjs
CHANGED
|
@@ -22,6 +22,115 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
22
22
|
};
|
|
23
23
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
24
24
|
|
|
25
|
+
// src/deeplink.ts
|
|
26
|
+
var deeplink_exports = {};
|
|
27
|
+
__export(deeplink_exports, {
|
|
28
|
+
compileDeeplinkFormat: () => compileDeeplinkFormat,
|
|
29
|
+
installDeeplinkWatch: () => installDeeplinkWatch
|
|
30
|
+
});
|
|
31
|
+
function compileDeeplinkFormat(format) {
|
|
32
|
+
const first = format.indexOf(PLACEHOLDER);
|
|
33
|
+
if (first < 0 || format.indexOf(PLACEHOLDER, first + 1) >= 0) return null;
|
|
34
|
+
let f;
|
|
35
|
+
try {
|
|
36
|
+
f = new URL(format.replace(PLACEHOLDER, SENTINEL));
|
|
37
|
+
} catch {
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
if (f.protocol !== "https:" && f.protocol !== "http:") return null;
|
|
41
|
+
const keys = [...f.searchParams.keys()];
|
|
42
|
+
if (new Set(keys).size !== keys.length) return null;
|
|
43
|
+
const fPath = trimSlash(f.pathname);
|
|
44
|
+
const segs = fPath.split("/");
|
|
45
|
+
const segIdx = segs.indexOf(SENTINEL);
|
|
46
|
+
let queryKey = null;
|
|
47
|
+
for (const [k, v] of f.searchParams) {
|
|
48
|
+
if (v === SENTINEL) queryKey = k;
|
|
49
|
+
}
|
|
50
|
+
if (segIdx >= 0 === (queryKey !== null)) return null;
|
|
51
|
+
return (href) => {
|
|
52
|
+
let u;
|
|
53
|
+
try {
|
|
54
|
+
u = new URL(href);
|
|
55
|
+
} catch {
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
if (u.origin !== f.origin) return null;
|
|
59
|
+
const uPath = trimSlash(u.pathname);
|
|
60
|
+
let token;
|
|
61
|
+
if (segIdx >= 0) {
|
|
62
|
+
const us = uPath.split("/");
|
|
63
|
+
if (us.length !== segs.length) return null;
|
|
64
|
+
for (let i = 0; i < segs.length; i++) {
|
|
65
|
+
if (i !== segIdx && us[i] !== segs[i]) return null;
|
|
66
|
+
}
|
|
67
|
+
token = us[segIdx];
|
|
68
|
+
for (const [k, v] of f.searchParams) {
|
|
69
|
+
if (u.searchParams.get(k) !== v) return null;
|
|
70
|
+
}
|
|
71
|
+
} else {
|
|
72
|
+
if (uPath !== fPath) return null;
|
|
73
|
+
for (const [k, v] of f.searchParams) {
|
|
74
|
+
if (v === SENTINEL) continue;
|
|
75
|
+
if (u.searchParams.get(k) !== v) return null;
|
|
76
|
+
}
|
|
77
|
+
token = u.searchParams.get(queryKey);
|
|
78
|
+
}
|
|
79
|
+
return token && TOKEN_RE.test(token) ? token : null;
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
function installDeeplinkWatch(format, onChange2) {
|
|
83
|
+
const match = compileDeeplinkFormat(format);
|
|
84
|
+
if (!match) return () => {
|
|
85
|
+
};
|
|
86
|
+
let last = null;
|
|
87
|
+
let stopped = false;
|
|
88
|
+
const fire = () => {
|
|
89
|
+
if (stopped) return;
|
|
90
|
+
try {
|
|
91
|
+
const token = match(location.href);
|
|
92
|
+
if (token !== last) {
|
|
93
|
+
last = token;
|
|
94
|
+
onChange2(token);
|
|
95
|
+
}
|
|
96
|
+
} catch (err) {
|
|
97
|
+
console.warn("[mf-embed] deeplink match failed", err);
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
const origPush = history.pushState;
|
|
101
|
+
const origReplace = history.replaceState;
|
|
102
|
+
const ourPush = function(...args) {
|
|
103
|
+
const r = origPush.apply(this, args);
|
|
104
|
+
fire();
|
|
105
|
+
return r;
|
|
106
|
+
};
|
|
107
|
+
const ourReplace = function(...args) {
|
|
108
|
+
const r = origReplace.apply(this, args);
|
|
109
|
+
fire();
|
|
110
|
+
return r;
|
|
111
|
+
};
|
|
112
|
+
history.pushState = ourPush;
|
|
113
|
+
history.replaceState = ourReplace;
|
|
114
|
+
window.addEventListener("popstate", fire);
|
|
115
|
+
fire();
|
|
116
|
+
return () => {
|
|
117
|
+
stopped = true;
|
|
118
|
+
window.removeEventListener("popstate", fire);
|
|
119
|
+
if (history.pushState === ourPush) history.pushState = origPush;
|
|
120
|
+
if (history.replaceState === ourReplace) history.replaceState = origReplace;
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
var PLACEHOLDER, SENTINEL, TOKEN_RE, trimSlash;
|
|
124
|
+
var init_deeplink = __esm({
|
|
125
|
+
"src/deeplink.ts"() {
|
|
126
|
+
"use strict";
|
|
127
|
+
PLACEHOLDER = "{share_token}";
|
|
128
|
+
SENTINEL = "mf-share-token-sentinel";
|
|
129
|
+
TOKEN_RE = /^[A-Za-z0-9._~-]{4,256}$/;
|
|
130
|
+
trimSlash = (path) => path.length > 1 && path.endsWith("/") ? path.slice(0, -1) : path;
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
|
|
25
134
|
// src/pageContextMode.ts
|
|
26
135
|
function parsePageContextMode(value) {
|
|
27
136
|
if (typeof value === "boolean") return value ? "full" : "off";
|
|
@@ -1362,8 +1471,8 @@ async function readFocus() {
|
|
|
1362
1471
|
}
|
|
1363
1472
|
const active = document.activeElement;
|
|
1364
1473
|
if (active && active !== document.body && !isPrivate(active) && !active.closest("[data-mf-private]")) {
|
|
1365
|
-
const { snapshot:
|
|
1366
|
-
void
|
|
1474
|
+
const { snapshot: snapshot3 } = await loadSnapshotModule();
|
|
1475
|
+
void snapshot3;
|
|
1367
1476
|
focus.focused = {
|
|
1368
1477
|
label: redact(describeControl(active)),
|
|
1369
1478
|
role: active.getAttribute("role") || active.tagName.toLowerCase()
|
|
@@ -1406,9 +1515,9 @@ async function sendSnapshot(emit) {
|
|
|
1406
1515
|
emit({ type: "host.focus", focus: lastFocus });
|
|
1407
1516
|
return;
|
|
1408
1517
|
}
|
|
1409
|
-
const { snapshot:
|
|
1518
|
+
const { snapshot: snapshot3 } = await loadSnapshotModule();
|
|
1410
1519
|
if (!allowsAuto(effectivePageContextMode())) return;
|
|
1411
|
-
const { yaml, truncated, visibleRefs } =
|
|
1520
|
+
const { yaml, truncated, visibleRefs } = snapshot3();
|
|
1412
1521
|
emit({
|
|
1413
1522
|
type: "host.snapshot",
|
|
1414
1523
|
snapshot: { yaml: redact(yaml), seq: ++snapshotSeq, truncated }
|
|
@@ -1618,7 +1727,7 @@ module.exports = __toCommonJS(react_exports);
|
|
|
1618
1727
|
var import_react2 = require("react");
|
|
1619
1728
|
|
|
1620
1729
|
// src/protocol.ts
|
|
1621
|
-
var PROTOCOL_VERSION =
|
|
1730
|
+
var PROTOCOL_VERSION = 4;
|
|
1622
1731
|
var CHANNEL = "mf-embed";
|
|
1623
1732
|
function envelope(payload, id) {
|
|
1624
1733
|
return {
|
|
@@ -1840,6 +1949,7 @@ function dockBox(g, vw, _vh) {
|
|
|
1840
1949
|
}
|
|
1841
1950
|
|
|
1842
1951
|
// src/loader.ts
|
|
1952
|
+
var EMBED_VERSION = "0.17.0";
|
|
1843
1953
|
function devRequested() {
|
|
1844
1954
|
try {
|
|
1845
1955
|
if (new URLSearchParams(location.search).get("mfdev") === "1") return true;
|
|
@@ -1927,6 +2037,8 @@ var EmbedHost = class {
|
|
|
1927
2037
|
this.inline = !!config.container;
|
|
1928
2038
|
}
|
|
1929
2039
|
mount() {
|
|
2040
|
+
const w = window;
|
|
2041
|
+
(w.matterfact ?? (w.matterfact = {})).embedVersion = EMBED_VERSION;
|
|
1930
2042
|
const host = document.createElement("div");
|
|
1931
2043
|
this.hostEl = host;
|
|
1932
2044
|
host.id = "matterfact-embed";
|
|
@@ -1970,7 +2082,7 @@ var EmbedHost = class {
|
|
|
1970
2082
|
"sandbox",
|
|
1971
2083
|
"allow-scripts allow-same-origin allow-forms allow-popups allow-popups-to-escape-sandbox allow-downloads"
|
|
1972
2084
|
);
|
|
1973
|
-
iframe.setAttribute("allow", "microphone; clipboard-write");
|
|
2085
|
+
iframe.setAttribute("allow", "microphone; clipboard-write; web-share");
|
|
1974
2086
|
iframe.src = `${this.config.origin}/embed/chat?k=${encodeURIComponent(
|
|
1975
2087
|
this.config.publishableKey
|
|
1976
2088
|
)}&o=${encodeURIComponent(location.origin)}` + (this.config.surface ? `&s=${encodeURIComponent(this.config.surface)}` : "") + // Either trigger works: the URL param (no redeploy needed) OR the config's
|
|
@@ -1983,6 +2095,17 @@ var EmbedHost = class {
|
|
|
1983
2095
|
window.addEventListener("resize", this.onViewportResize);
|
|
1984
2096
|
this.place();
|
|
1985
2097
|
}
|
|
2098
|
+
const fmt = this.config.shareDeeplinkFormat;
|
|
2099
|
+
if (fmt) {
|
|
2100
|
+
this.send({ type: "host.deeplinkFormat", format: fmt });
|
|
2101
|
+
void Promise.resolve().then(() => (init_deeplink(), deeplink_exports)).then((m) => {
|
|
2102
|
+
if (this.destroyed) return;
|
|
2103
|
+
this.deeplinkStop = m.installDeeplinkWatch(fmt, (token) => {
|
|
2104
|
+
this.send({ type: "host.openShare", token });
|
|
2105
|
+
});
|
|
2106
|
+
}).catch(() => {
|
|
2107
|
+
});
|
|
2108
|
+
}
|
|
1986
2109
|
}
|
|
1987
2110
|
/**
|
|
1988
2111
|
* Test seam. The shadow root is CLOSED, so a test cannot reach the iframe to forge a
|
|
@@ -2406,6 +2529,9 @@ var EmbedHost = class {
|
|
|
2406
2529
|
this.iframe = null;
|
|
2407
2530
|
this.shadow = null;
|
|
2408
2531
|
this.ready = false;
|
|
2532
|
+
this.destroyed = true;
|
|
2533
|
+
this.deeplinkStop?.();
|
|
2534
|
+
this.deeplinkStop = null;
|
|
2409
2535
|
void this.context?.then((m) => m.stop());
|
|
2410
2536
|
}
|
|
2411
2537
|
};
|
|
@@ -2522,6 +2648,7 @@ function MatterfactAgent({
|
|
|
2522
2648
|
publishableKey: publishableKeyProp,
|
|
2523
2649
|
widgetOrigin: widgetOriginProp,
|
|
2524
2650
|
surface = "",
|
|
2651
|
+
shareDeeplinkFormat,
|
|
2525
2652
|
theme: themeProp,
|
|
2526
2653
|
getAuthToken: getAuthTokenProp,
|
|
2527
2654
|
getPageContext,
|
|
@@ -2583,7 +2710,8 @@ function MatterfactAgent({
|
|
|
2583
2710
|
pageContextProvider: async () => await pageContextRef.current?.() ?? null,
|
|
2584
2711
|
container: inline ? slot.current : null,
|
|
2585
2712
|
pageContext,
|
|
2586
|
-
dev
|
|
2713
|
+
dev,
|
|
2714
|
+
shareDeeplinkFormat
|
|
2587
2715
|
};
|
|
2588
2716
|
let host = null;
|
|
2589
2717
|
try {
|
|
@@ -2603,6 +2731,7 @@ function MatterfactAgent({
|
|
|
2603
2731
|
publishableKey,
|
|
2604
2732
|
widgetOrigin2,
|
|
2605
2733
|
surface,
|
|
2734
|
+
shareDeeplinkFormat,
|
|
2606
2735
|
theme,
|
|
2607
2736
|
inline,
|
|
2608
2737
|
pageContext,
|
|
@@ -2624,6 +2753,13 @@ function MatterfactAgent({
|
|
|
2624
2753
|
);
|
|
2625
2754
|
}
|
|
2626
2755
|
var DEFAULT_ARTIFACT_ORIGIN = "https://app.matterfact.com";
|
|
2756
|
+
function snapshot2(params) {
|
|
2757
|
+
const out = /* @__PURE__ */ new Map();
|
|
2758
|
+
for (const [key, value] of Object.entries(params ?? {})) {
|
|
2759
|
+
out.set(key, JSON.stringify(value ?? null));
|
|
2760
|
+
}
|
|
2761
|
+
return out;
|
|
2762
|
+
}
|
|
2627
2763
|
function MatterfactArtifact({
|
|
2628
2764
|
name: nameProp,
|
|
2629
2765
|
slug,
|
|
@@ -2632,7 +2768,9 @@ function MatterfactArtifact({
|
|
|
2632
2768
|
widgetOrigin: widgetOriginProp,
|
|
2633
2769
|
theme: themeProp,
|
|
2634
2770
|
className: className2,
|
|
2635
|
-
style
|
|
2771
|
+
style,
|
|
2772
|
+
params,
|
|
2773
|
+
onParamsChange
|
|
2636
2774
|
}) {
|
|
2637
2775
|
const ctx = useMatterfactConfig();
|
|
2638
2776
|
const artifactName = nameProp ?? slug;
|
|
@@ -2643,12 +2781,72 @@ function MatterfactArtifact({
|
|
|
2643
2781
|
}
|
|
2644
2782
|
const origin = widgetOriginProp ?? ctx?.widgetOrigin ?? DEFAULT_ARTIFACT_ORIGIN;
|
|
2645
2783
|
const theme = themeProp ?? ctx?.theme ?? "auto";
|
|
2784
|
+
const frame = (0, import_react2.useRef)(null);
|
|
2785
|
+
const changeRef = (0, import_react2.useRef)(onParamsChange);
|
|
2786
|
+
changeRef.current = onParamsChange;
|
|
2787
|
+
const paramsRef = (0, import_react2.useRef)(params);
|
|
2788
|
+
paramsRef.current = params;
|
|
2789
|
+
const posted = (0, import_react2.useRef)(/* @__PURE__ */ new Map());
|
|
2790
|
+
const post = (0, import_react2.useCallback)(
|
|
2791
|
+
(values) => {
|
|
2792
|
+
if (Object.keys(values).length === 0) return;
|
|
2793
|
+
frame.current?.contentWindow?.postMessage(
|
|
2794
|
+
{ type: "host.artifactParams", params: values },
|
|
2795
|
+
origin
|
|
2796
|
+
);
|
|
2797
|
+
},
|
|
2798
|
+
[origin]
|
|
2799
|
+
);
|
|
2800
|
+
const postAll = (0, import_react2.useCallback)(() => {
|
|
2801
|
+
posted.current = snapshot2(paramsRef.current);
|
|
2802
|
+
post({ ...paramsRef.current });
|
|
2803
|
+
}, [post]);
|
|
2804
|
+
const onLoad = (0, import_react2.useCallback)(() => postAll(), [postAll]);
|
|
2805
|
+
(0, import_react2.useEffect)(() => {
|
|
2806
|
+
if (typeof window === "undefined") return;
|
|
2807
|
+
const onMessage = (event) => {
|
|
2808
|
+
if (!frame.current || event.source !== frame.current.contentWindow) return;
|
|
2809
|
+
const data = event.data;
|
|
2810
|
+
if (!data || typeof data !== "object") return;
|
|
2811
|
+
if (data.type === "widget.artifactReady") {
|
|
2812
|
+
postAll();
|
|
2813
|
+
return;
|
|
2814
|
+
}
|
|
2815
|
+
if (data.type === "widget.artifactParams" && data.params) {
|
|
2816
|
+
const source = data.source === "context" ? "context" : "user";
|
|
2817
|
+
try {
|
|
2818
|
+
changeRef.current?.(data.params, source);
|
|
2819
|
+
} catch {
|
|
2820
|
+
}
|
|
2821
|
+
}
|
|
2822
|
+
};
|
|
2823
|
+
window.addEventListener("message", onMessage);
|
|
2824
|
+
return () => window.removeEventListener("message", onMessage);
|
|
2825
|
+
}, [postAll]);
|
|
2826
|
+
const paramsKey = JSON.stringify(params ?? null);
|
|
2827
|
+
const settled = (0, import_react2.useRef)(false);
|
|
2828
|
+
(0, import_react2.useEffect)(() => {
|
|
2829
|
+
const next = snapshot2(paramsRef.current);
|
|
2830
|
+
if (!settled.current) {
|
|
2831
|
+
settled.current = true;
|
|
2832
|
+
posted.current = next;
|
|
2833
|
+
return;
|
|
2834
|
+
}
|
|
2835
|
+
const changed = {};
|
|
2836
|
+
for (const [key, json] of next) {
|
|
2837
|
+
if (posted.current.get(key) !== json) {
|
|
2838
|
+
changed[key] = paramsRef.current[key];
|
|
2839
|
+
}
|
|
2840
|
+
}
|
|
2841
|
+
posted.current = next;
|
|
2842
|
+
post(changed);
|
|
2843
|
+
}, [paramsKey, post]);
|
|
2646
2844
|
let src;
|
|
2647
|
-
if (
|
|
2648
|
-
src = `${origin}/embed/artifacts/${encodeURIComponent(artifactName)}?owner=${encodeURIComponent(owner)}&t=${encodeURIComponent(token)}&theme=${theme}`;
|
|
2649
|
-
} else if (ctx) {
|
|
2845
|
+
if (ctx) {
|
|
2650
2846
|
const hostOrigin = typeof window === "undefined" ? "" : window.location.origin;
|
|
2651
2847
|
src = `${origin}/embed/artifacts/${encodeURIComponent(artifactName)}?owner=${encodeURIComponent(owner)}&k=${encodeURIComponent(ctx.publishableKey)}&o=${encodeURIComponent(hostOrigin)}&theme=${theme}`;
|
|
2848
|
+
} else if (token) {
|
|
2849
|
+
src = `${origin}/embed/artifacts/${encodeURIComponent(artifactName)}?owner=${encodeURIComponent(owner)}&t=${encodeURIComponent(token)}&theme=${theme}`;
|
|
2652
2850
|
} else {
|
|
2653
2851
|
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
2654
2852
|
"div",
|
|
@@ -2670,7 +2868,9 @@ function MatterfactArtifact({
|
|
|
2670
2868
|
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
2671
2869
|
"iframe",
|
|
2672
2870
|
{
|
|
2871
|
+
ref: frame,
|
|
2673
2872
|
src,
|
|
2873
|
+
onLoad,
|
|
2674
2874
|
title: `matterfact artifact ${artifactName}`,
|
|
2675
2875
|
className: className2,
|
|
2676
2876
|
style: { width: "100%", height: 600, border: 0, ...style },
|
|
@@ -2683,10 +2883,10 @@ function diffDocParams(params, sent) {
|
|
|
2683
2883
|
const changed = {};
|
|
2684
2884
|
for (const [key, value] of Object.entries(params)) {
|
|
2685
2885
|
if (value === void 0) continue;
|
|
2686
|
-
const
|
|
2687
|
-
if (sent.get(key) ===
|
|
2886
|
+
const snapshot3 = JSON.stringify(value);
|
|
2887
|
+
if (sent.get(key) === snapshot3) continue;
|
|
2688
2888
|
changed[key] = value;
|
|
2689
|
-
sent.set(key,
|
|
2889
|
+
sent.set(key, snapshot3);
|
|
2690
2890
|
}
|
|
2691
2891
|
return changed;
|
|
2692
2892
|
}
|