@retor/react-native 0.4.5 → 0.4.6

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 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?)` — 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>`.
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, useAddNote, type RetorTag } from "@retor/react-native";
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
- onNoteSubmit={({ text, isPrivate, tagId, lineId, position }) => {
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
@@ -36,6 +36,8 @@ interface RetorLine {
36
36
  scrollType?: "track" | "observe";
37
37
  closed?: boolean;
38
38
  notesSupported?: boolean;
39
+ /** User-defined key/value fields set in the line editor. */
40
+ metadata?: Record<string, string | number | boolean>;
39
41
  tags: RetorTag[];
40
42
  }
41
43
  interface RetorProject {
package/dist/index.d.ts CHANGED
@@ -36,6 +36,8 @@ interface RetorLine {
36
36
  scrollType?: "track" | "observe";
37
37
  closed?: boolean;
38
38
  notesSupported?: boolean;
39
+ /** User-defined key/value fields set in the line editor. */
40
+ metadata?: Record<string, string | number | boolean>;
39
41
  tags: RetorTag[];
40
42
  }
41
43
  interface RetorProject {
package/dist/index.js CHANGED
@@ -667,7 +667,7 @@ function LineDetailSheet({ snapPoints = ["35%", "75%"], topInset, renderHeader,
667
667
  backgroundComponent: BlurBackground,
668
668
  topInset: effectiveTopInset
669
669
  },
670
- activeLine && (children ?? /* @__PURE__ */ import_react6.default.createElement(DefaultLineTagList, { listHeader: header }))
670
+ activeLine && (children ? /* @__PURE__ */ import_react6.default.createElement(import_bottom_sheet3.BottomSheetScrollView, { contentContainerStyle: styles3.customContent }, children) : /* @__PURE__ */ import_react6.default.createElement(DefaultLineTagList, { listHeader: header }))
671
671
  );
672
672
  }
673
673
  function DefaultHeader({
@@ -792,6 +792,7 @@ function DefaultTagItem({ tag, isActive }) {
792
792
  }
793
793
  var styles3 = import_react_native5.StyleSheet.create({
794
794
  handle: { backgroundColor: "rgba(255,255,255,0.3)" },
795
+ customContent: { paddingBottom: 120 },
795
796
  header: {
796
797
  flexDirection: "row",
797
798
  alignItems: "flex-start",
package/dist/index.mjs CHANGED
@@ -628,7 +628,7 @@ function LineDetailSheet({ snapPoints = ["35%", "75%"], topInset, renderHeader,
628
628
  backgroundComponent: BlurBackground,
629
629
  topInset: effectiveTopInset
630
630
  },
631
- activeLine && (children ?? /* @__PURE__ */ React6.createElement(DefaultLineTagList, { listHeader: header }))
631
+ activeLine && (children ? /* @__PURE__ */ React6.createElement(BottomSheetScrollView, { contentContainerStyle: styles3.customContent }, children) : /* @__PURE__ */ React6.createElement(DefaultLineTagList, { listHeader: header }))
632
632
  );
633
633
  }
634
634
  function DefaultHeader({
@@ -753,6 +753,7 @@ function DefaultTagItem({ tag, isActive }) {
753
753
  }
754
754
  var styles3 = StyleSheet5.create({
755
755
  handle: { backgroundColor: "rgba(255,255,255,0.3)" },
756
+ customContent: { paddingBottom: 120 },
756
757
  header: {
757
758
  flexDirection: "row",
758
759
  alignItems: "flex-start",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@retor/react-native",
3
- "version": "0.4.5",
3
+ "version": "0.4.6",
4
4
  "description": "React Native SDK for embedding Retor 3D experiences",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",