@matterfact/embed 0.17.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/dist/react.cjs CHANGED
@@ -25,10 +25,70 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
25
25
  // src/deeplink.ts
26
26
  var deeplink_exports = {};
27
27
  __export(deeplink_exports, {
28
+ compileDeeplink: () => compileDeeplink,
28
29
  compileDeeplinkFormat: () => compileDeeplinkFormat,
29
30
  installDeeplinkWatch: () => installDeeplinkWatch
30
31
  });
31
32
  function compileDeeplinkFormat(format) {
33
+ return compileDeeplink(format)?.match ?? null;
34
+ }
35
+ function compileDeeplink(format) {
36
+ if (format.includes(PATH_TOKEN)) return compileDynamic(format);
37
+ const match = compileStatic(format);
38
+ return match ? { match, mintFormat: () => format, dynamic: false } : null;
39
+ }
40
+ function compileDynamic(format) {
41
+ const pi = format.indexOf(PATH_TOKEN);
42
+ if (format.indexOf(PATH_TOKEN, pi + 1) >= 0) return null;
43
+ let prefix = format.slice(0, pi);
44
+ if (prefix.endsWith("/")) prefix = prefix.slice(0, -1);
45
+ const suffix = format.slice(pi + PATH_TOKEN.length);
46
+ let po;
47
+ try {
48
+ po = new URL(prefix);
49
+ } catch {
50
+ return null;
51
+ }
52
+ if (po.protocol !== "https:" && po.protocol !== "http:") return null;
53
+ if (po.origin !== prefix) return null;
54
+ if (!suffix.startsWith("?")) return null;
55
+ const c1 = suffix.indexOf(PLACEHOLDER);
56
+ if (c1 < 0 || suffix.indexOf(PLACEHOLDER, c1 + 1) >= 0) return null;
57
+ let probe;
58
+ try {
59
+ probe = new URL(prefix + "/__mfp__" + suffix.replace(PLACEHOLDER, SENTINEL));
60
+ } catch {
61
+ return null;
62
+ }
63
+ const keys = [...probe.searchParams.keys()];
64
+ if (new Set(keys).size !== keys.length) return null;
65
+ let queryKey = null;
66
+ for (const [k, v] of probe.searchParams) {
67
+ if (v === SENTINEL) queryKey = k;
68
+ }
69
+ if (!queryKey) return null;
70
+ const match = (href) => {
71
+ let u;
72
+ try {
73
+ u = new URL(href);
74
+ } catch {
75
+ return null;
76
+ }
77
+ if (u.origin !== prefix) return null;
78
+ for (const [k, v] of probe.searchParams) {
79
+ if (v === SENTINEL) continue;
80
+ if (u.searchParams.get(k) !== v) return null;
81
+ }
82
+ const token = u.searchParams.get(queryKey);
83
+ return token && TOKEN_RE.test(token) ? token : null;
84
+ };
85
+ return {
86
+ match,
87
+ mintFormat: (pathname) => prefix + pathname + suffix,
88
+ dynamic: true
89
+ };
90
+ }
91
+ function compileStatic(format) {
32
92
  const first = format.indexOf(PLACEHOLDER);
33
93
  if (first < 0 || format.indexOf(PLACEHOLDER, first + 1) >= 0) return null;
34
94
  let f;
@@ -79,18 +139,33 @@ function compileDeeplinkFormat(format) {
79
139
  return token && TOKEN_RE.test(token) ? token : null;
80
140
  };
81
141
  }
