@retor/react-native 0.3.0 → 0.3.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.d.mts +13 -6
- package/dist/index.d.ts +13 -6
- package/dist/index.js +112 -94
- package/dist/index.mjs +94 -72
- package/package.json +10 -3
package/dist/index.d.mts
CHANGED
|
@@ -214,15 +214,13 @@ interface LineDetailSheetProps {
|
|
|
214
214
|
/** Custom content (typically a `<LineTagList>`). */
|
|
215
215
|
children?: React.ReactNode;
|
|
216
216
|
}
|
|
217
|
-
/**
|
|
218
|
-
* Sheet shown when a line is open. Includes a default header with the
|
|
219
|
-
* autoplay button + minimize arrow, the tag list, and a Done footer.
|
|
220
|
-
*/
|
|
221
217
|
declare function LineDetailSheet({ snapPoints, renderHeader, children }: LineDetailSheetProps): React.JSX.Element;
|
|
222
218
|
interface LineTagListProps {
|
|
223
219
|
children: (tag: RetorTag, isActive: boolean) => React.ReactNode;
|
|
220
|
+
/** Optional header rendered above the list (used internally for the default header). */
|
|
221
|
+
listHeader?: React.ReactNode;
|
|
224
222
|
}
|
|
225
|
-
declare function LineTagList({ children }: LineTagListProps): React.JSX.Element | null;
|
|
223
|
+
declare function LineTagList({ children, listHeader }: LineTagListProps): React.JSX.Element | null;
|
|
226
224
|
|
|
227
225
|
interface AddNoteSheetProps {
|
|
228
226
|
/** Snap points. Defaults to ["50%"]. */
|
|
@@ -261,4 +259,13 @@ interface CoverPhotoProps {
|
|
|
261
259
|
*/
|
|
262
260
|
declare function CoverPhoto({ projectId, baseUrl, style }: CoverPhotoProps): React.JSX.Element;
|
|
263
261
|
|
|
264
|
-
|
|
262
|
+
/**
|
|
263
|
+
* Default background component for the SDK's bottom sheets.
|
|
264
|
+
* Renders an iOS-style blur with a dark tint overlay so the 3D scene
|
|
265
|
+
* remains visible behind the sheet.
|
|
266
|
+
*/
|
|
267
|
+
declare function BlurBackground({ style }: {
|
|
268
|
+
style?: StyleProp<ViewStyle>;
|
|
269
|
+
}): React.JSX.Element;
|
|
270
|
+
|
|
271
|
+
export { type AddNoteFormApi, AddNoteSheet, type AddNoteSheetProps, BlurBackground, CoverPhoto, type CoverPhotoProps, Hud, type HudProps, type InitPayload, LineDetailSheet, type LineDetailSheetProps, type LineProgressPayload, LineTagList, type LineTagListProps, LinesCarousel, type LinesCarouselProps, type NoteSubmitPayload, Notes, type NotesProps, ProjectSheet, type ProjectSheetProps, type RetorBridgeContextValue, type RetorLine, type RetorProject, type RetorTag, Viewer, type ViewerHandle, type ViewerProps, useActiveLine, useAddNote, useAutoplay, useLineProgress, useLines, useProject, useRetorBridge, useViewer };
|
package/dist/index.d.ts
CHANGED
|
@@ -214,15 +214,13 @@ interface LineDetailSheetProps {
|
|
|
214
214
|
/** Custom content (typically a `<LineTagList>`). */
|
|
215
215
|
children?: React.ReactNode;
|
|
216
216
|
}
|
|
217
|
-
/**
|
|
218
|
-
* Sheet shown when a line is open. Includes a default header with the
|
|
219
|
-
* autoplay button + minimize arrow, the tag list, and a Done footer.
|
|
220
|
-
*/
|
|
221
217
|
declare function LineDetailSheet({ snapPoints, renderHeader, children }: LineDetailSheetProps): React.JSX.Element;
|
|
222
218
|
interface LineTagListProps {
|
|
223
219
|
children: (tag: RetorTag, isActive: boolean) => React.ReactNode;
|
|
220
|
+
/** Optional header rendered above the list (used internally for the default header). */
|
|
221
|
+
listHeader?: React.ReactNode;
|
|
224
222
|
}
|
|
225
|
-
declare function LineTagList({ children }: LineTagListProps): React.JSX.Element | null;
|
|
223
|
+
declare function LineTagList({ children, listHeader }: LineTagListProps): React.JSX.Element | null;
|
|
226
224
|
|
|
227
225
|
interface AddNoteSheetProps {
|
|
228
226
|
/** Snap points. Defaults to ["50%"]. */
|
|
@@ -261,4 +259,13 @@ interface CoverPhotoProps {
|
|
|
261
259
|
*/
|
|
262
260
|
declare function CoverPhoto({ projectId, baseUrl, style }: CoverPhotoProps): React.JSX.Element;
|
|
263
261
|
|
|
264
|
-
|
|
262
|
+
/**
|
|
263
|
+
* Default background component for the SDK's bottom sheets.
|
|
264
|
+
* Renders an iOS-style blur with a dark tint overlay so the 3D scene
|
|
265
|
+
* remains visible behind the sheet.
|
|
266
|
+
*/
|
|
267
|
+
declare function BlurBackground({ style }: {
|
|
268
|
+
style?: StyleProp<ViewStyle>;
|
|
269
|
+
}): React.JSX.Element;
|
|
270
|
+
|
|
271
|
+
export { type AddNoteFormApi, AddNoteSheet, type AddNoteSheetProps, BlurBackground, CoverPhoto, type CoverPhotoProps, Hud, type HudProps, type InitPayload, LineDetailSheet, type LineDetailSheetProps, type LineProgressPayload, LineTagList, type LineTagListProps, LinesCarousel, type LinesCarouselProps, type NoteSubmitPayload, Notes, type NotesProps, ProjectSheet, type ProjectSheetProps, type RetorBridgeContextValue, type RetorLine, type RetorProject, type RetorTag, Viewer, type ViewerHandle, type ViewerProps, useActiveLine, useAddNote, useAutoplay, useLineProgress, useLines, useProject, useRetorBridge, useViewer };
|
package/dist/index.js
CHANGED
|
@@ -31,6 +31,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
31
31
|
var index_exports = {};
|
|
32
32
|
__export(index_exports, {
|
|
33
33
|
AddNoteSheet: () => AddNoteSheet,
|
|
34
|
+
BlurBackground: () => BlurBackground,
|
|
34
35
|
CoverPhoto: () => CoverPhoto,
|
|
35
36
|
Hud: () => Hud,
|
|
36
37
|
LineDetailSheet: () => LineDetailSheet,
|
|
@@ -356,16 +357,26 @@ function Hud({ children }) {
|
|
|
356
357
|
}
|
|
357
358
|
|
|
358
359
|
// src/ProjectSheet.tsx
|
|
359
|
-
var
|
|
360
|
-
var
|
|
360
|
+
var import_react5 = __toESM(require("react"));
|
|
361
|
+
var import_react_native4 = require("react-native");
|
|
361
362
|
var import_bottom_sheet2 = require("@gorhom/bottom-sheet");
|
|
362
363
|
var import_lucide_react_native = require("lucide-react-native");
|
|
364
|
+
|
|
365
|
+
// src/BlurBackground.tsx
|
|
366
|
+
var import_react4 = __toESM(require("react"));
|
|
367
|
+
var import_react_native3 = require("react-native");
|
|
368
|
+
var import_expo_blur = require("expo-blur");
|
|
369
|
+
function BlurBackground({ style }) {
|
|
370
|
+
return /* @__PURE__ */ import_react4.default.createElement(import_react_native3.View, { style: [style, import_react_native3.StyleSheet.absoluteFill, { overflow: "hidden", borderTopLeftRadius: 24, borderTopRightRadius: 24 }] }, /* @__PURE__ */ import_react4.default.createElement(import_expo_blur.BlurView, { intensity: 60, tint: "dark", style: import_react_native3.StyleSheet.absoluteFill }), /* @__PURE__ */ import_react4.default.createElement(import_react_native3.View, { style: [import_react_native3.StyleSheet.absoluteFill, { backgroundColor: "rgba(20,20,20,0.55)" }] }));
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
// src/ProjectSheet.tsx
|
|
363
374
|
function ProjectSheet({ snapPoints = ["35%", "85%"], renderHeader, children }) {
|
|
364
375
|
const { project, activeLineId, isAddNoteOpen } = useRetorBridge();
|
|
365
|
-
const sheetRef = (0,
|
|
366
|
-
const snapPointsArr = (0,
|
|
367
|
-
const [minimized, setMinimized] = (0,
|
|
368
|
-
(0,
|
|
376
|
+
const sheetRef = (0, import_react5.useRef)(null);
|
|
377
|
+
const snapPointsArr = (0, import_react5.useMemo)(() => snapPoints, [snapPoints]);
|
|
378
|
+
const [minimized, setMinimized] = (0, import_react5.useState)(false);
|
|
379
|
+
(0, import_react5.useEffect)(() => {
|
|
369
380
|
if (activeLineId || isAddNoteOpen) {
|
|
370
381
|
sheetRef.current?.dismiss();
|
|
371
382
|
} else {
|
|
@@ -383,7 +394,7 @@ function ProjectSheet({ snapPoints = ["35%", "85%"], renderHeader, children }) {
|
|
|
383
394
|
sheetRef.current?.snapToIndex(0);
|
|
384
395
|
}
|
|
385
396
|
};
|
|
386
|
-
return /* @__PURE__ */
|
|
397
|
+
return /* @__PURE__ */ import_react5.default.createElement(
|
|
387
398
|
import_bottom_sheet2.BottomSheetModal,
|
|
388
399
|
{
|
|
389
400
|
ref: sheetRef,
|
|
@@ -391,7 +402,7 @@ function ProjectSheet({ snapPoints = ["35%", "85%"], renderHeader, children }) {
|
|
|
391
402
|
enablePanDownToClose: false,
|
|
392
403
|
enableDismissOnClose: false,
|
|
393
404
|
onChange: handleSheetChange,
|
|
394
|
-
backdropComponent: (props) => /* @__PURE__ */
|
|
405
|
+
backdropComponent: (props) => /* @__PURE__ */ import_react5.default.createElement(
|
|
395
406
|
import_bottom_sheet2.BottomSheetBackdrop,
|
|
396
407
|
{
|
|
397
408
|
...props,
|
|
@@ -402,41 +413,40 @@ function ProjectSheet({ snapPoints = ["35%", "85%"], renderHeader, children }) {
|
|
|
402
413
|
}
|
|
403
414
|
),
|
|
404
415
|
handleIndicatorStyle: styles2.handle,
|
|
405
|
-
|
|
416
|
+
backgroundComponent: BlurBackground
|
|
406
417
|
},
|
|
407
|
-
/* @__PURE__ */
|
|
418
|
+
/* @__PURE__ */ import_react5.default.createElement(import_bottom_sheet2.BottomSheetView, { style: styles2.content }, renderHeader ? renderHeader({ name: project?.name, description: project?.description }) : /* @__PURE__ */ import_react5.default.createElement(import_react_native4.View, { style: styles2.header }, /* @__PURE__ */ import_react5.default.createElement(import_react_native4.View, { style: { flex: 1, minWidth: 0 } }, project?.name && /* @__PURE__ */ import_react5.default.createElement(import_react_native4.Text, { style: styles2.title, numberOfLines: 1 }, project.name), project?.description && /* @__PURE__ */ import_react5.default.createElement(import_react_native4.Text, { style: styles2.subtitle, numberOfLines: 4 }, project.description)), /* @__PURE__ */ import_react5.default.createElement(import_react_native4.Pressable, { style: styles2.iconBtn, onPress: toggleMinimize }, minimized ? /* @__PURE__ */ import_react5.default.createElement(import_lucide_react_native.ArrowUp, { size: 14, color: "rgba(255,255,255,0.6)" }) : /* @__PURE__ */ import_react5.default.createElement(import_lucide_react_native.ArrowDown, { size: 14, color: "rgba(255,255,255,0.6)" }))), children ?? /* @__PURE__ */ import_react5.default.createElement(DefaultLinesCarousel, null))
|
|
408
419
|
);
|
|
409
420
|
}
|
|
410
421
|
function DefaultLinesCarousel() {
|
|
411
|
-
return /* @__PURE__ */
|
|
422
|
+
return /* @__PURE__ */ import_react5.default.createElement(LinesCarousel, null, (line) => /* @__PURE__ */ import_react5.default.createElement(DefaultLineCard, { line }));
|
|
412
423
|
}
|
|
413
424
|
function LinesCarousel({ children, gap = 12, paddingHorizontal = 16 }) {
|
|
414
425
|
const { lines } = useRetorBridge();
|
|
415
426
|
if (lines.length === 0) return null;
|
|
416
|
-
return /* @__PURE__ */
|
|
417
|
-
|
|
427
|
+
return /* @__PURE__ */ import_react5.default.createElement(import_react_native4.View, { style: styles2.carouselWrap }, /* @__PURE__ */ import_react5.default.createElement(import_react_native4.Text, { style: styles2.carouselLabel }, "Routes"), /* @__PURE__ */ import_react5.default.createElement(
|
|
428
|
+
import_react_native4.ScrollView,
|
|
418
429
|
{
|
|
419
430
|
horizontal: true,
|
|
420
431
|
showsHorizontalScrollIndicator: false,
|
|
421
432
|
contentContainerStyle: { paddingHorizontal, gap }
|
|
422
433
|
},
|
|
423
|
-
lines.map((line, idx) => /* @__PURE__ */
|
|
434
|
+
lines.map((line, idx) => /* @__PURE__ */ import_react5.default.createElement(import_react5.default.Fragment, { key: line._id }, children(line, idx)))
|
|
424
435
|
));
|
|
425
436
|
}
|
|
426
437
|
function DefaultLineCard({ line }) {
|
|
427
438
|
const { controls } = useRetorBridge();
|
|
428
|
-
return /* @__PURE__ */
|
|
429
|
-
|
|
439
|
+
return /* @__PURE__ */ import_react5.default.createElement(
|
|
440
|
+
import_react_native4.Pressable,
|
|
430
441
|
{
|
|
431
442
|
onPress: () => controls.openLine(line._id),
|
|
432
443
|
style: styles2.lineCard
|
|
433
444
|
},
|
|
434
|
-
/* @__PURE__ */
|
|
435
|
-
line.subtitle && /* @__PURE__ */
|
|
445
|
+
/* @__PURE__ */ import_react5.default.createElement(import_react_native4.Text, { style: styles2.lineCardTitle, numberOfLines: 1 }, line.name || "Line"),
|
|
446
|
+
line.subtitle && /* @__PURE__ */ import_react5.default.createElement(import_react_native4.Text, { style: styles2.lineCardSubtitle, numberOfLines: 2 }, line.subtitle)
|
|
436
447
|
);
|
|
437
448
|
}
|
|
438
|
-
var styles2 =
|
|
439
|
-
background: { backgroundColor: "rgba(20,20,20,0.95)" },
|
|
449
|
+
var styles2 = import_react_native4.StyleSheet.create({
|
|
440
450
|
handle: { backgroundColor: "rgba(255,255,255,0.3)" },
|
|
441
451
|
content: { flex: 1, paddingTop: 12, paddingBottom: 24 },
|
|
442
452
|
header: {
|
|
@@ -477,17 +487,17 @@ var styles2 = import_react_native3.StyleSheet.create({
|
|
|
477
487
|
});
|
|
478
488
|
|
|
479
489
|
// src/LineDetailSheet.tsx
|
|
480
|
-
var
|
|
481
|
-
var
|
|
490
|
+
var import_react6 = __toESM(require("react"));
|
|
491
|
+
var import_react_native5 = require("react-native");
|
|
482
492
|
var import_bottom_sheet3 = require("@gorhom/bottom-sheet");
|
|
483
493
|
var import_react_native_svg = __toESM(require("react-native-svg"));
|
|
484
494
|
var import_lucide_react_native2 = require("lucide-react-native");
|
|
485
495
|
function LineDetailSheet({ snapPoints = ["35%", "85%"], renderHeader, children }) {
|
|
486
496
|
const { activeLine, isAddNoteOpen, controls } = useRetorBridge();
|
|
487
|
-
const sheetRef = (0,
|
|
488
|
-
const snapPointsArr = (0,
|
|
489
|
-
const [minimized, setMinimized] = (0,
|
|
490
|
-
(0,
|
|
497
|
+
const sheetRef = (0, import_react6.useRef)(null);
|
|
498
|
+
const snapPointsArr = (0, import_react6.useMemo)(() => snapPoints, [snapPoints]);
|
|
499
|
+
const [minimized, setMinimized] = (0, import_react6.useState)(false);
|
|
500
|
+
(0, import_react6.useEffect)(() => {
|
|
491
501
|
if (activeLine && !isAddNoteOpen) {
|
|
492
502
|
sheetRef.current?.present();
|
|
493
503
|
setMinimized(false);
|
|
@@ -505,7 +515,12 @@ function LineDetailSheet({ snapPoints = ["35%", "85%"], renderHeader, children }
|
|
|
505
515
|
sheetRef.current?.snapToIndex(0);
|
|
506
516
|
}
|
|
507
517
|
};
|
|
508
|
-
|
|
518
|
+
const renderFooter = (0, import_react6.useCallback)(
|
|
519
|
+
(props) => /* @__PURE__ */ import_react6.default.createElement(import_bottom_sheet3.BottomSheetFooter, { ...props, bottomInset: 0 }, /* @__PURE__ */ import_react6.default.createElement(import_react_native5.View, { style: styles3.footer }, /* @__PURE__ */ import_react6.default.createElement(import_react_native5.Pressable, { style: styles3.doneButton, onPress: () => controls.exitLine() }, /* @__PURE__ */ import_react6.default.createElement(import_react_native5.Text, { style: styles3.doneText }, "Done")))),
|
|
520
|
+
[controls]
|
|
521
|
+
);
|
|
522
|
+
const header = activeLine ? renderHeader ? renderHeader(activeLine) : /* @__PURE__ */ import_react6.default.createElement(DefaultHeader, { line: activeLine, minimized, onToggleMinimize: toggleMinimize }) : null;
|
|
523
|
+
return /* @__PURE__ */ import_react6.default.createElement(
|
|
509
524
|
import_bottom_sheet3.BottomSheetModal,
|
|
510
525
|
{
|
|
511
526
|
ref: sheetRef,
|
|
@@ -513,7 +528,8 @@ function LineDetailSheet({ snapPoints = ["35%", "85%"], renderHeader, children }
|
|
|
513
528
|
enablePanDownToClose: false,
|
|
514
529
|
enableDismissOnClose: false,
|
|
515
530
|
onChange: handleSheetChange,
|
|
516
|
-
|
|
531
|
+
footerComponent: renderFooter,
|
|
532
|
+
backdropComponent: (props) => /* @__PURE__ */ import_react6.default.createElement(
|
|
517
533
|
import_bottom_sheet3.BottomSheetBackdrop,
|
|
518
534
|
{
|
|
519
535
|
...props,
|
|
@@ -524,16 +540,9 @@ function LineDetailSheet({ snapPoints = ["35%", "85%"], renderHeader, children }
|
|
|
524
540
|
}
|
|
525
541
|
),
|
|
526
542
|
handleIndicatorStyle: styles3.handle,
|
|
527
|
-
|
|
543
|
+
backgroundComponent: BlurBackground
|
|
528
544
|
},
|
|
529
|
-
activeLine && /* @__PURE__ */
|
|
530
|
-
DefaultHeader,
|
|
531
|
-
{
|
|
532
|
-
line: activeLine,
|
|
533
|
-
minimized,
|
|
534
|
-
onToggleMinimize: toggleMinimize
|
|
535
|
-
}
|
|
536
|
-
), /* @__PURE__ */ import_react5.default.createElement(import_react_native4.View, { style: styles3.listContainer }, children ?? /* @__PURE__ */ import_react5.default.createElement(DefaultLineTagList, null)), /* @__PURE__ */ import_react5.default.createElement(import_react_native4.View, { style: styles3.footer }, /* @__PURE__ */ import_react5.default.createElement(import_react_native4.Pressable, { style: styles3.doneButton, onPress: () => controls.exitLine() }, /* @__PURE__ */ import_react5.default.createElement(import_react_native4.Text, { style: styles3.doneText }, "Done"))))
|
|
545
|
+
activeLine && (children ?? /* @__PURE__ */ import_react6.default.createElement(DefaultLineTagList, { listHeader: header }))
|
|
537
546
|
);
|
|
538
547
|
}
|
|
539
548
|
function DefaultHeader({
|
|
@@ -541,13 +550,13 @@ function DefaultHeader({
|
|
|
541
550
|
minimized,
|
|
542
551
|
onToggleMinimize
|
|
543
552
|
}) {
|
|
544
|
-
return /* @__PURE__ */
|
|
553
|
+
return /* @__PURE__ */ import_react6.default.createElement(import_react_native5.View, { style: styles3.header }, /* @__PURE__ */ import_react6.default.createElement(import_react_native5.View, { style: { flex: 1, minWidth: 0 } }, /* @__PURE__ */ import_react6.default.createElement(import_react_native5.Text, { style: styles3.title, numberOfLines: 1 }, line.name), line.subtitle && /* @__PURE__ */ import_react6.default.createElement(import_react_native5.Text, { style: styles3.subtitle, numberOfLines: 1 }, line.subtitle), line.description && /* @__PURE__ */ import_react6.default.createElement(import_react_native5.Text, { style: styles3.description, numberOfLines: minimized ? 2 : 4 }, line.description)), /* @__PURE__ */ import_react6.default.createElement(import_react_native5.View, { style: styles3.headerActions }, /* @__PURE__ */ import_react6.default.createElement(AutoplayButton, null), /* @__PURE__ */ import_react6.default.createElement(import_react_native5.Pressable, { style: styles3.iconBtn, onPress: onToggleMinimize }, minimized ? /* @__PURE__ */ import_react6.default.createElement(import_lucide_react_native2.ArrowUp, { size: 14, color: "rgba(255,255,255,0.6)" }) : /* @__PURE__ */ import_react6.default.createElement(import_lucide_react_native2.ArrowDown, { size: 14, color: "rgba(255,255,255,0.6)" }))));
|
|
545
554
|
}
|
|
546
555
|
function AutoplayButton() {
|
|
547
556
|
const { isPlaying, progress, controls } = useRetorBridge();
|
|
548
557
|
const r = 12.5;
|
|
549
558
|
const c = 2 * Math.PI * r;
|
|
550
|
-
return /* @__PURE__ */
|
|
559
|
+
return /* @__PURE__ */ import_react6.default.createElement(import_react_native5.Pressable, { style: styles3.iconBtn, onPress: () => controls.toggleAutoplay() }, /* @__PURE__ */ import_react6.default.createElement(import_react_native_svg.default, { width: 28, height: 28, style: import_react_native5.StyleSheet.absoluteFill }, /* @__PURE__ */ import_react6.default.createElement(
|
|
551
560
|
import_react_native_svg.Circle,
|
|
552
561
|
{
|
|
553
562
|
cx: 14,
|
|
@@ -561,59 +570,66 @@ function AutoplayButton() {
|
|
|
561
570
|
strokeLinecap: "round",
|
|
562
571
|
transform: "rotate(-90, 14, 14)"
|
|
563
572
|
}
|
|
564
|
-
)), isPlaying ? /* @__PURE__ */
|
|
573
|
+
)), isPlaying ? /* @__PURE__ */ import_react6.default.createElement(import_lucide_react_native2.Pause, { size: 11, color: "white", fill: "white" }) : /* @__PURE__ */ import_react6.default.createElement(import_lucide_react_native2.Play, { size: 11, color: "white", fill: "white", style: { marginLeft: 1 } }));
|
|
565
574
|
}
|
|
566
|
-
function LineTagList({ children }) {
|
|
575
|
+
function LineTagList({ children, listHeader }) {
|
|
567
576
|
const { activeLine, closestTagId } = useRetorBridge();
|
|
568
|
-
const listRef = (0,
|
|
569
|
-
const tags = (0,
|
|
577
|
+
const listRef = (0, import_react6.useRef)(null);
|
|
578
|
+
const tags = (0, import_react6.useMemo)(
|
|
570
579
|
() => (activeLine?.tags ?? []).filter((t) => t.name && t.name.trim().length > 0),
|
|
571
580
|
[activeLine]
|
|
572
581
|
);
|
|
573
|
-
(0,
|
|
582
|
+
(0, import_react6.useEffect)(() => {
|
|
574
583
|
if (!closestTagId) return;
|
|
575
|
-
const index = tags.findIndex((
|
|
584
|
+
const index = tags.findIndex((t2) => t2._id === closestTagId);
|
|
576
585
|
if (index < 0) return;
|
|
577
|
-
|
|
586
|
+
const t = setTimeout(() => {
|
|
578
587
|
try {
|
|
579
588
|
listRef.current?.scrollToIndex({ index, animated: true, viewPosition: 0 });
|
|
580
589
|
} catch {
|
|
581
590
|
}
|
|
582
|
-
});
|
|
591
|
+
}, 50);
|
|
592
|
+
return () => clearTimeout(t);
|
|
583
593
|
}, [closestTagId, tags]);
|
|
584
594
|
if (!activeLine) return null;
|
|
585
|
-
return /* @__PURE__ */
|
|
595
|
+
return /* @__PURE__ */ import_react6.default.createElement(
|
|
586
596
|
import_bottom_sheet3.BottomSheetFlatList,
|
|
587
597
|
{
|
|
588
598
|
ref: listRef,
|
|
589
599
|
data: tags,
|
|
590
600
|
keyExtractor: (t) => t._id,
|
|
591
|
-
|
|
601
|
+
ListHeaderComponent: listHeader ? () => /* @__PURE__ */ import_react6.default.createElement(import_react6.default.Fragment, null, listHeader) : void 0,
|
|
602
|
+
renderItem: ({ item }) => /* @__PURE__ */ import_react6.default.createElement(import_react_native5.View, null, children(item, item._id === closestTagId)),
|
|
592
603
|
contentContainerStyle: styles3.list,
|
|
604
|
+
removeClippedSubviews: false,
|
|
593
605
|
onScrollToIndexFailed: (info) => {
|
|
606
|
+
const offset = info.averageItemLength * info.index;
|
|
607
|
+
listRef.current?.scrollToOffset({ offset, animated: false });
|
|
594
608
|
setTimeout(() => {
|
|
595
|
-
|
|
609
|
+
try {
|
|
610
|
+
listRef.current?.scrollToIndex({ index: info.index, animated: true, viewPosition: 0 });
|
|
611
|
+
} catch {
|
|
612
|
+
}
|
|
596
613
|
}, 100);
|
|
597
614
|
}
|
|
598
615
|
}
|
|
599
616
|
);
|
|
600
617
|
}
|
|
601
|
-
function DefaultLineTagList() {
|
|
602
|
-
return /* @__PURE__ */
|
|
618
|
+
function DefaultLineTagList({ listHeader }) {
|
|
619
|
+
return /* @__PURE__ */ import_react6.default.createElement(LineTagList, { listHeader }, (tag, isActive) => /* @__PURE__ */ import_react6.default.createElement(DefaultTagItem, { tag, isActive }));
|
|
603
620
|
}
|
|
604
621
|
function DefaultTagItem({ tag, isActive }) {
|
|
605
|
-
const { controls, openAddNote
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
import_react_native4.Pressable,
|
|
622
|
+
const { controls, openAddNote } = useRetorBridge();
|
|
623
|
+
return /* @__PURE__ */ import_react6.default.createElement(
|
|
624
|
+
import_react_native5.Pressable,
|
|
609
625
|
{
|
|
610
626
|
onPress: () => controls.scrollToTag(tag._id),
|
|
611
627
|
style: [styles3.tagItem, isActive && styles3.tagItemActive]
|
|
612
628
|
},
|
|
613
|
-
/* @__PURE__ */
|
|
614
|
-
tag.subtitle && /* @__PURE__ */
|
|
615
|
-
|
|
616
|
-
|
|
629
|
+
/* @__PURE__ */ import_react6.default.createElement(import_react_native5.View, { style: { flex: 1, minWidth: 0 } }, /* @__PURE__ */ import_react6.default.createElement(import_react_native5.Text, { style: [styles3.tagText, isActive && styles3.tagTextActive], numberOfLines: 1 }, tag.name), isActive && tag.description && /* @__PURE__ */ import_react6.default.createElement(import_react_native5.Text, { style: styles3.tagDescription, numberOfLines: 2 }, tag.description)),
|
|
630
|
+
tag.subtitle && /* @__PURE__ */ import_react6.default.createElement(import_react_native5.Text, { style: styles3.tagSubtitle, numberOfLines: 1 }, tag.subtitle),
|
|
631
|
+
isActive && /* @__PURE__ */ import_react6.default.createElement(
|
|
632
|
+
import_react_native5.Pressable,
|
|
617
633
|
{
|
|
618
634
|
onPress: (e) => {
|
|
619
635
|
e.stopPropagation();
|
|
@@ -621,20 +637,18 @@ function DefaultTagItem({ tag, isActive }) {
|
|
|
621
637
|
},
|
|
622
638
|
style: styles3.plusBtn
|
|
623
639
|
},
|
|
624
|
-
/* @__PURE__ */
|
|
640
|
+
/* @__PURE__ */ import_react6.default.createElement(import_lucide_react_native2.Plus, { size: 14, color: "white" })
|
|
625
641
|
)
|
|
626
642
|
);
|
|
627
643
|
}
|
|
628
|
-
var styles3 =
|
|
629
|
-
background: { backgroundColor: "rgba(20,20,20,0.95)" },
|
|
644
|
+
var styles3 = import_react_native5.StyleSheet.create({
|
|
630
645
|
handle: { backgroundColor: "rgba(255,255,255,0.3)" },
|
|
631
|
-
root: { flex: 1 },
|
|
632
646
|
header: {
|
|
633
647
|
flexDirection: "row",
|
|
634
648
|
alignItems: "flex-start",
|
|
635
649
|
paddingHorizontal: 24,
|
|
636
650
|
paddingTop: 8,
|
|
637
|
-
paddingBottom:
|
|
651
|
+
paddingBottom: 16,
|
|
638
652
|
gap: 8
|
|
639
653
|
},
|
|
640
654
|
headerActions: { flexDirection: "row", alignItems: "center", gap: 6 },
|
|
@@ -650,8 +664,7 @@ var styles3 = import_react_native4.StyleSheet.create({
|
|
|
650
664
|
justifyContent: "center",
|
|
651
665
|
position: "relative"
|
|
652
666
|
},
|
|
653
|
-
|
|
654
|
-
list: { paddingHorizontal: 16, paddingBottom: 8, gap: 4 },
|
|
667
|
+
list: { paddingHorizontal: 16, paddingBottom: 96, gap: 4 },
|
|
655
668
|
tagItem: {
|
|
656
669
|
flexDirection: "row",
|
|
657
670
|
alignItems: "center",
|
|
@@ -666,14 +679,19 @@ var styles3 = import_react_native4.StyleSheet.create({
|
|
|
666
679
|
tagDescription: { color: "rgba(255,255,255,0.4)", fontSize: 11, marginTop: 2, lineHeight: 14 },
|
|
667
680
|
tagSubtitle: { color: "rgba(255,255,255,0.4)", fontSize: 10 },
|
|
668
681
|
plusBtn: {
|
|
669
|
-
width:
|
|
670
|
-
height:
|
|
671
|
-
borderRadius:
|
|
672
|
-
backgroundColor: "rgba(255,255,255,0.
|
|
682
|
+
width: 24,
|
|
683
|
+
height: 24,
|
|
684
|
+
borderRadius: 12,
|
|
685
|
+
backgroundColor: "rgba(255,255,255,0.2)",
|
|
673
686
|
alignItems: "center",
|
|
674
687
|
justifyContent: "center"
|
|
675
688
|
},
|
|
676
|
-
footer: {
|
|
689
|
+
footer: {
|
|
690
|
+
paddingHorizontal: 16,
|
|
691
|
+
paddingBottom: 24,
|
|
692
|
+
paddingTop: 8,
|
|
693
|
+
backgroundColor: "transparent"
|
|
694
|
+
},
|
|
677
695
|
doneButton: {
|
|
678
696
|
backgroundColor: "white",
|
|
679
697
|
borderRadius: 14,
|
|
@@ -684,8 +702,8 @@ var styles3 = import_react_native4.StyleSheet.create({
|
|
|
684
702
|
});
|
|
685
703
|
|
|
686
704
|
// src/AddNoteSheet.tsx
|
|
687
|
-
var
|
|
688
|
-
var
|
|
705
|
+
var import_react7 = __toESM(require("react"));
|
|
706
|
+
var import_react_native6 = require("react-native");
|
|
689
707
|
var import_bottom_sheet4 = require("@gorhom/bottom-sheet");
|
|
690
708
|
var import_lucide_react_native3 = require("lucide-react-native");
|
|
691
709
|
function AddNoteSheet({
|
|
@@ -695,11 +713,11 @@ function AddNoteSheet({
|
|
|
695
713
|
renderForm
|
|
696
714
|
}) {
|
|
697
715
|
const { isAddNoteOpen, addNoteTagId, activeLine, closeAddNote, submitNote } = useRetorBridge();
|
|
698
|
-
const sheetRef = (0,
|
|
699
|
-
const snapPointsArr = (0,
|
|
700
|
-
const [text, setText] = (0,
|
|
701
|
-
const [isPrivate, setPrivate] = (0,
|
|
702
|
-
(0,
|
|
716
|
+
const sheetRef = (0, import_react7.useRef)(null);
|
|
717
|
+
const snapPointsArr = (0, import_react7.useMemo)(() => snapPoints, [snapPoints]);
|
|
718
|
+
const [text, setText] = (0, import_react7.useState)("");
|
|
719
|
+
const [isPrivate, setPrivate] = (0, import_react7.useState)(true);
|
|
720
|
+
(0, import_react7.useEffect)(() => {
|
|
703
721
|
if (isAddNoteOpen) {
|
|
704
722
|
sheetRef.current?.present();
|
|
705
723
|
setText("");
|
|
@@ -708,7 +726,7 @@ function AddNoteSheet({
|
|
|
708
726
|
sheetRef.current?.dismiss();
|
|
709
727
|
}
|
|
710
728
|
}, [isAddNoteOpen]);
|
|
711
|
-
const tag = (0,
|
|
729
|
+
const tag = (0, import_react7.useMemo)(
|
|
712
730
|
() => activeLine?.tags.find((t) => t._id === addNoteTagId) ?? null,
|
|
713
731
|
[activeLine, addNoteTagId]
|
|
714
732
|
);
|
|
@@ -728,14 +746,14 @@ function AddNoteSheet({
|
|
|
728
746
|
close: closeAddNote,
|
|
729
747
|
maxLength
|
|
730
748
|
};
|
|
731
|
-
return /* @__PURE__ */
|
|
749
|
+
return /* @__PURE__ */ import_react7.default.createElement(
|
|
732
750
|
import_bottom_sheet4.BottomSheetModal,
|
|
733
751
|
{
|
|
734
752
|
ref: sheetRef,
|
|
735
753
|
snapPoints: snapPointsArr,
|
|
736
754
|
enablePanDownToClose: true,
|
|
737
755
|
onDismiss: closeAddNote,
|
|
738
|
-
backdropComponent: (props) => /* @__PURE__ */
|
|
756
|
+
backdropComponent: (props) => /* @__PURE__ */ import_react7.default.createElement(
|
|
739
757
|
import_bottom_sheet4.BottomSheetBackdrop,
|
|
740
758
|
{
|
|
741
759
|
...props,
|
|
@@ -745,9 +763,9 @@ function AddNoteSheet({
|
|
|
745
763
|
}
|
|
746
764
|
),
|
|
747
765
|
handleIndicatorStyle: styles4.handle,
|
|
748
|
-
|
|
766
|
+
backgroundComponent: BlurBackground
|
|
749
767
|
},
|
|
750
|
-
/* @__PURE__ */
|
|
768
|
+
/* @__PURE__ */ import_react7.default.createElement(import_bottom_sheet4.BottomSheetView, { style: styles4.content }, renderForm ? renderForm(formApi) : /* @__PURE__ */ import_react7.default.createElement(import_react_native6.View, { style: styles4.form }, /* @__PURE__ */ import_react7.default.createElement(import_react_native6.View, { style: styles4.headerRow }, /* @__PURE__ */ import_react7.default.createElement(import_react_native6.View, { style: { flex: 1 } }, activeLine && /* @__PURE__ */ import_react7.default.createElement(import_react_native6.Text, { style: styles4.title, numberOfLines: 1 }, activeLine.name), tag && /* @__PURE__ */ import_react7.default.createElement(import_react_native6.Text, { style: styles4.subtitle, numberOfLines: 1 }, tag.name)), /* @__PURE__ */ import_react7.default.createElement(import_react_native6.Pressable, { onPress: closeAddNote, style: styles4.closeBtn }, /* @__PURE__ */ import_react7.default.createElement(import_lucide_react_native3.X, { size: 14, color: "rgba(255,255,255,0.6)" }))), /* @__PURE__ */ import_react7.default.createElement(
|
|
751
769
|
import_bottom_sheet4.BottomSheetTextInput,
|
|
752
770
|
{
|
|
753
771
|
value: text,
|
|
@@ -760,26 +778,25 @@ function AddNoteSheet({
|
|
|
760
778
|
style: styles4.input,
|
|
761
779
|
autoFocus: true
|
|
762
780
|
}
|
|
763
|
-
), /* @__PURE__ */
|
|
764
|
-
|
|
781
|
+
), /* @__PURE__ */ import_react7.default.createElement(import_react_native6.View, { style: styles4.footer }, /* @__PURE__ */ import_react7.default.createElement(import_react_native6.Text, { style: [styles4.counter, text.length > maxLength * 0.9 && { color: "#fbbf24" }] }, text.length, "/", maxLength), /* @__PURE__ */ import_react7.default.createElement(import_react_native6.View, { style: { flex: 1 } }), /* @__PURE__ */ import_react7.default.createElement(
|
|
782
|
+
import_react_native6.Pressable,
|
|
765
783
|
{
|
|
766
784
|
onPress: () => setPrivate(!isPrivate),
|
|
767
785
|
style: [styles4.pill, !isPrivate && styles4.pillActive]
|
|
768
786
|
},
|
|
769
|
-
/* @__PURE__ */
|
|
770
|
-
), /* @__PURE__ */
|
|
771
|
-
|
|
787
|
+
/* @__PURE__ */ import_react7.default.createElement(import_react_native6.Text, { style: [styles4.pillText, !isPrivate && styles4.pillTextActive] }, isPrivate ? "Private" : "Public")
|
|
788
|
+
), /* @__PURE__ */ import_react7.default.createElement(
|
|
789
|
+
import_react_native6.Pressable,
|
|
772
790
|
{
|
|
773
791
|
onPress: handleSubmit,
|
|
774
792
|
disabled: !text.trim(),
|
|
775
793
|
style: [styles4.submit, !text.trim() && styles4.submitDisabled]
|
|
776
794
|
},
|
|
777
|
-
/* @__PURE__ */
|
|
795
|
+
/* @__PURE__ */ import_react7.default.createElement(import_lucide_react_native3.ArrowUp, { size: 16, color: "black", strokeWidth: 2.5 })
|
|
778
796
|
))))
|
|
779
797
|
);
|
|
780
798
|
}
|
|
781
|
-
var styles4 =
|
|
782
|
-
background: { backgroundColor: "rgba(20,20,20,0.98)" },
|
|
799
|
+
var styles4 = import_react_native6.StyleSheet.create({
|
|
783
800
|
handle: { backgroundColor: "rgba(255,255,255,0.3)" },
|
|
784
801
|
content: { flex: 1, padding: 24 },
|
|
785
802
|
form: { flex: 1 },
|
|
@@ -831,11 +848,11 @@ var styles4 = import_react_native5.StyleSheet.create({
|
|
|
831
848
|
});
|
|
832
849
|
|
|
833
850
|
// src/CoverPhoto.tsx
|
|
834
|
-
var
|
|
851
|
+
var import_react8 = __toESM(require("react"));
|
|
835
852
|
var import_react_native_webview2 = require("react-native-webview");
|
|
836
853
|
function CoverPhoto({ projectId, baseUrl = "https://retor.app", style }) {
|
|
837
854
|
const uri = `${baseUrl}/p/${projectId}?cover=true`;
|
|
838
|
-
return /* @__PURE__ */
|
|
855
|
+
return /* @__PURE__ */ import_react8.default.createElement(
|
|
839
856
|
import_react_native_webview2.WebView,
|
|
840
857
|
{
|
|
841
858
|
source: { uri },
|
|
@@ -850,6 +867,7 @@ function CoverPhoto({ projectId, baseUrl = "https://retor.app", style }) {
|
|
|
850
867
|
// Annotate the CommonJS export names for ESM import in node:
|
|
851
868
|
0 && (module.exports = {
|
|
852
869
|
AddNoteSheet,
|
|
870
|
+
BlurBackground,
|
|
853
871
|
CoverPhoto,
|
|
854
872
|
Hud,
|
|
855
873
|
LineDetailSheet,
|
package/dist/index.mjs
CHANGED
|
@@ -313,10 +313,20 @@ function Hud({ children }) {
|
|
|
313
313
|
}
|
|
314
314
|
|
|
315
315
|
// src/ProjectSheet.tsx
|
|
316
|
-
import
|
|
317
|
-
import { Pressable, ScrollView, StyleSheet as
|
|
316
|
+
import React5, { useEffect as useEffect2, useMemo as useMemo3, useRef as useRef2, useState as useState2 } from "react";
|
|
317
|
+
import { Pressable, ScrollView, StyleSheet as StyleSheet4, Text, View as View4 } from "react-native";
|
|
318
318
|
import { BottomSheetBackdrop, BottomSheetModal, BottomSheetView } from "@gorhom/bottom-sheet";
|
|
319
319
|
import { ArrowDown, ArrowUp } from "lucide-react-native";
|
|
320
|
+
|
|
321
|
+
// src/BlurBackground.tsx
|
|
322
|
+
import React4 from "react";
|
|
323
|
+
import { StyleSheet as StyleSheet3, View as View3 } from "react-native";
|
|
324
|
+
import { BlurView } from "expo-blur";
|
|
325
|
+
function BlurBackground({ style }) {
|
|
326
|
+
return /* @__PURE__ */ React4.createElement(View3, { style: [style, StyleSheet3.absoluteFill, { overflow: "hidden", borderTopLeftRadius: 24, borderTopRightRadius: 24 }] }, /* @__PURE__ */ React4.createElement(BlurView, { intensity: 60, tint: "dark", style: StyleSheet3.absoluteFill }), /* @__PURE__ */ React4.createElement(View3, { style: [StyleSheet3.absoluteFill, { backgroundColor: "rgba(20,20,20,0.55)" }] }));
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
// src/ProjectSheet.tsx
|
|
320
330
|
function ProjectSheet({ snapPoints = ["35%", "85%"], renderHeader, children }) {
|
|
321
331
|
const { project, activeLineId, isAddNoteOpen } = useRetorBridge();
|
|
322
332
|
const sheetRef = useRef2(null);
|
|
@@ -340,7 +350,7 @@ function ProjectSheet({ snapPoints = ["35%", "85%"], renderHeader, children }) {
|
|
|
340
350
|
sheetRef.current?.snapToIndex(0);
|
|
341
351
|
}
|
|
342
352
|
};
|
|
343
|
-
return /* @__PURE__ */
|
|
353
|
+
return /* @__PURE__ */ React5.createElement(
|
|
344
354
|
BottomSheetModal,
|
|
345
355
|
{
|
|
346
356
|
ref: sheetRef,
|
|
@@ -348,7 +358,7 @@ function ProjectSheet({ snapPoints = ["35%", "85%"], renderHeader, children }) {
|
|
|
348
358
|
enablePanDownToClose: false,
|
|
349
359
|
enableDismissOnClose: false,
|
|
350
360
|
onChange: handleSheetChange,
|
|
351
|
-
backdropComponent: (props) => /* @__PURE__ */
|
|
361
|
+
backdropComponent: (props) => /* @__PURE__ */ React5.createElement(
|
|
352
362
|
BottomSheetBackdrop,
|
|
353
363
|
{
|
|
354
364
|
...props,
|
|
@@ -359,41 +369,40 @@ function ProjectSheet({ snapPoints = ["35%", "85%"], renderHeader, children }) {
|
|
|
359
369
|
}
|
|
360
370
|
),
|
|
361
371
|
handleIndicatorStyle: styles2.handle,
|
|
362
|
-
|
|
372
|
+
backgroundComponent: BlurBackground
|
|
363
373
|
},
|
|
364
|
-
/* @__PURE__ */
|
|
374
|
+
/* @__PURE__ */ React5.createElement(BottomSheetView, { style: styles2.content }, renderHeader ? renderHeader({ name: project?.name, description: project?.description }) : /* @__PURE__ */ React5.createElement(View4, { style: styles2.header }, /* @__PURE__ */ React5.createElement(View4, { style: { flex: 1, minWidth: 0 } }, project?.name && /* @__PURE__ */ React5.createElement(Text, { style: styles2.title, numberOfLines: 1 }, project.name), project?.description && /* @__PURE__ */ React5.createElement(Text, { style: styles2.subtitle, numberOfLines: 4 }, project.description)), /* @__PURE__ */ React5.createElement(Pressable, { style: styles2.iconBtn, onPress: toggleMinimize }, minimized ? /* @__PURE__ */ React5.createElement(ArrowUp, { size: 14, color: "rgba(255,255,255,0.6)" }) : /* @__PURE__ */ React5.createElement(ArrowDown, { size: 14, color: "rgba(255,255,255,0.6)" }))), children ?? /* @__PURE__ */ React5.createElement(DefaultLinesCarousel, null))
|
|
365
375
|
);
|
|
366
376
|
}
|
|
367
377
|
function DefaultLinesCarousel() {
|
|
368
|
-
return /* @__PURE__ */
|
|
378
|
+
return /* @__PURE__ */ React5.createElement(LinesCarousel, null, (line) => /* @__PURE__ */ React5.createElement(DefaultLineCard, { line }));
|
|
369
379
|
}
|
|
370
380
|
function LinesCarousel({ children, gap = 12, paddingHorizontal = 16 }) {
|
|
371
381
|
const { lines } = useRetorBridge();
|
|
372
382
|
if (lines.length === 0) return null;
|
|
373
|
-
return /* @__PURE__ */
|
|
383
|
+
return /* @__PURE__ */ React5.createElement(View4, { style: styles2.carouselWrap }, /* @__PURE__ */ React5.createElement(Text, { style: styles2.carouselLabel }, "Routes"), /* @__PURE__ */ React5.createElement(
|
|
374
384
|
ScrollView,
|
|
375
385
|
{
|
|
376
386
|
horizontal: true,
|
|
377
387
|
showsHorizontalScrollIndicator: false,
|
|
378
388
|
contentContainerStyle: { paddingHorizontal, gap }
|
|
379
389
|
},
|
|
380
|
-
lines.map((line, idx) => /* @__PURE__ */
|
|
390
|
+
lines.map((line, idx) => /* @__PURE__ */ React5.createElement(React5.Fragment, { key: line._id }, children(line, idx)))
|
|
381
391
|
));
|
|
382
392
|
}
|
|
383
393
|
function DefaultLineCard({ line }) {
|
|
384
394
|
const { controls } = useRetorBridge();
|
|
385
|
-
return /* @__PURE__ */
|
|
395
|
+
return /* @__PURE__ */ React5.createElement(
|
|
386
396
|
Pressable,
|
|
387
397
|
{
|
|
388
398
|
onPress: () => controls.openLine(line._id),
|
|
389
399
|
style: styles2.lineCard
|
|
390
400
|
},
|
|
391
|
-
/* @__PURE__ */
|
|
392
|
-
line.subtitle && /* @__PURE__ */
|
|
401
|
+
/* @__PURE__ */ React5.createElement(Text, { style: styles2.lineCardTitle, numberOfLines: 1 }, line.name || "Line"),
|
|
402
|
+
line.subtitle && /* @__PURE__ */ React5.createElement(Text, { style: styles2.lineCardSubtitle, numberOfLines: 2 }, line.subtitle)
|
|
393
403
|
);
|
|
394
404
|
}
|
|
395
|
-
var styles2 =
|
|
396
|
-
background: { backgroundColor: "rgba(20,20,20,0.95)" },
|
|
405
|
+
var styles2 = StyleSheet4.create({
|
|
397
406
|
handle: { backgroundColor: "rgba(255,255,255,0.3)" },
|
|
398
407
|
content: { flex: 1, paddingTop: 12, paddingBottom: 24 },
|
|
399
408
|
header: {
|
|
@@ -434,9 +443,14 @@ var styles2 = StyleSheet3.create({
|
|
|
434
443
|
});
|
|
435
444
|
|
|
436
445
|
// src/LineDetailSheet.tsx
|
|
437
|
-
import
|
|
438
|
-
import { Pressable as Pressable2, StyleSheet as
|
|
439
|
-
import {
|
|
446
|
+
import React6, { useCallback as useCallback2, useEffect as useEffect3, useMemo as useMemo4, useRef as useRef3, useState as useState3 } from "react";
|
|
447
|
+
import { Pressable as Pressable2, StyleSheet as StyleSheet5, Text as Text2, View as View5 } from "react-native";
|
|
448
|
+
import {
|
|
449
|
+
BottomSheetBackdrop as BottomSheetBackdrop2,
|
|
450
|
+
BottomSheetFlatList,
|
|
451
|
+
BottomSheetFooter,
|
|
452
|
+
BottomSheetModal as BottomSheetModal2
|
|
453
|
+
} from "@gorhom/bottom-sheet";
|
|
440
454
|
import Svg, { Circle } from "react-native-svg";
|
|
441
455
|
import { ArrowDown as ArrowDown2, ArrowUp as ArrowUp2, Pause, Play, Plus } from "lucide-react-native";
|
|
442
456
|
function LineDetailSheet({ snapPoints = ["35%", "85%"], renderHeader, children }) {
|
|
@@ -462,7 +476,12 @@ function LineDetailSheet({ snapPoints = ["35%", "85%"], renderHeader, children }
|
|
|
462
476
|
sheetRef.current?.snapToIndex(0);
|
|
463
477
|
}
|
|
464
478
|
};
|
|
465
|
-
|
|
479
|
+
const renderFooter = useCallback2(
|
|
480
|
+
(props) => /* @__PURE__ */ React6.createElement(BottomSheetFooter, { ...props, bottomInset: 0 }, /* @__PURE__ */ React6.createElement(View5, { style: styles3.footer }, /* @__PURE__ */ React6.createElement(Pressable2, { style: styles3.doneButton, onPress: () => controls.exitLine() }, /* @__PURE__ */ React6.createElement(Text2, { style: styles3.doneText }, "Done")))),
|
|
481
|
+
[controls]
|
|
482
|
+
);
|
|
483
|
+
const header = activeLine ? renderHeader ? renderHeader(activeLine) : /* @__PURE__ */ React6.createElement(DefaultHeader, { line: activeLine, minimized, onToggleMinimize: toggleMinimize }) : null;
|
|
484
|
+
return /* @__PURE__ */ React6.createElement(
|
|
466
485
|
BottomSheetModal2,
|
|
467
486
|
{
|
|
468
487
|
ref: sheetRef,
|
|
@@ -470,7 +489,8 @@ function LineDetailSheet({ snapPoints = ["35%", "85%"], renderHeader, children }
|
|
|
470
489
|
enablePanDownToClose: false,
|
|
471
490
|
enableDismissOnClose: false,
|
|
472
491
|
onChange: handleSheetChange,
|
|
473
|
-
|
|
492
|
+
footerComponent: renderFooter,
|
|
493
|
+
backdropComponent: (props) => /* @__PURE__ */ React6.createElement(
|
|
474
494
|
BottomSheetBackdrop2,
|
|
475
495
|
{
|
|
476
496
|
...props,
|
|
@@ -481,16 +501,9 @@ function LineDetailSheet({ snapPoints = ["35%", "85%"], renderHeader, children }
|
|
|
481
501
|
}
|
|
482
502
|
),
|
|
483
503
|
handleIndicatorStyle: styles3.handle,
|
|
484
|
-
|
|
504
|
+
backgroundComponent: BlurBackground
|
|
485
505
|
},
|
|
486
|
-
activeLine && /* @__PURE__ */
|
|
487
|
-
DefaultHeader,
|
|
488
|
-
{
|
|
489
|
-
line: activeLine,
|
|
490
|
-
minimized,
|
|
491
|
-
onToggleMinimize: toggleMinimize
|
|
492
|
-
}
|
|
493
|
-
), /* @__PURE__ */ React5.createElement(View4, { style: styles3.listContainer }, children ?? /* @__PURE__ */ React5.createElement(DefaultLineTagList, null)), /* @__PURE__ */ React5.createElement(View4, { style: styles3.footer }, /* @__PURE__ */ React5.createElement(Pressable2, { style: styles3.doneButton, onPress: () => controls.exitLine() }, /* @__PURE__ */ React5.createElement(Text2, { style: styles3.doneText }, "Done"))))
|
|
506
|
+
activeLine && (children ?? /* @__PURE__ */ React6.createElement(DefaultLineTagList, { listHeader: header }))
|
|
494
507
|
);
|
|
495
508
|
}
|
|
496
509
|
function DefaultHeader({
|
|
@@ -498,13 +511,13 @@ function DefaultHeader({
|
|
|
498
511
|
minimized,
|
|
499
512
|
onToggleMinimize
|
|
500
513
|
}) {
|
|
501
|
-
return /* @__PURE__ */
|
|
514
|
+
return /* @__PURE__ */ React6.createElement(View5, { style: styles3.header }, /* @__PURE__ */ React6.createElement(View5, { style: { flex: 1, minWidth: 0 } }, /* @__PURE__ */ React6.createElement(Text2, { style: styles3.title, numberOfLines: 1 }, line.name), line.subtitle && /* @__PURE__ */ React6.createElement(Text2, { style: styles3.subtitle, numberOfLines: 1 }, line.subtitle), line.description && /* @__PURE__ */ React6.createElement(Text2, { style: styles3.description, numberOfLines: minimized ? 2 : 4 }, line.description)), /* @__PURE__ */ React6.createElement(View5, { style: styles3.headerActions }, /* @__PURE__ */ React6.createElement(AutoplayButton, null), /* @__PURE__ */ React6.createElement(Pressable2, { style: styles3.iconBtn, onPress: onToggleMinimize }, minimized ? /* @__PURE__ */ React6.createElement(ArrowUp2, { size: 14, color: "rgba(255,255,255,0.6)" }) : /* @__PURE__ */ React6.createElement(ArrowDown2, { size: 14, color: "rgba(255,255,255,0.6)" }))));
|
|
502
515
|
}
|
|
503
516
|
function AutoplayButton() {
|
|
504
517
|
const { isPlaying, progress, controls } = useRetorBridge();
|
|
505
518
|
const r = 12.5;
|
|
506
519
|
const c = 2 * Math.PI * r;
|
|
507
|
-
return /* @__PURE__ */
|
|
520
|
+
return /* @__PURE__ */ React6.createElement(Pressable2, { style: styles3.iconBtn, onPress: () => controls.toggleAutoplay() }, /* @__PURE__ */ React6.createElement(Svg, { width: 28, height: 28, style: StyleSheet5.absoluteFill }, /* @__PURE__ */ React6.createElement(
|
|
508
521
|
Circle,
|
|
509
522
|
{
|
|
510
523
|
cx: 14,
|
|
@@ -518,9 +531,9 @@ function AutoplayButton() {
|
|
|
518
531
|
strokeLinecap: "round",
|
|
519
532
|
transform: "rotate(-90, 14, 14)"
|
|
520
533
|
}
|
|
521
|
-
)), isPlaying ? /* @__PURE__ */
|
|
534
|
+
)), isPlaying ? /* @__PURE__ */ React6.createElement(Pause, { size: 11, color: "white", fill: "white" }) : /* @__PURE__ */ React6.createElement(Play, { size: 11, color: "white", fill: "white", style: { marginLeft: 1 } }));
|
|
522
535
|
}
|
|
523
|
-
function LineTagList({ children }) {
|
|
536
|
+
function LineTagList({ children, listHeader }) {
|
|
524
537
|
const { activeLine, closestTagId } = useRetorBridge();
|
|
525
538
|
const listRef = useRef3(null);
|
|
526
539
|
const tags = useMemo4(
|
|
@@ -529,47 +542,54 @@ function LineTagList({ children }) {
|
|
|
529
542
|
);
|
|
530
543
|
useEffect3(() => {
|
|
531
544
|
if (!closestTagId) return;
|
|
532
|
-
const index = tags.findIndex((
|
|
545
|
+
const index = tags.findIndex((t2) => t2._id === closestTagId);
|
|
533
546
|
if (index < 0) return;
|
|
534
|
-
|
|
547
|
+
const t = setTimeout(() => {
|
|
535
548
|
try {
|
|
536
549
|
listRef.current?.scrollToIndex({ index, animated: true, viewPosition: 0 });
|
|
537
550
|
} catch {
|
|
538
551
|
}
|
|
539
|
-
});
|
|
552
|
+
}, 50);
|
|
553
|
+
return () => clearTimeout(t);
|
|
540
554
|
}, [closestTagId, tags]);
|
|
541
555
|
if (!activeLine) return null;
|
|
542
|
-
return /* @__PURE__ */
|
|
556
|
+
return /* @__PURE__ */ React6.createElement(
|
|
543
557
|
BottomSheetFlatList,
|
|
544
558
|
{
|
|
545
559
|
ref: listRef,
|
|
546
560
|
data: tags,
|
|
547
561
|
keyExtractor: (t) => t._id,
|
|
548
|
-
|
|
562
|
+
ListHeaderComponent: listHeader ? () => /* @__PURE__ */ React6.createElement(React6.Fragment, null, listHeader) : void 0,
|
|
563
|
+
renderItem: ({ item }) => /* @__PURE__ */ React6.createElement(View5, null, children(item, item._id === closestTagId)),
|
|
549
564
|
contentContainerStyle: styles3.list,
|
|
565
|
+
removeClippedSubviews: false,
|
|
550
566
|
onScrollToIndexFailed: (info) => {
|
|
567
|
+
const offset = info.averageItemLength * info.index;
|
|
568
|
+
listRef.current?.scrollToOffset({ offset, animated: false });
|
|
551
569
|
setTimeout(() => {
|
|
552
|
-
|
|
570
|
+
try {
|
|
571
|
+
listRef.current?.scrollToIndex({ index: info.index, animated: true, viewPosition: 0 });
|
|
572
|
+
} catch {
|
|
573
|
+
}
|
|
553
574
|
}, 100);
|
|
554
575
|
}
|
|
555
576
|
}
|
|
556
577
|
);
|
|
557
578
|
}
|
|
558
|
-
function DefaultLineTagList() {
|
|
559
|
-
return /* @__PURE__ */
|
|
579
|
+
function DefaultLineTagList({ listHeader }) {
|
|
580
|
+
return /* @__PURE__ */ React6.createElement(LineTagList, { listHeader }, (tag, isActive) => /* @__PURE__ */ React6.createElement(DefaultTagItem, { tag, isActive }));
|
|
560
581
|
}
|
|
561
582
|
function DefaultTagItem({ tag, isActive }) {
|
|
562
|
-
const { controls, openAddNote
|
|
563
|
-
|
|
564
|
-
return /* @__PURE__ */ React5.createElement(
|
|
583
|
+
const { controls, openAddNote } = useRetorBridge();
|
|
584
|
+
return /* @__PURE__ */ React6.createElement(
|
|
565
585
|
Pressable2,
|
|
566
586
|
{
|
|
567
587
|
onPress: () => controls.scrollToTag(tag._id),
|
|
568
588
|
style: [styles3.tagItem, isActive && styles3.tagItemActive]
|
|
569
589
|
},
|
|
570
|
-
/* @__PURE__ */
|
|
571
|
-
tag.subtitle && /* @__PURE__ */
|
|
572
|
-
|
|
590
|
+
/* @__PURE__ */ React6.createElement(View5, { style: { flex: 1, minWidth: 0 } }, /* @__PURE__ */ React6.createElement(Text2, { style: [styles3.tagText, isActive && styles3.tagTextActive], numberOfLines: 1 }, tag.name), isActive && tag.description && /* @__PURE__ */ React6.createElement(Text2, { style: styles3.tagDescription, numberOfLines: 2 }, tag.description)),
|
|
591
|
+
tag.subtitle && /* @__PURE__ */ React6.createElement(Text2, { style: styles3.tagSubtitle, numberOfLines: 1 }, tag.subtitle),
|
|
592
|
+
isActive && /* @__PURE__ */ React6.createElement(
|
|
573
593
|
Pressable2,
|
|
574
594
|
{
|
|
575
595
|
onPress: (e) => {
|
|
@@ -578,20 +598,18 @@ function DefaultTagItem({ tag, isActive }) {
|
|
|
578
598
|
},
|
|
579
599
|
style: styles3.plusBtn
|
|
580
600
|
},
|
|
581
|
-
/* @__PURE__ */
|
|
601
|
+
/* @__PURE__ */ React6.createElement(Plus, { size: 14, color: "white" })
|
|
582
602
|
)
|
|
583
603
|
);
|
|
584
604
|
}
|
|
585
|
-
var styles3 =
|
|
586
|
-
background: { backgroundColor: "rgba(20,20,20,0.95)" },
|
|
605
|
+
var styles3 = StyleSheet5.create({
|
|
587
606
|
handle: { backgroundColor: "rgba(255,255,255,0.3)" },
|
|
588
|
-
root: { flex: 1 },
|
|
589
607
|
header: {
|
|
590
608
|
flexDirection: "row",
|
|
591
609
|
alignItems: "flex-start",
|
|
592
610
|
paddingHorizontal: 24,
|
|
593
611
|
paddingTop: 8,
|
|
594
|
-
paddingBottom:
|
|
612
|
+
paddingBottom: 16,
|
|
595
613
|
gap: 8
|
|
596
614
|
},
|
|
597
615
|
headerActions: { flexDirection: "row", alignItems: "center", gap: 6 },
|
|
@@ -607,8 +625,7 @@ var styles3 = StyleSheet4.create({
|
|
|
607
625
|
justifyContent: "center",
|
|
608
626
|
position: "relative"
|
|
609
627
|
},
|
|
610
|
-
|
|
611
|
-
list: { paddingHorizontal: 16, paddingBottom: 8, gap: 4 },
|
|
628
|
+
list: { paddingHorizontal: 16, paddingBottom: 96, gap: 4 },
|
|
612
629
|
tagItem: {
|
|
613
630
|
flexDirection: "row",
|
|
614
631
|
alignItems: "center",
|
|
@@ -623,14 +640,19 @@ var styles3 = StyleSheet4.create({
|
|
|
623
640
|
tagDescription: { color: "rgba(255,255,255,0.4)", fontSize: 11, marginTop: 2, lineHeight: 14 },
|
|
624
641
|
tagSubtitle: { color: "rgba(255,255,255,0.4)", fontSize: 10 },
|
|
625
642
|
plusBtn: {
|
|
626
|
-
width:
|
|
627
|
-
height:
|
|
628
|
-
borderRadius:
|
|
629
|
-
backgroundColor: "rgba(255,255,255,0.
|
|
643
|
+
width: 24,
|
|
644
|
+
height: 24,
|
|
645
|
+
borderRadius: 12,
|
|
646
|
+
backgroundColor: "rgba(255,255,255,0.2)",
|
|
630
647
|
alignItems: "center",
|
|
631
648
|
justifyContent: "center"
|
|
632
649
|
},
|
|
633
|
-
footer: {
|
|
650
|
+
footer: {
|
|
651
|
+
paddingHorizontal: 16,
|
|
652
|
+
paddingBottom: 24,
|
|
653
|
+
paddingTop: 8,
|
|
654
|
+
backgroundColor: "transparent"
|
|
655
|
+
},
|
|
634
656
|
doneButton: {
|
|
635
657
|
backgroundColor: "white",
|
|
636
658
|
borderRadius: 14,
|
|
@@ -641,8 +663,8 @@ var styles3 = StyleSheet4.create({
|
|
|
641
663
|
});
|
|
642
664
|
|
|
643
665
|
// src/AddNoteSheet.tsx
|
|
644
|
-
import
|
|
645
|
-
import { Pressable as Pressable3, StyleSheet as
|
|
666
|
+
import React7, { useEffect as useEffect4, useMemo as useMemo5, useRef as useRef4, useState as useState4 } from "react";
|
|
667
|
+
import { Pressable as Pressable3, StyleSheet as StyleSheet6, Text as Text3, View as View6 } from "react-native";
|
|
646
668
|
import {
|
|
647
669
|
BottomSheetBackdrop as BottomSheetBackdrop3,
|
|
648
670
|
BottomSheetModal as BottomSheetModal3,
|
|
@@ -690,14 +712,14 @@ function AddNoteSheet({
|
|
|
690
712
|
close: closeAddNote,
|
|
691
713
|
maxLength
|
|
692
714
|
};
|
|
693
|
-
return /* @__PURE__ */
|
|
715
|
+
return /* @__PURE__ */ React7.createElement(
|
|
694
716
|
BottomSheetModal3,
|
|
695
717
|
{
|
|
696
718
|
ref: sheetRef,
|
|
697
719
|
snapPoints: snapPointsArr,
|
|
698
720
|
enablePanDownToClose: true,
|
|
699
721
|
onDismiss: closeAddNote,
|
|
700
|
-
backdropComponent: (props) => /* @__PURE__ */
|
|
722
|
+
backdropComponent: (props) => /* @__PURE__ */ React7.createElement(
|
|
701
723
|
BottomSheetBackdrop3,
|
|
702
724
|
{
|
|
703
725
|
...props,
|
|
@@ -707,9 +729,9 @@ function AddNoteSheet({
|
|
|
707
729
|
}
|
|
708
730
|
),
|
|
709
731
|
handleIndicatorStyle: styles4.handle,
|
|
710
|
-
|
|
732
|
+
backgroundComponent: BlurBackground
|
|
711
733
|
},
|
|
712
|
-
/* @__PURE__ */
|
|
734
|
+
/* @__PURE__ */ React7.createElement(BottomSheetView2, { style: styles4.content }, renderForm ? renderForm(formApi) : /* @__PURE__ */ React7.createElement(View6, { style: styles4.form }, /* @__PURE__ */ React7.createElement(View6, { style: styles4.headerRow }, /* @__PURE__ */ React7.createElement(View6, { style: { flex: 1 } }, activeLine && /* @__PURE__ */ React7.createElement(Text3, { style: styles4.title, numberOfLines: 1 }, activeLine.name), tag && /* @__PURE__ */ React7.createElement(Text3, { style: styles4.subtitle, numberOfLines: 1 }, tag.name)), /* @__PURE__ */ React7.createElement(Pressable3, { onPress: closeAddNote, style: styles4.closeBtn }, /* @__PURE__ */ React7.createElement(X, { size: 14, color: "rgba(255,255,255,0.6)" }))), /* @__PURE__ */ React7.createElement(
|
|
713
735
|
BottomSheetTextInput,
|
|
714
736
|
{
|
|
715
737
|
value: text,
|
|
@@ -722,26 +744,25 @@ function AddNoteSheet({
|
|
|
722
744
|
style: styles4.input,
|
|
723
745
|
autoFocus: true
|
|
724
746
|
}
|
|
725
|
-
), /* @__PURE__ */
|
|
747
|
+
), /* @__PURE__ */ React7.createElement(View6, { style: styles4.footer }, /* @__PURE__ */ React7.createElement(Text3, { style: [styles4.counter, text.length > maxLength * 0.9 && { color: "#fbbf24" }] }, text.length, "/", maxLength), /* @__PURE__ */ React7.createElement(View6, { style: { flex: 1 } }), /* @__PURE__ */ React7.createElement(
|
|
726
748
|
Pressable3,
|
|
727
749
|
{
|
|
728
750
|
onPress: () => setPrivate(!isPrivate),
|
|
729
751
|
style: [styles4.pill, !isPrivate && styles4.pillActive]
|
|
730
752
|
},
|
|
731
|
-
/* @__PURE__ */
|
|
732
|
-
), /* @__PURE__ */
|
|
753
|
+
/* @__PURE__ */ React7.createElement(Text3, { style: [styles4.pillText, !isPrivate && styles4.pillTextActive] }, isPrivate ? "Private" : "Public")
|
|
754
|
+
), /* @__PURE__ */ React7.createElement(
|
|
733
755
|
Pressable3,
|
|
734
756
|
{
|
|
735
757
|
onPress: handleSubmit,
|
|
736
758
|
disabled: !text.trim(),
|
|
737
759
|
style: [styles4.submit, !text.trim() && styles4.submitDisabled]
|
|
738
760
|
},
|
|
739
|
-
/* @__PURE__ */
|
|
761
|
+
/* @__PURE__ */ React7.createElement(ArrowUp3, { size: 16, color: "black", strokeWidth: 2.5 })
|
|
740
762
|
))))
|
|
741
763
|
);
|
|
742
764
|
}
|
|
743
|
-
var styles4 =
|
|
744
|
-
background: { backgroundColor: "rgba(20,20,20,0.98)" },
|
|
765
|
+
var styles4 = StyleSheet6.create({
|
|
745
766
|
handle: { backgroundColor: "rgba(255,255,255,0.3)" },
|
|
746
767
|
content: { flex: 1, padding: 24 },
|
|
747
768
|
form: { flex: 1 },
|
|
@@ -793,11 +814,11 @@ var styles4 = StyleSheet5.create({
|
|
|
793
814
|
});
|
|
794
815
|
|
|
795
816
|
// src/CoverPhoto.tsx
|
|
796
|
-
import
|
|
817
|
+
import React8 from "react";
|
|
797
818
|
import { WebView as WebView2 } from "react-native-webview";
|
|
798
819
|
function CoverPhoto({ projectId, baseUrl = "https://retor.app", style }) {
|
|
799
820
|
const uri = `${baseUrl}/p/${projectId}?cover=true`;
|
|
800
|
-
return /* @__PURE__ */
|
|
821
|
+
return /* @__PURE__ */ React8.createElement(
|
|
801
822
|
WebView2,
|
|
802
823
|
{
|
|
803
824
|
source: { uri },
|
|
@@ -811,6 +832,7 @@ function CoverPhoto({ projectId, baseUrl = "https://retor.app", style }) {
|
|
|
811
832
|
}
|
|
812
833
|
export {
|
|
813
834
|
AddNoteSheet,
|
|
835
|
+
BlurBackground,
|
|
814
836
|
CoverPhoto,
|
|
815
837
|
Hud,
|
|
816
838
|
LineDetailSheet,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@retor/react-native",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"description": "React Native SDK for embedding Retor 3D experiences",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -27,6 +27,7 @@
|
|
|
27
27
|
"license": "MIT",
|
|
28
28
|
"peerDependencies": {
|
|
29
29
|
"@gorhom/bottom-sheet": ">=5",
|
|
30
|
+
"expo-blur": ">=14",
|
|
30
31
|
"lucide-react-native": ">=1",
|
|
31
32
|
"react": ">=18",
|
|
32
33
|
"react-native": ">=0.72",
|
|
@@ -35,9 +36,15 @@
|
|
|
35
36
|
"react-native-svg": ">=14",
|
|
36
37
|
"react-native-webview": ">=13"
|
|
37
38
|
},
|
|
39
|
+
"peerDependenciesMeta": {
|
|
40
|
+
"expo-blur": {
|
|
41
|
+
"optional": true
|
|
42
|
+
}
|
|
43
|
+
},
|
|
38
44
|
"devDependencies": {
|
|
39
45
|
"@gorhom/bottom-sheet": "^5.1.0",
|
|
40
46
|
"@types/react": "^19.0.0",
|
|
47
|
+
"expo-blur": "^55.0.14",
|
|
41
48
|
"lucide-react-native": "^1.8.0",
|
|
42
49
|
"react": "19.1.0",
|
|
43
50
|
"react-native": "0.81.4",
|
|
@@ -49,8 +56,8 @@
|
|
|
49
56
|
"typescript": "^5.4.0"
|
|
50
57
|
},
|
|
51
58
|
"scripts": {
|
|
52
|
-
"build": "tsup src/index.tsx --format cjs,esm --dts --clean --external react --external react-native --external react-native-webview --external @gorhom/bottom-sheet --external react-native-gesture-handler --external react-native-reanimated --external react-native-svg --external lucide-react-native",
|
|
53
|
-
"dev": "tsup src/index.tsx --format cjs,esm --dts --watch --external react --external react-native --external react-native-webview --external @gorhom/bottom-sheet --external react-native-gesture-handler --external react-native-reanimated --external react-native-svg --external lucide-react-native",
|
|
59
|
+
"build": "tsup src/index.tsx --format cjs,esm --dts --clean --external react --external react-native --external react-native-webview --external @gorhom/bottom-sheet --external react-native-gesture-handler --external react-native-reanimated --external react-native-svg --external lucide-react-native --external expo-blur",
|
|
60
|
+
"dev": "tsup src/index.tsx --format cjs,esm --dts --watch --external react --external react-native --external react-native-webview --external @gorhom/bottom-sheet --external react-native-gesture-handler --external react-native-reanimated --external react-native-svg --external lucide-react-native --external expo-blur",
|
|
54
61
|
"typecheck": "tsc --noEmit"
|
|
55
62
|
}
|
|
56
63
|
}
|