@guidelytech/react-native 0.5.0 → 0.6.1
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/index.cjs +181 -39
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +15 -6
- package/dist/index.d.ts +15 -6
- package/dist/index.js +197 -55
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.d.cts
CHANGED
|
@@ -319,7 +319,7 @@ interface UiState {
|
|
|
319
319
|
}
|
|
320
320
|
|
|
321
321
|
declare const SDK_NAME = "@guidelytech/react-native";
|
|
322
|
-
declare const SDK_VERSION = "0.
|
|
322
|
+
declare const SDK_VERSION = "0.6.1";
|
|
323
323
|
declare const DEFAULT_API_URL = "https://guidelytech.com";
|
|
324
324
|
/** Host-platform services the engine needs; the provider supplies React Native implementations. */
|
|
325
325
|
interface PlatformBridge {
|
|
@@ -637,9 +637,16 @@ declare function GuidelyOverlay({ client, insets: insetsProp, launcherOffset }:
|
|
|
637
637
|
* Tiny, tolerant HTML → rich-text converter for guide bodies (already sanitized server-side).
|
|
638
638
|
* Supports p, div, br, strong/b, em/i, u, a, code, ul/ol/li, h1–h6 and blockquote; every other tag
|
|
639
639
|
* is reduced to its text. `img` becomes an image block, and `video` / canonical embed `iframe`s
|
|
640
|
-
* become video blocks (shown as a link that opens the video).
|
|
641
|
-
*
|
|
640
|
+
* become video blocks (shown as a link that opens the video). A PDF (`div.gd-pdf`: its link and its
|
|
641
|
+
* pages as images) becomes one pdf block, and a lone file link (`a.gd-file`) a file block. Output is
|
|
642
|
+
* plain data so it can be unit-tested without React Native.
|
|
642
643
|
*/
|
|
644
|
+
interface PdfPage {
|
|
645
|
+
src: string;
|
|
646
|
+
alt: string;
|
|
647
|
+
width?: number;
|
|
648
|
+
height?: number;
|
|
649
|
+
}
|
|
643
650
|
interface TextRun {
|
|
644
651
|
text: string;
|
|
645
652
|
bold?: boolean;
|
|
@@ -649,7 +656,7 @@ interface TextRun {
|
|
|
649
656
|
href?: string;
|
|
650
657
|
}
|
|
651
658
|
interface TextBlock {
|
|
652
|
-
kind: "paragraph" | "heading" | "list-item" | "quote" | "image" | "video";
|
|
659
|
+
kind: "paragraph" | "heading" | "list-item" | "quote" | "image" | "video" | "pdf" | "file";
|
|
653
660
|
/** Heading level 1–3, list nesting depth from 1. */
|
|
654
661
|
level: number;
|
|
655
662
|
/** For list items: the bullet ("•") or number ("1.") to show. */
|
|
@@ -657,10 +664,12 @@ interface TextBlock {
|
|
|
657
664
|
runs: TextRun[];
|
|
658
665
|
/** Image blocks: http(s) or data:image source. */
|
|
659
666
|
src?: string;
|
|
660
|
-
/** Image alt text, or a
|
|
667
|
+
/** Image alt text, a video's label, or a PDF's file name. */
|
|
661
668
|
alt?: string;
|
|
662
|
-
/** Video blocks: the page or file to open. */
|
|
669
|
+
/** Video, pdf and file blocks: the page or file to open. */
|
|
663
670
|
href?: string;
|
|
671
|
+
/** Pdf blocks: the rendered pages, in order. */
|
|
672
|
+
pages?: PdfPage[];
|
|
664
673
|
/** Image intrinsic size from `width`/`height`, when present. */
|
|
665
674
|
width?: number;
|
|
666
675
|
height?: number;
|
package/dist/index.d.ts
CHANGED
|
@@ -319,7 +319,7 @@ interface UiState {
|
|
|
319
319
|
}
|
|
320
320
|
|
|
321
321
|
declare const SDK_NAME = "@guidelytech/react-native";
|
|
322
|
-
declare const SDK_VERSION = "0.
|
|
322
|
+
declare const SDK_VERSION = "0.6.1";
|
|
323
323
|
declare const DEFAULT_API_URL = "https://guidelytech.com";
|
|
324
324
|
/** Host-platform services the engine needs; the provider supplies React Native implementations. */
|
|
325
325
|
interface PlatformBridge {
|
|
@@ -637,9 +637,16 @@ declare function GuidelyOverlay({ client, insets: insetsProp, launcherOffset }:
|
|
|
637
637
|
* Tiny, tolerant HTML → rich-text converter for guide bodies (already sanitized server-side).
|
|
638
638
|
* Supports p, div, br, strong/b, em/i, u, a, code, ul/ol/li, h1–h6 and blockquote; every other tag
|
|
639
639
|
* is reduced to its text. `img` becomes an image block, and `video` / canonical embed `iframe`s
|
|
640
|
-
* become video blocks (shown as a link that opens the video).
|
|
641
|
-
*
|
|
640
|
+
* become video blocks (shown as a link that opens the video). A PDF (`div.gd-pdf`: its link and its
|
|
641
|
+
* pages as images) becomes one pdf block, and a lone file link (`a.gd-file`) a file block. Output is
|
|
642
|
+
* plain data so it can be unit-tested without React Native.
|
|
642
643
|
*/
|
|
644
|
+
interface PdfPage {
|
|
645
|
+
src: string;
|
|
646
|
+
alt: string;
|
|
647
|
+
width?: number;
|
|
648
|
+
height?: number;
|
|
649
|
+
}
|
|
643
650
|
interface TextRun {
|
|
644
651
|
text: string;
|
|
645
652
|
bold?: boolean;
|
|
@@ -649,7 +656,7 @@ interface TextRun {
|
|
|
649
656
|
href?: string;
|
|
650
657
|
}
|
|
651
658
|
interface TextBlock {
|
|
652
|
-
kind: "paragraph" | "heading" | "list-item" | "quote" | "image" | "video";
|
|
659
|
+
kind: "paragraph" | "heading" | "list-item" | "quote" | "image" | "video" | "pdf" | "file";
|
|
653
660
|
/** Heading level 1–3, list nesting depth from 1. */
|
|
654
661
|
level: number;
|
|
655
662
|
/** For list items: the bullet ("•") or number ("1.") to show. */
|
|
@@ -657,10 +664,12 @@ interface TextBlock {
|
|
|
657
664
|
runs: TextRun[];
|
|
658
665
|
/** Image blocks: http(s) or data:image source. */
|
|
659
666
|
src?: string;
|
|
660
|
-
/** Image alt text, or a
|
|
667
|
+
/** Image alt text, a video's label, or a PDF's file name. */
|
|
661
668
|
alt?: string;
|
|
662
|
-
/** Video blocks: the page or file to open. */
|
|
669
|
+
/** Video, pdf and file blocks: the page or file to open. */
|
|
663
670
|
href?: string;
|
|
671
|
+
/** Pdf blocks: the rendered pages, in order. */
|
|
672
|
+
pages?: PdfPage[];
|
|
664
673
|
/** Image intrinsic size from `width`/`height`, when present. */
|
|
665
674
|
width?: number;
|
|
666
675
|
height?: number;
|
package/dist/index.js
CHANGED
|
@@ -6,7 +6,7 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
|
6
6
|
import { useContext as useContext2, useEffect as useEffect8, useRef as useRef5, useState as useState7 } from "react";
|
|
7
7
|
import { AppState, Dimensions, Linking, Platform as Platform6 } from "react-native";
|
|
8
8
|
|
|
9
|
-
// ../shared/dist/chunk-
|
|
9
|
+
// ../shared/dist/chunk-OLWGMDRX.js
|
|
10
10
|
function fnv1a(input) {
|
|
11
11
|
let h = 2166136261;
|
|
12
12
|
for (let i = 0; i < input.length; i++) {
|
|
@@ -312,6 +312,13 @@ function sanitizeProperties(props) {
|
|
|
312
312
|
var SOURCEMAP_MAX_FILE_BYTES = 25 * 1024 * 1024;
|
|
313
313
|
var MEDIA_IMAGE_MAX_BYTES = 10 * 1024 * 1024;
|
|
314
314
|
var MEDIA_VIDEO_MAX_BYTES = 200 * 1024 * 1024;
|
|
315
|
+
var MEDIA_FILE_MAX_BYTES = 50 * 1024 * 1024;
|
|
316
|
+
var MEDIA_MAX_BYTES = Math.max(MEDIA_IMAGE_MAX_BYTES, MEDIA_VIDEO_MAX_BYTES, MEDIA_FILE_MAX_BYTES);
|
|
317
|
+
var FILE_LINK_CLASS = "gd-file";
|
|
318
|
+
var PDF_BLOCK_CLASS = "gd-pdf";
|
|
319
|
+
function isFileLink(className, href) {
|
|
320
|
+
return !!className && className.split(/\s+/).includes(FILE_LINK_CLASS) && isSafeMediaUrl(href);
|
|
321
|
+
}
|
|
315
322
|
var YOUTUBE_ID = /^[A-Za-z0-9_-]{11}$/;
|
|
316
323
|
var VIMEO_ID = /^\d{1,12}$/;
|
|
317
324
|
var VIMEO_HASH = /^[0-9a-f]{6,20}$/i;
|
|
@@ -452,8 +459,45 @@ function isArticleListed(collections, article, member) {
|
|
|
452
459
|
}
|
|
453
460
|
return true;
|
|
454
461
|
}
|
|
462
|
+
var CAPTURE_SCREENSHOT_MAX_BYTES = 8 * 1024 * 1024;
|
|
455
463
|
|
|
456
|
-
// ../sdk-core/dist/chunk-
|
|
464
|
+
// ../sdk-core/dist/chunk-CYAG6ZYX.js
|
|
465
|
+
function readJson(store, key, fallback) {
|
|
466
|
+
const raw = store.get(key);
|
|
467
|
+
if (raw == null) return fallback;
|
|
468
|
+
try {
|
|
469
|
+
return JSON.parse(raw);
|
|
470
|
+
} catch {
|
|
471
|
+
return fallback;
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
function writeJson(store, key, value) {
|
|
475
|
+
try {
|
|
476
|
+
store.set(key, JSON.stringify(value));
|
|
477
|
+
} catch {
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
var KEYS = {
|
|
481
|
+
anon: "guidely:anon",
|
|
482
|
+
seen: "guidely:seen",
|
|
483
|
+
config: (key) => `guidely:config:${key}`,
|
|
484
|
+
etag: (key) => `guidely:etag:${key}`,
|
|
485
|
+
state: (key) => `guidely:state:${key}`,
|
|
486
|
+
user: (key) => `guidely:user:${key}`,
|
|
487
|
+
queue: (key) => `guidely:queue:${key}`,
|
|
488
|
+
session: "guidely:session",
|
|
489
|
+
active: "guidely:active",
|
|
490
|
+
authoring: "guidely:authoring",
|
|
491
|
+
/** How-to capture session marker ({ token, … }) and its not-yet-uploaded steps. */
|
|
492
|
+
capture: "guidely:capture",
|
|
493
|
+
capturePending: "guidely:capture:pending",
|
|
494
|
+
/** Messenger conversations this browser can read: [{ id, token }]. */
|
|
495
|
+
conversations: (key) => `guidely:conversations:${key}`,
|
|
496
|
+
/** Announcement ids opened in the messenger's News tab. */
|
|
497
|
+
newsSeen: (key) => `guidely:news:${key}`
|
|
498
|
+
};
|
|
499
|
+
|
|
500
|
+
// ../sdk-core/dist/chunk-AKNE7D5M.js
|
|
457
501
|
var __defProp2 = Object.defineProperty;
|
|
458
502
|
var __defNormalProp2 = (obj, key, value) => key in obj ? __defProp2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
459
503
|
var __publicField2 = (obj, key, value) => __defNormalProp2(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
@@ -475,7 +519,8 @@ var Api = class {
|
|
|
475
519
|
const f = this.fetcher;
|
|
476
520
|
if (!f) throw new Error("fetch is not available");
|
|
477
521
|
const headers = { ...options.headers, "X-Guidely-Key": this.key, Accept: "application/json" };
|
|
478
|
-
|
|
522
|
+
const form = typeof FormData !== "undefined" && options.body instanceof FormData;
|
|
523
|
+
if (options.body !== void 0 && !form) headers["Content-Type"] = "application/json";
|
|
479
524
|
if (options.etag) headers["If-None-Match"] = options.etag;
|
|
480
525
|
const ac = typeof AbortController !== "undefined" ? new AbortController() : null;
|
|
481
526
|
const timer = ac ? setTimeout(() => ac.abort(), options.timeoutMs ?? 1e4) : null;
|
|
@@ -483,7 +528,7 @@ var Api = class {
|
|
|
483
528
|
const res = await f(this.url(path, options.params), {
|
|
484
529
|
method,
|
|
485
530
|
headers,
|
|
486
|
-
body: options.body === void 0 ? void 0 : JSON.stringify(options.body),
|
|
531
|
+
body: options.body === void 0 ? void 0 : form ? options.body : JSON.stringify(options.body),
|
|
487
532
|
keepalive: options.keepalive,
|
|
488
533
|
signal: ac?.signal,
|
|
489
534
|
credentials: "omit",
|
|
@@ -508,6 +553,10 @@ var Api = class {
|
|
|
508
553
|
post(path, body, options) {
|
|
509
554
|
return this.request("POST", path, { body, ...options });
|
|
510
555
|
}
|
|
556
|
+
/** Multipart POST (file uploads). No Content-Type header: the browser adds it with the boundary. */
|
|
557
|
+
postForm(path, form, options) {
|
|
558
|
+
return this.request("POST", path, { body: form, ...options });
|
|
559
|
+
}
|
|
511
560
|
/**
|
|
512
561
|
* POST that may answer with server-sent events. Each event is passed to `onEvent`; a JSON answer is
|
|
513
562
|
* returned instead. No timeout: Scout replies can take a while and the server keeps the stream alive.
|
|
@@ -550,10 +599,10 @@ var sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
|
550
599
|
function backoffMs(attempt, baseMs = 1e3, maxMs = 3e4) {
|
|
551
600
|
return Math.min(maxMs, baseMs * 2 ** Math.max(0, attempt));
|
|
552
601
|
}
|
|
553
|
-
async function
|
|
602
|
+
async function withRetry(send, attempts = 3, baseMs = 500) {
|
|
554
603
|
for (let i = 0; i < attempts; i++) {
|
|
555
604
|
try {
|
|
556
|
-
const res = await
|
|
605
|
+
const res = await send();
|
|
557
606
|
if (res.ok || res.status >= 400 && res.status < 500 && res.status !== 429) return res;
|
|
558
607
|
} catch {
|
|
559
608
|
}
|
|
@@ -561,6 +610,9 @@ async function postWithRetry(api, path, body, attempts = 3, baseMs = 500) {
|
|
|
561
610
|
}
|
|
562
611
|
return null;
|
|
563
612
|
}
|
|
613
|
+
function postWithRetry(api, path, body, attempts = 3, baseMs = 500) {
|
|
614
|
+
return withRetry(() => api.post(path, body), attempts, baseMs);
|
|
615
|
+
}
|
|
564
616
|
async function readEventStream(body, onEvent) {
|
|
565
617
|
const reader = body.getReader();
|
|
566
618
|
const decoder = new TextDecoder();
|
|
@@ -595,36 +647,7 @@ async function readEventStream(body, onEvent) {
|
|
|
595
647
|
if (buffer.trim()) dispatch(buffer);
|
|
596
648
|
}
|
|
597
649
|
|
|
598
|
-
// ../sdk-core/dist/chunk-
|
|
599
|
-
function readJson(store, key, fallback) {
|
|
600
|
-
const raw = store.get(key);
|
|
601
|
-
if (raw == null) return fallback;
|
|
602
|
-
try {
|
|
603
|
-
return JSON.parse(raw);
|
|
604
|
-
} catch {
|
|
605
|
-
return fallback;
|
|
606
|
-
}
|
|
607
|
-
}
|
|
608
|
-
function writeJson(store, key, value) {
|
|
609
|
-
try {
|
|
610
|
-
store.set(key, JSON.stringify(value));
|
|
611
|
-
} catch {
|
|
612
|
-
}
|
|
613
|
-
}
|
|
614
|
-
var KEYS = {
|
|
615
|
-
anon: "guidely:anon",
|
|
616
|
-
seen: "guidely:seen",
|
|
617
|
-
config: (key) => `guidely:config:${key}`,
|
|
618
|
-
etag: (key) => `guidely:etag:${key}`,
|
|
619
|
-
state: (key) => `guidely:state:${key}`,
|
|
620
|
-
user: (key) => `guidely:user:${key}`,
|
|
621
|
-
queue: (key) => `guidely:queue:${key}`,
|
|
622
|
-
session: "guidely:session",
|
|
623
|
-
active: "guidely:active",
|
|
624
|
-
authoring: "guidely:authoring",
|
|
625
|
-
/** Messenger conversations this browser can read: [{ id, token }]. */
|
|
626
|
-
conversations: (key) => `guidely:conversations:${key}`
|
|
627
|
-
};
|
|
650
|
+
// ../sdk-core/dist/chunk-GDF6RCHQ.js
|
|
628
651
|
var EventQueue = class {
|
|
629
652
|
constructor(opts) {
|
|
630
653
|
__publicField2(this, "opts", opts);
|
|
@@ -1706,7 +1729,7 @@ var PersistentStore = class {
|
|
|
1706
1729
|
|
|
1707
1730
|
// src/core/client.ts
|
|
1708
1731
|
var SDK_NAME = "@guidelytech/react-native";
|
|
1709
|
-
var SDK_VERSION = "0.
|
|
1732
|
+
var SDK_VERSION = "0.6.1";
|
|
1710
1733
|
var DEFAULT_API_URL = "https://guidelytech.com";
|
|
1711
1734
|
var PAGE_SCOPED = /* @__PURE__ */ new Set(["page_load", "url_match", "element_click", "element_visible", "delay"]);
|
|
1712
1735
|
var nowIso = () => (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -2843,7 +2866,7 @@ import { useCallback as useCallback2, useEffect as useEffect6, useRef as useRef3
|
|
|
2843
2866
|
import { Platform as Platform5, Pressable as Pressable8, StatusBar, StyleSheet as StyleSheet9, Text as Text8, useColorScheme, useWindowDimensions, View as View9 } from "react-native";
|
|
2844
2867
|
|
|
2845
2868
|
// src/ui/Checklist.tsx
|
|
2846
|
-
import { Pressable as Pressable3, ScrollView, StyleSheet as StyleSheet3, Text as Text3, View as View3 } from "react-native";
|
|
2869
|
+
import { Pressable as Pressable3, ScrollView as ScrollView2, StyleSheet as StyleSheet3, Text as Text3, View as View3 } from "react-native";
|
|
2847
2870
|
|
|
2848
2871
|
// src/ui/primitives.tsx
|
|
2849
2872
|
import { Pressable, StyleSheet, Text, View } from "react-native";
|
|
@@ -2898,7 +2921,7 @@ var styles = StyleSheet.create({
|
|
|
2898
2921
|
|
|
2899
2922
|
// src/ui/RichText.tsx
|
|
2900
2923
|
import { useEffect, useMemo, useState } from "react";
|
|
2901
|
-
import { Image, Platform, Pressable as Pressable2, StyleSheet as StyleSheet2, Text as Text2, View as View2 } from "react-native";
|
|
2924
|
+
import { Image, Modal, Platform, Pressable as Pressable2, ScrollView, StyleSheet as StyleSheet2, Text as Text2, View as View2 } from "react-native";
|
|
2902
2925
|
|
|
2903
2926
|
// src/core/html.ts
|
|
2904
2927
|
var ENTITIES = { amp: "&", lt: "<", gt: ">", quot: '"', apos: "'", nbsp: "\xA0", mdash: "\u2014", ndash: "\u2013", hellip: "\u2026", rsquo: "\u2019", lsquo: "\u2018", rdquo: "\u201D", ldquo: "\u201C", copy: "\xA9", reg: "\xAE", trade: "\u2122", times: "\xD7", rarr: "\u2192", larr: "\u2190", bull: "\u2022" };
|
|
@@ -2925,6 +2948,8 @@ function parseHtml(html) {
|
|
|
2925
2948
|
const lists = [];
|
|
2926
2949
|
let current = null;
|
|
2927
2950
|
let skipping = null;
|
|
2951
|
+
let pdf = null;
|
|
2952
|
+
let fileLink = null;
|
|
2928
2953
|
const media = (block) => {
|
|
2929
2954
|
flush();
|
|
2930
2955
|
blocks.push({ level: 1, runs: [], ...block });
|
|
@@ -2959,12 +2984,30 @@ function parseHtml(html) {
|
|
|
2959
2984
|
if (last && last.bold === run.bold && last.italic === run.italic && last.underline === run.underline && last.code === run.code && last.href === run.href) last.text += text;
|
|
2960
2985
|
else current.runs.push(run);
|
|
2961
2986
|
};
|
|
2987
|
+
const size = (attrs, name) => {
|
|
2988
|
+
const n = Number(attr(attrs, name));
|
|
2989
|
+
return n > 0 ? n : void 0;
|
|
2990
|
+
};
|
|
2991
|
+
const endPdf = (p) => {
|
|
2992
|
+
const name = p.name.replace(/\s+/g, " ").trim();
|
|
2993
|
+
if (p.href && p.pages.length) media({ kind: "pdf", href: p.href, alt: name || "PDF", pages: p.pages });
|
|
2994
|
+
else if (p.href) media({ kind: "file", href: p.href, alt: name || "Open PDF" });
|
|
2995
|
+
else for (const page of p.pages) media({ kind: "image", src: page.src, alt: page.alt, ...page.width && page.height ? { width: page.width, height: page.height } : {} });
|
|
2996
|
+
};
|
|
2962
2997
|
const re = /<!--[\s\S]*?-->|<\/?([a-zA-Z][a-zA-Z0-9]*)\b([^>]*)>|([^<]+|<)/g;
|
|
2963
2998
|
let m;
|
|
2964
2999
|
while (m = re.exec(html || "")) {
|
|
2965
3000
|
const [token, rawTag, attrs = "", text] = m;
|
|
2966
3001
|
if (text !== void 0) {
|
|
2967
3002
|
if (skipping) continue;
|
|
3003
|
+
if (pdf) {
|
|
3004
|
+
if (pdf.inLink) pdf.name += decodeEntities(text);
|
|
3005
|
+
continue;
|
|
3006
|
+
}
|
|
3007
|
+
if (fileLink) {
|
|
3008
|
+
fileLink.name += decodeEntities(text);
|
|
3009
|
+
continue;
|
|
3010
|
+
}
|
|
2968
3011
|
push(decodeEntities(text.replace(/\s+/g, " ")));
|
|
2969
3012
|
continue;
|
|
2970
3013
|
}
|
|
@@ -2988,6 +3031,44 @@ function parseHtml(html) {
|
|
|
2988
3031
|
if (!token.endsWith("/>")) skipping = tag;
|
|
2989
3032
|
continue;
|
|
2990
3033
|
}
|
|
3034
|
+
if (pdf) {
|
|
3035
|
+
if (tag === "div") {
|
|
3036
|
+
pdf.depth += closing ? -1 : 1;
|
|
3037
|
+
if (pdf.depth === 0) {
|
|
3038
|
+
endPdf(pdf);
|
|
3039
|
+
pdf = null;
|
|
3040
|
+
}
|
|
3041
|
+
} else if (tag === "a") {
|
|
3042
|
+
if (closing) pdf.inLink = false;
|
|
3043
|
+
else if (!pdf.href && isFileLink(attr(attrs, "class"), attr(attrs, "href"))) {
|
|
3044
|
+
pdf.href = attr(attrs, "href");
|
|
3045
|
+
pdf.inLink = true;
|
|
3046
|
+
}
|
|
3047
|
+
} else if (tag === "img" && !closing) {
|
|
3048
|
+
const src = attr(attrs, "src");
|
|
3049
|
+
const w = size(attrs, "width");
|
|
3050
|
+
const h = size(attrs, "height");
|
|
3051
|
+
if (isSafeMediaUrl(src)) pdf.pages.push({ src, alt: attr(attrs, "alt") ?? "", ...w && h ? { width: w, height: h } : {} });
|
|
3052
|
+
}
|
|
3053
|
+
continue;
|
|
3054
|
+
}
|
|
3055
|
+
if (fileLink) {
|
|
3056
|
+
if (closing && tag === "a") {
|
|
3057
|
+
media({ kind: "file", href: fileLink.href, alt: fileLink.name.replace(/\s+/g, " ").trim() || "Open PDF" });
|
|
3058
|
+
fileLink = null;
|
|
3059
|
+
}
|
|
3060
|
+
continue;
|
|
3061
|
+
}
|
|
3062
|
+
if (!closing && tag === "div" && (attr(attrs, "class") ?? "").split(/\s+/).includes(PDF_BLOCK_CLASS)) {
|
|
3063
|
+
flush();
|
|
3064
|
+
pdf = { depth: 1, name: "", inLink: false, pages: [] };
|
|
3065
|
+
continue;
|
|
3066
|
+
}
|
|
3067
|
+
if (!closing && tag === "a" && isFileLink(attr(attrs, "class"), attr(attrs, "href"))) {
|
|
3068
|
+
flush();
|
|
3069
|
+
fileLink = { href: attr(attrs, "href"), name: "" };
|
|
3070
|
+
continue;
|
|
3071
|
+
}
|
|
2991
3072
|
if (closing) {
|
|
2992
3073
|
if (tag === "b" || tag === "strong") style.bold = Math.max(0, style.bold - 1);
|
|
2993
3074
|
else if (tag === "i" || tag === "em") style.italic = Math.max(0, style.italic - 1);
|
|
@@ -3056,11 +3137,13 @@ function parseHtml(html) {
|
|
|
3056
3137
|
}
|
|
3057
3138
|
}
|
|
3058
3139
|
}
|
|
3140
|
+
if (pdf) endPdf(pdf);
|
|
3141
|
+
if (fileLink) media({ kind: "file", href: fileLink.href, alt: fileLink.name.replace(/\s+/g, " ").trim() || "Open PDF" });
|
|
3059
3142
|
flush();
|
|
3060
3143
|
return blocks;
|
|
3061
3144
|
}
|
|
3062
3145
|
function htmlToText(html) {
|
|
3063
|
-
return parseHtml(html).map((b) => b.kind === "image" || b.kind === "video" ? b.alt ?? "" : (b.marker ? `${b.marker} ` : "") + b.runs.map((r) => r.text).join("")).filter(Boolean).join("\n");
|
|
3146
|
+
return parseHtml(html).map((b) => b.kind === "image" || b.kind === "video" || b.kind === "pdf" || b.kind === "file" ? b.alt ?? "" : (b.marker ? `${b.marker} ` : "") + b.runs.map((r) => r.text).join("")).filter(Boolean).join("\n");
|
|
3064
3147
|
}
|
|
3065
3148
|
|
|
3066
3149
|
// src/ui/RichText.tsx
|
|
@@ -3096,6 +3179,48 @@ function BodyVideo({ block, palette: p, onLink }) {
|
|
|
3096
3179
|
/* @__PURE__ */ jsx2(Text2, { style: { color: p.primary, fontFamily: p.fontFamily, fontWeight: "600" }, children: block.alt })
|
|
3097
3180
|
] });
|
|
3098
3181
|
}
|
|
3182
|
+
var PAGE_RATIO = 1 / 1.414;
|
|
3183
|
+
var pageRatio = (p) => p.width && p.height ? p.width / p.height : PAGE_RATIO;
|
|
3184
|
+
function PdfBadge() {
|
|
3185
|
+
return /* @__PURE__ */ jsx2(View2, { style: styles2.badge, children: /* @__PURE__ */ jsx2(Text2, { style: styles2.badgeText, children: "PDF" }) });
|
|
3186
|
+
}
|
|
3187
|
+
function BodyFile({ block, palette: p, onLink }) {
|
|
3188
|
+
return /* @__PURE__ */ jsxs(Pressable2, { accessibilityRole: "link", accessibilityLabel: `${block.alt}, PDF`, onPress: () => onLink(block.href), style: ({ pressed }) => [styles2.video, { borderColor: p.border, backgroundColor: p.surface, opacity: pressed ? 0.7 : 1 }], children: [
|
|
3189
|
+
/* @__PURE__ */ jsx2(PdfBadge, {}),
|
|
3190
|
+
/* @__PURE__ */ jsx2(Text2, { numberOfLines: 2, ellipsizeMode: "middle", style: [styles2.flex, { color: p.text, fontFamily: p.fontFamily, fontWeight: "600" }], children: block.alt })
|
|
3191
|
+
] });
|
|
3192
|
+
}
|
|
3193
|
+
function BodyPdf({ block, palette: p, onLink }) {
|
|
3194
|
+
const pages = block.pages ?? [];
|
|
3195
|
+
const [width, setWidth] = useState(0);
|
|
3196
|
+
const [index, setIndex] = useState(0);
|
|
3197
|
+
const [reading, setReading] = useState(false);
|
|
3198
|
+
const height = width ? Math.max(...pages.map((pg) => width / pageRatio(pg))) : 0;
|
|
3199
|
+
const onScroll = (e) => width && setIndex(Math.round(e.nativeEvent.contentOffset.x / width));
|
|
3200
|
+
return /* @__PURE__ */ jsxs(View2, { style: [styles2.pdf, { borderColor: p.border, backgroundColor: p.surface }], children: [
|
|
3201
|
+
/* @__PURE__ */ jsxs(Pressable2, { accessibilityRole: "button", accessibilityLabel: `Read ${block.alt} full screen`, onPress: () => setReading(true), style: ({ pressed }) => [styles2.pdfHeader, { opacity: pressed ? 0.7 : 1 }], children: [
|
|
3202
|
+
/* @__PURE__ */ jsx2(PdfBadge, {}),
|
|
3203
|
+
/* @__PURE__ */ jsx2(Text2, { numberOfLines: 1, ellipsizeMode: "middle", style: [styles2.flex, { color: p.text, fontFamily: p.fontFamily, fontWeight: "600" }], children: block.alt }),
|
|
3204
|
+
/* @__PURE__ */ jsx2(Text2, { style: { color: p.muted, fontSize: 16 }, children: "\u2922" })
|
|
3205
|
+
] }),
|
|
3206
|
+
/* @__PURE__ */ jsxs(View2, { style: styles2.pdfPages, onLayout: (e) => setWidth(e.nativeEvent.layout.width), children: [
|
|
3207
|
+
width > 0 && /* @__PURE__ */ jsx2(ScrollView, { horizontal: true, pagingEnabled: true, showsHorizontalScrollIndicator: false, onScroll, scrollEventThrottle: 32, accessibilityLabel: `${block.alt}, page ${index + 1} of ${pages.length}`, children: pages.map((pg, i) => /* @__PURE__ */ jsx2(Pressable2, { onPress: () => setReading(true), accessibilityRole: "imagebutton", accessibilityLabel: pg.alt || `Page ${i + 1}`, accessibilityHint: "Opens the document full screen", style: { width, height, alignItems: "center", justifyContent: "center" }, children: /* @__PURE__ */ jsx2(Image, { source: { uri: pg.src }, resizeMode: "contain", style: [styles2.page, { width: Math.min(width, height * pageRatio(pg)), aspectRatio: pageRatio(pg) }] }) }, i)) }),
|
|
3208
|
+
pages.length > 1 && /* @__PURE__ */ jsx2(View2, { pointerEvents: "none", style: styles2.count, children: /* @__PURE__ */ jsxs(Text2, { style: styles2.countText, children: [
|
|
3209
|
+
index + 1,
|
|
3210
|
+
" / ",
|
|
3211
|
+
pages.length
|
|
3212
|
+
] }) })
|
|
3213
|
+
] }),
|
|
3214
|
+
/* @__PURE__ */ jsx2(Modal, { visible: reading, animationType: "slide", presentationStyle: "fullScreen", onRequestClose: () => setReading(false), children: /* @__PURE__ */ jsxs(View2, { style: styles2.reader, children: [
|
|
3215
|
+
/* @__PURE__ */ jsxs(View2, { style: styles2.readerBar, children: [
|
|
3216
|
+
/* @__PURE__ */ jsx2(Text2, { numberOfLines: 1, ellipsizeMode: "middle", style: [styles2.flex, styles2.readerTitle], accessibilityRole: "header", children: block.alt }),
|
|
3217
|
+
/* @__PURE__ */ jsx2(Pressable2, { accessibilityRole: "link", onPress: () => onLink(block.href), style: styles2.readerBtn, children: /* @__PURE__ */ jsx2(Text2, { style: styles2.readerBtnText, children: "Open PDF \u2197" }) }),
|
|
3218
|
+
/* @__PURE__ */ jsx2(Pressable2, { accessibilityRole: "button", accessibilityLabel: "Close", onPress: () => setReading(false), style: styles2.readerBtn, children: /* @__PURE__ */ jsx2(Text2, { style: styles2.readerBtnText, children: "Done" }) })
|
|
3219
|
+
] }),
|
|
3220
|
+
/* @__PURE__ */ jsx2(ScrollView, { contentContainerStyle: styles2.readerPages, children: pages.map((pg, i) => /* @__PURE__ */ jsx2(Image, { source: { uri: pg.src }, accessible: true, accessibilityLabel: pg.alt || `Page ${i + 1}`, resizeMode: "contain", style: [styles2.readerPage, { aspectRatio: pageRatio(pg) }] }, i)) })
|
|
3221
|
+
] }) })
|
|
3222
|
+
] });
|
|
3223
|
+
}
|
|
3099
3224
|
function RichText({ html, palette: p, onLink, size = 15 }) {
|
|
3100
3225
|
const blocks = useMemo(() => parseHtml(html), [html]);
|
|
3101
3226
|
if (!blocks.length) return null;
|
|
@@ -3103,6 +3228,8 @@ function RichText({ html, palette: p, onLink, size = 15 }) {
|
|
|
3103
3228
|
return /* @__PURE__ */ jsx2(View2, { style: styles2.wrap, children: blocks.map((b, i) => {
|
|
3104
3229
|
if (b.kind === "image") return /* @__PURE__ */ jsx2(BodyImage, { block: b, palette: p }, i);
|
|
3105
3230
|
if (b.kind === "video") return /* @__PURE__ */ jsx2(BodyVideo, { block: b, palette: p, onLink }, i);
|
|
3231
|
+
if (b.kind === "pdf") return /* @__PURE__ */ jsx2(BodyPdf, { block: b, palette: p, onLink }, i);
|
|
3232
|
+
if (b.kind === "file") return /* @__PURE__ */ jsx2(BodyFile, { block: b, palette: p, onLink }, i);
|
|
3106
3233
|
const runs = b.runs.map((r, j) => /* @__PURE__ */ jsx2(Text2, { style: runStyle(r, p), onPress: r.href ? () => onLink(r.href) : void 0, accessibilityRole: r.href ? "link" : void 0, children: r.text }, j));
|
|
3107
3234
|
if (b.kind === "list-item") {
|
|
3108
3235
|
return /* @__PURE__ */ jsxs(View2, { style: [styles2.li, { paddingLeft: (b.level - 1) * 14 }], children: [
|
|
@@ -3124,7 +3251,22 @@ var styles2 = StyleSheet2.create({
|
|
|
3124
3251
|
flex: { flex: 1 },
|
|
3125
3252
|
image: { width: "100%", borderRadius: 6 },
|
|
3126
3253
|
video: { flexDirection: "row", alignItems: "center", gap: 8, paddingVertical: 12, paddingHorizontal: 14, borderWidth: 1, borderRadius: 8 },
|
|
3127
|
-
play: { fontSize: 14 }
|
|
3254
|
+
play: { fontSize: 14 },
|
|
3255
|
+
badge: { backgroundColor: "#e5484d", borderRadius: 4, paddingHorizontal: 5, paddingVertical: 3 },
|
|
3256
|
+
badgeText: { color: "#fff", fontSize: 9, fontWeight: "700", letterSpacing: 0.4 },
|
|
3257
|
+
pdf: { borderWidth: 1, borderRadius: 10, overflow: "hidden" },
|
|
3258
|
+
pdfHeader: { flexDirection: "row", alignItems: "center", gap: 8, minHeight: 44, paddingHorizontal: 12 },
|
|
3259
|
+
pdfPages: { marginHorizontal: 10, marginBottom: 10 },
|
|
3260
|
+
page: { backgroundColor: "#fff", borderRadius: 3 },
|
|
3261
|
+
count: { position: "absolute", right: 8, bottom: 8, backgroundColor: "rgba(17,17,17,0.72)", borderRadius: 999, paddingHorizontal: 8, paddingVertical: 2 },
|
|
3262
|
+
countText: { color: "#fff", fontSize: 11, fontWeight: "500", fontVariant: ["tabular-nums"] },
|
|
3263
|
+
reader: { flex: 1, backgroundColor: "#0b0b0d" },
|
|
3264
|
+
readerBar: { flexDirection: "row", alignItems: "center", gap: 8, paddingTop: Platform.OS === "ios" ? 52 : 12, paddingBottom: 10, paddingHorizontal: 16 },
|
|
3265
|
+
readerTitle: { color: "#fff", fontSize: 16, fontWeight: "600" },
|
|
3266
|
+
readerBtn: { minHeight: 36, justifyContent: "center", paddingHorizontal: 12, borderRadius: 8, backgroundColor: "rgba(255,255,255,0.12)" },
|
|
3267
|
+
readerBtnText: { color: "#fff", fontWeight: "600" },
|
|
3268
|
+
readerPages: { gap: 12, paddingHorizontal: 12, paddingBottom: 32 },
|
|
3269
|
+
readerPage: { width: "100%", backgroundColor: "#fff", borderRadius: 2 }
|
|
3128
3270
|
});
|
|
3129
3271
|
|
|
3130
3272
|
// src/ui/Checklist.tsx
|
|
@@ -3158,7 +3300,7 @@ function Checklist({ view, client, palette: p, geometry, showLauncher, launcherB
|
|
|
3158
3300
|
] }),
|
|
3159
3301
|
/* @__PURE__ */ jsx3(View3, { style: [styles3.bar, { backgroundColor: p.surface }], accessibilityRole: "progressbar", accessibilityValue: { min: 0, max: total, now: completed }, children: /* @__PURE__ */ jsx3(View3, { style: [styles3.fill, { backgroundColor: p.primary, width: `${total ? completed / total * 100 : 0}%` }] }) }),
|
|
3160
3302
|
finished && config.completionBody ? /* @__PURE__ */ jsx3(RichText, { html: config.completionBody, palette: p, onLink: (u) => client.navigate(u), size: 14 }) : null,
|
|
3161
|
-
/* @__PURE__ */ jsx3(
|
|
3303
|
+
/* @__PURE__ */ jsx3(ScrollView2, { style: styles3.tasks, contentContainerStyle: styles3.tasksContent, children: config.tasks.map((task) => {
|
|
3162
3304
|
const isDone = done.has(task.id);
|
|
3163
3305
|
const locked = !!nextOpen && !isDone && task.id !== nextOpen;
|
|
3164
3306
|
return /* @__PURE__ */ jsxs2(
|
|
@@ -3241,7 +3383,7 @@ var styles3 = StyleSheet3.create({
|
|
|
3241
3383
|
|
|
3242
3384
|
// src/ui/Messenger.tsx
|
|
3243
3385
|
import { useCallback, useEffect as useEffect2, useMemo as useMemo2, useRef, useState as useState2, useSyncExternalStore } from "react";
|
|
3244
|
-
import { ActivityIndicator, Keyboard, Modal, Platform as Platform2, Pressable as Pressable4, ScrollView as
|
|
3386
|
+
import { ActivityIndicator, Keyboard, Modal as Modal2, Platform as Platform2, Pressable as Pressable4, ScrollView as ScrollView3, StyleSheet as StyleSheet4, Text as Text4, TextInput, View as View4 } from "react-native";
|
|
3245
3387
|
import { Fragment, jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
3246
3388
|
function useMessenger(store) {
|
|
3247
3389
|
return useSyncExternalStore(
|
|
@@ -3284,7 +3426,7 @@ function MessengerSheet({ store, client, palette: p, topInset, bottomInset }) {
|
|
|
3284
3426
|
const keyboard = useKeyboardHeight();
|
|
3285
3427
|
const v = snap.view;
|
|
3286
3428
|
const title = v.kind === "thread" ? snap.thread?.conversation?.subject || "New conversation" : v.kind === "article" ? "" : v.tab === "home" ? snap.config.name : v.tab === "messages" ? "Messages" : "Help";
|
|
3287
|
-
return /* @__PURE__ */ jsx4(
|
|
3429
|
+
return /* @__PURE__ */ jsx4(Modal2, { visible: snap.open, animationType: "slide", presentationStyle: Platform2.OS === "ios" ? "pageSheet" : "fullScreen", onRequestClose: () => v.kind === "tab" ? store.close() : store.back(), children: /* @__PURE__ */ jsxs3(View4, { style: [styles4.sheet, { backgroundColor: p.background, paddingTop: Platform2.OS === "ios" ? 8 : topInset, paddingBottom: keyboard }], children: [
|
|
3288
3430
|
/* @__PURE__ */ jsxs3(View4, { style: [styles4.header, { borderColor: p.border }], children: [
|
|
3289
3431
|
v.kind !== "tab" ? /* @__PURE__ */ jsx4(Pressable4, { accessibilityRole: "button", accessibilityLabel: "Back", onPress: () => store.back(), hitSlop: 10, children: /* @__PURE__ */ jsx4(Text4, { style: [styles4.back, { color: p.primary }], children: "\u2039 Back" }) }) : null,
|
|
3290
3432
|
/* @__PURE__ */ jsx4(Text4, { accessibilityRole: "header", numberOfLines: 1, style: [styles4.title, { color: p.text, fontFamily: p.fontFamily }], children: title }),
|
|
@@ -3314,7 +3456,7 @@ function Home({ store, palette: p }) {
|
|
|
3314
3456
|
const snap = useMessenger(store);
|
|
3315
3457
|
const recent = snap.conversations[0];
|
|
3316
3458
|
const [q, setQ] = useState2("");
|
|
3317
|
-
return /* @__PURE__ */ jsxs3(
|
|
3459
|
+
return /* @__PURE__ */ jsxs3(ScrollView3, { contentContainerStyle: styles4.content, keyboardShouldPersistTaps: "handled", children: [
|
|
3318
3460
|
/* @__PURE__ */ jsxs3(View4, { style: [styles4.hero, { backgroundColor: p.primary, borderRadius: p.radius }], children: [
|
|
3319
3461
|
/* @__PURE__ */ jsx4(Text4, { style: [styles4.heroTitle, { color: p.onPrimary }], children: snap.config.greeting || `Hi! I'm ${snap.config.name}.` }),
|
|
3320
3462
|
/* @__PURE__ */ jsx4(Text4, { style: [styles4.heroSub, { color: p.onPrimary }], children: snap.config.aiAvailable ? `${snap.config.name} answers right away${snap.config.handoffEnabled ? ", and the team is here when you need a person" : ""}.` : "The team usually replies within a few hours." })
|
|
@@ -3360,7 +3502,7 @@ function ConversationRow({ c, palette: p, onPress }) {
|
|
|
3360
3502
|
}
|
|
3361
3503
|
function Conversations({ store, palette: p }) {
|
|
3362
3504
|
const snap = useMessenger(store);
|
|
3363
|
-
return /* @__PURE__ */ jsxs3(
|
|
3505
|
+
return /* @__PURE__ */ jsxs3(ScrollView3, { contentContainerStyle: styles4.content, children: [
|
|
3364
3506
|
snap.conversations.length ? snap.conversations.map((c) => /* @__PURE__ */ jsx4(ConversationRow, { c, palette: p, onPress: () => void store.openConversation(c.id) }, c.id)) : /* @__PURE__ */ jsx4(Text4, { style: [styles4.empty, { color: p.muted }], children: "No conversations yet." }),
|
|
3365
3507
|
/* @__PURE__ */ jsx4(GButton, { label: "New conversation", palette: p, onPress: () => store.showNewMessage(), style: styles4.fullWidth })
|
|
3366
3508
|
] });
|
|
@@ -3405,7 +3547,7 @@ function Thread({ store, palette: p, bottomInset }) {
|
|
|
3405
3547
|
};
|
|
3406
3548
|
const canHandoff = snap.config.handoffEnabled && snap.config.aiAvailable && convo?.status === "bot" && !t.sending;
|
|
3407
3549
|
return /* @__PURE__ */ jsxs3(View4, { style: styles4.flex, children: [
|
|
3408
|
-
/* @__PURE__ */ jsxs3(
|
|
3550
|
+
/* @__PURE__ */ jsxs3(ScrollView3, { ref: scroll, contentContainerStyle: styles4.thread, onContentSizeChange: () => scroll.current?.scrollToEnd({ animated: true }), keyboardShouldPersistTaps: "handled", children: [
|
|
3409
3551
|
!t.messages.length && !t.sending ? /* @__PURE__ */ jsx4(Text4, { style: [styles4.empty, { color: p.muted }], children: snap.config.greeting || "Ask us anything." }) : null,
|
|
3410
3552
|
t.messages.map((m) => /* @__PURE__ */ jsx4(Bubble, { m, text: t.streaming[m.id] ?? m.body, name: snap.config.name, palette: p, onArticle: (id) => void store.openArticle(id), onGuide: (k) => store.startGuide(k) }, m.id)),
|
|
3411
3553
|
streamingIds.map((id) => /* @__PURE__ */ jsx4(Bubble, { m: { id, author: "scout", body: "", citations: [], suggestedGuides: [], status: "pending", createdAt: (/* @__PURE__ */ new Date()).toISOString() }, text: t.streaming[id] ?? "", name: snap.config.name, palette: p, onArticle: () => {
|
|
@@ -3477,7 +3619,7 @@ function Help({ store, client, palette: p }) {
|
|
|
3477
3619
|
const audiences = client.getAudienceIds();
|
|
3478
3620
|
const sections = resourceCenterSections(articles?.collections ?? [], articles?.articles ?? [], audiences);
|
|
3479
3621
|
const listed = results?.filter((a) => isArticleListed(articles?.collections ?? [], a, audiences));
|
|
3480
|
-
return /* @__PURE__ */ jsxs3(
|
|
3622
|
+
return /* @__PURE__ */ jsxs3(ScrollView3, { contentContainerStyle: styles4.content, keyboardShouldPersistTaps: "handled", children: [
|
|
3481
3623
|
/* @__PURE__ */ jsx4(TextInput, { value: q, onChangeText: setQ, placeholder: "Search articles", placeholderTextColor: p.muted, accessibilityLabel: "Search help articles", returnKeyType: "search", style: [styles4.search, { color: p.text, backgroundColor: p.surface, borderRadius: Math.min(10, p.radius) }] }),
|
|
3482
3624
|
listed ? section(`Results for \u201C${q.trim()}\u201D`, listed.length ? listed.map((a) => row(a.id, a.title, a.summary, () => open(a))) : /* @__PURE__ */ jsx4(Text4, { style: [styles4.rowSub, { color: p.muted }], children: "No articles found." })) : /* @__PURE__ */ jsxs3(Fragment, { children: [
|
|
3483
3625
|
recommended.length ? section("Recommended", recommended.map((g) => row(g.id, g.name, void 0, () => store.startGuide(g.key), "\u25B6"))) : null,
|
|
@@ -3499,7 +3641,7 @@ function Help({ store, client, palette: p }) {
|
|
|
3499
3641
|
}
|
|
3500
3642
|
function Article({ article, palette: p, client }) {
|
|
3501
3643
|
if (!article) return /* @__PURE__ */ jsx4(ActivityIndicator, { style: styles4.loading, color: p.muted });
|
|
3502
|
-
return /* @__PURE__ */ jsxs3(
|
|
3644
|
+
return /* @__PURE__ */ jsxs3(ScrollView3, { contentContainerStyle: styles4.content, children: [
|
|
3503
3645
|
/* @__PURE__ */ jsx4(Text4, { accessibilityRole: "header", style: [styles4.articleTitle, { color: p.text, fontFamily: p.fontFamily }], children: article.title }),
|
|
3504
3646
|
/* @__PURE__ */ jsx4(RichText, { html: article.body, palette: p, onLink: (u) => client.navigate(u) })
|
|
3505
3647
|
] });
|
|
@@ -3562,7 +3704,7 @@ var styles4 = StyleSheet4.create({
|
|
|
3562
3704
|
|
|
3563
3705
|
// src/ui/ResourceCenter.tsx
|
|
3564
3706
|
import { useEffect as useEffect3, useMemo as useMemo3, useState as useState3 } from "react";
|
|
3565
|
-
import { Modal as
|
|
3707
|
+
import { Modal as Modal3, Platform as Platform3, Pressable as Pressable5, ScrollView as ScrollView4, StyleSheet as StyleSheet5, Text as Text5, TextInput as TextInput2, View as View5 } from "react-native";
|
|
3566
3708
|
import { Fragment as Fragment2, jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
3567
3709
|
function ResourceCenter({ client, palette: p, open, topInset, bottomInset }) {
|
|
3568
3710
|
const rc = client.getResourceCenter();
|
|
@@ -3616,16 +3758,16 @@ function ResourceCenter({ client, palette: p, open, topInset, bottomInset }) {
|
|
|
3616
3758
|
const audiences = client.getAudienceIds();
|
|
3617
3759
|
const sections = resourceCenterSections(rc.collections, rc.articles, audiences);
|
|
3618
3760
|
const listed = results?.filter((a) => isArticleListed(rc.collections, a, audiences));
|
|
3619
|
-
return /* @__PURE__ */ jsx5(
|
|
3761
|
+
return /* @__PURE__ */ jsx5(Modal3, { visible: open, animationType: "slide", presentationStyle: Platform3.OS === "ios" ? "pageSheet" : "fullScreen", onRequestClose: () => article ? setArticle(null) : close(), children: /* @__PURE__ */ jsxs4(View5, { style: [styles5.sheet, { backgroundColor: p.background, paddingTop: Platform3.OS === "ios" ? 8 : topInset }], children: [
|
|
3620
3762
|
/* @__PURE__ */ jsxs4(View5, { style: [styles5.header, { borderColor: p.border }], children: [
|
|
3621
3763
|
article ? /* @__PURE__ */ jsx5(Pressable5, { accessibilityRole: "button", accessibilityLabel: "Back", onPress: () => setArticle(null), hitSlop: 10, children: /* @__PURE__ */ jsx5(Text5, { style: [styles5.back, { color: p.primary }], children: "\u2039 Back" }) }) : null,
|
|
3622
3764
|
/* @__PURE__ */ jsx5(Text5, { accessibilityRole: "header", style: [styles5.title, { color: p.text, fontFamily: p.fontFamily }], numberOfLines: 1, children: article ? "" : rc.title }),
|
|
3623
3765
|
/* @__PURE__ */ jsx5(CloseButton, { palette: p, onPress: close, label: "Close help" })
|
|
3624
3766
|
] }),
|
|
3625
|
-
article ? /* @__PURE__ */ jsxs4(
|
|
3767
|
+
article ? /* @__PURE__ */ jsxs4(ScrollView4, { contentContainerStyle: [styles5.content, { paddingBottom: bottomInset + 24 }], children: [
|
|
3626
3768
|
/* @__PURE__ */ jsx5(Text5, { accessibilityRole: "header", style: [styles5.articleTitle, { color: p.text, fontFamily: p.fontFamily }], children: article.title }),
|
|
3627
3769
|
/* @__PURE__ */ jsx5(RichText, { html: article.body, palette: p, onLink: (u) => client.navigate(u) })
|
|
3628
|
-
] }) : /* @__PURE__ */ jsxs4(
|
|
3770
|
+
] }) : /* @__PURE__ */ jsxs4(ScrollView4, { contentContainerStyle: [styles5.content, { paddingBottom: bottomInset + 24 }], keyboardShouldPersistTaps: "handled", children: [
|
|
3629
3771
|
/* @__PURE__ */ jsx5(
|
|
3630
3772
|
TextInput2,
|
|
3631
3773
|
{
|
|
@@ -3930,7 +4072,7 @@ import {
|
|
|
3930
4072
|
KeyboardAvoidingView,
|
|
3931
4073
|
Platform as Platform4,
|
|
3932
4074
|
Pressable as Pressable7,
|
|
3933
|
-
ScrollView as
|
|
4075
|
+
ScrollView as ScrollView5,
|
|
3934
4076
|
StyleSheet as StyleSheet8,
|
|
3935
4077
|
Text as Text7,
|
|
3936
4078
|
TextInput as TextInput3,
|
|
@@ -4026,7 +4168,7 @@ function Survey({
|
|
|
4026
4168
|
}
|
|
4027
4169
|
) : null,
|
|
4028
4170
|
/* @__PURE__ */ jsx8(GButton, { label: "Done", palette: p, onPress: close, style: styles8.end })
|
|
4029
|
-
] }) : /* @__PURE__ */ jsxs7(
|
|
4171
|
+
] }) : /* @__PURE__ */ jsxs7(ScrollView5, { contentContainerStyle: styles8.inner, keyboardShouldPersistTaps: "handled", children: [
|
|
4030
4172
|
config.questions.filter((q) => isQuestionVisible(q, answers)).map((q, i) => /* @__PURE__ */ jsxs7(View8, { style: styles8.question, children: [
|
|
4031
4173
|
/* @__PURE__ */ jsxs7(View8, { style: styles8.head, children: [
|
|
4032
4174
|
/* @__PURE__ */ jsxs7(Text7, { style: [styles8.qTitle, { color: p.text, fontFamily: p.fontFamily }], children: [
|