@retor/react-native 0.4.5 → 0.5.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 +44 -19
- package/dist/index.d.mts +36 -0
- package/dist/index.d.ts +36 -0
- package/dist/index.js +98 -6
- package/dist/index.mjs +98 -6
- package/package.json +9 -7
package/README.md
CHANGED
|
@@ -111,24 +111,43 @@ function MyLineCard({ line }: { line: RetorLine }) {
|
|
|
111
111
|
|
|
112
112
|
## Notes
|
|
113
113
|
|
|
114
|
-
`<AddNoteSheet>` triggers when you call `useAddNote().open(tagId?)
|
|
114
|
+
`<AddNoteSheet>` triggers when you call `useAddNote().open(tagId?)`. It collects text + private/public, then either:
|
|
115
|
+
- calls `onNoteSubmit` on the parent `<Viewer>` (if set) — **persistence is your responsibility**
|
|
116
|
+
- or falls back to persisting via Retor's own backend (Convex) when no `onNoteSubmit` is provided
|
|
117
|
+
|
|
118
|
+
Re-pass saved notes back to the 3D scene via `<Notes>`.
|
|
119
|
+
|
|
120
|
+
### Note fields for proper rendering
|
|
121
|
+
|
|
122
|
+
When passing notes via `<Notes>`, each note should include:
|
|
123
|
+
|
|
124
|
+
| Field | Required | Purpose |
|
|
125
|
+
|-------|----------|---------|
|
|
126
|
+
| `_id` | yes | Unique identifier |
|
|
127
|
+
| `name` | yes | The note text (displayed in the tag list and 3D scene) |
|
|
128
|
+
| `position` | yes | `{ x, y, z }` — where the note sits on the line |
|
|
129
|
+
| `objectId` | yes | Set to the `lineId` so the note associates with the correct line |
|
|
130
|
+
| `progress` | yes | `0..1` position along the line (from the submit payload) — used for sort order and scroll-to |
|
|
131
|
+
| `avatarUrl` | recommended | Profile image URL — renders as a circular avatar in the tag pill and list item |
|
|
132
|
+
| `authorName` | recommended | Display name — used as initial-letter fallback when no `avatarUrl` |
|
|
133
|
+
| `tagType` | recommended | Set to `"icon"` for the standard note pill appearance |
|
|
134
|
+
| `userId` | for deletion | The note author's user ID — compared against `Viewer.userId` to show the delete button |
|
|
135
|
+
|
|
136
|
+
### Creating + deleting notes
|
|
115
137
|
|
|
116
138
|
```tsx
|
|
117
139
|
import { useState } from "react";
|
|
118
|
-
import { Viewer, Hud, ProjectSheet, LineDetailSheet, AddNoteSheet, Notes,
|
|
119
|
-
|
|
120
|
-
function AddButton() {
|
|
121
|
-
const { open } = useAddNote();
|
|
122
|
-
return <Pressable onPress={() => open()}><Text>+</Text></Pressable>;
|
|
123
|
-
}
|
|
140
|
+
import { Viewer, Hud, ProjectSheet, LineDetailSheet, AddNoteSheet, Notes, type RetorTag } from "@retor/react-native";
|
|
124
141
|
|
|
125
142
|
export default function Scene() {
|
|
126
143
|
const [notes, setNotes] = useState<RetorTag[]>([]);
|
|
144
|
+
const currentUserId = "user_abc"; // your auth system's user ID
|
|
127
145
|
|
|
128
146
|
return (
|
|
129
147
|
<Viewer
|
|
130
148
|
projectId="abc123"
|
|
131
|
-
|
|
149
|
+
userId={currentUserId}
|
|
150
|
+
onNoteSubmit={({ text, isPrivate, lineId, position, progress }) => {
|
|
132
151
|
if (!position) return;
|
|
133
152
|
setNotes((prev) => [
|
|
134
153
|
...prev,
|
|
@@ -136,24 +155,24 @@ export default function Scene() {
|
|
|
136
155
|
_id: `note-${Date.now()}`,
|
|
137
156
|
name: text,
|
|
138
157
|
position,
|
|
158
|
+
progress,
|
|
139
159
|
objectId: lineId ?? undefined,
|
|
160
|
+
tagType: "icon",
|
|
161
|
+
avatarUrl: "https://example.com/avatar.jpg",
|
|
162
|
+
authorName: "Jane",
|
|
163
|
+
userId: currentUserId,
|
|
140
164
|
},
|
|
141
165
|
]);
|
|
142
166
|
}}
|
|
167
|
+
onNoteDelete={(noteId) => {
|
|
168
|
+
setNotes((prev) => prev.filter((n) => n._id !== noteId));
|
|
169
|
+
// also delete from your backend
|
|
170
|
+
}}
|
|
143
171
|
>
|
|
144
172
|
<Notes notes={notes} />
|
|
145
173
|
<Hud>
|
|
146
174
|
<ProjectSheet />
|
|
147
|
-
<LineDetailSheet
|
|
148
|
-
<LineTagList>
|
|
149
|
-
{(tag, isActive) => (
|
|
150
|
-
<View style={{ flexDirection: "row", padding: 12 }}>
|
|
151
|
-
<Text style={{ flex: 1, color: isActive ? "white" : "gray" }}>{tag.name}</Text>
|
|
152
|
-
{isActive && <AddButton />}
|
|
153
|
-
</View>
|
|
154
|
-
)}
|
|
155
|
-
</LineTagList>
|
|
156
|
-
</LineDetailSheet>
|
|
175
|
+
<LineDetailSheet />
|
|
157
176
|
<AddNoteSheet />
|
|
158
177
|
</Hud>
|
|
159
178
|
</Viewer>
|
|
@@ -161,6 +180,12 @@ export default function Scene() {
|
|
|
161
180
|
}
|
|
162
181
|
```
|
|
163
182
|
|
|
183
|
+
When `onNoteSubmit` is **not** provided, the SDK sends the note to Retor's backend automatically (using the signed-in Clerk session inside the WebView). No `<Notes>` re-injection needed in that case.
|
|
184
|
+
|
|
185
|
+
When a user deletes a note, the SDK:
|
|
186
|
+
1. Optimistically removes it from the local tag list
|
|
187
|
+
2. Fires `onNoteDelete(noteId)` so you can delete from your backend
|
|
188
|
+
|
|
164
189
|
## Hooks
|
|
165
190
|
|
|
166
191
|
All hooks read from the bridge context provided by the parent `<Viewer>`.
|
|
@@ -173,7 +198,7 @@ All hooks read from the bridge context provided by the parent `<Viewer>`.
|
|
|
173
198
|
| `useLineProgress()` | `{ progress, closestTagId }` |
|
|
174
199
|
| `useAutoplay()` | `{ isPlaying, toggle, play, pause }` |
|
|
175
200
|
| `useAddNote()` | `{ isOpen, tagId, open, close, submit }` |
|
|
176
|
-
| `useViewer()` | Imperative controls (`openLine`, `exitLine`, `scrollToTag`, ...) |
|
|
201
|
+
| `useViewer()` | Imperative controls (`openLine`, `exitLine`, `scrollToTag`, `scrollToProgress`, ...) |
|
|
177
202
|
|
|
178
203
|
## Imperative API
|
|
179
204
|
|
package/dist/index.d.mts
CHANGED
|
@@ -25,6 +25,13 @@ interface RetorTag {
|
|
|
25
25
|
authorName?: string;
|
|
26
26
|
/** ID of the user who created this note. Compared against `Viewer.userId` to show the delete button. */
|
|
27
27
|
userId?: string;
|
|
28
|
+
/** Absolute elevation in meters (above the GPS reference's elevation datum, typically MSL).
|
|
29
|
+
* Null if the project isn't georeferenced or has too few reference points (<4 non-coplanar). */
|
|
30
|
+
elevationAboveSeaLevel?: number | null;
|
|
31
|
+
/** Cumulative distance along the parent line from start to this tag, in meters.
|
|
32
|
+
* Uses the same arc-length lookup as `LineProgressPayload.distanceFromStart`, so the
|
|
33
|
+
* values are directly comparable. Null if the project isn't georeferenced. */
|
|
34
|
+
distanceFromStart?: number | null;
|
|
28
35
|
}
|
|
29
36
|
interface RetorLine {
|
|
30
37
|
_id: string;
|
|
@@ -36,6 +43,8 @@ interface RetorLine {
|
|
|
36
43
|
scrollType?: "track" | "observe";
|
|
37
44
|
closed?: boolean;
|
|
38
45
|
notesSupported?: boolean;
|
|
46
|
+
/** User-defined key/value fields set in the line editor. */
|
|
47
|
+
metadata?: Record<string, string | number | boolean>;
|
|
39
48
|
tags: RetorTag[];
|
|
40
49
|
}
|
|
41
50
|
interface RetorProject {
|
|
@@ -60,6 +69,25 @@ interface LineProgressPayload {
|
|
|
60
69
|
/** Distance along the line from the start.
|
|
61
70
|
* In meters if GPS is configured on the project, else project-local units. */
|
|
62
71
|
distanceFromStart?: number | null;
|
|
72
|
+
/** Pitch of the line tangent above the ground plane at the current point, in degrees.
|
|
73
|
+
* Positive = uphill, negative = downhill. Null if the curve isn't ready. */
|
|
74
|
+
pitchDeg?: number | null;
|
|
75
|
+
/** Absolute elevation in meters at the current point. Requires a georeferenced
|
|
76
|
+
* project (coord tags with lat/lon/elevation); null otherwise. */
|
|
77
|
+
elevationM?: number | null;
|
|
78
|
+
/** Cursor latitude in degrees. Null if not georeferenced. */
|
|
79
|
+
lat?: number | null;
|
|
80
|
+
/** Cursor longitude in degrees. Null if not georeferenced. */
|
|
81
|
+
lon?: number | null;
|
|
82
|
+
/** Elevation difference (meters) between the cursor and the line's first control tag.
|
|
83
|
+
* Positive = above start, negative = below. Null if not georeferenced. */
|
|
84
|
+
elevationGainM?: number | null;
|
|
85
|
+
/** Length in meters of the split-section the cursor is currently inside. */
|
|
86
|
+
sectionLengthM?: number | null;
|
|
87
|
+
/** 1-based index of the current split-section (1 if the line has no splits). */
|
|
88
|
+
sectionIndex?: number | null;
|
|
89
|
+
/** 0..1 progress of the cursor within the current section. */
|
|
90
|
+
sectionProgress?: number | null;
|
|
63
91
|
}
|
|
64
92
|
interface ViewerHandle {
|
|
65
93
|
openLine: (lineId: string) => void;
|
|
@@ -140,6 +168,14 @@ declare function useLineProgress(): {
|
|
|
140
168
|
z: number;
|
|
141
169
|
} | null;
|
|
142
170
|
distanceFromStart: number | null;
|
|
171
|
+
pitchDeg: number | null;
|
|
172
|
+
elevationM: number | null;
|
|
173
|
+
lat: number | null;
|
|
174
|
+
lon: number | null;
|
|
175
|
+
elevationGainM: number | null;
|
|
176
|
+
sectionLengthM: number | null;
|
|
177
|
+
sectionIndex: number | null;
|
|
178
|
+
sectionProgress: number | null;
|
|
143
179
|
};
|
|
144
180
|
/**
|
|
145
181
|
* Returns the autoplay state and controls.
|
package/dist/index.d.ts
CHANGED
|
@@ -25,6 +25,13 @@ interface RetorTag {
|
|
|
25
25
|
authorName?: string;
|
|
26
26
|
/** ID of the user who created this note. Compared against `Viewer.userId` to show the delete button. */
|
|
27
27
|
userId?: string;
|
|
28
|
+
/** Absolute elevation in meters (above the GPS reference's elevation datum, typically MSL).
|
|
29
|
+
* Null if the project isn't georeferenced or has too few reference points (<4 non-coplanar). */
|
|
30
|
+
elevationAboveSeaLevel?: number | null;
|
|
31
|
+
/** Cumulative distance along the parent line from start to this tag, in meters.
|
|
32
|
+
* Uses the same arc-length lookup as `LineProgressPayload.distanceFromStart`, so the
|
|
33
|
+
* values are directly comparable. Null if the project isn't georeferenced. */
|
|
34
|
+
distanceFromStart?: number | null;
|
|
28
35
|
}
|
|
29
36
|
interface RetorLine {
|
|
30
37
|
_id: string;
|
|
@@ -36,6 +43,8 @@ interface RetorLine {
|
|
|
36
43
|
scrollType?: "track" | "observe";
|
|
37
44
|
closed?: boolean;
|
|
38
45
|
notesSupported?: boolean;
|
|
46
|
+
/** User-defined key/value fields set in the line editor. */
|
|
47
|
+
metadata?: Record<string, string | number | boolean>;
|
|
39
48
|
tags: RetorTag[];
|
|
40
49
|
}
|
|
41
50
|
interface RetorProject {
|
|
@@ -60,6 +69,25 @@ interface LineProgressPayload {
|
|
|
60
69
|
/** Distance along the line from the start.
|
|
61
70
|
* In meters if GPS is configured on the project, else project-local units. */
|
|
62
71
|
distanceFromStart?: number | null;
|
|
72
|
+
/** Pitch of the line tangent above the ground plane at the current point, in degrees.
|
|
73
|
+
* Positive = uphill, negative = downhill. Null if the curve isn't ready. */
|
|
74
|
+
pitchDeg?: number | null;
|
|
75
|
+
/** Absolute elevation in meters at the current point. Requires a georeferenced
|
|
76
|
+
* project (coord tags with lat/lon/elevation); null otherwise. */
|
|
77
|
+
elevationM?: number | null;
|
|
78
|
+
/** Cursor latitude in degrees. Null if not georeferenced. */
|
|
79
|
+
lat?: number | null;
|
|
80
|
+
/** Cursor longitude in degrees. Null if not georeferenced. */
|
|
81
|
+
lon?: number | null;
|
|
82
|
+
/** Elevation difference (meters) between the cursor and the line's first control tag.
|
|
83
|
+
* Positive = above start, negative = below. Null if not georeferenced. */
|
|
84
|
+
elevationGainM?: number | null;
|
|
85
|
+
/** Length in meters of the split-section the cursor is currently inside. */
|
|
86
|
+
sectionLengthM?: number | null;
|
|
87
|
+
/** 1-based index of the current split-section (1 if the line has no splits). */
|
|
88
|
+
sectionIndex?: number | null;
|
|
89
|
+
/** 0..1 progress of the cursor within the current section. */
|
|
90
|
+
sectionProgress?: number | null;
|
|
63
91
|
}
|
|
64
92
|
interface ViewerHandle {
|
|
65
93
|
openLine: (lineId: string) => void;
|
|
@@ -140,6 +168,14 @@ declare function useLineProgress(): {
|
|
|
140
168
|
z: number;
|
|
141
169
|
} | null;
|
|
142
170
|
distanceFromStart: number | null;
|
|
171
|
+
pitchDeg: number | null;
|
|
172
|
+
elevationM: number | null;
|
|
173
|
+
lat: number | null;
|
|
174
|
+
lon: number | null;
|
|
175
|
+
elevationGainM: number | null;
|
|
176
|
+
sectionLengthM: number | null;
|
|
177
|
+
sectionIndex: number | null;
|
|
178
|
+
sectionProgress: number | null;
|
|
143
179
|
};
|
|
144
180
|
/**
|
|
145
181
|
* Returns the autoplay state and controls.
|
package/dist/index.js
CHANGED
|
@@ -59,6 +59,14 @@ var RetorProgressContext = (0, import_react.createContext)({
|
|
|
59
59
|
closestTagId: null,
|
|
60
60
|
targetPosition: null,
|
|
61
61
|
distanceFromStart: null,
|
|
62
|
+
pitchDeg: null,
|
|
63
|
+
elevationM: null,
|
|
64
|
+
lat: null,
|
|
65
|
+
lon: null,
|
|
66
|
+
elevationGainM: null,
|
|
67
|
+
sectionLengthM: null,
|
|
68
|
+
sectionIndex: null,
|
|
69
|
+
sectionProgress: null,
|
|
62
70
|
isPlaying: false
|
|
63
71
|
});
|
|
64
72
|
function noop() {
|
|
@@ -103,10 +111,49 @@ function useActiveLine() {
|
|
|
103
111
|
return useRetorBridge().activeLine;
|
|
104
112
|
}
|
|
105
113
|
function useLineProgress() {
|
|
106
|
-
const {
|
|
114
|
+
const {
|
|
115
|
+
progress,
|
|
116
|
+
closestTagId,
|
|
117
|
+
targetPosition,
|
|
118
|
+
distanceFromStart,
|
|
119
|
+
pitchDeg,
|
|
120
|
+
elevationM,
|
|
121
|
+
lat,
|
|
122
|
+
lon,
|
|
123
|
+
elevationGainM,
|
|
124
|
+
sectionLengthM,
|
|
125
|
+
sectionIndex,
|
|
126
|
+
sectionProgress
|
|
127
|
+
} = useRetorProgress();
|
|
107
128
|
return (0, import_react.useMemo)(
|
|
108
|
-
() => ({
|
|
109
|
-
|
|
129
|
+
() => ({
|
|
130
|
+
progress,
|
|
131
|
+
closestTagId,
|
|
132
|
+
targetPosition,
|
|
133
|
+
distanceFromStart,
|
|
134
|
+
pitchDeg,
|
|
135
|
+
elevationM,
|
|
136
|
+
lat,
|
|
137
|
+
lon,
|
|
138
|
+
elevationGainM,
|
|
139
|
+
sectionLengthM,
|
|
140
|
+
sectionIndex,
|
|
141
|
+
sectionProgress
|
|
142
|
+
}),
|
|
143
|
+
[
|
|
144
|
+
progress,
|
|
145
|
+
closestTagId,
|
|
146
|
+
targetPosition,
|
|
147
|
+
distanceFromStart,
|
|
148
|
+
pitchDeg,
|
|
149
|
+
elevationM,
|
|
150
|
+
lat,
|
|
151
|
+
lon,
|
|
152
|
+
elevationGainM,
|
|
153
|
+
sectionLengthM,
|
|
154
|
+
sectionIndex,
|
|
155
|
+
sectionProgress
|
|
156
|
+
]
|
|
110
157
|
);
|
|
111
158
|
}
|
|
112
159
|
function useAutoplay() {
|
|
@@ -218,6 +265,14 @@ var Viewer = (0, import_react2.forwardRef)(function Viewer2({ projectId, id = "d
|
|
|
218
265
|
const [progress, setProgress] = (0, import_react2.useState)(0);
|
|
219
266
|
const [targetPosition, setTargetPosition] = (0, import_react2.useState)(null);
|
|
220
267
|
const [distanceFromStart, setDistanceFromStart] = (0, import_react2.useState)(null);
|
|
268
|
+
const [pitchDeg, setPitchDeg] = (0, import_react2.useState)(null);
|
|
269
|
+
const [elevationM, setElevationM] = (0, import_react2.useState)(null);
|
|
270
|
+
const [lat, setLat] = (0, import_react2.useState)(null);
|
|
271
|
+
const [lon, setLon] = (0, import_react2.useState)(null);
|
|
272
|
+
const [elevationGainM, setElevationGainM] = (0, import_react2.useState)(null);
|
|
273
|
+
const [sectionLengthM, setSectionLengthM] = (0, import_react2.useState)(null);
|
|
274
|
+
const [sectionIndex, setSectionIndex] = (0, import_react2.useState)(null);
|
|
275
|
+
const [sectionProgress, setSectionProgress] = (0, import_react2.useState)(null);
|
|
221
276
|
const [isPlaying, setIsPlaying] = (0, import_react2.useState)(false);
|
|
222
277
|
const [isAddNoteOpen, setIsAddNoteOpen] = (0, import_react2.useState)(false);
|
|
223
278
|
const [addNoteTagId, setAddNoteTagId] = (0, import_react2.useState)(null);
|
|
@@ -366,6 +421,14 @@ var Viewer = (0, import_react2.forwardRef)(function Viewer2({ projectId, id = "d
|
|
|
366
421
|
setClosestTagId(payload.closestTagId);
|
|
367
422
|
setTargetPosition(payload.targetPosition ?? null);
|
|
368
423
|
setDistanceFromStart(payload.distanceFromStart ?? null);
|
|
424
|
+
setPitchDeg(payload.pitchDeg ?? null);
|
|
425
|
+
setElevationM(payload.elevationM ?? null);
|
|
426
|
+
setLat(payload.lat ?? null);
|
|
427
|
+
setLon(payload.lon ?? null);
|
|
428
|
+
setElevationGainM(payload.elevationGainM ?? null);
|
|
429
|
+
setSectionLengthM(payload.sectionLengthM ?? null);
|
|
430
|
+
setSectionIndex(payload.sectionIndex ?? null);
|
|
431
|
+
setSectionProgress(payload.sectionProgress ?? null);
|
|
369
432
|
onLineProgress?.(payload);
|
|
370
433
|
break;
|
|
371
434
|
}
|
|
@@ -413,8 +476,36 @@ var Viewer = (0, import_react2.forwardRef)(function Viewer2({ projectId, id = "d
|
|
|
413
476
|
[project, lines, activeLineId, activeLine, lineNotes, externalNotes, userId, isAddNoteOpen, addNoteTagId, controls, openAddNote, closeAddNote, submitNote, deleteNote]
|
|
414
477
|
);
|
|
415
478
|
const progressCtx = (0, import_react2.useMemo)(
|
|
416
|
-
() => ({
|
|
417
|
-
|
|
479
|
+
() => ({
|
|
480
|
+
progress,
|
|
481
|
+
closestTagId,
|
|
482
|
+
targetPosition,
|
|
483
|
+
distanceFromStart,
|
|
484
|
+
pitchDeg,
|
|
485
|
+
elevationM,
|
|
486
|
+
lat,
|
|
487
|
+
lon,
|
|
488
|
+
elevationGainM,
|
|
489
|
+
sectionLengthM,
|
|
490
|
+
sectionIndex,
|
|
491
|
+
sectionProgress,
|
|
492
|
+
isPlaying
|
|
493
|
+
}),
|
|
494
|
+
[
|
|
495
|
+
progress,
|
|
496
|
+
closestTagId,
|
|
497
|
+
targetPosition,
|
|
498
|
+
distanceFromStart,
|
|
499
|
+
pitchDeg,
|
|
500
|
+
elevationM,
|
|
501
|
+
lat,
|
|
502
|
+
lon,
|
|
503
|
+
elevationGainM,
|
|
504
|
+
sectionLengthM,
|
|
505
|
+
sectionIndex,
|
|
506
|
+
sectionProgress,
|
|
507
|
+
isPlaying
|
|
508
|
+
]
|
|
418
509
|
);
|
|
419
510
|
return /* @__PURE__ */ import_react2.default.createElement(RetorBridgeProvider, { value: ctxValue }, /* @__PURE__ */ import_react2.default.createElement(RetorProgressProvider, { value: progressCtx }, /* @__PURE__ */ import_react2.default.createElement(import_react_native.View, { style: [styles.root, style] }, /* @__PURE__ */ import_react2.default.createElement(
|
|
420
511
|
import_react_native_webview.WebView,
|
|
@@ -667,7 +758,7 @@ function LineDetailSheet({ snapPoints = ["35%", "75%"], topInset, renderHeader,
|
|
|
667
758
|
backgroundComponent: BlurBackground,
|
|
668
759
|
topInset: effectiveTopInset
|
|
669
760
|
},
|
|
670
|
-
activeLine && (children
|
|
761
|
+
activeLine && (children ? /* @__PURE__ */ import_react6.default.createElement(import_bottom_sheet3.BottomSheetScrollView, { contentContainerStyle: styles3.customContent }, children) : /* @__PURE__ */ import_react6.default.createElement(DefaultLineTagList, { listHeader: header }))
|
|
671
762
|
);
|
|
672
763
|
}
|
|
673
764
|
function DefaultHeader({
|
|
@@ -792,6 +883,7 @@ function DefaultTagItem({ tag, isActive }) {
|
|
|
792
883
|
}
|
|
793
884
|
var styles3 = import_react_native5.StyleSheet.create({
|
|
794
885
|
handle: { backgroundColor: "rgba(255,255,255,0.3)" },
|
|
886
|
+
customContent: { paddingBottom: 120 },
|
|
795
887
|
header: {
|
|
796
888
|
flexDirection: "row",
|
|
797
889
|
alignItems: "flex-start",
|
package/dist/index.mjs
CHANGED
|
@@ -6,6 +6,14 @@ var RetorProgressContext = createContext({
|
|
|
6
6
|
closestTagId: null,
|
|
7
7
|
targetPosition: null,
|
|
8
8
|
distanceFromStart: null,
|
|
9
|
+
pitchDeg: null,
|
|
10
|
+
elevationM: null,
|
|
11
|
+
lat: null,
|
|
12
|
+
lon: null,
|
|
13
|
+
elevationGainM: null,
|
|
14
|
+
sectionLengthM: null,
|
|
15
|
+
sectionIndex: null,
|
|
16
|
+
sectionProgress: null,
|
|
9
17
|
isPlaying: false
|
|
10
18
|
});
|
|
11
19
|
function noop() {
|
|
@@ -50,10 +58,49 @@ function useActiveLine() {
|
|
|
50
58
|
return useRetorBridge().activeLine;
|
|
51
59
|
}
|
|
52
60
|
function useLineProgress() {
|
|
53
|
-
const {
|
|
61
|
+
const {
|
|
62
|
+
progress,
|
|
63
|
+
closestTagId,
|
|
64
|
+
targetPosition,
|
|
65
|
+
distanceFromStart,
|
|
66
|
+
pitchDeg,
|
|
67
|
+
elevationM,
|
|
68
|
+
lat,
|
|
69
|
+
lon,
|
|
70
|
+
elevationGainM,
|
|
71
|
+
sectionLengthM,
|
|
72
|
+
sectionIndex,
|
|
73
|
+
sectionProgress
|
|
74
|
+
} = useRetorProgress();
|
|
54
75
|
return useMemo(
|
|
55
|
-
() => ({
|
|
56
|
-
|
|
76
|
+
() => ({
|
|
77
|
+
progress,
|
|
78
|
+
closestTagId,
|
|
79
|
+
targetPosition,
|
|
80
|
+
distanceFromStart,
|
|
81
|
+
pitchDeg,
|
|
82
|
+
elevationM,
|
|
83
|
+
lat,
|
|
84
|
+
lon,
|
|
85
|
+
elevationGainM,
|
|
86
|
+
sectionLengthM,
|
|
87
|
+
sectionIndex,
|
|
88
|
+
sectionProgress
|
|
89
|
+
}),
|
|
90
|
+
[
|
|
91
|
+
progress,
|
|
92
|
+
closestTagId,
|
|
93
|
+
targetPosition,
|
|
94
|
+
distanceFromStart,
|
|
95
|
+
pitchDeg,
|
|
96
|
+
elevationM,
|
|
97
|
+
lat,
|
|
98
|
+
lon,
|
|
99
|
+
elevationGainM,
|
|
100
|
+
sectionLengthM,
|
|
101
|
+
sectionIndex,
|
|
102
|
+
sectionProgress
|
|
103
|
+
]
|
|
57
104
|
);
|
|
58
105
|
}
|
|
59
106
|
function useAutoplay() {
|
|
@@ -174,6 +221,14 @@ var Viewer = forwardRef(function Viewer2({ projectId, id = "default", baseUrl =
|
|
|
174
221
|
const [progress, setProgress] = useState(0);
|
|
175
222
|
const [targetPosition, setTargetPosition] = useState(null);
|
|
176
223
|
const [distanceFromStart, setDistanceFromStart] = useState(null);
|
|
224
|
+
const [pitchDeg, setPitchDeg] = useState(null);
|
|
225
|
+
const [elevationM, setElevationM] = useState(null);
|
|
226
|
+
const [lat, setLat] = useState(null);
|
|
227
|
+
const [lon, setLon] = useState(null);
|
|
228
|
+
const [elevationGainM, setElevationGainM] = useState(null);
|
|
229
|
+
const [sectionLengthM, setSectionLengthM] = useState(null);
|
|
230
|
+
const [sectionIndex, setSectionIndex] = useState(null);
|
|
231
|
+
const [sectionProgress, setSectionProgress] = useState(null);
|
|
177
232
|
const [isPlaying, setIsPlaying] = useState(false);
|
|
178
233
|
const [isAddNoteOpen, setIsAddNoteOpen] = useState(false);
|
|
179
234
|
const [addNoteTagId, setAddNoteTagId] = useState(null);
|
|
@@ -322,6 +377,14 @@ var Viewer = forwardRef(function Viewer2({ projectId, id = "default", baseUrl =
|
|
|
322
377
|
setClosestTagId(payload.closestTagId);
|
|
323
378
|
setTargetPosition(payload.targetPosition ?? null);
|
|
324
379
|
setDistanceFromStart(payload.distanceFromStart ?? null);
|
|
380
|
+
setPitchDeg(payload.pitchDeg ?? null);
|
|
381
|
+
setElevationM(payload.elevationM ?? null);
|
|
382
|
+
setLat(payload.lat ?? null);
|
|
383
|
+
setLon(payload.lon ?? null);
|
|
384
|
+
setElevationGainM(payload.elevationGainM ?? null);
|
|
385
|
+
setSectionLengthM(payload.sectionLengthM ?? null);
|
|
386
|
+
setSectionIndex(payload.sectionIndex ?? null);
|
|
387
|
+
setSectionProgress(payload.sectionProgress ?? null);
|
|
325
388
|
onLineProgress?.(payload);
|
|
326
389
|
break;
|
|
327
390
|
}
|
|
@@ -369,8 +432,36 @@ var Viewer = forwardRef(function Viewer2({ projectId, id = "default", baseUrl =
|
|
|
369
432
|
[project, lines, activeLineId, activeLine, lineNotes, externalNotes, userId, isAddNoteOpen, addNoteTagId, controls, openAddNote, closeAddNote, submitNote, deleteNote]
|
|
370
433
|
);
|
|
371
434
|
const progressCtx = useMemo2(
|
|
372
|
-
() => ({
|
|
373
|
-
|
|
435
|
+
() => ({
|
|
436
|
+
progress,
|
|
437
|
+
closestTagId,
|
|
438
|
+
targetPosition,
|
|
439
|
+
distanceFromStart,
|
|
440
|
+
pitchDeg,
|
|
441
|
+
elevationM,
|
|
442
|
+
lat,
|
|
443
|
+
lon,
|
|
444
|
+
elevationGainM,
|
|
445
|
+
sectionLengthM,
|
|
446
|
+
sectionIndex,
|
|
447
|
+
sectionProgress,
|
|
448
|
+
isPlaying
|
|
449
|
+
}),
|
|
450
|
+
[
|
|
451
|
+
progress,
|
|
452
|
+
closestTagId,
|
|
453
|
+
targetPosition,
|
|
454
|
+
distanceFromStart,
|
|
455
|
+
pitchDeg,
|
|
456
|
+
elevationM,
|
|
457
|
+
lat,
|
|
458
|
+
lon,
|
|
459
|
+
elevationGainM,
|
|
460
|
+
sectionLengthM,
|
|
461
|
+
sectionIndex,
|
|
462
|
+
sectionProgress,
|
|
463
|
+
isPlaying
|
|
464
|
+
]
|
|
374
465
|
);
|
|
375
466
|
return /* @__PURE__ */ React2.createElement(RetorBridgeProvider, { value: ctxValue }, /* @__PURE__ */ React2.createElement(RetorProgressProvider, { value: progressCtx }, /* @__PURE__ */ React2.createElement(View, { style: [styles.root, style] }, /* @__PURE__ */ React2.createElement(
|
|
376
467
|
WebView,
|
|
@@ -628,7 +719,7 @@ function LineDetailSheet({ snapPoints = ["35%", "75%"], topInset, renderHeader,
|
|
|
628
719
|
backgroundComponent: BlurBackground,
|
|
629
720
|
topInset: effectiveTopInset
|
|
630
721
|
},
|
|
631
|
-
activeLine && (children
|
|
722
|
+
activeLine && (children ? /* @__PURE__ */ React6.createElement(BottomSheetScrollView, { contentContainerStyle: styles3.customContent }, children) : /* @__PURE__ */ React6.createElement(DefaultLineTagList, { listHeader: header }))
|
|
632
723
|
);
|
|
633
724
|
}
|
|
634
725
|
function DefaultHeader({
|
|
@@ -753,6 +844,7 @@ function DefaultTagItem({ tag, isActive }) {
|
|
|
753
844
|
}
|
|
754
845
|
var styles3 = StyleSheet5.create({
|
|
755
846
|
handle: { backgroundColor: "rgba(255,255,255,0.3)" },
|
|
847
|
+
customContent: { paddingBottom: 120 },
|
|
756
848
|
header: {
|
|
757
849
|
flexDirection: "row",
|
|
758
850
|
alignItems: "flex-start",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@retor/react-native",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "React Native SDK for embedding Retor 3D experiences",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -17,6 +17,12 @@
|
|
|
17
17
|
"README.md",
|
|
18
18
|
"LICENSE"
|
|
19
19
|
],
|
|
20
|
+
"scripts": {
|
|
21
|
+
"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",
|
|
22
|
+
"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",
|
|
23
|
+
"typecheck": "tsc --noEmit",
|
|
24
|
+
"prepublishOnly": "pnpm build"
|
|
25
|
+
},
|
|
20
26
|
"keywords": [
|
|
21
27
|
"retor",
|
|
22
28
|
"3d",
|
|
@@ -55,9 +61,5 @@
|
|
|
55
61
|
"tsup": "^8.0.0",
|
|
56
62
|
"typescript": "^5.4.0"
|
|
57
63
|
},
|
|
58
|
-
"
|
|
59
|
-
|
|
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",
|
|
61
|
-
"typecheck": "tsc --noEmit"
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
+
"packageManager": "pnpm@9.12.3+sha512.cce0f9de9c5a7c95bef944169cc5dfe8741abfb145078c0d508b868056848a87c81e626246cb60967cbd7fd29a6c062ef73ff840d96b3c86c40ac92cf4a813ee"
|
|
65
|
+
}
|