@matterfact/embed 0.16.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/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";
@@ -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 = 3;
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,
@@ -2713,11 +2842,11 @@ function MatterfactArtifact({
2713
2842
  post(changed);
2714
2843
  }, [paramsKey, post]);
2715
2844
  let src;
2716
- if (token) {
2717
- src = `${origin}/embed/artifacts/${encodeURIComponent(artifactName)}?owner=${encodeURIComponent(owner)}&t=${encodeURIComponent(token)}&theme=${theme}`;
2718
- } else if (ctx) {
2845
+ if (ctx) {
2719
2846
  const hostOrigin = typeof window === "undefined" ? "" : window.location.origin;
2720
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}`;
2721
2850
  } else {
2722
2851
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2723
2852
  "div",