82
- function installDeeplinkWatch(format, onChange2) {
83
- const match = compileDeeplinkFormat(format);
84
- if (!match) return () => {
142
+ function installDeeplinkWatch(format, onChange2, onFormat) {
143
+ const c = compileDeeplink(format);
144
+ if (!c) return () => {
85
145
  };
86
146
  let last = null;
147
+ let lastTokenPath = null;
148
+ let lastMintPath = null;
87
149
  let stopped = false;
150
+ const emitFormat = () => {
151
+ if (!onFormat) return;
152
+ const p = location.pathname;
153
+ if (lastMintPath === null || c.dynamic && p !== lastMintPath) {
154
+ lastMintPath = p;
155
+ onFormat(c.mintFormat(p));
156
+ }
157
+ };
88
158
  const fire = () => {
89
159
  if (stopped) return;
90
160
  try {
91
- const token = match(location.href);
161
+ emitFormat();
162
+ const token = c.match(location.href);
163
+ if (token === null && last !== null && trimSlash(location.pathname) === lastTokenPath) {
164
+ return;
165
+ }
92
166
  if (token !== last) {
93
167
  last = token;
168
+ if (token !== null) lastTokenPath = trimSlash(location.pathname);
94
169
  onChange2(token);
95
170
  }
96
171
  } catch (err) {
@@ -120,11 +195,12 @@ function installDeeplinkWatch(format, onChange2) {
120
195
  if (history.replaceState === ourReplace) history.replaceState = origReplace;
121
196
  };
122
197
  }
123
- var PLACEHOLDER, SENTINEL, TOKEN_RE, trimSlash;
198
+ var PLACEHOLDER, PATH_TOKEN, SENTINEL, TOKEN_RE, trimSlash;
124
199
  var init_deeplink = __esm({
125
200
  "src/deeplink.ts"() {
126
201
  "use strict";
127
202
  PLACEHOLDER = "{share_token}";
203
+ PATH_TOKEN = "{path}";
128
204
  SENTINEL = "mf-share-token-sentinel";
129
205
  TOKEN_RE = /^[A-Za-z0-9._~-]{4,256}$/;
130
206
  trimSlash = (path) => path.length > 1 && path.endsWith("/") ? path.slice(0, -1) : path;
@@ -1949,7 +2025,7 @@ function dockBox(g, vw, _vh) {
1949
2025
  }
1950
2026
 
1951
2027
  // src/loader.ts
1952
- var EMBED_VERSION = "0.17.0";
2028
+ var EMBED_VERSION = "0.18.0";
1953
2029
  function devRequested() {
1954
2030
  try {
1955
2031
  if (new URLSearchParams(location.search).get("mfdev") === "1") return true;
@@ -2097,12 +2173,13 @@ var EmbedHost = class {
2097
2173
  }
2098
2174
  const fmt = this.config.shareDeeplinkFormat;
2099
2175
  if (fmt) {
2100
- this.send({ type: "host.deeplinkFormat", format: fmt });
2101
2176
  void Promise.resolve().then(() => (init_deeplink(), deeplink_exports)).then((m) => {
2102
2177
  if (this.destroyed) return;
2103
- this.deeplinkStop = m.installDeeplinkWatch(fmt, (token) => {
2104
- this.send({ type: "host.openShare", token });
2105
- });
2178
+ this.deeplinkStop = m.installDeeplinkWatch(
2179
+ fmt,
2180
+ (token) => this.send({ type: "host.openShare", token }),
2181
+ (format) => this.send({ type: "host.deeplinkFormat", format })
2182
+ );
2106
2183
  }).catch(() => {
2107
2184
  });
2108
2185
  }
@@ -2644,6 +2721,27 @@ function toolDescriptorKey(artifacts, resolve, tools) {
2644
2721
  }))
2645
2722
  });
2646
2723
  }
2724
+ var KNOWN_AGENT_PROPS = [
2725
+ "publishableKey",
2726
+ "widgetOrigin",
2727
+ "surface",
2728
+ "shareDeeplinkFormat",
2729
+ "theme",
2730
+ "getAuthToken",
2731
+ "getPageContext",
2732
+ "inline",
2733
+ "className",
2734
+ "style",
2735
+ "pageContext",
2736
+ "dev",
2737
+ "actions",
2738
+ "sitemap",
2739
+ "artifacts",
2740
+ "resolve",
2741
+ "tools",
2742
+ "onToolEvent",
2743
+ "onEvent"
2744
+ ];
2647
2745
  function MatterfactAgent({
2648
2746
  publishableKey: publishableKeyProp,
2649
2747
  widgetOrigin: widgetOriginProp,
@@ -2663,8 +2761,20 @@ function MatterfactAgent({
2663
2761
  resolve,
2664
2762
  tools,
2665
2763
  onToolEvent,
2666
- onEvent
2764
+ onEvent,
2765
+ ...unknownProps
2667
2766
  }) {
2767
+ (0, import_react2.useEffect)(() => {
2768
+ if (process.env.NODE_ENV === "production") return;
2769
+ for (const key of Object.keys(unknownProps)) {
2770
+ const meant = KNOWN_AGENT_PROPS.find(
2771
+ (k) => k.toLowerCase() === key.toLowerCase()
2772
+ );
2773
+ console.warn(
2774
+ `[mf-embed] unknown prop "${key}" on <MatterfactAgent>` + (meant ? ` \u2014 did you mean "${meant}"?` : "")
2775
+ );
2776
+ }
2777
+ }, []);
2668
2778
  const ctx = useMatterfactConfig();
2669
2779
  const publishableKey = publishableKeyProp ?? ctx?.publishableKey;
2670
2780
  if (!publishableKey) {