jazz-tools 0.19.0 → 0.19.2
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/.turbo/turbo-build.log +53 -53
- package/CHANGELOG.md +21 -0
- package/dist/{chunk-P3YLNFN4.js → chunk-NCNM6UDZ.js} +61 -22
- package/dist/chunk-NCNM6UDZ.js.map +1 -0
- package/dist/index.js +1 -1
- package/dist/inspector/{custom-element-QESCMFY7.js → custom-element-ABVPHX53.js} +1118 -465
- package/dist/inspector/custom-element-ABVPHX53.js.map +1 -0
- package/dist/inspector/index.js +1090 -437
- package/dist/inspector/index.js.map +1 -1
- package/dist/inspector/register-custom-element.js +1 -1
- package/dist/inspector/tests/utils/history.test.d.ts +2 -0
- package/dist/inspector/tests/utils/history.test.d.ts.map +1 -0
- package/dist/inspector/tests/viewer/co-value-editor.test.d.ts +2 -0
- package/dist/inspector/tests/viewer/co-value-editor.test.d.ts.map +1 -0
- package/dist/inspector/tests/viewer/comap-view.test.d.ts +2 -0
- package/dist/inspector/tests/viewer/comap-view.test.d.ts.map +1 -0
- package/dist/inspector/ui/icon.d.ts +6 -0
- package/dist/inspector/ui/icon.d.ts.map +1 -1
- package/dist/inspector/ui/icons/add-icon.d.ts +2 -0
- package/dist/inspector/ui/icons/add-icon.d.ts.map +1 -0
- package/dist/inspector/ui/icons/edit-icon.d.ts +2 -0
- package/dist/inspector/ui/icons/edit-icon.d.ts.map +1 -0
- package/dist/inspector/ui/icons/history.d.ts +2 -0
- package/dist/inspector/ui/icons/history.d.ts.map +1 -0
- package/dist/inspector/utils/history.d.ts +3 -0
- package/dist/inspector/utils/history.d.ts.map +1 -0
- package/dist/inspector/utils/transactions-changes.d.ts +38 -0
- package/dist/inspector/utils/transactions-changes.d.ts.map +1 -0
- package/dist/inspector/viewer/co-map-view.d.ts +9 -0
- package/dist/inspector/viewer/co-map-view.d.ts.map +1 -0
- package/dist/inspector/viewer/co-value-editor.d.ts +10 -0
- package/dist/inspector/viewer/co-value-editor.d.ts.map +1 -0
- package/dist/inspector/viewer/grid-view.d.ts +3 -2
- package/dist/inspector/viewer/grid-view.d.ts.map +1 -1
- package/dist/inspector/viewer/history-view.d.ts.map +1 -1
- package/dist/inspector/viewer/page.d.ts.map +1 -1
- package/dist/testing.js +1 -1
- package/dist/tools/coValues/CoFieldInit.d.ts +2 -1
- package/dist/tools/coValues/CoFieldInit.d.ts.map +1 -1
- package/dist/tools/coValues/deepLoading.d.ts +8 -7
- package/dist/tools/coValues/deepLoading.d.ts.map +1 -1
- package/dist/tools/coValues/interfaces.d.ts +3 -3
- package/dist/tools/coValues/interfaces.d.ts.map +1 -1
- package/dist/tools/coValues/schemaUnion.d.ts +6 -9
- package/dist/tools/coValues/schemaUnion.d.ts.map +1 -1
- package/dist/tools/implementation/zodSchema/schemaTypes/CoDiscriminatedUnionSchema.d.ts +18 -7
- package/dist/tools/implementation/zodSchema/schemaTypes/CoDiscriminatedUnionSchema.d.ts.map +1 -1
- package/dist/tools/implementation/zodSchema/typeConverters/CoFieldSchemaInit.d.ts +3 -2
- package/dist/tools/implementation/zodSchema/typeConverters/CoFieldSchemaInit.d.ts.map +1 -1
- package/dist/tools/implementation/zodSchema/unionUtils.d.ts.map +1 -1
- package/dist/tools/subscribe/SubscriptionScope.d.ts +1 -0
- package/dist/tools/subscribe/SubscriptionScope.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/inspector/tests/utils/history.test.ts +401 -0
- package/src/inspector/tests/viewer/co-value-editor.test.tsx +903 -0
- package/src/inspector/tests/viewer/comap-view.test.tsx +581 -0
- package/src/inspector/ui/icon.tsx +6 -0
- package/src/inspector/ui/icons/add-icon.tsx +21 -0
- package/src/inspector/ui/icons/edit-icon.tsx +17 -0
- package/src/inspector/ui/icons/history.tsx +28 -0
- package/src/inspector/ui/modal.tsx +3 -3
- package/src/inspector/utils/history.ts +49 -0
- package/src/inspector/utils/transactions-changes.ts +98 -0
- package/src/inspector/viewer/co-map-view.tsx +312 -0
- package/src/inspector/viewer/co-value-editor.tsx +164 -0
- package/src/inspector/viewer/grid-view.tsx +139 -10
- package/src/inspector/viewer/history-view.tsx +16 -118
- package/src/inspector/viewer/page.tsx +13 -0
- package/src/react-core/tests/usePassPhraseAuth.test.ts +1 -1
- package/src/tools/coValues/CoFieldInit.ts +6 -3
- package/src/tools/coValues/coList.ts +1 -1
- package/src/tools/coValues/deepLoading.ts +85 -71
- package/src/tools/coValues/interfaces.ts +3 -3
- package/src/tools/coValues/schemaUnion.ts +19 -14
- package/src/tools/implementation/zodSchema/schemaTypes/CoDiscriminatedUnionSchema.ts +69 -9
- package/src/tools/implementation/zodSchema/typeConverters/CoFieldSchemaInit.ts +12 -7
- package/src/tools/implementation/zodSchema/unionUtils.ts +35 -4
- package/src/tools/subscribe/SubscriptionScope.ts +3 -14
- package/src/tools/tests/coDiscriminatedUnion.test.ts +347 -5
- package/src/tools/tests/coVector.test.ts +43 -0
- package/src/tools/tests/deepLoading.test.ts +55 -59
- package/src/tools/tests/schema.resolved.test.ts +70 -1
- package/dist/chunk-P3YLNFN4.js.map +0 -1
- package/dist/inspector/custom-element-QESCMFY7.js.map +0 -1
|
@@ -1,27 +1,93 @@
|
|
|
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";
|
|
11
15
|
|
|
12
16
|
function GridItem({
|
|
13
17
|
entry,
|
|
14
18
|
onNavigate,
|
|
15
19
|
node,
|
|
20
|
+
coValue,
|
|
16
21
|
}: {
|
|
17
22
|
entry: [string, JsonValue | undefined];
|
|
18
23
|
onNavigate: (pages: PageInfo[]) => void;
|
|
19
24
|
node: LocalNode;
|
|
25
|
+
coValue?: RawCoValue;
|
|
20
26
|
}) {
|
|
21
27
|
const [key, value] = entry;
|
|
22
28
|
const isCoValue = isCoId(value);
|
|
29
|
+
const [isEditing, setIsEditing] = useState(false);
|
|
23
30
|
|
|
24
|
-
const
|
|
31
|
+
const handleEditClick = (e: React.MouseEvent) => {
|
|
32
|
+
e.stopPropagation();
|
|
33
|
+
setIsEditing(true);
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
const handleCancel = () => {
|
|
37
|
+
setIsEditing(false);
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const handleDelete = (e: React.MouseEvent) => {
|
|
41
|
+
e.stopPropagation();
|
|
42
|
+
if (confirm(`Are you sure you want to delete the property "${key}"?`)) {
|
|
43
|
+
coValue?.core.makeTransaction(
|
|
44
|
+
[
|
|
45
|
+
{
|
|
46
|
+
op: "del",
|
|
47
|
+
key,
|
|
48
|
+
},
|
|
49
|
+
],
|
|
50
|
+
"private",
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
if (isEditing) {
|
|
56
|
+
return (
|
|
57
|
+
<Card
|
|
58
|
+
style={{
|
|
59
|
+
backgroundColor: "var(--j-foreground)",
|
|
60
|
+
borderColor: "var(--j-foreground)",
|
|
61
|
+
}}
|
|
62
|
+
>
|
|
63
|
+
<CardHeader>
|
|
64
|
+
<div style={{ display: "flex", alignItems: "center", gap: "0.5rem" }}>
|
|
65
|
+
{isCoValue ? (
|
|
66
|
+
<>
|
|
67
|
+
<Text strong>{key}</Text>
|
|
68
|
+
<Badge>
|
|
69
|
+
<ResolveIcon coId={value as CoID<RawCoValue>} node={node} />
|
|
70
|
+
</Badge>
|
|
71
|
+
</>
|
|
72
|
+
) : (
|
|
73
|
+
<Text strong>{key}</Text>
|
|
74
|
+
)}
|
|
75
|
+
</div>
|
|
76
|
+
</CardHeader>
|
|
77
|
+
<CardBody style={{ wordBreak: "break-word" }}>
|
|
78
|
+
<CoValueEditor
|
|
79
|
+
node={node}
|
|
80
|
+
property={key}
|
|
81
|
+
value={value}
|
|
82
|
+
coValue={coValue!}
|
|
83
|
+
onCancel={handleCancel}
|
|
84
|
+
/>
|
|
85
|
+
</CardBody>
|
|
86
|
+
</Card>
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const cardProps = isCoValue
|
|
25
91
|
? {
|
|
26
92
|
onClick: () =>
|
|
27
93
|
onNavigate([{ coId: value as CoID<RawCoValue>, name: key }]),
|
|
@@ -35,17 +101,37 @@ function GridItem({
|
|
|
35
101
|
};
|
|
36
102
|
|
|
37
103
|
return (
|
|
38
|
-
<Card {...
|
|
104
|
+
<Card {...cardProps}>
|
|
39
105
|
<CardHeader>
|
|
40
|
-
{
|
|
41
|
-
|
|
106
|
+
<div style={{ display: "flex", alignItems: "center", gap: "0.5rem" }}>
|
|
107
|
+
{isCoValue ? (
|
|
108
|
+
<>
|
|
109
|
+
<Text strong>{key}</Text>
|
|
110
|
+
<Badge>
|
|
111
|
+
<ResolveIcon coId={value as CoID<RawCoValue>} node={node} />
|
|
112
|
+
</Badge>
|
|
113
|
+
</>
|
|
114
|
+
) : (
|
|
42
115
|
<Text strong>{key}</Text>
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
116
|
+
)}
|
|
117
|
+
</div>
|
|
118
|
+
{coValue && (
|
|
119
|
+
<ActionButtons>
|
|
120
|
+
<EditButton
|
|
121
|
+
onClick={handleEditClick}
|
|
122
|
+
type="button"
|
|
123
|
+
aria-label="Edit"
|
|
124
|
+
>
|
|
125
|
+
<Icon name="edit" size="sm" />
|
|
126
|
+
</EditButton>
|
|
127
|
+
<DeleteButton
|
|
128
|
+
onClick={handleDelete}
|
|
129
|
+
type="button"
|
|
130
|
+
aria-label="Delete"
|
|
131
|
+
>
|
|
132
|
+
<Icon name="delete" size="sm" />
|
|
133
|
+
</DeleteButton>
|
|
134
|
+
</ActionButtons>
|
|
49
135
|
)}
|
|
50
136
|
</CardHeader>
|
|
51
137
|
<CardBody style={{ wordBreak: "break-word" }}>
|
|
@@ -68,10 +154,12 @@ export function GridView({
|
|
|
68
154
|
data,
|
|
69
155
|
onNavigate,
|
|
70
156
|
node,
|
|
157
|
+
coValue,
|
|
71
158
|
}: {
|
|
72
159
|
data: JsonObject;
|
|
73
160
|
onNavigate: (pages: PageInfo[]) => void;
|
|
74
161
|
node: LocalNode;
|
|
162
|
+
coValue?: RawCoValue;
|
|
75
163
|
}) {
|
|
76
164
|
const entries = Object.entries(data);
|
|
77
165
|
|
|
@@ -82,9 +170,50 @@ export function GridView({
|
|
|
82
170
|
entry={entry}
|
|
83
171
|
onNavigate={onNavigate}
|
|
84
172
|
node={node}
|
|
173
|
+
coValue={coValue}
|
|
85
174
|
key={childIndex}
|
|
86
175
|
/>
|
|
87
176
|
))}
|
|
88
177
|
</Grid>
|
|
89
178
|
);
|
|
90
179
|
}
|
|
180
|
+
|
|
181
|
+
const EditButton = styled("button")`
|
|
182
|
+
display: inline-flex;
|
|
183
|
+
align-items: center;
|
|
184
|
+
justify-content: center;
|
|
185
|
+
padding: 0.25rem;
|
|
186
|
+
border: none;
|
|
187
|
+
background: transparent;
|
|
188
|
+
cursor: pointer;
|
|
189
|
+
color: var(--j-text-color);
|
|
190
|
+
border-radius: var(--j-radius-sm);
|
|
191
|
+
transition: background-color 0.2s;
|
|
192
|
+
|
|
193
|
+
&:hover {
|
|
194
|
+
background-color: var(--j-foreground);
|
|
195
|
+
}
|
|
196
|
+
`;
|
|
197
|
+
|
|
198
|
+
const DeleteButton = styled("button")`
|
|
199
|
+
display: inline-flex;
|
|
200
|
+
align-items: center;
|
|
201
|
+
justify-content: center;
|
|
202
|
+
padding: 0.25rem;
|
|
203
|
+
border: none;
|
|
204
|
+
background: transparent;
|
|
205
|
+
cursor: pointer;
|
|
206
|
+
color: var(--j-text-color);
|
|
207
|
+
border-radius: var(--j-radius-sm);
|
|
208
|
+
transition: background-color 0.2s;
|
|
209
|
+
|
|
210
|
+
&:hover {
|
|
211
|
+
background-color: var(--j-foreground);
|
|
212
|
+
}
|
|
213
|
+
`;
|
|
214
|
+
|
|
215
|
+
const ActionButtons = styled("div")`
|
|
216
|
+
display: flex;
|
|
217
|
+
align-items: center;
|
|
218
|
+
gap: 0.25rem;
|
|
219
|
+
`;
|
|
@@ -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 {
|
|
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;
|
|
@@ -168,7 +150,7 @@ function mapTransactionToAction(
|
|
|
168
150
|
coValue: RawCoValue,
|
|
169
151
|
): string {
|
|
170
152
|
// Group changes
|
|
171
|
-
if (isUserPromotion(change)) {
|
|
153
|
+
if (TransactionChanges.isUserPromotion(change)) {
|
|
172
154
|
if (change.value === "revoked") {
|
|
173
155
|
return `${change.key} has been revoked`;
|
|
174
156
|
}
|
|
@@ -176,28 +158,28 @@ function mapTransactionToAction(
|
|
|
176
158
|
return `${change.key} has been promoted to ${change.value}`;
|
|
177
159
|
}
|
|
178
160
|
|
|
179
|
-
if (isGroupExtension(change)) {
|
|
161
|
+
if (TransactionChanges.isGroupExtension(change)) {
|
|
180
162
|
const child = change.key.slice(6);
|
|
181
163
|
return `Group became a member of ${child}`;
|
|
182
164
|
}
|
|
183
165
|
|
|
184
|
-
if (isGroupExtendRevocation(change)) {
|
|
166
|
+
if (TransactionChanges.isGroupExtendRevocation(change)) {
|
|
185
167
|
const child = change.key.slice(6);
|
|
186
168
|
return `Group's membership of ${child} has been revoked.`;
|
|
187
169
|
}
|
|
188
170
|
|
|
189
|
-
if (isGroupPromotion(change)) {
|
|
171
|
+
if (TransactionChanges.isGroupPromotion(change)) {
|
|
190
172
|
const parent = change.key.slice(7);
|
|
191
173
|
return `Group ${parent} has been promoted to ${change.value}`;
|
|
192
174
|
}
|
|
193
175
|
|
|
194
|
-
if (isKeyRevelation(change)) {
|
|
176
|
+
if (TransactionChanges.isKeyRevelation(change)) {
|
|
195
177
|
const [key, target] = change.key.split("_for_");
|
|
196
178
|
return `Key "${key}" has been revealed to "${target}"`;
|
|
197
179
|
}
|
|
198
180
|
|
|
199
181
|
// coList changes
|
|
200
|
-
if (isItemAppend(change)) {
|
|
182
|
+
if (TransactionChanges.isItemAppend(change)) {
|
|
201
183
|
if (change.after === "start") {
|
|
202
184
|
return `"${change.value}" has been appended`;
|
|
203
185
|
}
|
|
@@ -211,7 +193,7 @@ function mapTransactionToAction(
|
|
|
211
193
|
return `"${change.value}" has been inserted after "${(after as any).value}"`;
|
|
212
194
|
}
|
|
213
195
|
|
|
214
|
-
if (isItemPrepend(change)) {
|
|
196
|
+
if (TransactionChanges.isItemPrepend(change)) {
|
|
215
197
|
if (change.before === "end") {
|
|
216
198
|
return `"${change.value}" has been prepended`;
|
|
217
199
|
}
|
|
@@ -225,7 +207,7 @@ function mapTransactionToAction(
|
|
|
225
207
|
return `"${change.value}" has been inserted before "${(before as any).value}"`;
|
|
226
208
|
}
|
|
227
209
|
|
|
228
|
-
if (isItemDeletion(change)) {
|
|
210
|
+
if (TransactionChanges.isItemDeletion(change)) {
|
|
229
211
|
const insertion = findListChange(change.insertion, coValue);
|
|
230
212
|
if (insertion === undefined) {
|
|
231
213
|
return `An undefined item has been deleted`;
|
|
@@ -235,24 +217,24 @@ function mapTransactionToAction(
|
|
|
235
217
|
}
|
|
236
218
|
|
|
237
219
|
// coStream changes
|
|
238
|
-
if (isStreamStart(change)) {
|
|
220
|
+
if (TransactionChanges.isStreamStart(change)) {
|
|
239
221
|
return `Stream started with mime type "${change.mimeType}" and file name "${change.fileName}"`;
|
|
240
222
|
}
|
|
241
223
|
|
|
242
|
-
if (isStreamChunk(change)) {
|
|
224
|
+
if (TransactionChanges.isStreamChunk(change)) {
|
|
243
225
|
return `Stream chunk added`;
|
|
244
226
|
}
|
|
245
227
|
|
|
246
|
-
if (isStreamEnd(change)) {
|
|
228
|
+
if (TransactionChanges.isStreamEnd(change)) {
|
|
247
229
|
return `Stream ended`;
|
|
248
230
|
}
|
|
249
231
|
|
|
250
232
|
// coMap changes
|
|
251
|
-
if (isPropertySet(change)) {
|
|
233
|
+
if (TransactionChanges.isPropertySet(change)) {
|
|
252
234
|
return `Property "${change.key}" has been set to ${JSON.stringify(change.value)}`;
|
|
253
235
|
}
|
|
254
236
|
|
|
255
|
-
if (isPropertyDeletion(change)) {
|
|
237
|
+
if (TransactionChanges.isPropertyDeletion(change)) {
|
|
256
238
|
return `Property "${change.key}" has been deleted`;
|
|
257
239
|
}
|
|
258
240
|
|
|
@@ -269,90 +251,6 @@ const findListChange = (
|
|
|
269
251
|
)?.changes?.[opId.changeIdx];
|
|
270
252
|
};
|
|
271
253
|
|
|
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
254
|
const RedTooltip = styled("span")`
|
|
357
255
|
position:relative; /* making the .tooltip span a container for the tooltip text */
|
|
358
256
|
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
|
|
|
@@ -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
|
|
19
|
-
? V |
|
|
20
|
-
: V
|
|
19
|
+
: V extends CoVector | Readonly<CoVector>
|
|
20
|
+
? V | ReadonlyArray<number> | Float32Array
|
|
21
|
+
: V extends CoPlainText | CoRichText
|
|
22
|
+
? V | string
|
|
23
|
+
: V;
|
|
@@ -6,16 +6,23 @@ import { type CoKeys } from "./coMap.js";
|
|
|
6
6
|
import { type CoValue, type ID } from "./interfaces.js";
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
|
-
*
|
|
9
|
+
* Returns a boolean for whether the given type is a union.
|
|
10
10
|
*
|
|
11
|
-
*
|
|
12
|
-
* The right hand side is always a single function type.
|
|
11
|
+
* Taken from https://github.com/sindresorhus/type-fest/blob/main/source/is-union.d.ts
|
|
13
12
|
*/
|
|
14
|
-
type IsUnion<T, U = T> = (
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
13
|
+
type IsUnion<T, U = T> = (
|
|
14
|
+
[T] extends [never]
|
|
15
|
+
? false
|
|
16
|
+
: T extends any
|
|
17
|
+
? [U] extends [T]
|
|
18
|
+
? false
|
|
19
|
+
: true
|
|
20
|
+
: never
|
|
21
|
+
) extends infer Result
|
|
22
|
+
? boolean extends Result
|
|
23
|
+
? true
|
|
24
|
+
: Result
|
|
25
|
+
: never;
|
|
19
26
|
|
|
20
27
|
/**
|
|
21
28
|
* A CoValue that may or may not be loaded.
|
|
@@ -67,61 +74,57 @@ export type RefsToResolve<
|
|
|
67
74
|
| (DepthLimit extends CurrentDepth["length"]
|
|
68
75
|
? // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
69
76
|
any
|
|
70
|
-
:
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
77
|
+
: // Basically V extends CoList - but if we used that we'd introduce circularity into the definition of CoList itself
|
|
78
|
+
V extends ReadonlyArray<infer Item>
|
|
79
|
+
? LoadedAndRequired<Item> extends CoValue
|
|
80
|
+
?
|
|
81
|
+
| ({
|
|
82
|
+
$each?: RefsToResolve<
|
|
83
|
+
AsLoaded<Item>,
|
|
84
|
+
DepthLimit,
|
|
85
|
+
[0, ...CurrentDepth]
|
|
86
|
+
>;
|
|
87
|
+
} & OnError)
|
|
88
|
+
| boolean
|
|
89
|
+
: OnError | boolean
|
|
90
|
+
: // Basically V extends CoMap | Group | Account - but if we used that we'd introduce circularity into the definition of CoMap itself
|
|
91
|
+
V extends { [TypeSym]: "CoMap" | "Group" | "Account" }
|
|
92
|
+
?
|
|
93
|
+
| ({
|
|
94
|
+
[Key in CoKeys<V> as LoadedAndRequired<V[Key]> extends CoValue
|
|
95
|
+
? Key
|
|
96
|
+
: never]?: RefsToResolve<
|
|
97
|
+
LoadedAndRequired<V[Key]>,
|
|
98
|
+
DepthLimit,
|
|
99
|
+
[0, ...CurrentDepth]
|
|
100
|
+
>;
|
|
101
|
+
} & OnError)
|
|
102
|
+
| (ItemsSym extends keyof V
|
|
103
|
+
? {
|
|
104
|
+
$each: RefsToResolve<
|
|
105
|
+
LoadedAndRequired<V[ItemsSym]>,
|
|
106
|
+
DepthLimit,
|
|
107
|
+
[0, ...CurrentDepth]
|
|
108
|
+
>;
|
|
109
|
+
} & OnError
|
|
110
|
+
: never)
|
|
111
|
+
| boolean
|
|
112
|
+
: V extends {
|
|
113
|
+
[TypeSym]: "CoStream";
|
|
114
|
+
byMe: CoFeedEntry<infer Item> | undefined;
|
|
115
|
+
}
|
|
75
116
|
?
|
|
76
117
|
| ({
|
|
77
|
-
$each
|
|
118
|
+
$each: RefsToResolve<
|
|
78
119
|
AsLoaded<Item>,
|
|
79
120
|
DepthLimit,
|
|
80
121
|
[0, ...CurrentDepth]
|
|
81
122
|
>;
|
|
82
123
|
} & OnError)
|
|
83
124
|
| boolean
|
|
84
|
-
:
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
?
|
|
88
|
-
| ({
|
|
89
|
-
[Key in CoKeys<V> as LoadedAndRequired<
|
|
90
|
-
V[Key]
|
|
91
|
-
> extends CoValue
|
|
92
|
-
? Key
|
|
93
|
-
: never]?: RefsToResolve<
|
|
94
|
-
LoadedAndRequired<V[Key]>,
|
|
95
|
-
DepthLimit,
|
|
96
|
-
[0, ...CurrentDepth]
|
|
97
|
-
>;
|
|
98
|
-
} & OnError)
|
|
99
|
-
| (ItemsSym extends keyof V
|
|
100
|
-
? {
|
|
101
|
-
$each: RefsToResolve<
|
|
102
|
-
LoadedAndRequired<V[ItemsSym]>,
|
|
103
|
-
DepthLimit,
|
|
104
|
-
[0, ...CurrentDepth]
|
|
105
|
-
>;
|
|
106
|
-
} & OnError
|
|
107
|
-
: never)
|
|
108
|
-
| boolean
|
|
109
|
-
: V extends {
|
|
110
|
-
[TypeSym]: "CoStream";
|
|
111
|
-
byMe: CoFeedEntry<infer Item> | undefined;
|
|
112
|
-
}
|
|
113
|
-
?
|
|
114
|
-
| ({
|
|
115
|
-
$each: RefsToResolve<
|
|
116
|
-
AsLoaded<Item>,
|
|
117
|
-
DepthLimit,
|
|
118
|
-
[0, ...CurrentDepth]
|
|
119
|
-
>;
|
|
120
|
-
} & OnError)
|
|
121
|
-
| boolean
|
|
122
|
-
: V extends { [TypeSym]: "CoPlainText" | "BinaryCoStream" }
|
|
123
|
-
? boolean | OnError
|
|
124
|
-
: boolean);
|
|
125
|
+
: V extends { [TypeSym]: "CoPlainText" | "BinaryCoStream" }
|
|
126
|
+
? boolean | OnError
|
|
127
|
+
: boolean);
|
|
125
128
|
|
|
126
129
|
export type RefsToResolveStrict<T, V> = [V] extends [RefsToResolve<T>]
|
|
127
130
|
? RefsToResolve<T>
|
|
@@ -130,7 +133,7 @@ export type RefsToResolveStrict<T, V> = [V] extends [RefsToResolve<T>]
|
|
|
130
133
|
export type Resolved<
|
|
131
134
|
T,
|
|
132
135
|
R extends RefsToResolve<T> | undefined = true,
|
|
133
|
-
> = DeeplyLoaded<T, R
|
|
136
|
+
> = DeeplyLoaded<T, R>;
|
|
134
137
|
|
|
135
138
|
/**
|
|
136
139
|
* If the resolve query contains `$onError: "catch"`, we return a not loaded value for this nested CoValue.
|
|
@@ -145,21 +148,32 @@ type CoMapLikeLoaded<
|
|
|
145
148
|
Depth,
|
|
146
149
|
DepthLimit extends number,
|
|
147
150
|
CurrentDepth extends number[],
|
|
148
|
-
> =
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
151
|
+
> = IsUnion<LoadedAndRequired<V>> extends true
|
|
152
|
+
? // Trigger conditional type distributivity to deeply resolve each member of the union separately
|
|
153
|
+
// Otherwise, deeply loaded values will resolve to `never`
|
|
154
|
+
V extends V
|
|
155
|
+
? CoMapLikeLoaded<
|
|
156
|
+
V,
|
|
157
|
+
Pick<Depth, keyof V & keyof Depth>,
|
|
158
|
+
DepthLimit,
|
|
159
|
+
CurrentDepth
|
|
160
|
+
>
|
|
161
|
+
: never
|
|
162
|
+
: {
|
|
163
|
+
readonly [Key in keyof Omit<Depth, "$onError">]-?: Key extends CoKeys<V>
|
|
164
|
+
? LoadedAndRequired<V[Key]> extends CoValue
|
|
165
|
+
?
|
|
166
|
+
| DeeplyLoaded<
|
|
167
|
+
LoadedAndRequired<V[Key]>,
|
|
168
|
+
Depth[Key],
|
|
169
|
+
DepthLimit,
|
|
170
|
+
[0, ...CurrentDepth]
|
|
171
|
+
>
|
|
172
|
+
| (undefined extends V[Key] ? undefined : never)
|
|
173
|
+
| OnErrorResolvedValue<V[Key], Depth[Key]>
|
|
174
|
+
: never
|
|
175
|
+
: never;
|
|
176
|
+
} & V;
|
|
163
177
|
|
|
164
178
|
export type DeeplyLoaded<
|
|
165
179
|
V,
|