jazz-tools 0.19.1 → 0.19.3

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.
Files changed (67) hide show
  1. package/.turbo/turbo-build.log +63 -63
  2. package/CHANGELOG.md +21 -0
  3. package/dist/{chunk-NCNM6UDZ.js → chunk-JPWM4CS2.js} +4 -2
  4. package/dist/{chunk-NCNM6UDZ.js.map → chunk-JPWM4CS2.js.map} +1 -1
  5. package/dist/index.js +1 -1
  6. package/dist/inspector/{custom-element-QESCMFY7.js → custom-element-3JAYHXWQ.js} +1134 -464
  7. package/dist/inspector/custom-element-3JAYHXWQ.js.map +1 -0
  8. package/dist/inspector/index.js +1104 -434
  9. package/dist/inspector/index.js.map +1 -1
  10. package/dist/inspector/register-custom-element.js +1 -1
  11. package/dist/inspector/tests/utils/history.test.d.ts +2 -0
  12. package/dist/inspector/tests/utils/history.test.d.ts.map +1 -0
  13. package/dist/inspector/tests/viewer/co-value-editor.test.d.ts +2 -0
  14. package/dist/inspector/tests/viewer/co-value-editor.test.d.ts.map +1 -0
  15. package/dist/inspector/tests/viewer/comap-view.test.d.ts +2 -0
  16. package/dist/inspector/tests/viewer/comap-view.test.d.ts.map +1 -0
  17. package/dist/inspector/ui/icon.d.ts +6 -0
  18. package/dist/inspector/ui/icon.d.ts.map +1 -1
  19. package/dist/inspector/ui/icons/add-icon.d.ts +2 -0
  20. package/dist/inspector/ui/icons/add-icon.d.ts.map +1 -0
  21. package/dist/inspector/ui/icons/edit-icon.d.ts +2 -0
  22. package/dist/inspector/ui/icons/edit-icon.d.ts.map +1 -0
  23. package/dist/inspector/ui/icons/history.d.ts +2 -0
  24. package/dist/inspector/ui/icons/history.d.ts.map +1 -0
  25. package/dist/inspector/utils/history.d.ts +3 -0
  26. package/dist/inspector/utils/history.d.ts.map +1 -0
  27. package/dist/inspector/utils/permissions.d.ts +3 -0
  28. package/dist/inspector/utils/permissions.d.ts.map +1 -0
  29. package/dist/inspector/utils/transactions-changes.d.ts +38 -0
  30. package/dist/inspector/utils/transactions-changes.d.ts.map +1 -0
  31. package/dist/inspector/viewer/co-map-view.d.ts +9 -0
  32. package/dist/inspector/viewer/co-map-view.d.ts.map +1 -0
  33. package/dist/inspector/viewer/co-value-editor.d.ts +10 -0
  34. package/dist/inspector/viewer/co-value-editor.d.ts.map +1 -0
  35. package/dist/inspector/viewer/grid-view.d.ts +3 -2
  36. package/dist/inspector/viewer/grid-view.d.ts.map +1 -1
  37. package/dist/inspector/viewer/history-view.d.ts.map +1 -1
  38. package/dist/inspector/viewer/page.d.ts.map +1 -1
  39. package/dist/testing.js +1 -1
  40. package/dist/tools/coValues/CoFieldInit.d.ts +2 -1
  41. package/dist/tools/coValues/CoFieldInit.d.ts.map +1 -1
  42. package/dist/tools/implementation/zodSchema/typeConverters/CoFieldSchemaInit.d.ts +3 -2
  43. package/dist/tools/implementation/zodSchema/typeConverters/CoFieldSchemaInit.d.ts.map +1 -1
  44. package/dist/tools/implementation/zodSchema/unionUtils.d.ts.map +1 -1
  45. package/package.json +4 -4
  46. package/src/inspector/tests/utils/history.test.ts +401 -0
  47. package/src/inspector/tests/viewer/co-value-editor.test.tsx +903 -0
  48. package/src/inspector/tests/viewer/comap-view.test.tsx +889 -0
  49. package/src/inspector/ui/icon.tsx +6 -0
  50. package/src/inspector/ui/icons/add-icon.tsx +21 -0
  51. package/src/inspector/ui/icons/edit-icon.tsx +17 -0
  52. package/src/inspector/ui/icons/history.tsx +28 -0
  53. package/src/inspector/ui/modal.tsx +3 -3
  54. package/src/inspector/utils/history.ts +49 -0
  55. package/src/inspector/utils/permissions.ts +10 -0
  56. package/src/inspector/utils/transactions-changes.ts +98 -0
  57. package/src/inspector/viewer/co-map-view.tsx +324 -0
  58. package/src/inspector/viewer/co-value-editor.tsx +164 -0
  59. package/src/inspector/viewer/grid-view.tsx +140 -10
  60. package/src/inspector/viewer/history-view.tsx +19 -119
  61. package/src/inspector/viewer/page.tsx +13 -0
  62. package/src/react-core/tests/usePassPhraseAuth.test.ts +1 -1
  63. package/src/tools/coValues/CoFieldInit.ts +6 -3
  64. package/src/tools/implementation/zodSchema/typeConverters/CoFieldSchemaInit.ts +12 -7
  65. package/src/tools/implementation/zodSchema/unionUtils.ts +3 -4
  66. package/src/tools/tests/coVector.test.ts +43 -0
  67. package/dist/inspector/custom-element-QESCMFY7.js.map +0 -1
