@meetreeve/capacitor-bridge 0.1.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 +134 -0
- package/compliance/PrivacyInfo.xcprivacy.template +155 -0
- package/compliance/README.md +42 -0
- package/compliance/index.cjs +60 -0
- package/compliance/permission-strings.json +14 -0
- package/dist/bugreport/index.cjs +143 -0
- package/dist/bugreport/index.d.cts +76 -0
- package/dist/bugreport/index.d.ts +76 -0
- package/dist/bugreport/index.js +111 -0
- package/dist/core/index.cjs +160 -0
- package/dist/core/index.d.cts +29 -0
- package/dist/core/index.d.ts +29 -0
- package/dist/core/index.js +124 -0
- package/dist/deeplink/index.cjs +166 -0
- package/dist/deeplink/index.d.cts +81 -0
- package/dist/deeplink/index.d.ts +81 -0
- package/dist/deeplink/index.js +133 -0
- package/dist/paywall/index.cjs +103 -0
- package/dist/paywall/index.d.cts +75 -0
- package/dist/paywall/index.d.ts +75 -0
- package/dist/paywall/index.js +71 -0
- package/dist/react/index.cjs +523 -0
- package/dist/react/index.d.cts +68 -0
- package/dist/react/index.d.ts +68 -0
- package/dist/react/index.js +483 -0
- package/dist/safe-area-B67yGQOn.d.cts +51 -0
- package/dist/safe-area-B67yGQOn.d.ts +51 -0
- package/package.json +78 -0
|
@@ -0,0 +1,523 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// src/react/index.ts
|
|
31
|
+
var react_exports = {};
|
|
32
|
+
__export(react_exports, {
|
|
33
|
+
BugReportButton: () => BugReportButton,
|
|
34
|
+
CapacitorProvider: () => CapacitorProvider,
|
|
35
|
+
useCapacitor: () => useCapacitor,
|
|
36
|
+
useSafeArea: () => useSafeArea
|
|
37
|
+
});
|
|
38
|
+
module.exports = __toCommonJS(react_exports);
|
|
39
|
+
|
|
40
|
+
// src/react/CapacitorProvider.tsx
|
|
41
|
+
var React = __toESM(require("react"), 1);
|
|
42
|
+
|
|
43
|
+
// src/core/platform.ts
|
|
44
|
+
function getCapacitor() {
|
|
45
|
+
if (typeof window === "undefined") return null;
|
|
46
|
+
const cap = window.Capacitor;
|
|
47
|
+
if (!cap || typeof cap.isNativePlatform !== "function") return null;
|
|
48
|
+
return cap;
|
|
49
|
+
}
|
|
50
|
+
function getPlatform() {
|
|
51
|
+
const cap = getCapacitor();
|
|
52
|
+
if (!cap) return "web";
|
|
53
|
+
const p = cap.getPlatform();
|
|
54
|
+
return p === "ios" ? "ios" : p === "android" ? "android" : "web";
|
|
55
|
+
}
|
|
56
|
+
function isNativePlatform() {
|
|
57
|
+
return getPlatform() !== "web";
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// src/core/safe-area.ts
|
|
61
|
+
var ZERO = { top: 0, right: 0, bottom: 0, left: 0 };
|
|
62
|
+
function getSafeAreaInsets() {
|
|
63
|
+
if (typeof window === "undefined" || typeof document === "undefined") {
|
|
64
|
+
return ZERO;
|
|
65
|
+
}
|
|
66
|
+
const root = document.documentElement;
|
|
67
|
+
const styles = window.getComputedStyle(root);
|
|
68
|
+
const read = (side) => {
|
|
69
|
+
const v = styles.getPropertyValue(`--safe-area-inset-${side}`).trim();
|
|
70
|
+
const n = parseFloat(v);
|
|
71
|
+
return Number.isFinite(n) ? n : 0;
|
|
72
|
+
};
|
|
73
|
+
return {
|
|
74
|
+
top: read("top"),
|
|
75
|
+
right: read("right"),
|
|
76
|
+
bottom: read("bottom"),
|
|
77
|
+
left: read("left")
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
function installSafeAreaVars() {
|
|
81
|
+
if (typeof document === "undefined") return;
|
|
82
|
+
const TAG = "reeve-capacitor-bridge-safe-area";
|
|
83
|
+
if (document.querySelector(`style[data-${TAG}]`)) return;
|
|
84
|
+
const style = document.createElement("style");
|
|
85
|
+
style.setAttribute(`data-${TAG}`, "1");
|
|
86
|
+
style.textContent = `
|
|
87
|
+
:root {
|
|
88
|
+
--safe-area-inset-top: env(safe-area-inset-top, 0px);
|
|
89
|
+
--safe-area-inset-right: env(safe-area-inset-right, 0px);
|
|
90
|
+
--safe-area-inset-bottom: env(safe-area-inset-bottom, 0px);
|
|
91
|
+
--safe-area-inset-left: env(safe-area-inset-left, 0px);
|
|
92
|
+
}
|
|
93
|
+
`;
|
|
94
|
+
document.head.appendChild(style);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// src/core/splash.ts
|
|
98
|
+
function getSplashPlugin() {
|
|
99
|
+
if (typeof window === "undefined") return null;
|
|
100
|
+
const cap = window.Capacitor;
|
|
101
|
+
return cap?.Plugins?.SplashScreen ?? null;
|
|
102
|
+
}
|
|
103
|
+
var GLOBAL_KEY = /* @__PURE__ */ Symbol.for("@meetreeve/capacitor-bridge/splash@1");
|
|
104
|
+
function getGlobalState() {
|
|
105
|
+
const g = globalThis;
|
|
106
|
+
if (!g[GLOBAL_KEY]) g[GLOBAL_KEY] = { done: null, pending: null };
|
|
107
|
+
return g[GLOBAL_KEY];
|
|
108
|
+
}
|
|
109
|
+
async function dismissSplash(fadeOutDuration = 250) {
|
|
110
|
+
if (!isNativePlatform()) return;
|
|
111
|
+
const state = getGlobalState();
|
|
112
|
+
if (state.done) return state.done;
|
|
113
|
+
if (state.pending) return state.pending;
|
|
114
|
+
const plugin = getSplashPlugin();
|
|
115
|
+
if (!plugin) return;
|
|
116
|
+
const attempt = (async () => {
|
|
117
|
+
try {
|
|
118
|
+
await plugin.hide({ fadeOutDuration });
|
|
119
|
+
state.done = Promise.resolve();
|
|
120
|
+
} catch (err) {
|
|
121
|
+
state.pending = null;
|
|
122
|
+
throw err;
|
|
123
|
+
} finally {
|
|
124
|
+
if (state.done) state.pending = null;
|
|
125
|
+
}
|
|
126
|
+
})();
|
|
127
|
+
state.pending = attempt;
|
|
128
|
+
return attempt.catch(() => {
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// src/react/CapacitorProvider.tsx
|
|
133
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
134
|
+
var FALLBACK_VALUE = {
|
|
135
|
+
platform: "web",
|
|
136
|
+
isNative: false,
|
|
137
|
+
isIOS: false,
|
|
138
|
+
isAndroid: false,
|
|
139
|
+
dismissSplash: async () => {
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
var CapacitorContext = React.createContext(FALLBACK_VALUE);
|
|
143
|
+
function CapacitorProvider({
|
|
144
|
+
children,
|
|
145
|
+
autoDismissSplash = true
|
|
146
|
+
}) {
|
|
147
|
+
const value = React.useMemo(() => {
|
|
148
|
+
const platform = getPlatform();
|
|
149
|
+
return {
|
|
150
|
+
platform,
|
|
151
|
+
isNative: platform !== "web",
|
|
152
|
+
isIOS: platform === "ios",
|
|
153
|
+
isAndroid: platform === "android",
|
|
154
|
+
dismissSplash
|
|
155
|
+
};
|
|
156
|
+
}, []);
|
|
157
|
+
React.useEffect(() => {
|
|
158
|
+
installSafeAreaVars();
|
|
159
|
+
if (typeof document !== "undefined") {
|
|
160
|
+
document.documentElement.setAttribute("data-platform", value.platform);
|
|
161
|
+
}
|
|
162
|
+
if (autoDismissSplash) {
|
|
163
|
+
void dismissSplash();
|
|
164
|
+
}
|
|
165
|
+
}, [autoDismissSplash, value.platform]);
|
|
166
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CapacitorContext.Provider, { value, children });
|
|
167
|
+
}
|
|
168
|
+
function useCapacitor() {
|
|
169
|
+
return React.useContext(CapacitorContext);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// src/react/useSafeArea.ts
|
|
173
|
+
var React2 = __toESM(require("react"), 1);
|
|
174
|
+
function useSafeArea() {
|
|
175
|
+
const [insets, setInsets] = React2.useState(() => getSafeAreaInsets());
|
|
176
|
+
React2.useEffect(() => {
|
|
177
|
+
if (typeof window === "undefined") return;
|
|
178
|
+
const update = () => setInsets(getSafeAreaInsets());
|
|
179
|
+
window.addEventListener("orientationchange", update);
|
|
180
|
+
window.addEventListener("resize", update);
|
|
181
|
+
return () => {
|
|
182
|
+
window.removeEventListener("orientationchange", update);
|
|
183
|
+
window.removeEventListener("resize", update);
|
|
184
|
+
};
|
|
185
|
+
}, []);
|
|
186
|
+
return insets;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// src/react/BugReportButton.tsx
|
|
190
|
+
var React3 = __toESM(require("react"), 1);
|
|
191
|
+
|
|
192
|
+
// src/bugreport/index.ts
|
|
193
|
+
var GLOBAL_KEY2 = /* @__PURE__ */ Symbol.for("@meetreeve/capacitor-bridge/bugreport@1");
|
|
194
|
+
function getGlobalState2() {
|
|
195
|
+
const g = globalThis;
|
|
196
|
+
if (!g[GLOBAL_KEY2]) g[GLOBAL_KEY2] = { config: null };
|
|
197
|
+
return g[GLOBAL_KEY2];
|
|
198
|
+
}
|
|
199
|
+
function getBugReportEnvironment() {
|
|
200
|
+
const config = getGlobalState2().config;
|
|
201
|
+
if (typeof window === "undefined") {
|
|
202
|
+
return {
|
|
203
|
+
platform: getPlatform(),
|
|
204
|
+
userAgent: "",
|
|
205
|
+
currentUrl: "",
|
|
206
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
return {
|
|
210
|
+
platform: getPlatform(),
|
|
211
|
+
userAgent: window.navigator?.userAgent ?? "",
|
|
212
|
+
appVersion: config?.appVersion,
|
|
213
|
+
buildNumber: config?.buildNumber,
|
|
214
|
+
currentUrl: window.location?.href ?? "",
|
|
215
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
async function submitBugReport(payload) {
|
|
219
|
+
const config = getGlobalState2().config;
|
|
220
|
+
if (!config) {
|
|
221
|
+
throw new Error(
|
|
222
|
+
"[@meetreeve/capacitor-bridge/bugreport] submitBugReport called without configureBugReport({endpoint})."
|
|
223
|
+
);
|
|
224
|
+
}
|
|
225
|
+
const submission = {
|
|
226
|
+
...payload,
|
|
227
|
+
environment: getBugReportEnvironment()
|
|
228
|
+
};
|
|
229
|
+
const headers = {
|
|
230
|
+
"Content-Type": "application/json"
|
|
231
|
+
};
|
|
232
|
+
if (config.headers) {
|
|
233
|
+
const extraHeaders = await config.headers();
|
|
234
|
+
Object.assign(headers, extraHeaders);
|
|
235
|
+
}
|
|
236
|
+
const response = await fetch(config.endpoint, {
|
|
237
|
+
method: "POST",
|
|
238
|
+
headers,
|
|
239
|
+
body: JSON.stringify(submission),
|
|
240
|
+
credentials: config.credentials ?? "omit"
|
|
241
|
+
});
|
|
242
|
+
if (!response.ok) {
|
|
243
|
+
throw new Error(
|
|
244
|
+
`[@meetreeve/capacitor-bridge/bugreport] bug-report submission failed: ${response.status} ${response.statusText}`
|
|
245
|
+
);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
async function captureScreenshot() {
|
|
249
|
+
if (typeof window === "undefined") return null;
|
|
250
|
+
const cap = window.Capacitor;
|
|
251
|
+
const plugin = cap?.Plugins?.Screenshot;
|
|
252
|
+
if (plugin) {
|
|
253
|
+
try {
|
|
254
|
+
const { base64 } = await plugin.take();
|
|
255
|
+
return `data:image/png;base64,${base64}`;
|
|
256
|
+
} catch {
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
return null;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
// src/react/BugReportButton.tsx
|
|
263
|
+
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
264
|
+
var initialState = {
|
|
265
|
+
open: false,
|
|
266
|
+
message: "",
|
|
267
|
+
screenshot: null,
|
|
268
|
+
capturing: false,
|
|
269
|
+
submitting: false,
|
|
270
|
+
error: null
|
|
271
|
+
};
|
|
272
|
+
function BugReportButton({
|
|
273
|
+
userIdentifier,
|
|
274
|
+
renderTrigger,
|
|
275
|
+
extra,
|
|
276
|
+
onSubmitted
|
|
277
|
+
}) {
|
|
278
|
+
const [state, setState] = React3.useState(initialState);
|
|
279
|
+
const triggerRef = React3.useRef(null);
|
|
280
|
+
const textareaRef = React3.useRef(null);
|
|
281
|
+
const previouslyFocusedRef = React3.useRef(null);
|
|
282
|
+
const open = React3.useCallback(() => {
|
|
283
|
+
previouslyFocusedRef.current = document.activeElement;
|
|
284
|
+
setState({ ...initialState, open: true });
|
|
285
|
+
}, []);
|
|
286
|
+
const close = React3.useCallback(() => {
|
|
287
|
+
setState(initialState);
|
|
288
|
+
const prev = previouslyFocusedRef.current;
|
|
289
|
+
if (prev && typeof prev.focus === "function") {
|
|
290
|
+
prev.focus();
|
|
291
|
+
}
|
|
292
|
+
}, []);
|
|
293
|
+
const captureScreen = React3.useCallback(async () => {
|
|
294
|
+
setState((s) => ({ ...s, capturing: true, error: null }));
|
|
295
|
+
try {
|
|
296
|
+
const img = await captureScreenshot();
|
|
297
|
+
setState((s) => ({ ...s, screenshot: img, capturing: false }));
|
|
298
|
+
} catch (err) {
|
|
299
|
+
setState((s) => ({
|
|
300
|
+
...s,
|
|
301
|
+
capturing: false,
|
|
302
|
+
error: err instanceof Error ? err.message : String(err)
|
|
303
|
+
}));
|
|
304
|
+
}
|
|
305
|
+
}, []);
|
|
306
|
+
React3.useEffect(() => {
|
|
307
|
+
if (!state.open) return;
|
|
308
|
+
textareaRef.current?.focus();
|
|
309
|
+
const onKey = (e) => {
|
|
310
|
+
if (e.key === "Escape" && !state.submitting) {
|
|
311
|
+
e.stopPropagation();
|
|
312
|
+
close();
|
|
313
|
+
}
|
|
314
|
+
};
|
|
315
|
+
document.addEventListener("keydown", onKey);
|
|
316
|
+
return () => document.removeEventListener("keydown", onKey);
|
|
317
|
+
}, [state.open, state.submitting, close]);
|
|
318
|
+
const submit = React3.useCallback(async () => {
|
|
319
|
+
if (!state.message.trim()) return;
|
|
320
|
+
setState((s) => ({ ...s, submitting: true, error: null }));
|
|
321
|
+
const payload = {
|
|
322
|
+
message: state.message,
|
|
323
|
+
userIdentifier,
|
|
324
|
+
extra
|
|
325
|
+
};
|
|
326
|
+
if (state.screenshot) payload.screenshot = state.screenshot;
|
|
327
|
+
try {
|
|
328
|
+
await submitBugReport(payload);
|
|
329
|
+
setState(initialState);
|
|
330
|
+
onSubmitted?.();
|
|
331
|
+
} catch (err) {
|
|
332
|
+
setState((s) => ({
|
|
333
|
+
...s,
|
|
334
|
+
submitting: false,
|
|
335
|
+
error: err instanceof Error ? err.message : String(err)
|
|
336
|
+
}));
|
|
337
|
+
}
|
|
338
|
+
}, [state.message, state.screenshot, userIdentifier, extra, onSubmitted]);
|
|
339
|
+
const trigger = renderTrigger ? renderTrigger(open) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
340
|
+
"button",
|
|
341
|
+
{
|
|
342
|
+
ref: triggerRef,
|
|
343
|
+
type: "button",
|
|
344
|
+
onClick: open,
|
|
345
|
+
style: {
|
|
346
|
+
position: "fixed",
|
|
347
|
+
bottom: "calc(env(safe-area-inset-bottom, 0px) + 16px)",
|
|
348
|
+
right: "calc(env(safe-area-inset-right, 0px) + 16px)",
|
|
349
|
+
zIndex: 9999,
|
|
350
|
+
padding: "10px 14px",
|
|
351
|
+
background: "rgba(0,0,0,0.78)",
|
|
352
|
+
color: "white",
|
|
353
|
+
border: "none",
|
|
354
|
+
borderRadius: "999px",
|
|
355
|
+
fontSize: 14,
|
|
356
|
+
fontWeight: 500,
|
|
357
|
+
boxShadow: "0 4px 12px rgba(0,0,0,0.25)",
|
|
358
|
+
cursor: "pointer"
|
|
359
|
+
},
|
|
360
|
+
"aria-label": "Report a bug",
|
|
361
|
+
children: "Report bug"
|
|
362
|
+
}
|
|
363
|
+
);
|
|
364
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
|
|
365
|
+
trigger,
|
|
366
|
+
state.open && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
367
|
+
"div",
|
|
368
|
+
{
|
|
369
|
+
role: "dialog",
|
|
370
|
+
"aria-modal": "true",
|
|
371
|
+
"aria-label": "Report a bug",
|
|
372
|
+
style: {
|
|
373
|
+
position: "fixed",
|
|
374
|
+
inset: 0,
|
|
375
|
+
zIndex: 1e4,
|
|
376
|
+
background: "rgba(0,0,0,0.55)",
|
|
377
|
+
display: "flex",
|
|
378
|
+
alignItems: "flex-end",
|
|
379
|
+
justifyContent: "center"
|
|
380
|
+
},
|
|
381
|
+
onClick: (e) => {
|
|
382
|
+
if (e.target === e.currentTarget && !state.submitting) close();
|
|
383
|
+
},
|
|
384
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
385
|
+
"div",
|
|
386
|
+
{
|
|
387
|
+
style: {
|
|
388
|
+
width: "100%",
|
|
389
|
+
maxWidth: 460,
|
|
390
|
+
background: "white",
|
|
391
|
+
color: "#111",
|
|
392
|
+
borderTopLeftRadius: 16,
|
|
393
|
+
borderTopRightRadius: 16,
|
|
394
|
+
padding: "20px 20px calc(env(safe-area-inset-bottom, 0px) + 20px)",
|
|
395
|
+
boxSizing: "border-box"
|
|
396
|
+
},
|
|
397
|
+
children: [
|
|
398
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h2", { style: { margin: "0 0 12px", fontSize: 18 }, children: "Report a bug" }),
|
|
399
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
400
|
+
"textarea",
|
|
401
|
+
{
|
|
402
|
+
ref: textareaRef,
|
|
403
|
+
value: state.message,
|
|
404
|
+
onChange: (e) => setState((s) => ({ ...s, message: e.target.value })),
|
|
405
|
+
placeholder: "What broke? What were you doing when it broke?",
|
|
406
|
+
rows: 4,
|
|
407
|
+
style: {
|
|
408
|
+
width: "100%",
|
|
409
|
+
boxSizing: "border-box",
|
|
410
|
+
padding: 10,
|
|
411
|
+
fontSize: 15,
|
|
412
|
+
border: "1px solid #ddd",
|
|
413
|
+
borderRadius: 8,
|
|
414
|
+
resize: "vertical"
|
|
415
|
+
},
|
|
416
|
+
disabled: state.submitting
|
|
417
|
+
}
|
|
418
|
+
),
|
|
419
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
420
|
+
"div",
|
|
421
|
+
{
|
|
422
|
+
style: {
|
|
423
|
+
marginTop: 10,
|
|
424
|
+
display: "flex",
|
|
425
|
+
gap: 8,
|
|
426
|
+
alignItems: "center"
|
|
427
|
+
},
|
|
428
|
+
children: [
|
|
429
|
+
state.screenshot ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
430
|
+
"img",
|
|
431
|
+
{
|
|
432
|
+
src: state.screenshot,
|
|
433
|
+
alt: "screenshot",
|
|
434
|
+
style: {
|
|
435
|
+
width: 56,
|
|
436
|
+
height: 56,
|
|
437
|
+
borderRadius: 6,
|
|
438
|
+
objectFit: "cover",
|
|
439
|
+
border: "1px solid #eee"
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
443
|
+
"button",
|
|
444
|
+
{
|
|
445
|
+
type: "button",
|
|
446
|
+
onClick: captureScreen,
|
|
447
|
+
disabled: state.capturing || state.submitting,
|
|
448
|
+
style: {
|
|
449
|
+
padding: "6px 10px",
|
|
450
|
+
fontSize: 13,
|
|
451
|
+
border: "1px solid #ccc",
|
|
452
|
+
borderRadius: 6,
|
|
453
|
+
background: "white",
|
|
454
|
+
cursor: "pointer"
|
|
455
|
+
},
|
|
456
|
+
children: state.capturing ? "Capturing\u2026" : "Attach screenshot"
|
|
457
|
+
}
|
|
458
|
+
),
|
|
459
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { flex: 1 } }),
|
|
460
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
461
|
+
"button",
|
|
462
|
+
{
|
|
463
|
+
type: "button",
|
|
464
|
+
onClick: close,
|
|
465
|
+
disabled: state.submitting,
|
|
466
|
+
style: {
|
|
467
|
+
padding: "8px 14px",
|
|
468
|
+
fontSize: 14,
|
|
469
|
+
border: "1px solid #ccc",
|
|
470
|
+
borderRadius: 6,
|
|
471
|
+
background: "white",
|
|
472
|
+
cursor: "pointer"
|
|
473
|
+
},
|
|
474
|
+
children: "Cancel"
|
|
475
|
+
}
|
|
476
|
+
),
|
|
477
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
478
|
+
"button",
|
|
479
|
+
{
|
|
480
|
+
type: "button",
|
|
481
|
+
onClick: submit,
|
|
482
|
+
disabled: !state.message.trim() || state.submitting,
|
|
483
|
+
style: {
|
|
484
|
+
padding: "8px 14px",
|
|
485
|
+
fontSize: 14,
|
|
486
|
+
border: "none",
|
|
487
|
+
borderRadius: 6,
|
|
488
|
+
background: state.message.trim() ? "#111" : "#bbb",
|
|
489
|
+
color: "white",
|
|
490
|
+
cursor: state.message.trim() ? "pointer" : "default"
|
|
491
|
+
},
|
|
492
|
+
children: state.submitting ? "Sending\u2026" : "Send"
|
|
493
|
+
}
|
|
494
|
+
)
|
|
495
|
+
]
|
|
496
|
+
}
|
|
497
|
+
),
|
|
498
|
+
state.error && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
499
|
+
"div",
|
|
500
|
+
{
|
|
501
|
+
role: "alert",
|
|
502
|
+
style: {
|
|
503
|
+
marginTop: 12,
|
|
504
|
+
color: "#b00020",
|
|
505
|
+
fontSize: 13
|
|
506
|
+
},
|
|
507
|
+
children: state.error
|
|
508
|
+
}
|
|
509
|
+
)
|
|
510
|
+
]
|
|
511
|
+
}
|
|
512
|
+
)
|
|
513
|
+
}
|
|
514
|
+
)
|
|
515
|
+
] });
|
|
516
|
+
}
|
|
517
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
518
|
+
0 && (module.exports = {
|
|
519
|
+
BugReportButton,
|
|
520
|
+
CapacitorProvider,
|
|
521
|
+
useCapacitor,
|
|
522
|
+
useSafeArea
|
|
523
|
+
});
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { P as Platform, S as SafeAreaInsets } from '../safe-area-B67yGQOn.cjs';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* <CapacitorProvider> is the one-line install for consumer apps. Mount it at
|
|
6
|
+
* the top of the tree and every child gets useCapacitor() with platform info,
|
|
7
|
+
* safe-area insets, and a stable dismissSplash() callback.
|
|
8
|
+
*
|
|
9
|
+
* On mount the provider also installs the --safe-area-inset-* CSS vars and
|
|
10
|
+
* marks the document body with a data-platform="ios|android|web" attribute
|
|
11
|
+
* so CSS can target native chrome without JS.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
interface CapacitorContextValue {
|
|
15
|
+
platform: Platform;
|
|
16
|
+
isNative: boolean;
|
|
17
|
+
isIOS: boolean;
|
|
18
|
+
isAndroid: boolean;
|
|
19
|
+
dismissSplash: (fadeOutDuration?: number) => Promise<void>;
|
|
20
|
+
}
|
|
21
|
+
interface CapacitorProviderProps {
|
|
22
|
+
children: React.ReactNode;
|
|
23
|
+
/**
|
|
24
|
+
* Dismiss the native splash screen automatically on first child render.
|
|
25
|
+
* Defaults to true — consumer apps almost always want this; set false if
|
|
26
|
+
* the splash should stay visible until some later signal (e.g. after auth
|
|
27
|
+
* bootstrap).
|
|
28
|
+
*/
|
|
29
|
+
autoDismissSplash?: boolean;
|
|
30
|
+
}
|
|
31
|
+
declare function CapacitorProvider({ children, autoDismissSplash, }: CapacitorProviderProps): React.ReactElement;
|
|
32
|
+
declare function useCapacitor(): CapacitorContextValue;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* useSafeArea returns the current safe-area inset values and re-reads them
|
|
36
|
+
* on orientation change. Consumer components inset their layout with these
|
|
37
|
+
* numbers when they can't (or don't want to) use the env() CSS vars directly
|
|
38
|
+
* — e.g. computing a virtual list's first-row offset.
|
|
39
|
+
*/
|
|
40
|
+
|
|
41
|
+
declare function useSafeArea(): SafeAreaInsets;
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* <BugReportButton> — TestFlight bug-report widget React component.
|
|
45
|
+
*
|
|
46
|
+
* Drop it once in a Capacitor consumer app (typically a floating button in
|
|
47
|
+
* a beta-only nav surface) and beta testers get a one-tap path to send a
|
|
48
|
+
* message + optional screenshot + environment context to the consumer's
|
|
49
|
+
* backend (which fans out to Slack, Sentry, etc.).
|
|
50
|
+
*
|
|
51
|
+
* Visual chrome is intentionally tiny — consumers wrap this in their own
|
|
52
|
+
* styled trigger if they want. The default appearance is a small floating
|
|
53
|
+
* pill in the bottom-right with a "Bug" label.
|
|
54
|
+
*/
|
|
55
|
+
|
|
56
|
+
interface BugReportButtonProps {
|
|
57
|
+
/** Subscriber / user id, attached to every submission. */
|
|
58
|
+
userIdentifier?: string;
|
|
59
|
+
/** Override the default floating-pill chrome with your own. */
|
|
60
|
+
renderTrigger?: (open: () => void) => React.ReactNode;
|
|
61
|
+
/** Extra metadata merged into every submission. */
|
|
62
|
+
extra?: Record<string, unknown>;
|
|
63
|
+
/** Called after a successful submission — close UI, show toast, etc. */
|
|
64
|
+
onSubmitted?: () => void;
|
|
65
|
+
}
|
|
66
|
+
declare function BugReportButton({ userIdentifier, renderTrigger, extra, onSubmitted, }: BugReportButtonProps): React.ReactElement;
|
|
67
|
+
|
|
68
|
+
export { BugReportButton, type BugReportButtonProps, type CapacitorContextValue, CapacitorProvider, useCapacitor, useSafeArea };
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { P as Platform, S as SafeAreaInsets } from '../safe-area-B67yGQOn.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* <CapacitorProvider> is the one-line install for consumer apps. Mount it at
|
|
6
|
+
* the top of the tree and every child gets useCapacitor() with platform info,
|
|
7
|
+
* safe-area insets, and a stable dismissSplash() callback.
|
|
8
|
+
*
|
|
9
|
+
* On mount the provider also installs the --safe-area-inset-* CSS vars and
|
|
10
|
+
* marks the document body with a data-platform="ios|android|web" attribute
|
|
11
|
+
* so CSS can target native chrome without JS.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
interface CapacitorContextValue {
|
|
15
|
+
platform: Platform;
|
|
16
|
+
isNative: boolean;
|
|
17
|
+
isIOS: boolean;
|
|
18
|
+
isAndroid: boolean;
|
|
19
|
+
dismissSplash: (fadeOutDuration?: number) => Promise<void>;
|
|
20
|
+
}
|
|
21
|
+
interface CapacitorProviderProps {
|
|
22
|
+
children: React.ReactNode;
|
|
23
|
+
/**
|
|
24
|
+
* Dismiss the native splash screen automatically on first child render.
|
|
25
|
+
* Defaults to true — consumer apps almost always want this; set false if
|
|
26
|
+
* the splash should stay visible until some later signal (e.g. after auth
|
|
27
|
+
* bootstrap).
|
|
28
|
+
*/
|
|
29
|
+
autoDismissSplash?: boolean;
|
|
30
|
+
}
|
|
31
|
+
declare function CapacitorProvider({ children, autoDismissSplash, }: CapacitorProviderProps): React.ReactElement;
|
|
32
|
+
declare function useCapacitor(): CapacitorContextValue;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* useSafeArea returns the current safe-area inset values and re-reads them
|
|
36
|
+
* on orientation change. Consumer components inset their layout with these
|
|
37
|
+
* numbers when they can't (or don't want to) use the env() CSS vars directly
|
|
38
|
+
* — e.g. computing a virtual list's first-row offset.
|
|
39
|
+
*/
|
|
40
|
+
|
|
41
|
+
declare function useSafeArea(): SafeAreaInsets;
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* <BugReportButton> — TestFlight bug-report widget React component.
|
|
45
|
+
*
|
|
46
|
+
* Drop it once in a Capacitor consumer app (typically a floating button in
|
|
47
|
+
* a beta-only nav surface) and beta testers get a one-tap path to send a
|
|
48
|
+
* message + optional screenshot + environment context to the consumer's
|
|
49
|
+
* backend (which fans out to Slack, Sentry, etc.).
|
|
50
|
+
*
|
|
51
|
+
* Visual chrome is intentionally tiny — consumers wrap this in their own
|
|
52
|
+
* styled trigger if they want. The default appearance is a small floating
|
|
53
|
+
* pill in the bottom-right with a "Bug" label.
|
|
54
|
+
*/
|
|
55
|
+
|
|
56
|
+
interface BugReportButtonProps {
|
|
57
|
+
/** Subscriber / user id, attached to every submission. */
|
|
58
|
+
userIdentifier?: string;
|
|
59
|
+
/** Override the default floating-pill chrome with your own. */
|
|
60
|
+
renderTrigger?: (open: () => void) => React.ReactNode;
|
|
61
|
+
/** Extra metadata merged into every submission. */
|
|
62
|
+
extra?: Record<string, unknown>;
|
|
63
|
+
/** Called after a successful submission — close UI, show toast, etc. */
|
|
64
|
+
onSubmitted?: () => void;
|
|
65
|
+
}
|
|
66
|
+
declare function BugReportButton({ userIdentifier, renderTrigger, extra, onSubmitted, }: BugReportButtonProps): React.ReactElement;
|
|
67
|
+
|
|
68
|
+
export { BugReportButton, type BugReportButtonProps, type CapacitorContextValue, CapacitorProvider, useCapacitor, useSafeArea };
|