@retor/react-native 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +151 -91
- package/dist/index.d.mts +209 -30
- package/dist/index.d.ts +209 -30
- package/dist/index.js +595 -85
- package/dist/index.mjs +586 -85
- package/package.json +9 -3
package/README.md
CHANGED
|
@@ -1,147 +1,207 @@
|
|
|
1
1
|
# @retor/react-native
|
|
2
2
|
|
|
3
|
-
Embed Retor 3D experiences in a React Native / Expo app
|
|
3
|
+
Embed Retor 3D experiences in a React Native / Expo app — with composable bottom-sheet UI built on `@gorhom/bottom-sheet`.
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
7
|
-
Install the peer dependency:
|
|
8
|
-
|
|
9
7
|
```bash
|
|
10
8
|
# Expo
|
|
11
|
-
npx expo install react-native-webview
|
|
9
|
+
npx expo install react-native-webview react-native-gesture-handler react-native-reanimated
|
|
10
|
+
npm install @gorhom/bottom-sheet @retor/react-native
|
|
12
11
|
|
|
13
12
|
# bare React Native
|
|
14
|
-
npm install react-native-webview
|
|
13
|
+
npm install react-native-webview react-native-gesture-handler react-native-reanimated @gorhom/bottom-sheet @retor/react-native
|
|
15
14
|
cd ios && pod install
|
|
16
15
|
```
|
|
17
16
|
|
|
18
|
-
|
|
17
|
+
You also need to wrap your app root in a `GestureHandlerRootView` (per `@gorhom/bottom-sheet` requirements):
|
|
19
18
|
|
|
20
|
-
```
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
19
|
+
```tsx
|
|
20
|
+
import { GestureHandlerRootView } from "react-native-gesture-handler";
|
|
21
|
+
|
|
22
|
+
export default function App() {
|
|
23
|
+
return (
|
|
24
|
+
<GestureHandlerRootView style={{ flex: 1 }}>
|
|
25
|
+
<YourApp />
|
|
26
|
+
</GestureHandlerRootView>
|
|
27
|
+
);
|
|
28
|
+
}
|
|
26
29
|
```
|
|
27
30
|
|
|
28
|
-
## Quick Start
|
|
31
|
+
## Quick Start — Default UI
|
|
32
|
+
|
|
33
|
+
The fastest way: drop in `<Hud>` with the three sheets and they'll work out of the box.
|
|
29
34
|
|
|
30
35
|
```tsx
|
|
31
36
|
import { View } from "react-native";
|
|
32
|
-
import { Viewer, Hud } from "@retor/react-native";
|
|
37
|
+
import { Viewer, Hud, ProjectSheet, LineDetailSheet, AddNoteSheet } from "@retor/react-native";
|
|
33
38
|
|
|
34
39
|
export default function Scene() {
|
|
35
40
|
return (
|
|
36
41
|
<View style={{ flex: 1 }}>
|
|
37
|
-
<Viewer projectId="abc123"
|
|
38
|
-
<Hud
|
|
42
|
+
<Viewer projectId="abc123">
|
|
43
|
+
<Hud>
|
|
44
|
+
<ProjectSheet />
|
|
45
|
+
<LineDetailSheet />
|
|
46
|
+
<AddNoteSheet />
|
|
47
|
+
</Hud>
|
|
39
48
|
</Viewer>
|
|
40
49
|
</View>
|
|
41
50
|
);
|
|
42
51
|
}
|
|
43
52
|
```
|
|
44
53
|
|
|
45
|
-
|
|
54
|
+
What you get:
|
|
55
|
+
- A bottom sheet showing the project name and a horizontal carousel of lines
|
|
56
|
+
- Tap a line → second sheet opens with the tag list and a Done button
|
|
57
|
+
- Tap a tag → camera scrolls to it
|
|
58
|
+
- Done returns to the browse sheet
|
|
46
59
|
|
|
47
|
-
|
|
60
|
+
## Concepts
|
|
48
61
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
62
|
+
- **`<Viewer>`** wraps the WebView and exposes scene state via React context. Always vanilla — Retor itself shows no UI.
|
|
63
|
+
- **`<Hud>`** sets up `BottomSheetModalProvider`. Place sheets and other overlays inside.
|
|
64
|
+
- **Sheets** auto-present based on bridge state:
|
|
65
|
+
- `<ProjectSheet>` shows when no line is open
|
|
66
|
+
- `<LineDetailSheet>` shows when a line is open
|
|
67
|
+
- `<AddNoteSheet>` shows when `useAddNote().open()` is called
|
|
68
|
+
- **Composition components** (`<LinesCarousel>`, `<LineTagList>`) take a render prop so you can replace the visuals while keeping the data wiring.
|
|
69
|
+
|
|
70
|
+
## Customising the visuals
|
|
53
71
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
}) {
|
|
59
|
-
const { openLine, exitLine, scrollToTag } = useViewer();
|
|
72
|
+
Each sheet accepts:
|
|
73
|
+
- `snapPoints` — override the default snap points
|
|
74
|
+
- `renderHeader` — replace the header
|
|
75
|
+
- `children` — replace the body (typically a render-prop list)
|
|
60
76
|
|
|
77
|
+
```tsx
|
|
78
|
+
import { Pressable, Text } from "react-native";
|
|
79
|
+
import { ProjectSheet, LinesCarousel, LineDetailSheet, LineTagList, useViewer } from "@retor/react-native";
|
|
80
|
+
|
|
81
|
+
function MyLineCard({ line }: { line: RetorLine }) {
|
|
82
|
+
const { openLine } = useViewer();
|
|
61
83
|
return (
|
|
62
|
-
<
|
|
63
|
-
{
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
keyExtractor={(t) => t._id}
|
|
69
|
-
renderItem={({ item }) => (
|
|
70
|
-
<Pressable onPress={() => scrollToTag(item._id)}>
|
|
71
|
-
<Text style={{ color: item._id === closestTagId ? "white" : "gray" }}>
|
|
72
|
-
{item.name}
|
|
73
|
-
</Text>
|
|
74
|
-
</Pressable>
|
|
75
|
-
)}
|
|
76
|
-
/>
|
|
77
|
-
<Pressable onPress={() => exitLine()}>
|
|
78
|
-
<Text style={{ color: "white" }}>Done</Text>
|
|
79
|
-
</Pressable>
|
|
80
|
-
</View>
|
|
81
|
-
) : (
|
|
82
|
-
<FlatList
|
|
83
|
-
horizontal
|
|
84
|
-
data={lines}
|
|
85
|
-
keyExtractor={(l) => l._id}
|
|
86
|
-
renderItem={({ item }) => (
|
|
87
|
-
<Pressable onPress={() => openLine(item._id)}>
|
|
88
|
-
<Text style={{ color: "white", padding: 16 }}>{item.name}</Text>
|
|
89
|
-
</Pressable>
|
|
90
|
-
)}
|
|
91
|
-
/>
|
|
92
|
-
)}
|
|
93
|
-
</View>
|
|
84
|
+
<Pressable
|
|
85
|
+
onPress={() => openLine(line._id)}
|
|
86
|
+
style={{ width: 200, padding: 16, backgroundColor: "#222", borderRadius: 16 }}
|
|
87
|
+
>
|
|
88
|
+
<Text style={{ color: "white", fontWeight: "600" }}>{line.name}</Text>
|
|
89
|
+
</Pressable>
|
|
94
90
|
);
|
|
95
91
|
}
|
|
96
92
|
|
|
93
|
+
<ProjectSheet snapPoints={["20%", "50%"]}>
|
|
94
|
+
<LinesCarousel>
|
|
95
|
+
{(line) => <MyLineCard line={line} />}
|
|
96
|
+
</LinesCarousel>
|
|
97
|
+
</ProjectSheet>
|
|
98
|
+
|
|
99
|
+
<LineDetailSheet>
|
|
100
|
+
<LineTagList>
|
|
101
|
+
{(tag, isActive) => (
|
|
102
|
+
<Pressable style={{ padding: 12 }}>
|
|
103
|
+
<Text style={{ color: isActive ? "white" : "gray" }}>{tag.name}</Text>
|
|
104
|
+
</Pressable>
|
|
105
|
+
)}
|
|
106
|
+
</LineTagList>
|
|
107
|
+
</LineDetailSheet>
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## Notes
|
|
111
|
+
|
|
112
|
+
`<AddNoteSheet>` triggers when you call `useAddNote().open(tagId?)` — for example from a "+" button on the active tag in your `LineTagList`. It collects text + private/public, then calls `onNoteSubmit` on the parent `<Viewer>`. **Persistence is your responsibility** — store the note however you like, then re-pass updated notes back to Retor via `<Notes>`.
|
|
113
|
+
|
|
114
|
+
```tsx
|
|
115
|
+
import { useState } from "react";
|
|
116
|
+
import { Viewer, Hud, ProjectSheet, LineDetailSheet, AddNoteSheet, Notes, useAddNote, type RetorTag } from "@retor/react-native";
|
|
117
|
+
|
|
118
|
+
function AddButton() {
|
|
119
|
+
const { open } = useAddNote();
|
|
120
|
+
return <Pressable onPress={() => open()}><Text>+</Text></Pressable>;
|
|
121
|
+
}
|
|
122
|
+
|
|
97
123
|
export default function Scene() {
|
|
98
|
-
const [
|
|
99
|
-
const [activeLine, setActiveLine] = useState<RetorLine | null>(null);
|
|
100
|
-
const [closestTagId, setClosestTagId] = useState<string | null>(null);
|
|
124
|
+
const [notes, setNotes] = useState<RetorTag[]>([]);
|
|
101
125
|
|
|
102
126
|
return (
|
|
103
|
-
<
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
127
|
+
<Viewer
|
|
128
|
+
projectId="abc123"
|
|
129
|
+
onNoteSubmit={({ text, isPrivate, tagId, lineId, position }) => {
|
|
130
|
+
if (!position) return;
|
|
131
|
+
setNotes((prev) => [
|
|
132
|
+
...prev,
|
|
133
|
+
{
|
|
134
|
+
_id: `note-${Date.now()}`,
|
|
135
|
+
name: text,
|
|
136
|
+
position,
|
|
137
|
+
objectId: lineId ?? undefined,
|
|
138
|
+
},
|
|
139
|
+
]);
|
|
140
|
+
}}
|
|
141
|
+
>
|
|
142
|
+
<Notes notes={notes} />
|
|
143
|
+
<Hud>
|
|
144
|
+
<ProjectSheet />
|
|
145
|
+
<LineDetailSheet>
|
|
146
|
+
<LineTagList>
|
|
147
|
+
{(tag, isActive) => (
|
|
148
|
+
<View style={{ flexDirection: "row", padding: 12 }}>
|
|
149
|
+
<Text style={{ flex: 1, color: isActive ? "white" : "gray" }}>{tag.name}</Text>
|
|
150
|
+
{isActive && <AddButton />}
|
|
151
|
+
</View>
|
|
152
|
+
)}
|
|
153
|
+
</LineTagList>
|
|
154
|
+
</LineDetailSheet>
|
|
155
|
+
<AddNoteSheet />
|
|
156
|
+
</Hud>
|
|
157
|
+
</Viewer>
|
|
117
158
|
);
|
|
118
159
|
}
|
|
119
160
|
```
|
|
120
161
|
|
|
121
|
-
##
|
|
162
|
+
## Hooks
|
|
122
163
|
|
|
123
|
-
|
|
124
|
-
- Inline media playback is enabled without user gesture
|
|
125
|
-
- Messages are JSON-stringified across the bridge — handled transparently
|
|
126
|
-
- On Android, inbound messages are dispatched via `injectJavaScript`
|
|
164
|
+
All hooks read from the bridge context provided by the parent `<Viewer>`.
|
|
127
165
|
|
|
128
|
-
|
|
166
|
+
| Hook | Returns |
|
|
167
|
+
|------|---------|
|
|
168
|
+
| `useProject()` | The current `RetorProject` (or null) |
|
|
169
|
+
| `useLines()` | Array of `RetorLine` |
|
|
170
|
+
| `useActiveLine()` | The currently open line (or null) |
|
|
171
|
+
| `useLineProgress()` | `{ progress, closestTagId }` |
|
|
172
|
+
| `useAutoplay()` | `{ isPlaying, toggle, play, pause }` |
|
|
173
|
+
| `useAddNote()` | `{ isOpen, tagId, open, close, submit }` |
|
|
174
|
+
| `useViewer()` | Imperative controls (`openLine`, `exitLine`, `scrollToTag`, ...) |
|
|
129
175
|
|
|
130
|
-
|
|
176
|
+
## Imperative API
|
|
177
|
+
|
|
178
|
+
The `useViewer` hook also supports controlling a specific viewer by ID:
|
|
131
179
|
|
|
132
180
|
```tsx
|
|
133
|
-
|
|
181
|
+
<Viewer id="left" projectId="..." />
|
|
182
|
+
<Viewer id="right" projectId="..." />
|
|
183
|
+
|
|
184
|
+
const left = useViewer("left");
|
|
185
|
+
left.openLine("line-a");
|
|
186
|
+
```
|
|
134
187
|
|
|
135
|
-
|
|
188
|
+
Or pass a ref directly:
|
|
136
189
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
190
|
+
```tsx
|
|
191
|
+
const ref = useRef<ViewerHandle>(null);
|
|
192
|
+
<Viewer ref={ref} projectId="..." />
|
|
193
|
+
ref.current?.openLine("...");
|
|
140
194
|
```
|
|
141
195
|
|
|
142
|
-
##
|
|
196
|
+
## Cover photo
|
|
143
197
|
|
|
144
|
-
|
|
198
|
+
A static thumbnail of a project's start view — no 3D, no bridge:
|
|
199
|
+
|
|
200
|
+
```tsx
|
|
201
|
+
import { CoverPhoto } from "@retor/react-native";
|
|
202
|
+
|
|
203
|
+
<CoverPhoto projectId="abc123" style={{ width: 200, height: 120 }} />
|
|
204
|
+
```
|
|
145
205
|
|
|
146
206
|
## License
|
|
147
207
|
|
package/dist/index.d.mts
CHANGED
|
@@ -16,6 +16,7 @@ interface RetorTag {
|
|
|
16
16
|
color?: string;
|
|
17
17
|
tagType?: string;
|
|
18
18
|
iconName?: string;
|
|
19
|
+
objectId?: string;
|
|
19
20
|
}
|
|
20
21
|
interface RetorLine {
|
|
21
22
|
_id: string;
|
|
@@ -50,12 +51,106 @@ interface ViewerHandle {
|
|
|
50
51
|
toggleAutoplay: () => void;
|
|
51
52
|
setAutoplay: (playing: boolean) => void;
|
|
52
53
|
}
|
|
54
|
+
|
|
55
|
+
interface NoteSubmitPayload {
|
|
56
|
+
text: string;
|
|
57
|
+
isPrivate: boolean;
|
|
58
|
+
tagId: string | null;
|
|
59
|
+
lineId: string | null;
|
|
60
|
+
position: {
|
|
61
|
+
x: number;
|
|
62
|
+
y: number;
|
|
63
|
+
z: number;
|
|
64
|
+
} | null;
|
|
65
|
+
}
|
|
66
|
+
interface RetorBridgeContextValue {
|
|
67
|
+
project: RetorProject | null;
|
|
68
|
+
lines: RetorLine[];
|
|
69
|
+
activeLineId: string | null;
|
|
70
|
+
activeLine: RetorLine | null;
|
|
71
|
+
closestTagId: string | null;
|
|
72
|
+
progress: number;
|
|
73
|
+
isPlaying: boolean;
|
|
74
|
+
isAddNoteOpen: boolean;
|
|
75
|
+
addNoteTagId: string | null;
|
|
76
|
+
controls: ViewerHandle;
|
|
77
|
+
openAddNote: (tagId?: string) => void;
|
|
78
|
+
closeAddNote: () => void;
|
|
79
|
+
submitNote: (text: string, isPrivate?: boolean) => void;
|
|
80
|
+
onNoteSubmit?: (payload: NoteSubmitPayload) => void;
|
|
81
|
+
}
|
|
82
|
+
declare function useRetorBridge(): RetorBridgeContextValue;
|
|
83
|
+
/** Returns the array of all lines in the current project. */
|
|
84
|
+
declare function useLines(): RetorLine[];
|
|
85
|
+
/** Returns the project metadata once `init` has fired. */
|
|
86
|
+
declare function useProject(): RetorProject | null;
|
|
87
|
+
/**
|
|
88
|
+
* Returns the line that's currently open (after the user enters a scroll path),
|
|
89
|
+
* or null when in browse mode.
|
|
90
|
+
*/
|
|
91
|
+
declare function useActiveLine(): RetorLine | null;
|
|
92
|
+
/**
|
|
93
|
+
* Returns scroll progress (0..1) and the id of the closest tag along the
|
|
94
|
+
* currently active line. Both are null when no line is open.
|
|
95
|
+
*/
|
|
96
|
+
declare function useLineProgress(): {
|
|
97
|
+
progress: number;
|
|
98
|
+
closestTagId: string | null;
|
|
99
|
+
};
|
|
100
|
+
/**
|
|
101
|
+
* Returns the autoplay state and controls.
|
|
102
|
+
*/
|
|
103
|
+
declare function useAutoplay(): {
|
|
104
|
+
isPlaying: boolean;
|
|
105
|
+
toggle: () => void;
|
|
106
|
+
play: () => void;
|
|
107
|
+
pause: () => void;
|
|
108
|
+
};
|
|
109
|
+
/**
|
|
110
|
+
* Returns the current add-note flow state and actions.
|
|
111
|
+
*/
|
|
112
|
+
declare function useAddNote(): {
|
|
113
|
+
isOpen: boolean;
|
|
114
|
+
tagId: string | null;
|
|
115
|
+
open: (tagId?: string) => void;
|
|
116
|
+
close: () => void;
|
|
117
|
+
submit: (text: string, isPrivate?: boolean) => void;
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Hook for controlling a Viewer from anywhere in your tree.
|
|
122
|
+
*
|
|
123
|
+
* Default usage (single viewer):
|
|
124
|
+
* ```tsx
|
|
125
|
+
* const { openLine, exitLine } = useViewer();
|
|
126
|
+
* ```
|
|
127
|
+
*
|
|
128
|
+
* Multiple viewers:
|
|
129
|
+
* ```tsx
|
|
130
|
+
* <Viewer id="left" projectId="..." />
|
|
131
|
+
* const left = useViewer("left");
|
|
132
|
+
* ```
|
|
133
|
+
*
|
|
134
|
+
* With a ref:
|
|
135
|
+
* ```tsx
|
|
136
|
+
* const ref = useRef<ViewerHandle>(null);
|
|
137
|
+
* const { openLine } = useViewer(ref);
|
|
138
|
+
* ```
|
|
139
|
+
*/
|
|
140
|
+
declare function useViewer(target?: string | React.RefObject<ViewerHandle | null>): ViewerHandle;
|
|
141
|
+
interface NotesProps {
|
|
142
|
+
/** Array of notes (same shape as RetorTag) to push into the 3D scene. */
|
|
143
|
+
notes: RetorTag[];
|
|
144
|
+
}
|
|
145
|
+
declare function Notes(_props: NotesProps): React.ReactElement | null;
|
|
53
146
|
interface ViewerProps {
|
|
54
147
|
projectId: string;
|
|
55
148
|
/** Identifier for this viewer instance. Used by `useViewer(id)`. Defaults to "default". */
|
|
56
149
|
id?: string;
|
|
57
150
|
/** Base URL where Retor is hosted. Defaults to https://retor.app */
|
|
58
151
|
baseUrl?: string;
|
|
152
|
+
/** Called when a note is submitted via `<AddNoteSheet>`. Receives the text + position. */
|
|
153
|
+
onNoteSubmit?: (note: NoteSubmitPayload) => void;
|
|
59
154
|
onInit?: (data: InitPayload) => void;
|
|
60
155
|
onLineOpen?: (data: {
|
|
61
156
|
lineId: string;
|
|
@@ -66,48 +161,132 @@ interface ViewerProps {
|
|
|
66
161
|
style?: StyleProp<ViewStyle>;
|
|
67
162
|
children?: React.ReactNode;
|
|
68
163
|
}
|
|
164
|
+
declare const Viewer: React.ForwardRefExoticComponent<ViewerProps & React.RefAttributes<ViewerHandle>>;
|
|
165
|
+
|
|
166
|
+
interface HudProps {
|
|
167
|
+
children: React.ReactNode;
|
|
168
|
+
}
|
|
69
169
|
/**
|
|
70
|
-
*
|
|
170
|
+
* Sets up the bottom-sheet provider tree for the SDK's UI components
|
|
171
|
+
* (`<ProjectSheet>`, `<LineDetailSheet>`, `<AddNoteSheet>`).
|
|
71
172
|
*
|
|
72
|
-
*
|
|
73
|
-
* ```tsx
|
|
74
|
-
* <Viewer projectId="..." /> // id defaults to "default"
|
|
75
|
-
* const { openLine, exitLine } = useViewer();
|
|
76
|
-
* ```
|
|
173
|
+
* Place inside `<Viewer>` so the sheets can read scene state from the bridge:
|
|
77
174
|
*
|
|
78
|
-
* With an explicit ID (multiple viewers on one screen):
|
|
79
175
|
* ```tsx
|
|
80
|
-
* <Viewer
|
|
81
|
-
*
|
|
82
|
-
*
|
|
83
|
-
*
|
|
176
|
+
* <Viewer projectId="...">
|
|
177
|
+
* <Hud>
|
|
178
|
+
* <ProjectSheet />
|
|
179
|
+
* <LineDetailSheet />
|
|
180
|
+
* <AddNoteSheet />
|
|
181
|
+
* </Hud>
|
|
182
|
+
* </Viewer>
|
|
84
183
|
* ```
|
|
184
|
+
*/
|
|
185
|
+
declare function Hud({ children }: HudProps): React.JSX.Element;
|
|
186
|
+
|
|
187
|
+
interface ProjectSheetProps {
|
|
188
|
+
/**
|
|
189
|
+
* Snap points for the sheet. Defaults to ["20%", "60%"].
|
|
190
|
+
*/
|
|
191
|
+
snapPoints?: (string | number)[];
|
|
192
|
+
/**
|
|
193
|
+
* Override the default header (project name + description).
|
|
194
|
+
* Receives the project metadata.
|
|
195
|
+
*/
|
|
196
|
+
renderHeader?: (project: {
|
|
197
|
+
name?: string;
|
|
198
|
+
description?: string;
|
|
199
|
+
}) => React.ReactNode;
|
|
200
|
+
/**
|
|
201
|
+
* Children to render below the header. Typically a `<LinesCarousel>`.
|
|
202
|
+
* If omitted, a default LinesCarousel is rendered.
|
|
203
|
+
*/
|
|
204
|
+
children?: React.ReactNode;
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* The browse-mode bottom sheet. Auto-presents whenever no line is open.
|
|
85
208
|
*
|
|
86
|
-
* With a ref (if you prefer imperative style):
|
|
87
209
|
* ```tsx
|
|
88
|
-
*
|
|
89
|
-
*
|
|
90
|
-
*
|
|
210
|
+
* <ProjectSheet>
|
|
211
|
+
* <LinesCarousel>
|
|
212
|
+
* {(line) => <MyLineCard line={line} />}
|
|
213
|
+
* </LinesCarousel>
|
|
214
|
+
* </ProjectSheet>
|
|
91
215
|
* ```
|
|
92
216
|
*/
|
|
93
|
-
declare function
|
|
217
|
+
declare function ProjectSheet({ snapPoints, renderHeader, children }: ProjectSheetProps): React.JSX.Element;
|
|
218
|
+
interface LinesCarouselProps {
|
|
219
|
+
children: (line: RetorLine, index: number) => React.ReactNode;
|
|
220
|
+
/** Optional gap between items. Defaults to 12. */
|
|
221
|
+
gap?: number;
|
|
222
|
+
/** Optional horizontal padding. Defaults to 16. */
|
|
223
|
+
paddingHorizontal?: number;
|
|
224
|
+
}
|
|
94
225
|
/**
|
|
95
|
-
*
|
|
96
|
-
*
|
|
97
|
-
*
|
|
226
|
+
* Renders a horizontally scrolling list of lines using a render prop.
|
|
227
|
+
* Place inside `<ProjectSheet>`.
|
|
228
|
+
*
|
|
229
|
+
* Pressing an item is up to your render — use `useViewer().openLine(line._id)`.
|
|
98
230
|
*/
|
|
99
|
-
declare function
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
231
|
+
declare function LinesCarousel({ children, gap, paddingHorizontal }: LinesCarouselProps): React.JSX.Element | null;
|
|
232
|
+
|
|
233
|
+
interface LineDetailSheetProps {
|
|
234
|
+
/** Snap points. Defaults to ["25%", "75%"]. */
|
|
235
|
+
snapPoints?: (string | number)[];
|
|
236
|
+
/** Override the header. Receives the active line. */
|
|
237
|
+
renderHeader?: (line: RetorLine) => React.ReactNode;
|
|
238
|
+
/** Custom content (typically a `<LineTagList>`). Defaults to a built-in tag list. */
|
|
239
|
+
children?: React.ReactNode;
|
|
103
240
|
}
|
|
104
241
|
/**
|
|
105
|
-
*
|
|
106
|
-
*
|
|
107
|
-
* the scene and tag lists. Persistence is handled entirely by your app:
|
|
108
|
-
* re-render with an updated `notes` array to sync changes.
|
|
242
|
+
* Sheet that auto-presents when the user enters a line. Shows the line's
|
|
243
|
+
* tags and a Done button. Pass `<LineTagList>` as a child to customise items.
|
|
109
244
|
*/
|
|
110
|
-
declare function
|
|
111
|
-
|
|
245
|
+
declare function LineDetailSheet({ snapPoints, renderHeader, children }: LineDetailSheetProps): React.JSX.Element;
|
|
246
|
+
interface LineTagListProps {
|
|
247
|
+
children: (tag: RetorTag, isActive: boolean) => React.ReactNode;
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Renders the tags of the active line as a vertical list. Re-renders the
|
|
251
|
+
* active item when the camera scrolls to it. Empty when no line is open.
|
|
252
|
+
*/
|
|
253
|
+
declare function LineTagList({ children }: LineTagListProps): React.JSX.Element | null;
|
|
254
|
+
|
|
255
|
+
interface AddNoteSheetProps {
|
|
256
|
+
/** Snap points. Defaults to ["50%"]. */
|
|
257
|
+
snapPoints?: (string | number)[];
|
|
258
|
+
/** Max characters allowed. Defaults to 280. */
|
|
259
|
+
maxLength?: number;
|
|
260
|
+
/** Placeholder text. */
|
|
261
|
+
placeholder?: string;
|
|
262
|
+
/** Override the entire form. Receives helpers + state. */
|
|
263
|
+
renderForm?: (api: AddNoteFormApi) => React.ReactNode;
|
|
264
|
+
}
|
|
265
|
+
interface AddNoteFormApi {
|
|
266
|
+
text: string;
|
|
267
|
+
setText: (v: string) => void;
|
|
268
|
+
isPrivate: boolean;
|
|
269
|
+
setPrivate: (v: boolean) => void;
|
|
270
|
+
submit: () => void;
|
|
271
|
+
close: () => void;
|
|
272
|
+
maxLength: number;
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Sheet for adding a note. Auto-presents when `useAddNote().open()` is called.
|
|
276
|
+
* On submit, fires `onNoteSubmit` on the parent `<Viewer>` with the text + position.
|
|
277
|
+
*/
|
|
278
|
+
declare function AddNoteSheet({ snapPoints, maxLength, placeholder, renderForm, }: AddNoteSheetProps): React.JSX.Element;
|
|
279
|
+
|
|
280
|
+
interface CoverPhotoProps {
|
|
281
|
+
projectId: string;
|
|
282
|
+
/** Base URL where Retor is hosted. Defaults to https://retor.app */
|
|
283
|
+
baseUrl?: string;
|
|
284
|
+
style?: StyleProp<ViewStyle>;
|
|
285
|
+
}
|
|
286
|
+
/**
|
|
287
|
+
* Renders a Retor project's start view as a static cover image.
|
|
288
|
+
* No 3D rendering, no bridge — use as a thumbnail or hero.
|
|
289
|
+
*/
|
|
290
|
+
declare function CoverPhoto({ projectId, baseUrl, style }: CoverPhotoProps): React.JSX.Element;
|
|
112
291
|
|
|
113
|
-
export { Hud, type InitPayload, type LineProgressPayload, Notes, type NotesProps, type RetorLine, type RetorProject, type RetorTag, Viewer, type ViewerHandle, type ViewerProps, useViewer };
|
|
292
|
+
export { type AddNoteFormApi, AddNoteSheet, type AddNoteSheetProps, 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 };
|