@@ -0,0 +1,164 @@
1
+ import { LocalNode, RawCoValue } from "cojson";
2
+ import { JsonValue } from "cojson";
3
+ import { useState } from "react";
4
+ import { styled } from "goober";
5
+ import { Button } from "../ui/button.js";
6
+ import { Select } from "../ui/select.js";
7
+
8
+ type ValueType =
9
+ | "number"
10
+ | "string"
11
+ | "true"
12
+ | "false"
13
+ | "object"
14
+ | "null"
15
+ | "undefined";
16
+
17
+ export function CoValueEditor({
18
+ node,
19
+ property,
20
+ value,
21
+ coValue,
22
+ onCancel,
23
+ }: {
24
+ node: LocalNode;
25
+ property: string;
26
+ value: JsonValue | undefined;
27
+ coValue: RawCoValue;
28
+ onCancel: () => void;
29
+ }) {
30
+ const getInitialType = (): ValueType => {
31
+ if (value === null) return "null";
32
+ if (value === undefined) return "undefined";
33
+ if (typeof value === "number") return "number";
34
+ if (typeof value === "string") return "string";
35
+ if (typeof value === "boolean") return value ? "true" : "false";
36
+ if (typeof value === "object") return "object";
37
+ return "undefined";
38
+ };
39
+
40
+ const [selectedType, setSelectedType] = useState<ValueType>(getInitialType());
41
+ const [editValue, setEditValue] = useState(
42
+ value === undefined || value === null
43
+ ? ""
44
+ : typeof value === "object"
45
+ ? JSON.stringify(value, null, 2)
46
+ : String(value),
47
+ );
48
+
49
+ const handleSubmit = (e: React.FormEvent) => {
50
+ e.preventDefault();
51
+ e.stopPropagation();
52
+
53
+ let newValue;
54
+ switch (selectedType) {
55
+ case "null":
56
+ newValue = null;
57
+ break;
58
+ case "undefined":
59
+ newValue = undefined;
60
+ break;
61
+ case "true":
62
+ newValue = true;
63
+ break;
64
+ case "false":
65
+ newValue = false;
66
+ break;
67
+ case "number":
68
+ newValue = parseFloat(editValue);
69
+ break;
70
+ case "string":
71
+ newValue = editValue;
72
+ break;
73
+ case "object":
74
+ newValue = JSON.parse(editValue);
75
+ break;
76
+ default:
77
+ throw new Error(`Invalid type: ${selectedType}`);
78
+ }
79
+
80
+ coValue.core.makeTransaction(
81
+ [
82
+ {
83
+ op: "set",
84
+ key: property,
85
+ value: newValue,
86
+ },
87
+ ],
88
+ "private",
89
+ );
90
+
91
+ onCancel();
92
+ };
93
+
94
+ const showTextarea =
95
+ selectedType === "number" ||
96
+ selectedType === "string" ||
97
+ selectedType === "object";
98
+
99
+ return (
100
+ <EditForm onSubmit={handleSubmit}>
101
+ <Select
102
+ label="Type"
103
+ value={selectedType}
104
+ onChange={(e) => {
105
+ setSelectedType(e.target.value as ValueType);
106
+ }}
107
+ onClick={(e) => e.stopPropagation()}
108
+ >
109
+ <option value="number">number</option>
110
+ <option value="string">string</option>
111
+ <option value="true">true</option>
112
+ <option value="false">false</option>
113
+ <option value="object">object</option>
114
+ <option value="null">null</option>
115
+ <option value="undefined">undefined</option>
116
+ </Select>
117
+ {showTextarea && (
118
+ <StyledTextarea
119
+ value={editValue}
120
+ onChange={(e) => setEditValue(e.target.value)}
121
+ onClick={(e) => e.stopPropagation()}
122
+ />
123
+ )}
124
+ <FormActions>
125
+ <Button type="button" variant="secondary" onClick={onCancel}>
126
+ Cancel
127
+ </Button>
128
+ <Button type="submit" variant="primary">
129
+ Submit
130
+ </Button>
131
+ </FormActions>
132
+ </EditForm>
133
+ );
134
+ }
135
+
136
+ const EditForm = styled("form")`
137
+ display: flex;
138
+ flex-direction: column;
139
+ gap: 0.75rem;
140
+ `;
141
+
142
+ const StyledTextarea = styled("textarea")`
143
+ width: 100%;
144
+ min-height: 120px;
145
+ border-radius: var(--j-radius-md);
146
+ border: 1px solid var(--j-border-color);
147
+ padding: 0.5rem 0.875rem;
148
+ box-shadow: var(--j-shadow-sm);
149
+ font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
150
+ font-size: 0.875rem;
151
+ background-color: white;
152
+ color: var(--j-text-color-strong);
153
+ resize: vertical;
154
+
155
+ @media (prefers-color-scheme: dark) {
156
+ background-color: var(--j-foreground);
157
+ }
158
+ `;
159
+
160
+ const FormActions = styled("div")`
161
+ display: flex;
162
+ gap: 0.5rem;
163
+ justify-content: flex-end;
164
+ `;
@@ -1,27 +1,94 @@
1
1
  import { CoID, LocalNode, RawCoValue } from "cojson";
