@matterfact/embed 0.16.0 → 0.18.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 +25 -0
- package/dist/chunk-5X2WFSIL.js +2 -0
- package/dist/chunk-5X2WFSIL.js.map +7 -0
- package/dist/deeplink-KCGMGNIR.js +180 -0
- package/dist/deeplink-KCGMGNIR.js.map +1 -0
- package/dist/deeplink-X7IQDBCR.js +176 -0
- package/dist/deeplink-X7IQDBCR.js.map +1 -0
- package/dist/embed.js +1 -1
- package/dist/embed.js.map +3 -3
- package/dist/index.cjs +208 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +38 -1
- package/dist/index.d.ts +38 -1
- package/dist/index.js +24 -3
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +246 -7
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +32 -7
- package/dist/react.d.ts +32 -7
- package/dist/react.js +61 -7
- package/dist/react.js.map +1 -1
- package/examples/embed-demo/src/App.tsx +6 -0
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -12,6 +12,190 @@ var __export = (target, all) => {
|
|
|
12
12
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
13
13
|
};
|
|
14
14
|
|
|
15
|
+
// src/deeplink.ts
|
|
16
|
+
var deeplink_exports = {};
|
|
17
|
+
__export(deeplink_exports, {
|
|
18
|
+
compileDeeplink: () => compileDeeplink,
|
|
19
|
+
compileDeeplinkFormat: () => compileDeeplinkFormat,
|
|
20
|
+
installDeeplinkWatch: () => installDeeplinkWatch
|
|
21
|
+
});
|
|
22
|
+
function compileDeeplinkFormat(format) {
|
|
23
|
+
return compileDeeplink(format)?.match ?? null;
|
|
24
|
+
}
|
|
25
|
+
function compileDeeplink(format) {
|
|
26
|
+
if (format.includes(PATH_TOKEN)) return compileDynamic(format);
|
|
27
|
+
const match = compileStatic(format);
|
|
28
|
+
return match ? { match, mintFormat: () => format, dynamic: false } : null;
|
|
29
|
+
}
|
|
30
|
+
function compileDynamic(format) {
|
|
31
|
+
const pi = format.indexOf(PATH_TOKEN);
|
|
32
|
+
if (format.indexOf(PATH_TOKEN, pi + 1) >= 0) return null;
|
|
33
|
+
let prefix = format.slice(0, pi);
|
|
34
|
+
if (prefix.endsWith("/")) prefix = prefix.slice(0, -1);
|
|
35
|
+
const suffix = format.slice(pi + PATH_TOKEN.length);
|
|
36
|
+
let po;
|
|
37
|
+
try {
|
|
38
|
+
po = new URL(prefix);
|
|
39
|
+
} catch {
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
if (po.protocol !== "https:" && po.protocol !== "http:") return null;
|
|
43
|
+
if (po.origin !== prefix) return null;
|
|
44
|
+
if (!suffix.startsWith("?")) return null;
|
|
45
|
+
const c1 = suffix.indexOf(PLACEHOLDER);
|
|
46
|
+
if (c1 < 0 || suffix.indexOf(PLACEHOLDER, c1 + 1) >= 0) return null;
|
|
47
|
+
let probe;
|
|
48
|
+
try {
|
|
49
|
+
probe = new URL(prefix + "/__mfp__" + suffix.replace(PLACEHOLDER, SENTINEL));
|
|
50
|
+
} catch {
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
const keys = [...probe.searchParams.keys()];
|
|
54
|
+
if (new Set(keys).size !== keys.length) return null;
|
|
55
|
+
let queryKey = null;
|
|
56
|
+
for (const [k, v] of probe.searchParams) {
|
|
57
|
+
if (v === SENTINEL) queryKey = k;
|
|
58
|
+
}
|
|
59
|
+
if (!queryKey) return null;
|
|
60
|
+
const match = (href) => {
|
|
61
|
+
let u;
|
|
62
|
+
try {
|
|
63
|
+
u = new URL(href);
|
|
64
|
+
} catch {
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
if (u.origin !== prefix) return null;
|
|
68
|
+
for (const [k, v] of probe.searchParams) {
|
|
69
|
+
if (v === SENTINEL) continue;
|
|
70
|
+
if (u.searchParams.get(k) !== v) return null;
|
|
71
|
+
}
|
|
72
|
+
const token = u.searchParams.get(queryKey);
|
|
73
|
+
return token && TOKEN_RE.test(token) ? token : null;
|
|
74
|
+
};
|
|
75
|
+
return {
|
|
76
|
+
match,
|
|
77
|
+
mintFormat: (pathname) => prefix + pathname + suffix,
|
|
78
|
+
dynamic: true
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
function compileStatic(format) {
|
|
82
|
+
const first = format.indexOf(PLACEHOLDER);
|
|
83
|
+
if (first < 0 || format.indexOf(PLACEHOLDER, first + 1) >= 0) return null;
|
|
84
|
+
let f;
|
|
85
|
+
try {
|
|
86
|
+
f = new URL(format.replace(PLACEHOLDER, SENTINEL));
|
|
87
|
+
} catch {
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
if (f.protocol !== "https:" && f.protocol !== "http:") return null;
|
|
91
|
+
const keys = [...f.searchParams.keys()];
|
|
92
|
+
if (new Set(keys).size !== keys.length) return null;
|
|
93
|
+
const fPath = trimSlash(f.pathname);
|
|
94
|
+
const segs = fPath.split("/");
|
|
95
|
+
const segIdx = segs.indexOf(SENTINEL);
|
|
96
|
+
let queryKey = null;
|
|
97
|
+
for (const [k, v] of f.searchParams) {
|
|
98
|
+
if (v === SENTINEL) queryKey = k;
|
|
99
|
+
}
|
|
100
|
+
if (segIdx >= 0 === (queryKey !== null)) return null;
|
|
101
|
+
return (href) => {
|
|
102
|
+
let u;
|
|
103
|
+
try {
|
|
104
|
+
u = new URL(href);
|
|
105
|
+
} catch {
|
|
106
|
+
return null;
|
|
107
|
+
}
|
|
108
|
+
if (u.origin !== f.origin) return null;
|
|
109
|
+
const uPath = trimSlash(u.pathname);
|
|
110
|
+
let token;
|
|
111
|
+
if (segIdx >= 0) {
|
|
112
|
+
const us = uPath.split("/");
|
|
113
|
+
if (us.length !== segs.length) return null;
|
|
114
|
+
for (let i = 0; i < segs.length; i++) {
|
|
115
|
+
if (i !== segIdx && us[i] !== segs[i]) return null;
|
|
116
|
+
}
|
|
117
|
+
token = us[segIdx];
|
|
118
|
+
for (const [k, v] of f.searchParams) {
|
|
119
|
+
if (u.searchParams.get(k) !== v) return null;
|
|
120
|
+
}
|
|
121
|
+
} else {
|
|
122
|
+
if (uPath !== fPath) return null;
|
|
123
|
+
for (const [k, v] of f.searchParams) {
|
|
124
|
+
if (v === SENTINEL) continue;
|
|
125
|
+
if (u.searchParams.get(k) !== v) return null;
|
|
126
|
+
}
|
|
127
|
+
token = u.searchParams.get(queryKey);
|
|
128
|
+
}
|
|
129
|
+
return token && TOKEN_RE.test(token) ? token : null;
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
function installDeeplinkWatch(format, onChange2, onFormat) {
|
|
133
|
+
const c = compileDeeplink(format);
|
|
134
|
+
if (!c) return () => {
|
|
135
|
+
};
|
|
136
|
+
let last = null;
|
|
137
|
+
let lastTokenPath = null;
|
|
138
|
+
let lastMintPath = null;
|
|
139
|
+
let stopped = false;
|
|
140
|
+
const emitFormat = () => {
|
|
141
|
+
if (!onFormat) return;
|
|
142
|
+
const p = location.pathname;
|
|
143
|
+
if (lastMintPath === null || c.dynamic && p !== lastMintPath) {
|
|
144
|
+
lastMintPath = p;
|
|
145
|
+
onFormat(c.mintFormat(p));
|
|
146
|
+
}
|
|
147
|
+
};
|
|
148
|
+
const fire = () => {
|
|
149
|
+
if (stopped) return;
|
|
150
|
+
try {
|
|
151
|
+
emitFormat();
|
|
152
|
+
const token = c.match(location.href);
|
|
153
|
+
if (token === null && last !== null && trimSlash(location.pathname) === lastTokenPath) {
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
if (token !== last) {
|
|
157
|
+
last = token;
|
|
158
|
+
if (token !== null) lastTokenPath = trimSlash(location.pathname);
|
|
159
|
+
onChange2(token);
|
|
160
|
+
}
|
|
161
|
+
} catch (err) {
|
|
162
|
+
console.warn("[mf-embed] deeplink match failed", err);
|
|
163
|
+
}
|
|
164
|
+
};
|
|
165
|
+
const origPush = history.pushState;
|
|
166
|
+
const origReplace = history.replaceState;
|
|
167
|
+
const ourPush = function(...args) {
|
|
168
|
+
const r = origPush.apply(this, args);
|
|
169
|
+
fire();
|
|
170
|
+
return r;
|
|
171
|
+
};
|
|
172
|
+
const ourReplace = function(...args) {
|
|
173
|
+
const r = origReplace.apply(this, args);
|
|
174
|
+
fire();
|
|
175
|
+
return r;
|
|
176
|
+
};
|
|
177
|
+
history.pushState = ourPush;
|
|
178
|
+
history.replaceState = ourReplace;
|
|
179
|
+
window.addEventListener("popstate", fire);
|
|
180
|
+
fire();
|
|
181
|
+
return () => {
|
|
182
|
+
stopped = true;
|
|
183
|
+
window.removeEventListener("popstate", fire);
|
|
184
|
+
if (history.pushState === ourPush) history.pushState = origPush;
|
|
185
|
+
if (history.replaceState === ourReplace) history.replaceState = origReplace;
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
var PLACEHOLDER, PATH_TOKEN, SENTINEL, TOKEN_RE, trimSlash;
|
|
189
|
+
var init_deeplink = __esm({
|
|
190
|
+
"src/deeplink.ts"() {
|
|
191
|
+
PLACEHOLDER = "{share_token}";
|
|
192
|
+
PATH_TOKEN = "{path}";
|
|
193
|
+
SENTINEL = "mf-share-token-sentinel";
|
|
194
|
+
TOKEN_RE = /^[A-Za-z0-9._~-]{4,256}$/;
|
|
195
|
+
trimSlash = (path) => path.length > 1 && path.endsWith("/") ? path.slice(0, -1) : path;
|
|
196
|
+
}
|
|
197
|
+
});
|
|
198
|
+
|
|
15
199
|
// src/pageContextMode.ts
|
|
16
200
|
function parsePageContextMode(value) {
|
|
17
201
|
if (typeof value === "boolean") return value ? "full" : "off";
|
|
@@ -1583,7 +1767,7 @@ var init_context = __esm({
|
|
|
1583
1767
|
});
|
|
1584
1768
|
|
|
1585
1769
|
// src/protocol.ts
|
|
1586
|
-
var PROTOCOL_VERSION =
|
|
1770
|
+
var PROTOCOL_VERSION = 4;
|
|
1587
1771
|
var CHANNEL = "mf-embed";
|
|
1588
1772
|
function envelope(payload, id) {
|
|
1589
1773
|
return {
|
|
@@ -1806,6 +1990,7 @@ function dockBox(g, vw, _vh) {
|
|
|
1806
1990
|
|
|
1807
1991
|
// src/loader.ts
|
|
1808
1992
|
var DEFAULT_ORIGIN = "https://app.matterfact.com";
|
|
1993
|
+
var EMBED_VERSION = "0.18.0";
|
|
1809
1994
|
function devRequested() {
|
|
1810
1995
|
try {
|
|
1811
1996
|
if (new URLSearchParams(location.search).get("mfdev") === "1") return true;
|
|
@@ -1850,7 +2035,10 @@ function readConfig() {
|
|
|
1850
2035
|
theme: el?.dataset.theme || "auto",
|
|
1851
2036
|
surface: el?.dataset.surface || "",
|
|
1852
2037
|
container,
|
|
1853
|
-
pageContext
|
|
2038
|
+
pageContext,
|
|
2039
|
+
// `data-share-deeplink-format="https://…/{share_token}"` — the script-tag twin of
|
|
2040
|
+
// the React `shareDeeplinkFormat` prop.
|
|
2041
|
+
shareDeeplinkFormat: el?.dataset.shareDeeplinkFormat
|
|
1854
2042
|
// No `data-dev` — see the `dev` field's doc comment: the URL trigger is the
|
|
1855
2043
|
// point for the script-tag path, so there is deliberately no script-tag knob here.
|
|
1856
2044
|
// No `data-actions` either: the action policy lives entirely in the lazy chunk,
|
|
@@ -1931,6 +2119,8 @@ var EmbedHost = class {
|
|
|
1931
2119
|
this.inline = !!config.container;
|
|
1932
2120
|
}
|
|
1933
2121
|
mount() {
|
|
2122
|
+
const w = window;
|
|
2123
|
+
(w.matterfact ?? (w.matterfact = {})).embedVersion = EMBED_VERSION;
|
|
1934
2124
|
const host = document.createElement("div");
|
|
1935
2125
|
this.hostEl = host;
|
|
1936
2126
|
host.id = "matterfact-embed";
|
|
@@ -1974,7 +2164,7 @@ var EmbedHost = class {
|
|
|
1974
2164
|
"sandbox",
|
|
1975
2165
|
"allow-scripts allow-same-origin allow-forms allow-popups allow-popups-to-escape-sandbox allow-downloads"
|
|
1976
2166
|
);
|
|
1977
|
-
iframe.setAttribute("allow", "microphone; clipboard-write");
|
|
2167
|
+
iframe.setAttribute("allow", "microphone; clipboard-write; web-share");
|
|
1978
2168
|
iframe.src = `${this.config.origin}/embed/chat?k=${encodeURIComponent(
|
|
1979
2169
|
this.config.publishableKey
|
|
1980
2170
|
)}&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
|
|
@@ -1987,6 +2177,18 @@ var EmbedHost = class {
|
|
|
1987
2177
|
window.addEventListener("resize", this.onViewportResize);
|
|
1988
2178
|
this.place();
|
|
1989
2179
|
}
|
|
2180
|
+
const fmt = this.config.shareDeeplinkFormat;
|
|
2181
|
+
if (fmt) {
|
|
2182
|
+
void Promise.resolve().then(() => (init_deeplink(), deeplink_exports)).then((m) => {
|
|
2183
|
+
if (this.destroyed) return;
|
|
2184
|
+
this.deeplinkStop = m.installDeeplinkWatch(
|
|
2185
|
+
fmt,
|
|
2186
|
+
(token) => this.send({ type: "host.openShare", token }),
|
|
2187
|
+
(format) => this.send({ type: "host.deeplinkFormat", format })
|
|
2188
|
+
);
|
|
2189
|
+
}).catch(() => {
|
|
2190
|
+
});
|
|
2191
|
+
}
|
|
1990
2192
|
}
|
|
1991
2193
|
/**
|
|
1992
2194
|
* Test seam. The shadow root is CLOSED, so a test cannot reach the iframe to forge a
|
|
@@ -2409,6 +2611,9 @@ var EmbedHost = class {
|
|
|
2409
2611
|
this.iframe = null;
|
|
2410
2612
|
this.shadow = null;
|
|
2411
2613
|
this.ready = false;
|
|
2614
|
+
this.destroyed = true;
|
|
2615
|
+
this.deeplinkStop?.();
|
|
2616
|
+
this.deeplinkStop = null;
|
|
2412
2617
|
void this.context?.then((m) => m.stop());
|
|
2413
2618
|
}
|
|
2414
2619
|
};
|