2
2
  import { JsonObject, JsonValue } from "cojson";
3
+ import { useState } from "react";
4
+ import { styled } from "goober";
3
5
  import { ResolveIcon } from "./type-icon.js";
4
6
  import { PageInfo, isCoId } from "./types.js";
5
7
  import { CoMapPreview, ValueRenderer } from "./value-renderer.js";
8
+ import { CoValueEditor } from "./co-value-editor.js";
6
9
 
7
10
  import { Badge } from "../ui/badge.js";
8
11
  import { Card, CardBody, CardHeader } from "../ui/card.js";
9
12
  import { Grid } from "../ui/grid.js";
13
+ import { Icon } from "../ui/icon.js";
10
14
  import { Text } from "../ui/text.js";
15
+ import { isWriter } from "../utils/permissions.js";
11
16
 
12
17
  function GridItem({
13
18
  entry,
14
19
  onNavigate,
15
20
  node,
21
+ coValue,
16
22
  }: {
17
23
  entry: [string, JsonValue | undefined];
18
24
  onNavigate: (pages: PageInfo[]) => void;
19
25
  node: LocalNode;
26
+ coValue?: RawCoValue;
20
27
  }) {
21
28
  const [key, value] = entry;
22
29
  const isCoValue = isCoId(value);
30
+ const [isEditing, setIsEditing] = useState(false);
23
31
 
24
- const props = isCoValue
32
+ const handleEditClick = (e: React.MouseEvent) => {
33
+ e.stopPropagation();
34
+ setIsEditing(true);
35
+ };
36
+
37
+ const handleCancel = () => {
38
+ setIsEditing(false);
39
+ };
40
+
41
+ const handleDelete = (e: React.MouseEvent) => {
42
+ e.stopPropagation();
43
+ if (confirm(`Are you sure you want to delete the property "${key}"?`)) {
44
+ coValue?.core.makeTransaction(
45
+ [
46
+ {
47
+ op: "del",
48
+ key,
49
+ },
50
+ ],
51
+ "private",
52
+ );
53
+ }
54
+ };
55
+
56
+ if (isEditing) {
57
+ return (
58
+ <Card
59
+ style={{
60
+ backgroundColor: "var(--j-foreground)",
61
+ borderColor: "var(--j-foreground)",
62
+ }}
63
+ >
64
+ <CardHeader>
65
+ <div style={{ display: "flex", alignItems: "center", gap: "0.5rem" }}>
66
+ {isCoValue ? (
67
+ <>
68
+ <Text strong>{key}</Text>
69
+ <Badge>
70
+ <ResolveIcon coId={value as CoID<RawCoValue>} node={node} />
71
+ </Badge>
72
+ </>
73
+ ) : (
74
+ <Text strong>{key}</Text>
75
+ )}
76
+ </div>
77
+ </CardHeader>
78
+ <CardBody style={{ wordBreak: "break-word" }}>
79
+ <CoValueEditor
80
+ node={node}
81
+ property={key}
82
+ value={value}
83
+ coValue={coValue!}
84
+ onCancel={handleCancel}
85
+ />
86
+ </CardBody>
87
+ </Card>
88
+ );
89
+ }
90
+
91
+ const cardProps = isCoValue
25
92
  ? {
26
93
  onClick: () =>
27
94
  onNavigate([{ coId: value as CoID<RawCoValue>, name: key }]),
@@ -35,17 +102,37 @@ function GridItem({
35
102
  };
36
103
 
37
104
  return (
38
- <Card {...props}>
105
+ <Card {...cardProps}>
39
106
  <CardHeader>
40
- {isCoValue ? (
41
- <>
107
+ <div style={{ display: "flex", alignItems: "center", gap: "0.5rem" }}>
108
+ {isCoValue ? (
109
+ <>
110
+ <Text strong>{key}</Text>
111
+ <Badge>
112
+ <ResolveIcon coId={value as CoID<RawCoValue>} node={node} />
113
+ </Badge>
114
+ </>
115
+ ) : (
42
116
  <Text strong>{key}</Text>
43
- <Badge>
44
- <ResolveIcon coId={value as CoID<RawCoValue>} node={node} />
45
- </Badge>
46
- </>
47
- ) : (
48
- <Text strong>{key}</Text>
117
+ )}
118
+ </div>
119
+ {coValue && isWriter(coValue.group.myRole()) && (
120
+ <ActionButtons>
121
+ <EditButton
122
+ onClick={handleEditClick}
123
+ type="button"
124
+ aria-label="Edit"
125
+ >
126
+ <Icon name="edit" size="sm" />
127
+ </EditButton>
128
+ <DeleteButton
129
+ onClick={handleDelete}
130
+ type="button"
131
+ aria-label="Delete"
132
+ >
133
+ <Icon name="delete" size="sm" />
134
+ </DeleteButton>
135
+ </ActionButtons>
49
136
  )}
50
137
  </CardHeader>
51
138
  <CardBody style={{ wordBreak: "break-word" }}>
@@ -68,10 +155,12 @@ export function GridView({
68
155
  data,
69
156
  onNavigate,
70
157
  node,
158
+ coValue,
71
159
  }: {
72
160
  data: JsonObject;
73
161
  onNavigate: (pages: PageInfo[]) => void;
74
162
  node: LocalNode;
163
+ coValue?: RawCoValue;
75
164
  }) {
76
165
  const entries = Object.entries(data);
77
166
 
@@ -82,9 +171,50 @@ export function GridView({
82
171
  entry={entry}
83
172
  onNavigate={onNavigate}
84
173
  node={node}
174
+ coValue={coValue}
85
175
  key={childIndex}
86
176
  />
87
177
  ))}
88
178
  </Grid>
89
179
  );
90
180
  }
181
+
182
+ const EditButton = styled("button")`
183
+ display: inline-flex;
184
+ align-items: center;
185
+ justify-content: center;
186
+ padding: 0.25rem;
187
+ border: none;
188
+ background: transparent;
189
+ cursor: pointer;
190
+ color: var(--j-text-color);
191
+ border-radius: var(--j-radius-sm);
192
+ transition: background-color 0.2s;
193
+
194
+ &:hover {
195
+ background-color: var(--j-foreground);
196
+ }
197
+ `;
198
+
199
+ const DeleteButton = styled("button")`
200
+ display: inline-flex;
201
+ align-items: center;
202
+ justify-content: center;
203
+ padding: 0.25rem;
204
+ border: none;
205
+ background: transparent;
206
+ cursor: pointer;
207
+ color: var(--j-text-color);
208
+ border-radius: var(--j-radius-sm);
209
+ transition: background-color 0.2s;
210
+
211
+ &:hover {
212
+ background-color: var(--j-foreground);
213
+ }
214
+ `;
215
+
216
+ const ActionButtons = styled("div")`
217
+ display: flex;
218
+ align-items: center;
219
+ gap: 0.25rem;
220
+ `;
@@ -1,29 +1,11 @@
1
- import {
2
- AccountRole,
3
- BinaryStreamStart,
4
- CoID,
5
- JsonValue,
6
- LocalNode,
7
- OpID,
8
- RawCoValue,
9
- Role,
10
- } from "cojson";
1
+ import { CoID, JsonValue, LocalNode, OpID, RawCoValue } from "cojson";
11
2
  import { useMemo } from "react";
12
3
  import { styled } from "goober";
13
- import { isCoId } from "./types";
14
4
  import { AccountOrGroupText } from "./account-or-group-text";
15
5
  import { DataTable, ColumnDef } from "../ui/data-table";
16
- import { MapOpPayload } from "cojson/dist/coValues/coMap.js";
17
- import {
18
- DeletionOpPayload,
19
- InsertionOpPayload,
20
- } from "cojson/dist/coValues/coList.js";
21
- import {
22
- BinaryStreamChunk,
23
- BinaryStreamEnd,
24
- } from "cojson/dist/coValues/coStream.js";
25
- import { VerifiedTransaction } from "cojson/dist/coValueCore/coValueCore.js";
6
+ import type { VerifiedTransaction } from "cojson/dist/coValueCore/coValueCore.js";
26
7
  import { Icon, Accordion } from "../ui";
8
+ import * as TransactionChanges from "../utils/transactions-changes";
27
9
 
28
10
  type HistoryEntry = {
29
11
  id: string;
@@ -133,7 +115,9 @@ function getTransactionChanges(
133
115
  if (tx.isValid === false && tx.tx.privacy === "private") {
134
116
  const readKey = coValue.core.getReadKey(tx.tx.keyUsed);
135
117
  if (!readKey) {
136
- throw new Error("Read key not found");
118
+ return [
119
+ `Unable to decrypt transaction: read key ${tx.tx.keyUsed} not found.`,
120
+ ];
137
121
  }
138
122
 
139
123
  return (
@@ -168,7 +152,7 @@ function mapTransactionToAction(
168
152
  coValue: RawCoValue,
169
153
  ): string {
170
154
  // Group changes
171
- if (isUserPromotion(change)) {
155
+ if (TransactionChanges.isUserPromotion(change)) {
172
156
  if (change.value === "revoked") {
173
157
  return `${change.key} has been revoked`;
174
158
  }
@@ -176,28 +160,28 @@ function mapTransactionToAction(
176
160
  return `${change.key} has been promoted to ${change.value}`;
177
161
  }
178
162
 
179
- if (isGroupExtension(change)) {
163
+ if (TransactionChanges.isGroupExtension(change)) {
180
164
  const child = change.key.slice(6);
181
165
  return `Group became a member of ${child}`;
182
166
  }
183
167
 
184
- if (isGroupExtendRevocation(change)) {
168
+ if (TransactionChanges.isGroupExtendRevocation(change)) {
185
169
  const child = change.key.slice(6);
186
170
  return `Group's membership of ${child} has been revoked.`;
187
171
  }
188
172
 
189
- if (isGroupPromotion(change)) {
173
+ if (TransactionChanges.isGroupPromotion(change)) {
190
174
  const parent = change.key.slice(7);
191
175
  return `Group ${parent} has been promoted to ${change.value}`;
192
176
  }
193
177
 
194
- if (isKeyRevelation(change)) {
178
+ if (TransactionChanges.isKeyRevelation(change)) {
195
179
  const [key, target] = change.key.split("_for_");
196
180
  return `Key "${key}" has been revealed to "${target}"`;
197
181
  }
198
182
 
199
183
  // coList changes
200
- if (isItemAppend(change)) {
184
+ if (TransactionChanges.isItemAppend(change)) {
201
185
  if (change.after === "start") {
202
186
  return `"${change.value}" has been appended`;
203
187
  }
@@ -211,7 +195,7 @@ function mapTransactionToAction(
211
195
  return `"${change.value}" has been inserted after "${(after as any).value}"`;
212
196
  }
213
197
 
214
- if (isItemPrepend(change)) {
198
+ if (TransactionChanges.isItemPrepend(change)) {
215
199
  if (change.before === "end") {
216
200
  return `"${change.value}" has been prepended`;
217
201
  }
@@ -225,7 +209,7 @@ function mapTransactionToAction(
225
209
  return `"${change.value}" has been inserted before "${(before as any).value}"`;
226
210
  }
227
211
 
228
- if (isItemDeletion(change)) {
212
+ if (TransactionChanges.isItemDeletion(change)) {
229
213
  const insertion = findListChange(change.insertion, coValue);
230
214
  if (insertion === undefined) {
231
215
  return `An undefined item has been deleted`;
@@ -235,24 +219,24 @@ function mapTransactionToAction(
235
219
  }
236
220
 
237
221
  // coStream changes
238
- if (isStreamStart(change)) {
222
+ if (TransactionChanges.isStreamStart(change)) {
239
223
  return `Stream started with mime type "${change.mimeType}" and file name "${change.fileName}"`;
240
224
  }
241
225
 
242
- if (isStreamChunk(change)) {
226
+ if (TransactionChanges.isStreamChunk(change)) {
243
227
  return `Stream chunk added`;
244
228
  }
245
229
 
246
- if (isStreamEnd(change)) {
230
+ if (TransactionChanges.isStreamEnd(change)) {
247
231
  return `Stream ended`;
248
232
  }
249
233
 
250
234
  // coMap changes
251
- if (isPropertySet(change)) {
235
+ if (TransactionChanges.isPropertySet(change)) {
252
236
  return `Property "${change.key}" has been set to ${JSON.stringify(change.value)}`;
253
237
  }
254
238
 
255
- if (isPropertyDeletion(change)) {
239
+ if (TransactionChanges.isPropertyDeletion(change)) {
256
240
  return `Property "${change.key}" has been deleted`;
257
241
  }
258
242
 
@@ -269,90 +253,6 @@ const findListChange = (
269
253
  )?.changes?.[opId.changeIdx];
270
254
  };
271
255
 
272
- const isGroupExtension = (
273
- change: any,
274
- ): change is Extract<
275
- MapOpPayload<`child_${string}`, "extend">,
276
- { op: "set" }
277
- > => {
278
- return change?.op === "set" && change?.value === "extend";
279
- };
280
-
281
- const isGroupExtendRevocation = (
282
- change: any,
283
- ): change is Extract<
284
- MapOpPayload<`child_${string}`, "revoked">,
285
- { op: "set" }
286
- > => {
287
- return change?.op === "set" && change?.value === "revoked";
288
- };
289
-
290
- const isGroupPromotion = (
291
- change: any,
292
- ): change is Extract<
293
- MapOpPayload<`parent_co_${string}`, AccountRole>,
294
- { op: "set" }
295
- > => {
296
- return change?.op === "set" && change?.key.startsWith("parent_co_");
297
- };
298
-
299
- const isUserPromotion = (
300
- change: any,
301
- ): change is Extract<MapOpPayload<CoID<RawCoValue>, Role>, { op: "set" }> => {
302
- return (
303
- change?.op === "set" && (isCoId(change?.key) || change?.key === "everyone")
304
- );
305
- };
306
-
307
- const isKeyRevelation = (
308
- change: any,
309
- ): change is Extract<
310
- MapOpPayload<`${string}_for_${string}`, string>,
311
- { op: "set" }
312
- > => {
313
- return change?.op === "set" && change?.key.includes("_for_");
314
- };
315
-
316
- const isPropertySet = (
317
- change: any,
318
- ): change is Extract<MapOpPayload<string, any>, { op: "set" }> => {
319
- return change?.op === "set" && "key" in change && "value" in change;
320
- };
321
- const isPropertyDeletion = (
322
- change: any,
323
- ): change is Extract<MapOpPayload<string, any>, { op: "del" }> => {
324
- return change?.op === "del" && "key" in change;
325
- };
326
-
327
- const isItemAppend = (
328
- change: any,
329
- ): change is Extract<InsertionOpPayload<any>, { op: "app" }> => {
330
- return change?.op === "app" && "after" in change && "value" in change;
331
- };
332
- const isItemPrepend = (
333
- change: any,
334
- ): change is Extract<InsertionOpPayload<any>, { op: "pre" }> => {
335
- return change?.op === "pre" && "before" in change && "value" in change;
336
- };
337
-
338
- const isItemDeletion = (
339
- change: any,
340
- ): change is Extract<DeletionOpPayload, { op: "del" }> => {
341
- return change?.op === "del" && "insertion" in change;
342
- };
343
-
344
- const isStreamStart = (change: any): change is BinaryStreamStart => {
345
- return change?.type === "start" && "mimeType" in change;
346
- };
347
-
348
- const isStreamChunk = (change: any): change is BinaryStreamChunk => {
349
- return change?.type === "chunk" && "chunk" in change;
350
- };
351
-
352
- const isStreamEnd = (change: any): change is BinaryStreamEnd => {
353
- return change?.type === "end";
354
- };
355
-
356
256
  const RedTooltip = styled("span")`
357
257
  position:relative; /* making the .tooltip span a container for the tooltip text */
358
258
  border-bottom:1px dashed #000; /* little indicater to indicate it's hoverable */
@@ -2,6 +2,7 @@ import {
2
2
  CoID,
3
3
  LocalNode,
4
4
  RawCoList,
5
+ RawCoMap,
5
6
  RawCoStream,
6
7
  RawCoValue,
7
8
  RawGroup,
@@ -23,6 +24,7 @@ import { TypeIcon } from "./type-icon.js";
23
24
  import { PageInfo } from "./types.js";
24
25
  import { resolveCoValue, useResolvedCoValue } from "./use-resolve-covalue.js";
25
26
  import { HistoryView } from "./history-view.js";
27
+ import { CoMapView } from "./co-map-view.js";
26
28
 
27
29
  interface PageContainerProps extends React.HTMLAttributes<HTMLDivElement> {
28
30
  isTopLevel?: boolean;
@@ -165,6 +167,17 @@ function View(
165
167
  return <TableView data={snapshot} node={node} onNavigate={onNavigate} />;
166
168
  }
167
169
 
170
+ if (type === "comap") {
171
+ return (
172
+ <CoMapView
173
+ coValue={value as RawCoMap}
174
+ data={snapshot}
175
+ node={node}
176
+ onNavigate={onNavigate}
177
+ />
178
+ );
179
+ }
180
+
168
181
  return <GridView data={snapshot} onNavigate={onNavigate} node={node} />;
169
182
  }
170
183
 
@@ -119,7 +119,7 @@ describe("usePassphraseAuth", () => {
119
119
  const me = useAccount();
120
120
  const logOut = useLogOut();
121
121
 
122
- if (me) {
122
+ if (me.$isLoaded) {
123
123
  if (!accounts.includes(me.$jazz.id)) {
124
124
  accounts.push(me.$jazz.id);
125
125
  }
@@ -3,6 +3,7 @@ import { CoList } from "./coList.js";
3
3
  import { CoMap, CoMapInit } from "./coMap.js";
4
4
  import { CoPlainText } from "./coPlainText.js";
5
5
  import { CoRichText } from "./coRichText.js";
6
+ import { CoVector } from "./coVector.js";
6
7
 
7
8
  /**
8
9
  * Returns the type of values that can be used to initialize a field of the provided type.
@@ -15,6 +16,8 @@ export type CoFieldInit<V> = V extends CoMap
15
16
  ? V | CoMapInit<V>
16
17
  : V extends CoList<infer T> | CoFeed<infer T>
17
18
  ? V | ReadonlyArray<CoFieldInit<T>>
18
- : V extends CoPlainText | CoRichText
19
- ? V | string
20
- : V;
19
+ : V extends CoVector | Readonly<CoVector>
20
+ ? V | ReadonlyArray<number> | Float32Array
21
+ : V extends CoPlainText | CoRichText
22
+ ? V | string
23
+ : V;
@@ -5,6 +5,7 @@ import {
5
5
  CoreCoListSchema,
6
6
  CoreCoMapSchema,
7
7
  CoreCoRecordSchema,
8
+ CoreCoVectorSchema,
8
9
  CorePlainTextSchema,
9
10
  Simplify,
10
11
  } from "../../../internal.js";
@@ -33,13 +34,15 @@ export type CoFieldSchemaInit<S extends CoValueClass | AnyZodOrCoValueSchema> =
33
34
  ? CoListSchemaInit<T>
34
35
  : S extends CoreCoFeedSchema<infer T>
35
36
  ? CoFeedSchemaInit<T>
36
- : S extends CorePlainTextSchema | CoreRichTextSchema
37
- ? string
38
- : S extends CoreCoOptionalSchema<infer T>
39
- ? CoFieldSchemaInit<T> | undefined
40
- : S extends CoDiscriminatedUnionSchema<infer Members>
41
- ? CoFieldSchemaInit<Members[number]>
42
- : never)
37
+ : S extends CoreCoVectorSchema
38
+ ? CoVectorSchemaInit
39
+ : S extends CorePlainTextSchema | CoreRichTextSchema
40
+ ? string
41
+ : S extends CoreCoOptionalSchema<infer T>
42
+ ? CoFieldSchemaInit<T> | undefined
43
+ : S extends CoDiscriminatedUnionSchema<infer Members>
44
+ ? CoFieldSchemaInit<Members[number]>
45
+ : never)
43
46
  : S extends z.core.$ZodType
44
47
  ? TypeOfZodSchema<S>
45
48
  : S extends CoValueClass
@@ -76,6 +79,8 @@ export type CoFeedSchemaInit<T extends AnyZodOrCoValueSchema> = Simplify<
76
79
  ReadonlyArray<CoFieldSchemaInit<T>>
77
80
  >;
78
81
 
82
+ export type CoVectorSchemaInit = ReadonlyArray<number> | Float32Array;
83
+
79
84
  /**
80
85
  * The convenience type for extracting the init type of a CoValue schema.
81
86
  */