jazz-tools 0.19.8 → 0.19.11

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 (154) hide show
  1. package/.turbo/turbo-build.log +56 -50
  2. package/CHANGELOG.md +30 -3
  3. package/dist/{chunk-2S3Z2CN6.js → chunk-HX5S6W5E.js} +372 -103
  4. package/dist/chunk-HX5S6W5E.js.map +1 -0
  5. package/dist/index.js +1 -1
  6. package/dist/inspector/account-switcher.d.ts +4 -0
  7. package/dist/inspector/account-switcher.d.ts.map +1 -0
  8. package/dist/inspector/chunk-C6BJPHBQ.js +4096 -0
  9. package/dist/inspector/chunk-C6BJPHBQ.js.map +1 -0
  10. package/dist/inspector/contexts/node.d.ts +19 -0
  11. package/dist/inspector/contexts/node.d.ts.map +1 -0
  12. package/dist/inspector/{custom-element-P76EIWEV.js → custom-element-GJVBPZES.js} +1011 -884
  13. package/dist/inspector/custom-element-GJVBPZES.js.map +1 -0
  14. package/dist/inspector/{viewer/new-app.d.ts → in-app.d.ts} +3 -3
  15. package/dist/inspector/in-app.d.ts.map +1 -0
  16. package/dist/inspector/index.d.ts +0 -11
  17. package/dist/inspector/index.d.ts.map +1 -1
  18. package/dist/inspector/index.js +56 -3910
  19. package/dist/inspector/index.js.map +1 -1
  20. package/dist/inspector/pages/home.d.ts +2 -0
  21. package/dist/inspector/pages/home.d.ts.map +1 -0
  22. package/dist/inspector/register-custom-element.js +1 -1
  23. package/dist/inspector/router/context.d.ts +12 -0
  24. package/dist/inspector/router/context.d.ts.map +1 -0
  25. package/dist/inspector/router/hash-router.d.ts +7 -0
  26. package/dist/inspector/router/hash-router.d.ts.map +1 -0
  27. package/dist/inspector/router/in-memory-router.d.ts +7 -0
  28. package/dist/inspector/router/in-memory-router.d.ts.map +1 -0
  29. package/dist/inspector/router/index.d.ts +5 -0
  30. package/dist/inspector/router/index.d.ts.map +1 -0
  31. package/dist/inspector/standalone.d.ts +6 -0
  32. package/dist/inspector/standalone.d.ts.map +1 -0
  33. package/dist/inspector/standalone.js +420 -0
  34. package/dist/inspector/standalone.js.map +1 -0
  35. package/dist/inspector/tests/router/hash-router.test.d.ts +2 -0
  36. package/dist/inspector/tests/router/hash-router.test.d.ts.map +1 -0
  37. package/dist/inspector/tests/router/in-memory-router.test.d.ts +2 -0
  38. package/dist/inspector/tests/router/in-memory-router.test.d.ts.map +1 -0
  39. package/dist/inspector/ui/modal.d.ts +1 -0
  40. package/dist/inspector/ui/modal.d.ts.map +1 -1
  41. package/dist/inspector/viewer/breadcrumbs.d.ts +1 -7
  42. package/dist/inspector/viewer/breadcrumbs.d.ts.map +1 -1
  43. package/dist/inspector/viewer/header.d.ts +7 -0
  44. package/dist/inspector/viewer/header.d.ts.map +1 -0
  45. package/dist/inspector/viewer/page-stack.d.ts +4 -13
  46. package/dist/inspector/viewer/page-stack.d.ts.map +1 -1
  47. package/dist/inspector/viewer/page.d.ts.map +1 -1
  48. package/dist/react/hooks.d.ts +1 -1
  49. package/dist/react/hooks.d.ts.map +1 -1
  50. package/dist/react/index.d.ts +1 -1
  51. package/dist/react/index.d.ts.map +1 -1
  52. package/dist/react/index.js +5 -1
  53. package/dist/react/index.js.map +1 -1
  54. package/dist/react-core/hooks.d.ts +59 -0
  55. package/dist/react-core/hooks.d.ts.map +1 -1
  56. package/dist/react-core/index.js +124 -36
  57. package/dist/react-core/index.js.map +1 -1
  58. package/dist/react-core/tests/testUtils.d.ts +1 -0
  59. package/dist/react-core/tests/testUtils.d.ts.map +1 -1
  60. package/dist/react-core/tests/useSuspenseAccount.test.d.ts +2 -0
  61. package/dist/react-core/tests/useSuspenseAccount.test.d.ts.map +1 -0
  62. package/dist/react-core/tests/useSuspenseCoState.test.d.ts +2 -0
  63. package/dist/react-core/tests/useSuspenseCoState.test.d.ts.map +1 -0
  64. package/dist/react-core/use.d.ts +3 -0
  65. package/dist/react-core/use.d.ts.map +1 -0
  66. package/dist/react-native/index.js +5 -1
  67. package/dist/react-native/index.js.map +1 -1
  68. package/dist/react-native-core/crypto/RNCrypto.d.ts +2 -0
  69. package/dist/react-native-core/crypto/RNCrypto.d.ts.map +1 -0
  70. package/dist/react-native-core/crypto/RNCrypto.js +3 -0
  71. package/dist/react-native-core/crypto/RNCrypto.js.map +1 -0
  72. package/dist/react-native-core/hooks.d.ts +1 -1
  73. package/dist/react-native-core/hooks.d.ts.map +1 -1
  74. package/dist/react-native-core/index.js +5 -1
  75. package/dist/react-native-core/index.js.map +1 -1
  76. package/dist/react-native-core/platform.d.ts +2 -1
  77. package/dist/react-native-core/platform.d.ts.map +1 -1
  78. package/dist/testing.js +1 -1
  79. package/dist/testing.js.map +1 -1
  80. package/dist/tools/coValues/account.d.ts +7 -1
  81. package/dist/tools/coValues/account.d.ts.map +1 -1
  82. package/dist/tools/coValues/interfaces.d.ts +1 -1
  83. package/dist/tools/coValues/interfaces.d.ts.map +1 -1
  84. package/dist/tools/implementation/ContextManager.d.ts +3 -0
  85. package/dist/tools/implementation/ContextManager.d.ts.map +1 -1
  86. package/dist/tools/implementation/zodSchema/schemaTypes/AccountSchema.d.ts +8 -1
  87. package/dist/tools/implementation/zodSchema/schemaTypes/AccountSchema.d.ts.map +1 -1
  88. package/dist/tools/implementation/zodSchema/zodCo.d.ts.map +1 -1
  89. package/dist/tools/subscribe/CoValueCoreSubscription.d.ts +8 -22
  90. package/dist/tools/subscribe/CoValueCoreSubscription.d.ts.map +1 -1
  91. package/dist/tools/subscribe/SubscriptionCache.d.ts +51 -0
  92. package/dist/tools/subscribe/SubscriptionCache.d.ts.map +1 -0
  93. package/dist/tools/subscribe/SubscriptionScope.d.ts +17 -1
  94. package/dist/tools/subscribe/SubscriptionScope.d.ts.map +1 -1
  95. package/dist/tools/subscribe/utils.d.ts +9 -1
  96. package/dist/tools/subscribe/utils.d.ts.map +1 -1
  97. package/dist/tools/testing.d.ts +2 -2
  98. package/dist/tools/testing.d.ts.map +1 -1
  99. package/dist/tools/tests/SubscriptionCache.test.d.ts +2 -0
  100. package/dist/tools/tests/SubscriptionCache.test.d.ts.map +1 -0
  101. package/package.json +18 -6
  102. package/src/inspector/account-switcher.tsx +440 -0
  103. package/src/inspector/contexts/node.tsx +129 -0
  104. package/src/inspector/custom-element.tsx +2 -2
  105. package/src/inspector/in-app.tsx +61 -0
  106. package/src/inspector/index.tsx +2 -22
  107. package/src/inspector/pages/home.tsx +77 -0
  108. package/src/inspector/router/context.ts +21 -0
  109. package/src/inspector/router/hash-router.tsx +128 -0
  110. package/src/inspector/{viewer/use-page-path.ts → router/in-memory-router.tsx} +31 -29
  111. package/src/inspector/router/index.ts +4 -0
  112. package/src/inspector/standalone.tsx +60 -0
  113. package/src/inspector/tests/router/hash-router.test.tsx +847 -0
  114. package/src/inspector/tests/router/in-memory-router.test.tsx +724 -0
  115. package/src/inspector/ui/modal.tsx +5 -2
  116. package/src/inspector/viewer/breadcrumbs.tsx +5 -11
  117. package/src/inspector/viewer/header.tsx +67 -0
  118. package/src/inspector/viewer/page-stack.tsx +18 -26
  119. package/src/inspector/viewer/page.tsx +0 -1
  120. package/src/react/hooks.tsx +2 -0
  121. package/src/react/index.ts +1 -14
  122. package/src/react-core/hooks.ts +167 -18
  123. package/src/react-core/tests/createCoValueSubscriptionContext.test.tsx +18 -8
  124. package/src/react-core/tests/testUtils.tsx +67 -5
  125. package/src/react-core/tests/useCoState.test.ts +3 -7
  126. package/src/react-core/tests/useSubscriptionSelector.test.ts +3 -7
  127. package/src/react-core/tests/useSuspenseAccount.test.tsx +343 -0
  128. package/src/react-core/tests/useSuspenseCoState.test.tsx +1182 -0
  129. package/src/react-core/use.ts +46 -0
  130. package/src/react-native-core/crypto/RNCrypto.ts +1 -0
  131. package/src/react-native-core/hooks.tsx +2 -0
  132. package/src/react-native-core/platform.ts +2 -1
  133. package/src/tools/coValues/account.ts +13 -2
  134. package/src/tools/coValues/interfaces.ts +2 -3
  135. package/src/tools/implementation/ContextManager.ts +13 -0
  136. package/src/tools/implementation/zodSchema/schemaTypes/AccountSchema.ts +8 -1
  137. package/src/tools/subscribe/CoValueCoreSubscription.ts +71 -100
  138. package/src/tools/subscribe/SubscriptionCache.ts +272 -0
  139. package/src/tools/subscribe/SubscriptionScope.ts +113 -7
  140. package/src/tools/subscribe/utils.ts +77 -0
  141. package/src/tools/testing.ts +0 -3
  142. package/src/tools/tests/CoValueCoreSubscription.test.ts +46 -12
  143. package/src/tools/tests/ContextManager.test.ts +85 -0
  144. package/src/tools/tests/SubscriptionCache.test.ts +237 -0
  145. package/src/tools/tests/account.test.ts +11 -4
  146. package/src/tools/tests/coMap.test.ts +5 -7
  147. package/src/tools/tests/schema.resolved.test.ts +3 -3
  148. package/tsup.config.ts +2 -0
  149. package/dist/chunk-2S3Z2CN6.js.map +0 -1
  150. package/dist/inspector/custom-element-P76EIWEV.js.map +0 -1
  151. package/dist/inspector/viewer/new-app.d.ts.map +0 -1
  152. package/dist/inspector/viewer/use-page-path.d.ts +0 -10
  153. package/dist/inspector/viewer/use-page-path.d.ts.map +0 -1
  154. package/src/inspector/viewer/new-app.tsx +0 -156
@@ -1,3660 +1,24 @@
1
1
  "use client";
2
+ import {
3
+ GlobalStyles,
4
+ Header,
5
+ InMemoryRouterProvider,
6
+ NodeProvider,
7
+ PageStack
8
+ } from "./chunk-C6BJPHBQ.js";
2
9
 
3
- // src/inspector/index.tsx
4
- import React8, { useEffect as useEffect10, useState as useState18 } from "react";
5
-
6
- // src/inspector/viewer/new-app.tsx
7
- import { styled as styled27 } from "goober";
8
- import { useState as useState17 } from "react";
9
-
10
- // src/inspector/ui/button.tsx
11
- import { styled } from "goober";
12
- import { forwardRef } from "react";
13
- import { jsx } from "react/jsx-runtime";
14
- var StyledButton = styled("button")`
15
- display: inline-flex;
16
- align-items: center;
17
- justify-content: center;
18
- gap: 0.5rem;
19
- text-align: center;
20
- transition: colors 0.2s;
21
- border-radius: var(--j-radius-lg);
22
- pointer-events: ${(props) => props.disabled ? "none" : "auto"};
23
- opacity: ${(props) => props.disabled ? 0.5 : 1};
24
- cursor: ${(props) => props.disabled ? "not-allowed" : "pointer"};
25
-
26
- ${(props) => {
27
- switch (props.variant) {
28
- case "primary":
29
- return `
30
- padding: 0.375rem 0.75rem;
31
- background-color: var(--j-primary-color);
32
- border-color: var(--j-primary-color);
33
- color: white;
34
- font-weight: 500;
35
- &:hover {
36
- opacity: 0.8;
37
- }
38
- `;
39
- case "secondary":
40
- return `
41
- padding: 0.375rem 0.75rem;
42
- color: var(--j-text-color-strong);
43
- border: 1px solid var(--j-border-color);
44
- font-weight: 500;
45
- &:hover {
46
- border-color: var(--j-border-color-hover);
47
- }
48
- `;
49
- case "link":
50
- return `
51
- color: var(--j-link-color);
52
- &:hover {
53
- text-decoration: underline;
54
- }
55
- `;
56
- case "destructive":
57
- return `
58
- padding: 0.375rem 0.75rem;
59
- background-color: var(--j-destructive-color);
60
- border-color: var(--j-destructive-color);
61
- color: white;
62
- font-weight: 500;
63
- &:hover {
64
- opacity: 0.8;
65
- }
66
- `;
67
- default:
68
- return "";
69
- }
70
- }}
71
- `;
72
- var Button = forwardRef(
73
- ({
74
- className,
75
- children,
76
- variant = "primary",
77
- disabled,
78
- type = "button",
79
- ...buttonProps
80
- }, ref) => {
81
- return /* @__PURE__ */ jsx(
82
- StyledButton,
83
- {
84
- ref,
85
- ...buttonProps,
86
- disabled,
87
- className,
88
- type,
89
- variant,
90
- children
91
- }
92
- );
93
- }
94
- );
95
-
96
- // src/inspector/ui/input.tsx
97
- import { styled as styled2 } from "goober";
98
- import { forwardRef as forwardRef2, useId } from "react";
99
- import { jsx as jsx2, jsxs } from "react/jsx-runtime";
100
- var Container = styled2("div")`
101
- display: grid;
102
- gap: 0.25rem;
103
- `;
104
- var StyledInput = styled2("input")`
105
- width: 100%;
106
- border-radius: var(--j-radius-md);
107
- border: 1px solid var(--j-border-color);
108
- padding: 0.5rem 0.875rem;
109
- box-shadow: var(--j-shadow-sm);
110
- font-weight: 500;
111
- background-color: white;
112
- color: var(--j-text-color-strong);
113
-
114
- @media (prefers-color-scheme: dark) {
115
- background-color: var(--j-foreground);
116
- }
117
- `;
118
- var Input = forwardRef2(
119
- ({ label, className, hideLabel, id: customId, ...inputProps }, ref) => {
120
- const generatedId = useId();
121
- const id = customId || generatedId;
122
- return /* @__PURE__ */ jsxs(Container, { className, children: [
123
- /* @__PURE__ */ jsx2(
124
- "label",
125
- {
126
- htmlFor: id,
127
- className: hideLabel ? "j-sr-only" : "",
128
- style: { color: "var(--j-text-color)" },
129
- children: label
130
- }
131
- ),
132
- /* @__PURE__ */ jsx2(StyledInput, { ref, ...inputProps, id })
133
- ] });
134
- }
135
- );
136
-
137
- // src/inspector/viewer/breadcrumbs.tsx
138
- import { styled as styled3 } from "goober";
139
- import React from "react";
140
- import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
141
- var BreadcrumbsContainer = styled3("div")`
142
- position: relative;
143
- z-index: 20;
144
- flex: 1;
145
- display: flex;
146
- align-items: center;
147
- `;
148
- var Separator = styled3("span")`
149
- padding: 0 0.125rem;
150
- `;
151
- var Breadcrumbs = ({
152
- path,
153
- onBreadcrumbClick
154
- }) => {
155
- return /* @__PURE__ */ jsxs2(BreadcrumbsContainer, { children: [
156
- /* @__PURE__ */ jsx3(
157
- Button,
158
- {
159
- variant: "link",
160
- style: { padding: "0 0.25rem" },
161
- onClick: () => onBreadcrumbClick(-1),
162
- children: "Home"
163
- }
164
- ),
165
- path.map((page, index) => {
166
- return /* @__PURE__ */ jsxs2(React.Fragment, { children: [
167
- /* @__PURE__ */ jsx3(Separator, { "aria-hidden": true, children: "/" }),
168
- /* @__PURE__ */ jsx3(
169
- Button,
170
- {
171
- variant: "link",
172
- style: { padding: "0 0.25rem" },
173
- onClick: () => onBreadcrumbClick(index),
174
- children: index === 0 ? page.name || "Root" : page.name
175
- }
176
- )
177
- ] }, page.coId);
178
- })
179
- ] });
180
- };
181
-
182
- // src/inspector/viewer/page-stack.tsx
183
- import { styled as styled24 } from "goober";
184
-
185
- // src/inspector/viewer/page.tsx
186
- import { styled as styled22 } from "goober";
187
- import React5 from "react";
188
-
189
- // src/inspector/ui/badge.tsx
190
- import { styled as styled4 } from "goober";
191
- import { jsx as jsx4 } from "react/jsx-runtime";
192
- var StyledBadge = styled4("span")`
193
- font-size: 0.875rem;
194
- font-weight: 500;
195
- padding: 0.125rem 0.25rem;
196
- margin-left: -0.125rem;
197
- border-radius: var(--j-radius-sm);
198
- background-color: var(--j-foreground);
199
- display: inline-block;
200
- font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
201
- color: var(--j-text-color-strong);
202
- `;
203
- function Badge({
204
- children,
205
- className
206
- }) {
207
- return /* @__PURE__ */ jsx4(StyledBadge, { className, children });
208
- }
209
-
210
- // src/inspector/ui/heading.tsx
211
- import { styled as styled5 } from "goober";
212
- import { jsx as jsx5 } from "react/jsx-runtime";
213
- var StyledHeading = styled5("h1")`
214
- font-size: 1.125rem;
215
- text-align: center;
216
- font-weight: 500;
217
- color: var(--j-text-color-strong);
218
- `;
219
- function Heading({
220
- children,
221
- className,
222
- id
223
- }) {
224
- return /* @__PURE__ */ jsx5(StyledHeading, { className, id, children });
225
- }
226
-
227
- // src/inspector/ui/text.tsx
228
- import { styled as styled6 } from "goober";
229
- import React2 from "react";
230
- import { jsx as jsx6 } from "react/jsx-runtime";
231
- var BaseText = React2.forwardRef(
232
- ({ muted, strong, small, inline, mono, ...rest }, ref) => /* @__PURE__ */ jsx6("div", { ref, ...rest })
233
- );
234
- var StyledText = styled6(BaseText)`
235
- ${(props) => props.muted && `
236
- color: var(--j-neutral-500);
237
- `}
238
-
239
- ${(props) => props.strong && `
240
- font-weight: 500;
241
- color: var(--j-text-color-strong);
242
- `}
243
-
244
- ${(props) => props.small && `
245
- font-size: 0.875rem;
246
- `}
247
-
248
- ${(props) => props.inline && `
249
- display: inline;
250
- `}
251
-
252
- ${(props) => props.mono && `
253
- font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
254
- `}
255
- `;
256
- function Text(props) {
257
- return /* @__PURE__ */ jsx6(StyledText, { ...props });
258
- }
259
-
260
- // src/inspector/viewer/account-or-group-text.tsx
261
- import { useEffect as useEffect3, useState as useState3 } from "react";
262
-
263
- // src/inspector/viewer/use-resolve-covalue.ts
264
- import { useEffect as useEffect2, useState as useState2 } from "react";
265
-
266
- // src/inspector/viewer/co-stream-view.tsx
267
- import { base64URLtoBytes } from "cojson";
268
- import { styled as styled7 } from "goober";
269
- import { useEffect, useState } from "react";
270
- import { Fragment, jsx as jsx7, jsxs as jsxs3 } from "react/jsx-runtime";
271
- function isBinaryStreamStart(item) {
272
- return typeof item === "object" && item !== null && "type" in item && item.type === "start";
273
- }
274
- function detectCoStreamType(value) {
275
- const firstKey = Object.keys(value.items)[0];
276
- if (!firstKey)
277
- return {
278
- type: "unknown"
279
- };
280
- const items = value.items[firstKey]?.map((v) => v.value);
281
- if (!items)
282
- return {
283
- type: "unknown"
284
- };
285
- const firstItem = items[0];
286
- if (!firstItem)
287
- return {
288
- type: "unknown"
289
- };
290
- if (isBinaryStreamStart(firstItem)) {
291
- return {
292
- type: "binary",
293
- items
294
- };
295
- } else {
296
- return {
297
- type: "coStream"
298
- };
299
- }
300
- }
301
- async function getBlobFromCoStream({
302
- items,
303
- onlyFirstChunk = false
304
- }) {
305
- if (onlyFirstChunk && items.length > 1) {
306
- items = items.slice(0, 2);
307
- }
308
- const chunks = [];
309
- const binary_U_prefixLength = 8;
310
- let lastProgressUpdate = Date.now();
311
- for (const item of items.slice(1)) {
312
- if (item.type === "end") {
313
- break;
314
- }
315
- if (item.type !== "chunk") {
316
- console.error("Invalid binary stream chunk", item);
317
- return void 0;
318
- }
319
- const chunk = base64URLtoBytes(item.chunk.slice(binary_U_prefixLength));
320
- chunks.push(chunk);
321
- if (Date.now() - lastProgressUpdate > 100) {
322
- lastProgressUpdate = Date.now();
323
- }
324
- }
325
- const defaultMime = items[0] && "mimeType" in items[0] ? items[0].mimeType : null;
326
- const blob = new Blob(chunks, defaultMime ? { type: defaultMime } : {});
327
- const mimeType = defaultMime === "" ? await detectPDFMimeType(blob) : defaultMime;
328
- return {
329
- blob,
330
- mimeType,
331
- unfinishedChunks: items.length > 1,
332
- totalSize: items[0] && "totalSizeBytes" in items[0] ? items[0].totalSizeBytes : void 0
333
- };
334
- }
335
- var detectPDFMimeType = async (blob) => {
336
- const arrayBuffer = await blob.slice(0, 4).arrayBuffer();
337
- const uint8Array = new Uint8Array(arrayBuffer);
338
- const header = uint8Array.reduce(
339
- (acc, byte) => acc + String.fromCharCode(byte),
340
- ""
341
- );
342
- if (header === "%PDF") {
343
- return "application/pdf";
344
- }
345
- return "unknown";
346
- };
347
- var BinaryDownloadButton = ({
348
- pdfBlob,
349
- fileName = "document",
350
- label,
351
- mimeType
352
- }) => {
353
- const downloadFile = () => {
354
- const url = URL.createObjectURL(
355
- new Blob([pdfBlob], mimeType ? { type: mimeType } : {})
356
- );
357
- const link = document.createElement("a");
358
- link.href = url;
359
- link.download = mimeType === "application/pdf" ? `${fileName}.pdf` : fileName;
360
- document.body.appendChild(link);
361
- link.click();
362
- document.body.removeChild(link);
363
- URL.revokeObjectURL(url);
364
- };
365
- return /* @__PURE__ */ jsxs3(Button, { variant: "secondary", onClick: downloadFile, children: [
366
- "\u2B07\uFE0F ",
367
- label
368
- ] });
369
- };
370
- var LabelContentPairContainer = styled7("div")`
371
- display: flex;
372
- flex-direction: column;
373
- gap: 0.375rem;
374
- `;
375
- var BinaryStreamGrid = styled7("div")`
376
- display: grid;
377
- grid-template-columns: repeat(3, 1fr);
378
- gap: 0.5rem;
379
- max-width: 48rem;
380
- `;
381
- var ImagePreviewContainer = styled7("div")`
382
- background-color: rgb(249 250 251);
383
- padding: 0.75rem;
384
- border-radius: var(--j-radius-md);
385
- @media (prefers-color-scheme: dark) {
386
- background-color: rgb(28 25 23);
387
- }
388
- `;
389
- var CoStreamGrid = styled7("div")`
390
- display: grid;
391
- grid-template-columns: repeat(3, 1fr);
392
- gap: 0.5rem;
393
- `;
394
- var CoStreamItemContainer = styled7("div")`
395
- padding: 0.75rem;
396
- border-radius: var(--j-radius-lg);
397
- overflow: hidden;
398
- border: 1px solid rgb(229 231 235);
399
- cursor: pointer;
400
- box-shadow: var(--j-shadow-sm);
401
- &:hover {
402
- background-color: rgb(243 244 246 / 0.05);
403
- }
404
- `;
405
- var LabelContentPair = ({
406
- label,
407
- content
408
- }) => {
409
- return /* @__PURE__ */ jsxs3(LabelContentPairContainer, { children: [
410
- /* @__PURE__ */ jsx7("span", { children: label }),
411
- /* @__PURE__ */ jsx7("span", { children: content })
412
- ] });
413
- };
414
- function RenderCoBinaryStream({
415
- value,
416
- items
417
- }) {
418
- const [file, setFile] = useState(null);
419
- const [isLoading, setIsLoading] = useState(true);
420
- useEffect(() => {
421
- getBlobFromCoStream({
422
- items,
423
- onlyFirstChunk: true
424
- }).then((v) => {
425
- if (v) {
426
- setFile(v);
427
- if (v.mimeType.includes("image")) {
428
- getBlobFromCoStream({
429
- items
430
- }).then((s) => {
431
- if (s) setFile(s);
432
- });
433
- }
434
- }
435
- }).finally(() => setIsLoading(false));
436
- }, [items]);
437
- if (!isLoading && !file) return /* @__PURE__ */ jsx7("div", { children: "No blob" });
438
- if (isLoading) return /* @__PURE__ */ jsx7("div", { children: "Loading..." });
439
- if (!file) return /* @__PURE__ */ jsx7("div", { children: "No blob" });
440
- const { blob, mimeType } = file;
441
- const sizeInKB = (file.totalSize || 0) / 1024;
442
- return /* @__PURE__ */ jsxs3(Fragment, { children: [
443
- /* @__PURE__ */ jsxs3(BinaryStreamGrid, { children: [
444
- /* @__PURE__ */ jsx7(
445
- LabelContentPair,
446
- {
447
- label: "Mime Type",
448
- content: /* @__PURE__ */ jsx7(Badge, { children: mimeType || "No mime type" })
449
- }
450
- ),
451
- /* @__PURE__ */ jsx7(
452
- LabelContentPair,
453
- {
454
- label: "Size",
455
- content: /* @__PURE__ */ jsxs3("span", { children: [
456
- sizeInKB.toFixed(2),
457
- " KB"
458
- ] })
459
- }
460
- ),
461
- /* @__PURE__ */ jsx7(
462
- LabelContentPair,
463
- {
464
- label: "Download",
465
- content: /* @__PURE__ */ jsx7(
466
- BinaryDownloadButton,
467
- {
468
- fileName: value.id.toString(),
469
- pdfBlob: blob,
470
- mimeType,
471
- label: mimeType === "application/pdf" ? "Download PDF" : "Download file"
472
- }
473
- )
474
- }
475
- )
476
- ] }),
477
- mimeType === "image/png" || mimeType === "image/jpeg" ? /* @__PURE__ */ jsx7(
478
- LabelContentPair,
479
- {
480
- label: "Preview",
481
- content: /* @__PURE__ */ jsx7(ImagePreviewContainer, { children: /* @__PURE__ */ jsx7(RenderBlobImage, { blob }) })
482
- }
483
- ) : null
484
- ] });
485
- }
486
- function RenderCoStream({
487
- value,
488
- node
489
- }) {
490
- const streamPerUser = Object.keys(value.items);
491
- const userCoIds = streamPerUser.map((stream) => stream.split("_session")[0]);
492
- return /* @__PURE__ */ jsx7(CoStreamGrid, { children: userCoIds.map((id, idx) => /* @__PURE__ */ jsxs3(CoStreamItemContainer, { children: [
493
- /* @__PURE__ */ jsx7(AccountOrGroupText, { coId: id, node }),
494
- value.items[streamPerUser[idx]]?.map(
495
- (item) => /* @__PURE__ */ jsxs3("div", { children: [
496
- new Date(item.madeAt).toLocaleString(),
497
- " ",
498
- JSON.stringify(item.value)
499
- ] }, item.tx.txIndex + item.tx.sessionID)
500
- )
501
- ] }, id)) });
502
- }
503
- function CoStreamView({
504
- value,
505
- node
506
- }) {
507
- const streamType = detectCoStreamType(value);
508
- if (streamType.type === "binary") {
509
- if (streamType.items === void 0) {
510
- return /* @__PURE__ */ jsx7("div", { children: "No binary stream" });
511
- }
512
- return /* @__PURE__ */ jsx7(
513
- RenderCoBinaryStream,
514
- {
515
- value,
516
- items: streamType.items
517
- }
518
- );
519
- }
520
- if (streamType.type === "coStream") {
521
- return /* @__PURE__ */ jsx7(RenderCoStream, { value, node });
522
- }
523
- if (streamType.type === "unknown") return /* @__PURE__ */ jsx7("div", { children: "Unknown stream type" });
524
- return /* @__PURE__ */ jsx7("div", { children: "Unknown stream type" });
525
- }
526
- function RenderBlobImage({ blob }) {
527
- const urlCreator = window.URL || window.webkitURL;
528
- return /* @__PURE__ */ jsx7("img", { src: urlCreator.createObjectURL(blob) });
529
- }
530
-
531
- // src/inspector/viewer/use-resolve-covalue.ts
532
- var isBrowserImage = (coValue) => {
533
- return "originalSize" in coValue && "placeholderDataURL" in coValue;
534
- };
535
- async function resolveCoValue(coValueId, node) {
536
- const value = await node.load(coValueId);
537
- if (value === "unavailable") {
538
- return {
539
- value: void 0,
540
- snapshot: "unavailable",
541
- type: null,
542
- extendedType: void 0
543
- };
544
- }
545
- const snapshot = value.toJSON();
546
- const type = value.type;
547
- let extendedType;
548
- if (type === "comap") {
549
- if (isBrowserImage(snapshot)) {
550
- extendedType = "image";
551
- } else if (value.headerMeta?.type === "account") {
552
- extendedType = "account";
553
- } else if (value.core.isGroup()) {
554
- extendedType = "group";
555
- }
556
- }
557
- return {
558
- value,
559
- snapshot,
560
- type,
561
- extendedType
562
- };
563
- }
564
- function subscribeToCoValue(coValueId, node, callback) {
565
- return node.subscribe(coValueId, (value) => {
566
- if (value === "unavailable") {
567
- callback({
568
- value: void 0,
569
- snapshot: "unavailable",
570
- type: null,
571
- extendedType: void 0
572
- });
573
- } else {
574
- const snapshot = value.toJSON();
575
- const type = value.type;
576
- let extendedType;
577
- if (type === "comap") {
578
- if (isBrowserImage(snapshot)) {
579
- extendedType = "image";
580
- } else if (value.headerMeta?.type === "account") {
581
- extendedType = "account";
582
- } else if (value.core.isGroup()) {
583
- extendedType = "group";
584
- }
585
- } else if (type === "costream") {
586
- const coStream = detectCoStreamType(value);
587
- if (coStream.type === "binary") {
588
- extendedType = "file";
589
- }
590
- }
591
- callback({
592
- value,
593
- snapshot,
594
- type,
595
- extendedType
596
- });
597
- }
598
- });
599
- }
600
- function useResolvedCoValue(coValueId, node) {
601
- const [result, setResult] = useState2();
602
- useEffect2(() => {
603
- let isMounted = true;
604
- const unsubscribe = subscribeToCoValue(coValueId, node, (newResult) => {
605
- if (isMounted) {
606
- setResult(newResult);
607
- }
608
- });
609
- return () => {
610
- isMounted = false;
611
- unsubscribe();
612
- };
613
- }, [coValueId, node]);
614
- return result || {
615
- value: void 0,
616
- snapshot: void 0,
617
- type: void 0,
618
- extendedType: void 0
619
- };
620
- }
621
- function useResolvedCoValues(coValueIds, node) {
622
- const [results, setResults] = useState2([]);
623
- useEffect2(() => {
624
- let isMounted = true;
625
- const unsubscribes = [];
626
- coValueIds.forEach((coValueId, index) => {
627
- const unsubscribe = subscribeToCoValue(coValueId, node, (newResult) => {
628
- if (isMounted) {
629
- setResults((prevResults) => {
630
- const newResults = prevResults.slice(0, coValueIds.length);
631
- newResults[index] = newResult;
632
- return newResults;
633
- });
634
- }
635
- });
636
- unsubscribes.push(unsubscribe);
637
- });
638
- return () => {
639
- isMounted = false;
640
- unsubscribes.forEach((unsubscribe) => unsubscribe());
641
- };
642
- }, [coValueIds, node]);
643
- return results;
644
- }
645
-
646
- // src/inspector/viewer/account-or-group-text.tsx
647
- import { Fragment as Fragment2, jsx as jsx8 } from "react/jsx-runtime";
648
- function AccountOrGroupText({
649
- coId,
650
- node,
651
- showId = false,
652
- onClick
653
- }) {
654
- const { snapshot, extendedType } = useResolvedCoValue(coId, node);
655
- const [name, setName] = useState3(null);
656
- useEffect3(() => {
657
- if (snapshot && typeof snapshot === "object" && "profile" in snapshot) {
658
- const profileId = snapshot.profile;
659
- resolveCoValue(profileId, node).then((profileResult) => {
660
- if (profileResult.snapshot && typeof profileResult.snapshot === "object" && "name" in profileResult.snapshot) {
661
- setName(profileResult.snapshot.name);
662
- }
663
- });
664
- }
665
- }, [snapshot, node, extendedType]);
666
- if (!snapshot) return /* @__PURE__ */ jsx8("span", { children: "Loading..." });
667
- if (extendedType !== "account" && extendedType !== "group") {
668
- return /* @__PURE__ */ jsx8("span", { children: "CoID is not an account or group" });
669
- }
670
- const displayName = extendedType === "account" ? name || "Account" : "Group";
671
- const displayText = showId ? `${displayName} <${coId}>` : displayName;
672
- if (onClick) {
673
- return /* @__PURE__ */ jsx8(Button, { variant: "link", onClick: () => onClick(displayName), children: displayText });
674
- }
675
- return /* @__PURE__ */ jsx8(Fragment2, { children: displayText });
676
- }
677
-
678
- // src/inspector/viewer/grid-view.tsx
679
- import { useState as useState6 } from "react";
680
- import { styled as styled14 } from "goober";
681
-
682
- // src/inspector/viewer/type-icon.tsx
683
- import { styled as styled8 } from "goober";
684
- import { jsx as jsx9 } from "react/jsx-runtime";
685
- var IconText = styled8("span")`
686
- font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
687
- `;
688
- var UnavailableText = styled8("div")`
689
- font-weight: 500;
690
- `;
691
- var EmptySpace = styled8("div")`
692
- white-space: pre;
693
- width: 3.5rem;
694
- font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
695
- `;
696
- var TypeIcon = ({
697
- type,
698
- extendedType
699
- }) => {
700
- const iconMap = {
701
- record: "{} Record",
702
- image: "\u{1F5BC}\uFE0F Image",
703
- comap: "{} CoMap",
704
- costream: "\u224B CoFeed",
705
- colist: "\u2630 CoList",
706
- account: "\u{1F464} Account",
707
- group: "\u{1F465} Group",
708
- file: "\u{1F4C3} FileStream",
709
- coplaintext: "\u{1F4C4} CoPlainText"
710
- };
711
- const iconKey = extendedType || type;
712
- const icon2 = iconMap[iconKey];
713
- return icon2 ? /* @__PURE__ */ jsx9(IconText, { children: icon2 }) : null;
714
- };
715
- var ResolveIcon = ({
716
- coId,
717
- node
718
- }) => {
719
- const { type, extendedType, snapshot } = useResolvedCoValue(coId, node);
720
- if (snapshot === "unavailable" && !type) {
721
- return /* @__PURE__ */ jsx9(UnavailableText, { children: "Unavailable" });
722
- }
723
- if (!type) return /* @__PURE__ */ jsx9(EmptySpace, { children: " " });
724
- return /* @__PURE__ */ jsx9(TypeIcon, { type, extendedType });
725
- };
726
-
727
- // src/inspector/viewer/types.ts
728
- var isCoId = (coId) => typeof coId === "string" && coId.startsWith("co_") && !coId.includes("inviteSecret");
729
-
730
- // src/inspector/viewer/value-renderer.tsx
731
- import { styled as styled9 } from "goober";
732
- import React3, { useState as useState4 } from "react";
733
-
734
- // src/inspector/ui/icons/caution.tsx
735
- import { jsx as jsx10, jsxs as jsxs4 } from "react/jsx-runtime";
736
- function CautionIcon(props) {
737
- return /* @__PURE__ */ jsxs4(
738
- "svg",
739
- {
740
- ...props,
741
- xmlns: "http://www.w3.org/2000/svg",
742
- width: "24",
743
- height: "24",
744
- viewBox: "0 0 24 24",
745
- fill: "none",
746
- stroke: "currentColor",
747
- strokeLinejoin: "round",
748
- children: [
749
- /* @__PURE__ */ jsx10("circle", { cx: "12", cy: "12", r: "12", fill: "currentColor" }),
750
- /* @__PURE__ */ jsx10("rect", { x: "10.5", y: "6", width: "3", height: "7.5", rx: "1.5", fill: "#fff" }),
751
- /* @__PURE__ */ jsx10("rect", { x: "10.5", y: "16.5", width: "3", height: "3", rx: "1.5", fill: "#fff" })
752
- ]
753
- }
754
- );
755
- }
756
-
757
- // src/inspector/ui/icons/chevron-down-icon.tsx
758
- import { jsx as jsx11 } from "react/jsx-runtime";
759
- function ChevronDownIcon(props) {
760
- return /* @__PURE__ */ jsx11(
761
- "svg",
762
- {
763
- ...props,
764
- xmlns: "http://www.w3.org/2000/svg",
765
- width: "24",
766
- height: "24",
767
- viewBox: "0 0 24 24",
768
- fill: "none",
769
- stroke: "currentColor",
770
- strokeLinejoin: "round",
771
- children: /* @__PURE__ */ jsx11("path", { d: "m6 9 6 6 6-6" })
772
- }
773
- );
774
- }
775
-
776
- // src/inspector/ui/icons/delete-icon.tsx
777
- import { jsx as jsx12, jsxs as jsxs5 } from "react/jsx-runtime";
778
- function DeleteIcon(props) {
779
- return /* @__PURE__ */ jsxs5(
780
- "svg",
781
- {
782
- ...props,
783
- xmlns: "http://www.w3.org/2000/svg",
784
- width: "24",
785
- height: "24",
786
- viewBox: "0 0 24 24",
787
- fill: "none",
788
- stroke: "currentColor",
789
- strokeLinejoin: "round",
790
- className: "lucide lucide-trash-icon lucide-trash",
791
- children: [
792
- /* @__PURE__ */ jsx12("path", { d: "M3 6h18" }),
793
- /* @__PURE__ */ jsx12("path", { d: "M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6" }),
794
- /* @__PURE__ */ jsx12("path", { d: "M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2" })
795
- ]
796
- }
797
- );
798
- }
799
-
800
- // src/inspector/ui/icons/edit-icon.tsx
801
- import { jsx as jsx13 } from "react/jsx-runtime";
802
- function EditIcon(props) {
803
- return /* @__PURE__ */ jsx13(
804
- "svg",
805
- {
806
- ...props,
807
- xmlns: "http://www.w3.org/2000/svg",
808
- width: "24",
809
- height: "24",
810
- viewBox: "0 0 24 24",
811
- fill: "none",
812
- stroke: "currentColor",
813
- strokeLinejoin: "round",
814
- className: "lucide lucide-edit lucide-pencil",
815
- children: /* @__PURE__ */ jsx13("path", { d: "M13.2942 7.95881C13.5533 7.63559 13.5013 7.16358 13.178 6.90453C12.8548 6.64549 12.3828 6.6975 12.1238 7.02072L13.2942 7.95881ZM6.811 14.8488L7.37903 15.3385C7.38489 15.3317 7.39062 15.3248 7.39623 15.3178L6.811 14.8488ZM6.64 15.2668L5.89146 15.2179L5.8908 15.2321L6.64 15.2668ZM6.5 18.2898L5.7508 18.2551C5.74908 18.2923 5.75013 18.3296 5.75396 18.3667L6.5 18.2898ZM7.287 18.9768L7.31152 19.7264C7.36154 19.7247 7.41126 19.7181 7.45996 19.7065L7.287 18.9768ZM10.287 18.2658L10.46 18.9956L10.4716 18.9927L10.287 18.2658ZM10.672 18.0218L11.2506 18.4991L11.2571 18.491L10.672 18.0218ZM17.2971 10.959C17.5562 10.6358 17.5043 10.1638 17.1812 9.90466C16.8581 9.64552 16.386 9.69742 16.1269 10.0206L17.2971 10.959ZM12.1269 7.02052C11.8678 7.34365 11.9196 7.81568 12.2428 8.07484C12.5659 8.33399 13.0379 8.28213 13.2971 7.95901L12.1269 7.02052ZM14.3 5.50976L14.8851 5.97901C14.8949 5.96672 14.9044 5.95412 14.9135 5.94123L14.3 5.50976ZM15.929 5.18976L16.4088 4.61332C16.3849 4.59344 16.3598 4.57507 16.3337 4.5583L15.929 5.18976ZM18.166 7.05176L18.6968 6.52192C18.6805 6.50561 18.6635 6.49007 18.6458 6.47532L18.166 7.05176ZM18.5029 7.87264L19.2529 7.87676V7.87676L18.5029 7.87264ZM18.157 8.68976L17.632 8.15412C17.6108 8.17496 17.5908 8.19704 17.5721 8.22025L18.157 8.68976ZM16.1271 10.0203C15.8678 10.3433 15.9195 10.8153 16.2425 11.0746C16.5655 11.3339 17.0376 11.2823 17.2969 10.9593L16.1271 10.0203ZM13.4537 7.37862C13.3923 6.96898 13.0105 6.68666 12.6009 6.74805C12.1912 6.80943 11.9089 7.19127 11.9703 7.60091L13.4537 7.37862ZM16.813 11.2329C17.2234 11.1772 17.5109 10.7992 17.4552 10.3888C17.3994 9.97834 17.0215 9.69082 16.611 9.74659L16.813 11.2329ZM12.1238 7.02072L6.22577 14.3797L7.39623 15.3178L13.2942 7.95881L12.1238 7.02072ZM6.24297 14.359C6.03561 14.5995 5.91226 14.9011 5.89159 15.218L7.38841 15.3156C7.38786 15.324 7.38457 15.3321 7.37903 15.3385L6.24297 14.359ZM5.8908 15.2321L5.7508 18.2551L7.2492 18.3245L7.3892 15.3015L5.8908 15.2321ZM5.75396 18.3667C5.83563 19.1586 6.51588 19.7524 7.31152 19.7264L7.26248 18.2272C7.25928 18.2273 7.25771 18.2268 7.25669 18.2264C7.25526 18.2259 7.25337 18.2249 7.25144 18.2232C7.2495 18.2215 7.24825 18.2198 7.24754 18.2185C7.24703 18.2175 7.24637 18.216 7.24604 18.2128L5.75396 18.3667ZM7.45996 19.7065L10.46 18.9955L10.114 17.536L7.11404 18.247L7.45996 19.7065ZM10.4716 18.9927C10.7771 18.9151 11.05 18.7422 11.2506 18.499L10.0934 17.5445C10.0958 17.5417 10.0989 17.5397 10.1024 17.5388L10.4716 18.9927ZM11.2571 18.491L17.2971 10.959L16.1269 10.0206L10.0869 17.5526L11.2571 18.491ZM13.2971 7.95901L14.8851 5.97901L13.7149 5.04052L12.1269 7.02052L13.2971 7.95901ZM14.9135 5.94123C15.0521 5.74411 15.3214 5.6912 15.5243 5.82123L16.3337 4.5583C15.4544 3.99484 14.2873 4.2241 13.6865 5.0783L14.9135 5.94123ZM15.4492 5.7662L17.6862 7.6282L18.6458 6.47532L16.4088 4.61332L15.4492 5.7662ZM17.6352 7.58161C17.7111 7.6577 17.7535 7.761 17.7529 7.86852L19.2529 7.87676C19.2557 7.36905 19.0555 6.88127 18.6968 6.52192L17.6352 7.58161ZM17.7529 7.86852C17.7524 7.97604 17.7088 8.07886 17.632 8.15412L18.682 9.22541C19.0446 8.87002 19.2501 8.38447 19.2529 7.87676L17.7529 7.86852ZM17.5721 8.22025L16.1271 10.0203L17.2969 10.9593L18.7419 9.15928L17.5721 8.22025ZM11.9703 7.60091C12.3196 9.93221 14.4771 11.5503 16.813 11.2329L16.611 9.74659C15.0881 9.95352 13.6815 8.89855 13.4537 7.37862L11.9703 7.60091Z" })
816
- }
817
- );
818
- }
819
-
820
- // src/inspector/ui/icons/link-icon.tsx
821
- import { jsx as jsx14 } from "react/jsx-runtime";
822
- function LinkIcon(props) {
823
- return /* @__PURE__ */ jsx14(
824
- "svg",
825
- {
826
- xmlns: "http://www.w3.org/2000/svg",
827
- fill: "none",
828
- viewBox: "0 0 24 24",
829
- strokeWidth: 1.5,
830
- stroke: "currentColor",
831
- ...props,
832
- children: /* @__PURE__ */ jsx14(
833
- "path",
834
- {
835
- strokeLinecap: "round",
836
- strokeLinejoin: "round",
837
- d: "M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622 1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"
838
- }
839
- )
840
- }
841
- );
842
- }
843
-
844
- // src/inspector/ui/icons/history.tsx
845
- import { jsx as jsx15, jsxs as jsxs6 } from "react/jsx-runtime";
846
- function HistoryIcon(props) {
847
- return /* @__PURE__ */ jsxs6(
848
- "svg",
849
- {
850
- ...props,
851
- xmlns: "http://www.w3.org/2000/svg",
852
- width: "24",
853
- height: "24",
854
- viewBox: "0 0 24 24",
855
- fill: "none",
856
- stroke: "currentColor",
857
- strokeLinejoin: "round",
858
- className: "lucide lucide-trash-icon lucide-trash",
859
- children: [
860
- /* @__PURE__ */ jsx15(
861
- "path",
862
- {
863
- d: "M5.52786 16.7023C6.6602 18.2608 8.3169 19.3584 10.1936 19.7934C12.0703 20.2284 14.0409 19.9716 15.7434 19.0701C17.446 18.1687 18.766 16.6832 19.4611 14.8865C20.1562 13.0898 20.1796 11.1027 19.527 9.29011C18.8745 7.47756 17.5898 5.96135 15.909 5.02005C14.2282 4.07875 12.2641 3.77558 10.3777 4.16623C8.49129 4.55689 6.80919 5.61514 5.64045 7.14656C4.47171 8.67797 3.89482 10.5797 4.01579 12.5023M4.01579 12.5023L2.51579 11.0023M4.01579 12.5023L5.51579 11.0023",
864
- strokeWidth: "2",
865
- strokeLinecap: "round",
866
- strokeLinejoin: "round"
867
- }
868
- ),
869
- /* @__PURE__ */ jsx15(
870
- "path",
871
- {
872
- d: "M12 8V12L15 15",
873
- strokeWidth: "2",
874
- strokeLinecap: "round",
875
- strokeLinejoin: "round"
876
- }
877
- )
878
- ]
879
- }
880
- );
881
- }
882
-
883
- // src/inspector/ui/icons/add-icon.tsx
884
- import { jsx as jsx16 } from "react/jsx-runtime";
885
- function AddIcon(props) {
886
- return /* @__PURE__ */ jsx16(
887
- "svg",
888
- {
889
- ...props,
890
- xmlns: "http://www.w3.org/2000/svg",
891
- width: "24",
892
- height: "24",
893
- viewBox: "0 0 24 24",
894
- fill: "none",
895
- stroke: "currentColor",
896
- strokeLinejoin: "round",
897
- children: /* @__PURE__ */ jsx16(
898
- "path",
899
- {
900
- d: "M4 12H20M12 4V20",
901
- "stroke-width": "2",
902
- "stroke-linecap": "round",
903
- "stroke-linejoin": "round"
904
- }
905
- )
906
- }
907
- );
908
- }
909
-
910
- // src/inspector/ui/icon.tsx
911
- import { jsx as jsx17 } from "react/jsx-runtime";
912
- var icons = {
913
- caution: CautionIcon,
914
- chevronDown: ChevronDownIcon,
915
- delete: DeleteIcon,
916
- edit: EditIcon,
917
- link: LinkIcon,
918
- history: HistoryIcon,
919
- add: AddIcon
920
- };
921
- var sizes = {
922
- "2xs": 14,
923
- xs: 16,
924
- sm: 20,
925
- md: 24,
926
- lg: 28,
927
- xl: 28,
928
- "2xl": 32,
929
- "3xl": 36,
930
- "4xl": 40,
931
- "5xl": 48,
932
- "6xl": 60,
933
- "7xl": 72,
934
- "8xl": 96,
935
- "9xl": 128
936
- };
937
- var strokeWidths = {
938
- "2xs": 2.5,
939
- xs: 2,
940
- sm: 2,
941
- md: 1.5,
942
- lg: 1.5,
943
- xl: 1.5,
944
- "2xl": 1.25,
945
- "3xl": 1.25,
946
- "4xl": 1.25,
947
- "5xl": 1,
948
- "6xl": 1,
949
- "7xl": 1,
950
- "8xl": 1,
951
- "9xl": 1
952
- };
953
- function Icon({
954
- name,
955
- size = "md",
956
- className,
957
- ...svgProps
958
- }) {
959
- if (!name || !icons.hasOwnProperty(name)) {
960
- throw new Error(`Icon not found: ${name}`);
961
- }
962
- const IconComponent = icons?.hasOwnProperty(name) ? icons[name] : icon;
963
- return /* @__PURE__ */ jsx17(
964
- IconComponent,
965
- {
966
- "aria-hidden": "true",
967
- size: sizes[size],
968
- strokeWidth: strokeWidths[size],
969
- strokeLinecap: "round",
970
- ...svgProps
971
- }
972
- );
973
- }
974
-
975
- // src/inspector/viewer/value-renderer.tsx
976
- import { Fragment as Fragment3, jsx as jsx18, jsxs as jsxs7 } from "react/jsx-runtime";
977
- var LinkContainer = styled9("span")`
978
- display: inline-flex;
979
- gap: 0.25rem;
980
- align-items: center;
981
- `;
982
- var BooleanText = styled9("span")`
983
- font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
984
- ${(props) => props.value ? `
985
- color: var(--j-success-color);
986
- ` : `
987
- color: var(--j-destructive-color);
988
- `}
989
- `;
990
- var ObjectContent = styled9("pre")`
991
- margin-top: 0.375rem;
992
- font-size: 0.875rem;
993
- white-space: pre-wrap;
994
- `;
995
- var PreviewContainer = styled9("div")`
996
- font-size: 0.875rem;
997
- display: flex;
998
- flex-direction: column;
999
- gap: 0.5rem;
1000
- align-items: flex-start;
1001
- `;
1002
- var PreviewGrid = styled9("div")`
1003
- display: grid;
1004
- grid-template-columns: auto 1fr;
1005
- gap: 0.5rem;
1006
- `;
1007
- var PreviewMoreText = styled9(Text)`
1008
- text-align: left;
1009
- margin-top: 0.5rem;
1010
- `;
1011
- var ImagePreviewContainer2 = styled9("div")`
1012
- display: flex;
1013
- flex-direction: column;
1014
- align-items: flex-start;
1015
- `;
1016
- var PreviewImage = styled9("img")`
1017
- width: 2rem;
1018
- height: 2rem;
1019
- border: 2px solid white;
1020
- box-shadow: var(--j-shadow-sm);
1021
- margin: 0.5rem 0;
1022
- `;
1023
- var RecordText = styled9("div")`
1024
- display: flex;
1025
- align-items: center;
1026
- gap: 0.25rem;
1027
- `;
1028
- var ListText = styled9("div")`
1029
- display: flex;
1030
- align-items: center;
1031
- gap: 0.25rem;
1032
- `;
1033
- function ValueRenderer({
1034
- json,
1035
- onCoIDClick,
1036
- compact
1037
- }) {
1038
- const [isExpanded, setIsExpanded] = useState4(false);
1039
- if (typeof json === "undefined" || json === void 0) {
1040
- return /* @__PURE__ */ jsx18(Text, { muted: true, children: "undefined" });
1041
- }
1042
- if (json === null) {
1043
- return /* @__PURE__ */ jsx18(Text, { muted: true, children: "null" });
1044
- }
1045
- if (typeof json === "string" && isCoId(json)) {
1046
- const content = /* @__PURE__ */ jsxs7(Fragment3, { children: [
1047
- json,
1048
- onCoIDClick && /* @__PURE__ */ jsx18(Icon, { name: "link" })
1049
- ] });
1050
- if (onCoIDClick) {
1051
- return /* @__PURE__ */ jsx18(
1052
- Button,
1053
- {
1054
- variant: "link",
1055
- onClick: () => {
1056
- onCoIDClick?.(json);
1057
- },
1058
- children: content
1059
- }
1060
- );
1061
- }
1062
- return /* @__PURE__ */ jsx18(LinkContainer, { children: content });
1063
- }
1064
- if (typeof json === "string") {
1065
- return /* @__PURE__ */ jsx18(Text, { children: json });
1066
- }
1067
- if (typeof json === "number") {
1068
- return /* @__PURE__ */ jsx18(Text, { mono: true, children: json });
1069
- }
1070
- if (typeof json === "boolean") {
1071
- return /* @__PURE__ */ jsx18(BooleanText, { value: json, children: json.toString() });
1072
- }
1073
- const longJson = JSON.stringify(json, null, 2);
1074
- const shortJson = longJson.split("\n").slice(0, compact ? 3 : 8).join("\n");
1075
- const hasDifference = longJson !== shortJson;
1076
- if (typeof json === "object") {
1077
- return /* @__PURE__ */ jsxs7(Fragment3, { children: [
1078
- /* @__PURE__ */ jsx18("p", { children: Array.isArray(json) ? /* @__PURE__ */ jsxs7(Fragment3, { children: [
1079
- "Array (",
1080
- json.length,
1081
- ")"
1082
- ] }) : /* @__PURE__ */ jsx18(Fragment3, { children: "Object" }) }),
1083
- /* @__PURE__ */ jsxs7(ObjectContent, { children: [
1084
- isExpanded ? longJson : shortJson,
1085
- hasDifference && !isExpanded ? "\n ..." : null
1086
- ] }),
1087
- !compact && hasDifference ? /* @__PURE__ */ jsx18(Button, { variant: "link", onClick: () => setIsExpanded(!isExpanded), children: isExpanded ? "Show less" : "Show more" }) : null
1088
- ] });
1089
- }
1090
- return /* @__PURE__ */ jsx18("span", { children: String(json) });
1091
- }
1092
- var CoMapPreview = ({
1093
- coId,
1094
- node,
1095
- limit = 6
1096
- }) => {
1097
- const { value, snapshot, type, extendedType } = useResolvedCoValue(
1098
- coId,
1099
- node
1100
- );
1101
- if (!snapshot) {
1102
- return /* @__PURE__ */ jsx18(
1103
- "div",
1104
- {
1105
- style: {
1106
- borderRadius: "0.25rem",
1107
- backgroundColor: "var(--j-foreground)",
1108
- animation: "pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite",
1109
- whiteSpace: "pre",
1110
- width: "6rem"
1111
- },
1112
- children: " "
1113
- }
1114
- );
1115
- }
1116
- if (snapshot === "unavailable" && !value) {
1117
- return /* @__PURE__ */ jsx18(Text, { inline: true, muted: true, children: "Unavailable" });
1118
- }
1119
- if (type === "coplaintext") {
1120
- return /* @__PURE__ */ jsx18(Fragment3, { children: value.toString() });
1121
- }
1122
- if (extendedType === "image" && isBrowserImage(snapshot)) {
1123
- return /* @__PURE__ */ jsxs7(ImagePreviewContainer2, { children: [
1124
- /* @__PURE__ */ jsx18(PreviewImage, { src: snapshot.placeholderDataURL }),
1125
- /* @__PURE__ */ jsxs7(Text, { inline: true, small: true, muted: true, children: [
1126
- snapshot.originalSize[0],
1127
- " x ",
1128
- snapshot.originalSize[1]
1129
- ] })
1130
- ] });
1131
- }
1132
- if (extendedType === "record") {
1133
- return /* @__PURE__ */ jsxs7(RecordText, { children: [
1134
- "Record",
1135
- " ",
1136
- /* @__PURE__ */ jsxs7(Text, { inline: true, muted: true, children: [
1137
- "(",
1138
- Object.keys(snapshot).length,
1139
- ")"
1140
- ] })
1141
- ] });
1142
- }
1143
- if (type === "colist") {
1144
- return /* @__PURE__ */ jsxs7(ListText, { children: [
1145
- "List",
1146
- " ",
1147
- /* @__PURE__ */ jsxs7(Text, { inline: true, muted: true, children: [
1148
- "(",
1149
- snapshot.length,
1150
- ")"
1151
- ] })
1152
- ] });
1153
- }
1154
- const properties = Object.entries(snapshot);
1155
- const limitedProperties = extendedType === "account" ? properties.filter(
1156
- ([key]) => !key.startsWith("key_z") && !key.startsWith("sealer_z") && key !== "readKey"
1157
- ).slice(0, limit) : properties.slice(0, limit);
1158
- return /* @__PURE__ */ jsxs7(PreviewContainer, { children: [
1159
- /* @__PURE__ */ jsx18(PreviewGrid, { children: limitedProperties.map(([key, value2]) => /* @__PURE__ */ jsxs7(React3.Fragment, { children: [
1160
- /* @__PURE__ */ jsxs7(Text, { strong: true, children: [
1161
- key,
1162
- ": "
1163
- ] }),
1164
- /* @__PURE__ */ jsx18(ValueRenderer, { compact: true, json: value2 })
1165
- ] }, key)) }),
1166
- properties.length > limit && /* @__PURE__ */ jsxs7(PreviewMoreText, { muted: true, small: true, children: [
1167
- properties.length - limit,
1168
- " more"
1169
- ] })
1170
- ] });
1171
- };
1172
-
1173
- // src/inspector/viewer/co-value-editor.tsx
1174
- import { useState as useState5 } from "react";
1175
- import { styled as styled11 } from "goober";
1176
-
1177
- // src/inspector/ui/select.tsx
1178
- import { styled as styled10 } from "goober";
1179
- import { useId as useId2 } from "react";
1180
- import { jsx as jsx19, jsxs as jsxs8 } from "react/jsx-runtime";
1181
- var SelectContainer = styled10("div")`
1182
- display: grid;
1183
- gap: 0.25rem;
1184
- `;
1185
- var SelectWrapper = styled10("div")`
1186
- position: relative;
1187
- display: flex;
1188
- align-items: center;
1189
- `;
1190
- var StyledSelect = styled10("select")`
1191
- width: 100%;
1192
- border-radius: var(--j-radius-md);
1193
- border: 1px solid var(--j-border-color);
1194
- padding: 0.5rem 0.875rem 0.5rem 0.875rem;
1195
- padding-right: 2rem;
1196
- box-shadow: var(--j-shadow-sm);
1197
- font-weight: 500;
1198
- color: var(--j-text-color-strong);
1199
- appearance: none;
1200
- overflow: hidden;
1201
- text-overflow: ellipsis;
1202
- white-space: nowrap;
1203
-
1204
- @media (prefers-color-scheme: dark) {
1205
- background-color: var(--j-foreground);
1206
- }
1207
- `;
1208
- var SelectIcon = styled10("span")`
1209
- position: absolute;
1210
- right: 0.5em;
1211
- color: var(--j-neutral-400);
1212
- pointer-events: none;
1213
-
1214
- @media (prefers-color-scheme: dark) {
1215
- color: var(--j-neutral-900);
1216
- }
1217
- `;
1218
- function Select(props) {
1219
- const { label, hideLabel, id: customId, className, ...selectProps } = props;
1220
- const generatedId = useId2();
1221
- const id = customId || generatedId;
1222
- return /* @__PURE__ */ jsxs8(SelectContainer, { className, children: [
1223
- /* @__PURE__ */ jsx19("label", { htmlFor: id, className: hideLabel ? "j-sr-only" : "", children: label }),
1224
- /* @__PURE__ */ jsxs8(SelectWrapper, { children: [
1225
- /* @__PURE__ */ jsx19(StyledSelect, { ...selectProps, id, children: props.children }),
1226
- /* @__PURE__ */ jsx19(SelectIcon, { children: /* @__PURE__ */ jsx19(Icon, { name: "chevronDown", size: "sm" }) })
1227
- ] })
1228
- ] });
1229
- }
1230
-
1231
- // src/inspector/viewer/co-value-editor.tsx
1232
- import { jsx as jsx20, jsxs as jsxs9 } from "react/jsx-runtime";
1233
- function CoValueEditor({
1234
- node,
1235
- property,
1236
- value,
1237
- coValue,
1238
- onCancel
1239
- }) {
1240
- const getInitialType = () => {
1241
- if (value === null) return "null";
1242
- if (value === void 0) return "undefined";
1243
- if (typeof value === "number") return "number";
1244
- if (typeof value === "string") return "string";
1245
- if (typeof value === "boolean") return value ? "true" : "false";
1246
- if (typeof value === "object") return "object";
1247
- return "undefined";
1248
- };
1249
- const [selectedType, setSelectedType] = useState5(getInitialType());
1250
- const [editValue, setEditValue] = useState5(
1251
- value === void 0 || value === null ? "" : typeof value === "object" ? JSON.stringify(value, null, 2) : String(value)
1252
- );
1253
- const handleSubmit = (e) => {
1254
- e.preventDefault();
1255
- e.stopPropagation();
1256
- let newValue;
1257
- switch (selectedType) {
1258
- case "null":
1259
- newValue = null;
1260
- break;
1261
- case "undefined":
1262
- newValue = void 0;
1263
- break;
1264
- case "true":
1265
- newValue = true;
1266
- break;
1267
- case "false":
1268
- newValue = false;
1269
- break;
1270
- case "number":
1271
- newValue = parseFloat(editValue);
1272
- break;
1273
- case "string":
1274
- newValue = editValue;
1275
- break;
1276
- case "object":
1277
- newValue = JSON.parse(editValue);
1278
- break;
1279
- default:
1280
- throw new Error(`Invalid type: ${selectedType}`);
1281
- }
1282
- coValue.core.makeTransaction(
1283
- [
1284
- {
1285
- op: "set",
1286
- key: property,
1287
- value: newValue
1288
- }
1289
- ],
1290
- "private"
1291
- );
1292
- onCancel();
1293
- };
1294
- const showTextarea = selectedType === "number" || selectedType === "string" || selectedType === "object";
1295
- return /* @__PURE__ */ jsxs9(EditForm, { onSubmit: handleSubmit, children: [
1296
- /* @__PURE__ */ jsxs9(
1297
- Select,
1298
- {
1299
- label: "Type",
1300
- value: selectedType,
1301
- onChange: (e) => {
1302
- setSelectedType(e.target.value);
1303
- },
1304
- onClick: (e) => e.stopPropagation(),
1305
- children: [
1306
- /* @__PURE__ */ jsx20("option", { value: "number", children: "number" }),
1307
- /* @__PURE__ */ jsx20("option", { value: "string", children: "string" }),
1308
- /* @__PURE__ */ jsx20("option", { value: "true", children: "true" }),
1309
- /* @__PURE__ */ jsx20("option", { value: "false", children: "false" }),
1310
- /* @__PURE__ */ jsx20("option", { value: "object", children: "object" }),
1311
- /* @__PURE__ */ jsx20("option", { value: "null", children: "null" }),
1312
- /* @__PURE__ */ jsx20("option", { value: "undefined", children: "undefined" })
1313
- ]
1314
- }
1315
- ),
1316
- showTextarea && /* @__PURE__ */ jsx20(
1317
- StyledTextarea,
1318
- {
1319
- value: editValue,
1320
- onChange: (e) => setEditValue(e.target.value),
1321
- onClick: (e) => e.stopPropagation()
1322
- }
1323
- ),
1324
- /* @__PURE__ */ jsxs9(FormActions, { children: [
1325
- /* @__PURE__ */ jsx20(Button, { type: "button", variant: "secondary", onClick: onCancel, children: "Cancel" }),
1326
- /* @__PURE__ */ jsx20(Button, { type: "submit", variant: "primary", children: "Submit" })
1327
- ] })
1328
- ] });
1329
- }
1330
- var EditForm = styled11("form")`
1331
- display: flex;
1332
- flex-direction: column;
1333
- gap: 0.75rem;
1334
- `;
1335
- var StyledTextarea = styled11("textarea")`
1336
- width: 100%;
1337
- min-height: 120px;
1338
- border-radius: var(--j-radius-md);
1339
- border: 1px solid var(--j-border-color);
1340
- padding: 0.5rem 0.875rem;
1341
- box-shadow: var(--j-shadow-sm);
1342
- font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
1343
- font-size: 0.875rem;
1344
- background-color: white;
1345
- color: var(--j-text-color-strong);
1346
- resize: vertical;
1347
-
1348
- @media (prefers-color-scheme: dark) {
1349
- background-color: var(--j-foreground);
1350
- }
1351
- `;
1352
- var FormActions = styled11("div")`
1353
- display: flex;
1354
- gap: 0.5rem;
1355
- justify-content: flex-end;
1356
- `;
1357
-
1358
- // src/inspector/ui/card.tsx
1359
- import { styled as styled12 } from "goober";
1360
- var Card = styled12("div")`
1361
- background-color: var(--j-background);
1362
- border-radius: var(--j-radius-lg);
1363
- box-shadow: var(--j-shadow-sm);
1364
- border: 1px solid var(--j-border-color);
1365
- padding: 1rem;
1366
- text-align: left;
1367
- overflow-x: hidden;
1368
- display: flex;
1369
- flex-direction: column;
1370
- gap: 0.5rem;
1371
- `;
1372
- var CardHeader = styled12("div")`
1373
- display: flex;
1374
- justify-content: space-between;
1375
- align-items: center;
1376
- `;
1377
- var CardBody = styled12("div")`
1378
- flex: 1;
1379
- `;
1380
-
1381
- // src/inspector/ui/grid.tsx
1382
- import { styled as styled13 } from "goober";
1383
- import { jsx as jsx21 } from "react/jsx-runtime";
1384
- var GridThreeColumns = styled13("div")`
1385
- display: grid;
1386
- grid-template-columns: repeat(1, minmax(0, 1fr));
1387
- gap: 1rem;
1388
-
1389
- @media (min-width: 768px) {
1390
- grid-template-columns: repeat(2, minmax(0, 1fr));
1391
- }
1392
-
1393
- @media (min-width: 1280px) {
1394
- grid-template-columns: repeat(3, minmax(0, 1fr));
1395
- }
1396
- `;
1397
- var GridTwoColumns = styled13("div")`
1398
- display: grid;
1399
- grid-template-columns: repeat(1, minmax(0, 1fr));
1400
- gap: 1rem;
1401
-
1402
- @media (min-width: 768px) {
1403
- grid-template-columns: repeat(2, minmax(0, 1fr));
1404
- }
1405
- `;
1406
- var GridOneColumn = styled13("div")`
1407
- display: grid;
1408
- grid-template-columns: repeat(1, minmax(0, 1fr));
1409
- gap: 1rem;
1410
- `;
1411
- function Grid(props) {
1412
- const { cols, children, ...rest } = props;
1413
- switch (cols) {
1414
- case 1:
1415
- return /* @__PURE__ */ jsx21(GridOneColumn, { ...rest, children });
1416
- case 2:
1417
- return /* @__PURE__ */ jsx21(GridTwoColumns, { ...rest, children });
1418
- case 3:
1419
- return /* @__PURE__ */ jsx21(GridThreeColumns, { ...rest, children });
1420
- default:
1421
- throw new Error(`Invalid number of columns: ${cols}`);
1422
- }
1423
- }
1424
-
1425
- // src/inspector/utils/permissions.ts
1426
- function isWriter(role) {
1427
- return role === "writer" || role === "admin" || role === "manager" || role === "writeOnly";
1428
- }
1429
-
1430
- // src/inspector/viewer/grid-view.tsx
1431
- import { Fragment as Fragment4, jsx as jsx22, jsxs as jsxs10 } from "react/jsx-runtime";
1432
- function GridItem({
1433
- entry,
1434
- onNavigate,
1435
- node,
1436
- coValue
1437
- }) {
1438
- const [key, value] = entry;
1439
- const isCoValue = isCoId(value);
1440
- const [isEditing, setIsEditing] = useState6(false);
1441
- const handleEditClick = (e) => {
1442
- e.stopPropagation();
1443
- setIsEditing(true);
1444
- };
1445
- const handleCancel = () => {
1446
- setIsEditing(false);
1447
- };
1448
- const handleDelete = (e) => {
1449
- e.stopPropagation();
1450
- if (confirm(`Are you sure you want to delete the property "${key}"?`)) {
1451
- coValue?.core.makeTransaction(
1452
- [
1453
- {
1454
- op: "del",
1455
- key
1456
- }
1457
- ],
1458
- "private"
1459
- );
1460
- }
1461
- };
1462
- if (isEditing) {
1463
- return /* @__PURE__ */ jsxs10(
1464
- Card,
1465
- {
1466
- style: {
1467
- backgroundColor: "var(--j-foreground)",
1468
- borderColor: "var(--j-foreground)"
1469
- },
1470
- children: [
1471
- /* @__PURE__ */ jsx22(CardHeader, { children: /* @__PURE__ */ jsx22("div", { style: { display: "flex", alignItems: "center", gap: "0.5rem" }, children: isCoValue ? /* @__PURE__ */ jsxs10(Fragment4, { children: [
1472
- /* @__PURE__ */ jsx22(Text, { strong: true, children: key }),
1473
- /* @__PURE__ */ jsx22(Badge, { children: /* @__PURE__ */ jsx22(ResolveIcon, { coId: value, node }) })
1474
- ] }) : /* @__PURE__ */ jsx22(Text, { strong: true, children: key }) }) }),
1475
- /* @__PURE__ */ jsx22(CardBody, { style: { wordBreak: "break-word" }, children: /* @__PURE__ */ jsx22(
1476
- CoValueEditor,
1477
- {
1478
- node,
1479
- property: key,
1480
- value,
1481
- coValue,
1482
- onCancel: handleCancel
1483
- }
1484
- ) })
1485
- ]
1486
- }
1487
- );
1488
- }
1489
- const cardProps = isCoValue ? {
1490
- onClick: () => onNavigate([{ coId: value, name: key }]),
1491
- as: "button"
1492
- } : {
1493
- style: {
1494
- backgroundColor: "var(--j-foreground)",
1495
- borderColor: "var(--j-foreground)"
1496
- }
1497
- };
1498
- return /* @__PURE__ */ jsxs10(Card, { ...cardProps, children: [
1499
- /* @__PURE__ */ jsxs10(CardHeader, { children: [
1500
- /* @__PURE__ */ jsx22("div", { style: { display: "flex", alignItems: "center", gap: "0.5rem" }, children: isCoValue ? /* @__PURE__ */ jsxs10(Fragment4, { children: [
1501
- /* @__PURE__ */ jsx22(Text, { strong: true, children: key }),
1502
- /* @__PURE__ */ jsx22(Badge, { children: /* @__PURE__ */ jsx22(ResolveIcon, { coId: value, node }) })
1503
- ] }) : /* @__PURE__ */ jsx22(Text, { strong: true, children: key }) }),
1504
- coValue && isWriter(coValue.group.myRole()) && /* @__PURE__ */ jsxs10(ActionButtons, { children: [
1505
- /* @__PURE__ */ jsx22(
1506
- EditButton,
1507
- {
1508
- onClick: handleEditClick,
1509
- type: "button",
1510
- "aria-label": "Edit",
1511
- children: /* @__PURE__ */ jsx22(Icon, { name: "edit", size: "sm" })
1512
- }
1513
- ),
1514
- /* @__PURE__ */ jsx22(
1515
- DeleteButton,
1516
- {
1517
- onClick: handleDelete,
1518
- type: "button",
1519
- "aria-label": "Delete",
1520
- children: /* @__PURE__ */ jsx22(Icon, { name: "delete", size: "sm" })
1521
- }
1522
- )
1523
- ] })
1524
- ] }),
1525
- /* @__PURE__ */ jsx22(CardBody, { style: { wordBreak: "break-word" }, children: isCoValue ? /* @__PURE__ */ jsx22(CoMapPreview, { coId: value, node }) : /* @__PURE__ */ jsx22(
1526
- ValueRenderer,
1527
- {
1528
- json: value,
1529
- onCoIDClick: (coId) => {
1530
- onNavigate([{ coId, name: key }]);
1531
- }
1532
- }
1533
- ) })
1534
- ] });
1535
- }
1536
- function GridView({
1537
- data,
1538
- onNavigate,
1539
- node,
1540
- coValue
1541
- }) {
1542
- const entries = Object.entries(data);
1543
- return /* @__PURE__ */ jsx22(Grid, { cols: entries.length === 1 ? 1 : 3, children: entries.map((entry, childIndex) => /* @__PURE__ */ jsx22(
1544
- GridItem,
1545
- {
1546
- entry,
1547
- onNavigate,
1548
- node,
1549
- coValue
1550
- },
1551
- childIndex
1552
- )) });
1553
- }
1554
- var EditButton = styled14("button")`
1555
- display: inline-flex;
1556
- align-items: center;
1557
- justify-content: center;
1558
- padding: 0.25rem;
1559
- border: none;
1560
- background: transparent;
1561
- cursor: pointer;
1562
- color: var(--j-text-color);
1563
- border-radius: var(--j-radius-sm);
1564
- transition: background-color 0.2s;
1565
-
1566
- &:hover {
1567
- background-color: var(--j-foreground);
1568
- }
1569
- `;
1570
- var DeleteButton = styled14("button")`
1571
- display: inline-flex;
1572
- align-items: center;
1573
- justify-content: center;
1574
- padding: 0.25rem;
1575
- border: none;
1576
- background: transparent;
1577
- cursor: pointer;
1578
- color: var(--j-text-color);
1579
- border-radius: var(--j-radius-sm);
1580
- transition: background-color 0.2s;
1581
-
1582
- &:hover {
1583
- background-color: var(--j-foreground);
1584
- }
1585
- `;
1586
- var ActionButtons = styled14("div")`
1587
- display: flex;
1588
- align-items: center;
1589
- gap: 0.25rem;
1590
- `;
1591
-
1592
- // src/inspector/viewer/raw-data-card.tsx
1593
- import { useEffect as useEffect7, useState as useState9 } from "react";
1594
-
1595
- // src/inspector/ui/modal.tsx
1596
- import { styled as styled15 } from "goober";
1597
- import { forwardRef as forwardRef3, useEffect as useEffect4, useRef } from "react";
1598
- import { jsx as jsx23, jsxs as jsxs11 } from "react/jsx-runtime";
1599
- var ModalContent = styled15("dialog")`
1600
- background-color: var(--j-background);
1601
- border-radius: var(--j-radius-lg);
1602
- box-shadow: 0 10px 25px rgba(0, 0, 0, 0.2);
1603
- border: 1px solid var(--j-border-color);
1604
- max-width: 32rem;
1605
- margin-block: auto;
1606
- margin-inline: auto;
1607
- &::backdrop {
1608
- background-color: rgba(0, 0, 0, 0.7);
1609
- }
1610
-
1611
- `;
1612
- var ModalHeader = styled15("div")`
1613
- display: flex;
1614
- justify-content: space-between;
1615
- align-items: flex-start;
1616
- padding: 1.5rem 1.5rem 0 1.5rem;
1617
- gap: 1rem;
1618
- `;
1619
- var ModalBody = styled15("div")`
1620
- padding: 1rem 1.5rem;
1621
- flex: 1;
1622
- `;
1623
- var ModalFooter = styled15("div")`
1624
- display: flex;
1625
- justify-content: flex-end;
1626
- gap: 0.75rem;
1627
- padding: 0 1.5rem 1.5rem 1.5rem;
1628
- `;
1629
- var CloseButton = styled15("button")`
1630
- background: none;
1631
- border: none;
1632
- cursor: pointer;
1633
- padding: 0.25rem;
1634
- border-radius: var(--j-radius-sm);
1635
- color: var(--j-text-color);
1636
- font-size: 1.25rem;
1637
- line-height: 1;
1638
- display: flex;
1639
- align-items: center;
1640
- justify-content: center;
1641
- min-width: 2rem;
1642
- min-height: 2rem;
1643
-
1644
- &:hover {
1645
- background-color: var(--j-foreground);
1646
- }
1647
-
1648
- &:focus-visible {
1649
- outline: 2px solid var(--j-border-focus);
1650
- outline-offset: 2px;
1651
- }
1652
- `;
1653
- var Modal = forwardRef3(
1654
- ({
1655
- isOpen,
1656
- onClose,
1657
- heading,
1658
- text,
1659
- children,
1660
- confirmText = "Confirm",
1661
- cancelText = "Cancel",
1662
- onConfirm,
1663
- onCancel,
1664
- showButtons = true,
1665
- className
1666
- }, ref) => {
1667
- const modalRef = useRef(null);
1668
- useEffect4(() => {
1669
- if (isOpen) {
1670
- modalRef.current?.showModal();
1671
- } else {
1672
- onClose();
1673
- modalRef.current?.close();
1674
- }
1675
- }, [isOpen, onClose]);
1676
- const handleConfirm = () => {
1677
- onConfirm?.();
1678
- onClose();
1679
- };
1680
- const handleCancel = () => {
1681
- onCancel?.();
1682
- onClose();
1683
- };
1684
- if (!isOpen) return null;
1685
- return /* @__PURE__ */ jsxs11(
1686
- ModalContent,
1687
- {
1688
- ref: ref || modalRef,
1689
- className,
1690
- role: "dialog",
1691
- "aria-labelledby": "modal-heading",
1692
- onClose,
1693
- children: [
1694
- /* @__PURE__ */ jsxs11(ModalHeader, { children: [
1695
- /* @__PURE__ */ jsx23(Heading, { id: "modal-heading", children: heading }),
1696
- /* @__PURE__ */ jsx23(CloseButton, { onClick: onClose, "aria-label": "Close modal", type: "button", children: "\xD7" })
1697
- ] }),
1698
- /* @__PURE__ */ jsxs11(ModalBody, { children: [
1699
- text && /* @__PURE__ */ jsx23("p", { style: { margin: "0 0 1rem 0", color: "var(--j-text-color)" }, children: text }),
1700
- children
1701
- ] }),
1702
- showButtons && /* @__PURE__ */ jsxs11(ModalFooter, { children: [
1703
- /* @__PURE__ */ jsx23(Button, { variant: "secondary", onClick: handleCancel, children: cancelText }),
1704
- /* @__PURE__ */ jsx23(Button, { variant: "primary", onClick: handleConfirm, children: confirmText })
1705
- ] })
1706
- ]
1707
- }
1708
- );
1709
- }
1710
- );
1711
- Modal.displayName = "Modal";
1712
-
1713
- // src/inspector/ui/data-table.tsx
1714
- import { useEffect as useEffect5, useMemo, useState as useState7 } from "react";
1715
-
1716
- // src/inspector/ui/table.tsx
1717
- import { styled as styled16 } from "goober";
1718
- import React4 from "react";
1719
- import { jsx as jsx24 } from "react/jsx-runtime";
1720
- var StyledTable = styled16("table")`
1721
- width: 100%;
1722
- `;
1723
- var StyledThead = styled16("thead")`
1724
- text-align: left;
1725
- border-bottom: 1px solid var(--j-border-color);
1726
- background-color: var(--j-neutral-100);
1727
-
1728
- @media (prefers-color-scheme: dark) {
1729
- background-color: var(--j-neutral-925);
1730
- }
1731
- `;
1732
- var StyledTbody = styled16("tbody")`
1733
- tr {
1734
- border-bottom: 1px solid var(--j-border-color);
1735
-
1736
- &:last-child {
1737
- border-bottom: none;
1738
- }
1739
- }
1740
- `;
1741
- var StyledTh = styled16("th")`
1742
- font-weight: 500;
1743
- padding: 0.5rem 0.75rem;
1744
- color: var(--j-text-color-strong);
1745
- `;
1746
- var StyledTd = styled16("td")`
1747
- padding: 0.5rem 0.75rem;
1748
- `;
1749
- var Table = React4.forwardRef(({ children, ...props }, ref) => /* @__PURE__ */ jsx24(StyledTable, { ref, ...props, children }));
1750
- var TableHead = React4.forwardRef(({ children, ...props }, ref) => /* @__PURE__ */ jsx24(StyledThead, { ref, ...props, children }));
1751
- var TableBody = React4.forwardRef(({ children, ...props }, ref) => /* @__PURE__ */ jsx24(StyledTbody, { ref, ...props, children }));
1752
- var TableRow = React4.forwardRef(({ children, ...props }, ref) => /* @__PURE__ */ jsx24("tr", { ref, ...props, children }));
1753
- var TableHeader = React4.forwardRef(({ children, ...props }, ref) => /* @__PURE__ */ jsx24(StyledTh, { ref, ...props, children }));
1754
- var TableCell = React4.forwardRef(({ children, ...props }, ref) => /* @__PURE__ */ jsx24(StyledTd, { ref, ...props, children }));
1755
-
1756
- // src/inspector/ui/data-table.tsx
1757
- import { Fragment as Fragment5, jsx as jsx25, jsxs as jsxs12 } from "react/jsx-runtime";
1758
- function DataTable({
1759
- columns,
1760
- data,
1761
- pageSize = 10,
1762
- initialSort = null,
1763
- getRowKey,
1764
- emptyMessage = "No data available"
1765
- }) {
1766
- const [currentPage, setCurrentPage] = useState7(1);
1767
- const [sortConfig, setSortConfig] = useState7(initialSort);
1768
- const [filters, setFilters] = useState7({});
1769
- const filteredData = useMemo(() => {
1770
- return data.filter((row) => {
1771
- return Object.entries(filters).every(([columnId, filterValue]) => {
1772
- if (!filterValue) return true;
1773
- const column = columns.find((col) => col.id === columnId);
1774
- if (!column?.filterable) return true;
1775
- if (column.filterFn) {
1776
- return column.filterFn(row, filterValue);
1777
- }
1778
- const cellValue = String(column.accessor(row));
1779
- return cellValue.toLowerCase().includes(filterValue.toLowerCase());
1780
- });
1781
- });
1782
- }, [data, filters, columns]);
1783
- const sortedData = useMemo(() => {
1784
- if (!sortConfig) return filteredData;
1785
- const column = columns.find((col) => col.id === sortConfig.columnId);
1786
- if (!column?.sortable) return filteredData;
1787
- const sorted = [...filteredData].sort((a, b) => {
1788
- if (column.sortFn) {
1789
- return column.sortFn(a, b);
1790
- }
1791
- const aValue = String(column.accessor(a));
1792
- const bValue = String(column.accessor(b));
1793
- return aValue.localeCompare(bValue);
1794
- });
1795
- return sortConfig.direction === "desc" ? sorted.reverse() : sorted;
1796
- }, [filteredData, sortConfig, columns]);
1797
- const totalPages = Math.ceil(sortedData.length / pageSize);
1798
- const showPagination = sortedData.length > pageSize;
1799
- const startIndex = (currentPage - 1) * pageSize;
1800
- const endIndex = startIndex + pageSize;
1801
- const paginatedData = sortedData.slice(startIndex, endIndex);
1802
- useEffect5(() => {
1803
- setCurrentPage(1);
1804
- }, [filters]);
1805
- const handleSort = (columnId) => {
1806
- const column = columns.find((col) => col.id === columnId);
1807
- if (!column?.sortable) return;
1808
- setSortConfig((current) => {
1809
- if (current?.columnId === columnId) {
1810
- if (current.direction === "asc") {
1811
- return { columnId, direction: "desc" };
1812
- }
1813
- return null;
1814
- }
1815
- return { columnId, direction: "asc" };
1816
- });
1817
- };
1818
- const handleFilterChange = (columnId, value) => {
1819
- setFilters((current) => ({
1820
- ...current,
1821
- [columnId]: value
1822
- }));
1823
- };
1824
- const handlePageChange = (page) => {
1825
- setCurrentPage(Math.max(1, Math.min(page, totalPages)));
1826
- };
1827
- return /* @__PURE__ */ jsxs12(Fragment5, { children: [
1828
- /* @__PURE__ */ jsxs12(Table, { children: [
1829
- /* @__PURE__ */ jsx25(TableHead, { children: /* @__PURE__ */ jsx25(TableRow, { children: columns.map((column) => /* @__PURE__ */ jsx25(TableHeader, { children: /* @__PURE__ */ jsxs12(
1830
- "div",
1831
- {
1832
- style: {
1833
- display: "flex",
1834
- alignItems: "center",
1835
- gap: "8px",
1836
- cursor: column.sortable ? "pointer" : "default"
1837
- },
1838
- onClick: () => handleSort(column.id),
1839
- children: [
1840
- /* @__PURE__ */ jsx25("span", { children: column.header }),
1841
- column.sortable && /* @__PURE__ */ jsx25(
1842
- "span",
1843
- {
1844
- style: {
1845
- fontSize: "12px",
1846
- opacity: 0.7
1847
- },
1848
- children: sortConfig?.columnId === column.id ? sortConfig.direction === "asc" ? "\u2191" : "\u2193" : "\u2195"
1849
- }
1850
- )
1851
- ]
1852
- }
1853
- ) }, column.id)) }) }),
1854
- /* @__PURE__ */ jsxs12(TableBody, { children: [
1855
- columns.some((column) => column.filterable) && /* @__PURE__ */ jsx25(TableRow, { children: columns.map((column) => /* @__PURE__ */ jsx25(TableCell, { children: column.filterable && /* @__PURE__ */ jsx25(
1856
- Input,
1857
- {
1858
- label: "Filter",
1859
- hideLabel: true,
1860
- type: "search",
1861
- placeholder: `Filter ${column.header.toLowerCase()}`,
1862
- value: filters[column.id] || "",
1863
- onChange: (e) => handleFilterChange(column.id, e.target.value),
1864
- onClick: (e) => e.stopPropagation()
1865
- }
1866
- ) }, column.id)) }),
1867
- paginatedData.length === 0 ? /* @__PURE__ */ jsx25(TableRow, { children: /* @__PURE__ */ jsx25(TableCell, { colSpan: columns.length, children: /* @__PURE__ */ jsx25(
1868
- "div",
1869
- {
1870
- style: {
1871
- textAlign: "center",
1872
- padding: "20px",
1873
- opacity: 0.6
1874
- },
1875
- children: emptyMessage
1876
- }
1877
- ) }) }) : paginatedData.map((row, index) => /* @__PURE__ */ jsx25(TableRow, { children: columns.map((column) => /* @__PURE__ */ jsx25(TableCell, { children: column.accessor(row) }, column.id)) }, getRowKey(row, startIndex + index)))
1878
- ] })
1879
- ] }),
1880
- showPagination && /* @__PURE__ */ jsxs12(
1881
- "div",
1882
- {
1883
- style: {
1884
- display: "flex",
1885
- justifyContent: "space-between",
1886
- alignItems: "center",
1887
- marginTop: "16px",
1888
- padding: "8px 0"
1889
- },
1890
- children: [
1891
- /* @__PURE__ */ jsxs12("div", { style: { fontSize: "14px", opacity: 0.7 }, children: [
1892
- "Showing ",
1893
- startIndex + 1,
1894
- " to ",
1895
- Math.min(endIndex, sortedData.length),
1896
- " ",
1897
- "of ",
1898
- sortedData.length,
1899
- " entries",
1900
- Object.keys(filters).some((key) => filters[key]) && ` (filtered from ${data.length})`
1901
- ] }),
1902
- /* @__PURE__ */ jsxs12("div", { style: { display: "flex", gap: "8px", alignItems: "center" }, children: [
1903
- /* @__PURE__ */ jsx25(
1904
- Button,
1905
- {
1906
- variant: "secondary",
1907
- onClick: () => handlePageChange(1),
1908
- disabled: currentPage === 1,
1909
- children: "\xAB\xAB"
1910
- }
1911
- ),
1912
- /* @__PURE__ */ jsx25(
1913
- Button,
1914
- {
1915
- variant: "secondary",
1916
- onClick: () => handlePageChange(currentPage - 1),
1917
- disabled: currentPage === 1,
1918
- children: "\xAB"
1919
- }
1920
- ),
1921
- /* @__PURE__ */ jsxs12("span", { style: { fontSize: "14px" }, children: [
1922
- "Page ",
1923
- currentPage,
1924
- " of ",
1925
- totalPages
1926
- ] }),
1927
- /* @__PURE__ */ jsx25(
1928
- Button,
1929
- {
1930
- variant: "secondary",
1931
- onClick: () => handlePageChange(currentPage + 1),
1932
- disabled: currentPage === totalPages,
1933
- children: "\xBB"
1934
- }
1935
- ),
1936
- /* @__PURE__ */ jsx25(
1937
- Button,
1938
- {
1939
- variant: "secondary",
1940
- onClick: () => handlePageChange(totalPages),
1941
- disabled: currentPage === totalPages,
1942
- children: "\xBB\xBB"
1943
- }
1944
- )
1945
- ] })
1946
- ]
1947
- }
1948
- )
1949
- ] });
1950
- }
1951
-
1952
- // src/inspector/ui/accordion.tsx
1953
- import { styled as styled17 } from "goober";
1954
- import { useEffect as useEffect6, useState as useState8 } from "react";
1955
- import { jsx as jsx26, jsxs as jsxs13 } from "react/jsx-runtime";
1956
- function Accordion({ title, children, storageKey }) {
1957
- const [open, setOpen] = useStoragedState(storageKey, false);
1958
- return /* @__PURE__ */ jsxs13(
1959
- "details",
1960
- {
1961
- open,
1962
- style: { display: "flex", flexDirection: "column", gap: "1rem" },
1963
- children: [
1964
- /* @__PURE__ */ jsx26(
1965
- StyledSummary,
1966
- {
1967
- onClick: (e) => {
1968
- e.preventDefault();
1969
- setOpen((v) => !v);
1970
- },
1971
- children: title
1972
- }
1973
- ),
1974
- children
1975
- ]
1976
- }
1977
- );
1978
- }
1979
- function useStoragedState(key, defaultValue) {
1980
- const [state, setState] = useState8(() => {
1981
- if (typeof window === "undefined") return defaultValue;
1982
- const stored = localStorage.getItem(key);
1983
- return stored ? JSON.parse(stored) : defaultValue;
1984
- });
1985
- useEffect6(() => {
1986
- localStorage.setItem(key, JSON.stringify(state));
1987
- }, [state]);
1988
- return [state, setState];
1989
- }
1990
- var StyledSummary = styled17("summary")`
1991
- font-size: 1.125rem;
1992
- cursor: pointer;
1993
- font-weight: 500;
1994
- color: var(--j-text-color-strong);
1995
- `;
1996
-
1997
- // src/inspector/viewer/raw-data-card.tsx
1998
- import { jsx as jsx27, jsxs as jsxs14 } from "react/jsx-runtime";
1999
- function CopyButton({ data }) {
2000
- const [copyCount, setCopyCount] = useState9(0);
2001
- const copied = copyCount > 0;
2002
- const stringifiedData = JSON.stringify(data);
2003
- useEffect7(() => {
2004
- if (copyCount > 0) {
2005
- const timeout = setTimeout(() => setCopyCount(0), 1e3);
2006
- return () => {
2007
- clearTimeout(timeout);
2008
- };
2009
- }
2010
- }, [copyCount]);
2011
- return /* @__PURE__ */ jsx27(
2012
- Button,
2013
- {
2014
- style: {
2015
- position: "absolute",
2016
- top: "10px",
2017
- right: "10px"
2018
- },
2019
- onClick: () => {
2020
- window.navigator.clipboard.writeText(stringifiedData).then(() => {
2021
- setCopyCount((count) => count + 1);
2022
- });
2023
- },
2024
- variant: "secondary",
2025
- children: copied ? "Copied" : "Copy"
2026
- }
2027
- );
2028
- }
2029
- function RawDataCard({ data }) {
2030
- return /* @__PURE__ */ jsx27(Accordion, { title: "Raw data", storageKey: "jazz-inspector-show-raw-data", children: /* @__PURE__ */ jsxs14(Card, { style: { position: "relative" }, children: [
2031
- /* @__PURE__ */ jsx27(CardHeader, { children: /* @__PURE__ */ jsx27(CopyButton, { data }) }),
2032
- /* @__PURE__ */ jsx27(CardBody, { children: /* @__PURE__ */ jsx27(ValueRenderer, { json: data }) })
2033
- ] }) });
2034
- }
2035
-
2036
- // src/inspector/viewer/account-view.tsx
2037
- import { Fragment as Fragment6, jsx as jsx28, jsxs as jsxs15 } from "react/jsx-runtime";
2038
- function AccountView({
2039
- data,
2040
- onNavigate,
2041
- node
2042
- }) {
2043
- const readableData = { ...data };
2044
- for (const key in readableData) {
2045
- if (key === "readKey" || key.startsWith("sealer_z") || key.startsWith("key_z")) {
2046
- delete readableData[key];
2047
- }
2048
- }
2049
- return /* @__PURE__ */ jsxs15(Fragment6, { children: [
2050
- /* @__PURE__ */ jsx28(GridView, { data: readableData, onNavigate, node }),
2051
- /* @__PURE__ */ jsx28(RawDataCard, { data })
2052
- ] });
2053
- }
2054
-
2055
- // src/inspector/viewer/co-plain-text-view.tsx
2056
- import { useState as useState10 } from "react";
2057
- import { styled as styled18 } from "goober";
2058
- import { CoPlainText } from "jazz-tools";
2059
- import { Fragment as Fragment7, jsx as jsx29, jsxs as jsxs16 } from "react/jsx-runtime";
2060
- function CoPlainTextView({
2061
- data,
2062
- coValue
2063
- }) {
2064
- const currentText = Object.values(data).join("");
2065
- const [isEditing, setIsEditing] = useState10(false);
2066
- const [editValue, setEditValue] = useState10("");
2067
- const canEdit2 = isWriter(coValue.group.myRole());
2068
- const handleEditClick = () => {
2069
- setIsEditing(true);
2070
- setEditValue(currentText);
2071
- };
2072
- const handleCancel = () => {
2073
- setIsEditing(false);
2074
- setEditValue(currentText);
2075
- };
2076
- const handleSave = (e) => {
2077
- e.preventDefault();
2078
- e.stopPropagation();
2079
- const coPlainText = CoPlainText.fromRaw(coValue);
2080
- coPlainText.$jazz.applyDiff(editValue);
2081
- setIsEditing(false);
2082
- };
2083
- if (!data) return;
2084
- if (isEditing) {
2085
- return /* @__PURE__ */ jsxs16(Fragment7, { children: [
2086
- /* @__PURE__ */ jsxs16(EditForm2, { onSubmit: handleSave, children: [
2087
- /* @__PURE__ */ jsx29(
2088
- StyledTextarea2,
2089
- {
2090
- value: editValue,
2091
- onChange: (e) => setEditValue(e.target.value),
2092
- onClick: (e) => e.stopPropagation()
2093
- }
2094
- ),
2095
- /* @__PURE__ */ jsxs16(FormActions2, { children: [
2096
- /* @__PURE__ */ jsx29(Button, { type: "button", variant: "secondary", onClick: handleCancel, children: "Cancel" }),
2097
- /* @__PURE__ */ jsx29(Button, { type: "submit", variant: "primary", children: "Save" })
2098
- ] })
2099
- ] }),
2100
- /* @__PURE__ */ jsx29(RawDataCard, { data })
2101
- ] });
2102
- }
2103
- return /* @__PURE__ */ jsxs16(Fragment7, { children: [
2104
- /* @__PURE__ */ jsx29("p", { children: currentText }),
2105
- /* @__PURE__ */ jsx29("div", { children: canEdit2 && /* @__PURE__ */ jsx29(Button, { variant: "secondary", onClick: handleEditClick, title: "Edit", children: /* @__PURE__ */ jsx29(Icon, { name: "edit" }) }) }),
2106
- /* @__PURE__ */ jsx29(RawDataCard, { data })
2107
- ] });
2108
- }
2109
- var EditForm2 = styled18("form")`
2110
- display: flex;
2111
- flex-direction: column;
2112
- gap: 0.75rem;
2113
- margin-bottom: 1rem;
2114
- `;
2115
- var StyledTextarea2 = styled18("textarea")`
2116
- width: 100%;
2117
- min-height: 120px;
2118
- border-radius: var(--j-radius-md);
2119
- border: 1px solid var(--j-border-color);
2120
- padding: 0.5rem 0.875rem;
2121
- box-shadow: var(--j-shadow-sm);
2122
- font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
2123
- font-size: 0.875rem;
2124
- background-color: white;
2125
- color: var(--j-text-color-strong);
2126
- resize: vertical;
2127
-
2128
- @media (prefers-color-scheme: dark) {
2129
- background-color: var(--j-foreground);
2130
- }
2131
- `;
2132
- var FormActions2 = styled18("div")`
2133
- display: flex;
2134
- gap: 0.5rem;
2135
- justify-content: flex-end;
2136
- `;
2137
-
2138
- // src/inspector/viewer/group-view.tsx
2139
- import { useState as useState11 } from "react";
2140
- import { Fragment as Fragment8, jsx as jsx30, jsxs as jsxs17 } from "react/jsx-runtime";
2141
- function partitionMembers(data) {
2142
- const everyone = Object.entries(data).filter(([key]) => key === "everyone").map(([key, value]) => ({
2143
- id: key,
2144
- role: value
2145
- }));
2146
- const members = Object.entries(data).filter(([key]) => isCoId(key)).map(([key, value]) => ({
2147
- id: key,
2148
- role: value
2149
- }));
2150
- const parentGroups = Object.entries(data).filter(([key]) => key.startsWith("parent_co_")).map(([key, value]) => ({
2151
- id: key.slice(7),
2152
- role: value
2153
- }));
2154
- const childGroups = Object.entries(data).filter(
2155
- ([key, value]) => key.startsWith("child_co_") && value !== "revoked"
2156
- ).map(([key, value]) => ({
2157
- id: key.slice(6),
2158
- role: value
2159
- }));
2160
- return { everyone, members, parentGroups, childGroups };
2161
- }
2162
- function GroupView({
2163
- coValue,
2164
- data,
2165
- onNavigate,
2166
- node
2167
- }) {
2168
- const [addMemberType, setAddMemberType] = useState11(null);
2169
- const { everyone, members, parentGroups, childGroups } = partitionMembers(
2170
- data
2171
- );
2172
- const onRemoveMember = async (id) => {
2173
- if (confirm("Are you sure you want to remove this member?") === false) {
2174
- return;
2175
- }
2176
- try {
2177
- const group = await node.load(coValue.id);
2178
- if (group === "unavailable") {
2179
- throw new Error("Group not found");
2180
- }
2181
- const rawGroup = group;
2182
- rawGroup.removeMember(id);
2183
- } catch (error) {
2184
- console.error(error);
2185
- throw error;
2186
- }
2187
- };
2188
- const onRemoveGroup = async (id) => {
2189
- if (confirm("Are you sure you want to remove this group?") === false) {
2190
- return;
2191
- }
2192
- try {
2193
- const group = await node.load(coValue.id);
2194
- if (group === "unavailable") {
2195
- throw new Error("Group not found");
2196
- }
2197
- const rawGroup = group;
2198
- const targetGroup = await node.load(id);
2199
- if (targetGroup === "unavailable") {
2200
- throw new Error("Group not found");
2201
- }
2202
- const rawTargetGroup = targetGroup;
2203
- rawGroup.revokeExtend(rawTargetGroup);
2204
- } catch (error) {
2205
- console.error(error);
2206
- throw error;
2207
- }
2208
- };
2209
- const handleAddMemberSubmit = async (event) => {
2210
- event.preventDefault();
2211
- const form = event.currentTarget;
2212
- const memberId = form.elements.namedItem("memberId")?.value;
2213
- const role = form.elements.namedItem("role")?.value;
2214
- try {
2215
- const group = await node.load(coValue.id);
2216
- if (group === "unavailable") {
2217
- throw new Error("Group not found");
2218
- }
2219
- const rawGroup = group;
2220
- if (addMemberType === "account") {
2221
- let rawAccount = "everyone";
2222
- if (memberId !== "everyone") {
2223
- const account = await node.load(memberId);
2224
- if (account === "unavailable") {
2225
- throw new Error("Account not found");
2226
- }
2227
- rawAccount = account;
2228
- }
2229
- rawGroup.addMember(rawAccount, role);
2230
- } else if (addMemberType === "group") {
2231
- const targetGroup = await node.load(memberId);
2232
- if (targetGroup === "unavailable") {
2233
- throw new Error("Group not found");
2234
- }
2235
- const rawTargetGroup = targetGroup;
2236
- rawGroup.extend(
2237
- rawTargetGroup,
2238
- role
2239
- );
2240
- }
2241
- setAddMemberType(null);
2242
- } catch (error) {
2243
- console.error(error);
2244
- alert(`Failed to add ${addMemberType}: ${error.message}`);
2245
- }
2246
- };
2247
- return /* @__PURE__ */ jsxs17(Fragment8, { children: [
2248
- /* @__PURE__ */ jsxs17(Table, { children: [
2249
- /* @__PURE__ */ jsx30(TableHead, { children: /* @__PURE__ */ jsxs17(TableRow, { children: [
2250
- /* @__PURE__ */ jsx30(TableHeader, { children: "Member" }),
2251
- /* @__PURE__ */ jsx30(TableHeader, { children: "Permission" }),
2252
- /* @__PURE__ */ jsx30(TableHeader, {})
2253
- ] }) }),
2254
- /* @__PURE__ */ jsxs17(TableBody, { children: [
2255
- everyone.map((member) => /* @__PURE__ */ jsxs17(TableRow, { children: [
2256
- /* @__PURE__ */ jsx30(TableCell, { children: member.id }),
2257
- /* @__PURE__ */ jsx30(TableCell, { children: member.role }),
2258
- /* @__PURE__ */ jsx30(TableCell, { children: member.role !== "revoked" && /* @__PURE__ */ jsx30(
2259
- Button,
2260
- {
2261
- variant: "secondary",
2262
- onClick: () => onRemoveMember(member.id),
2263
- children: /* @__PURE__ */ jsx30(Icon, { name: "delete" })
2264
- }
2265
- ) })
2266
- ] }, member.id)),
2267
- members.map((member) => /* @__PURE__ */ jsxs17(TableRow, { children: [
2268
- /* @__PURE__ */ jsx30(TableCell, { children: /* @__PURE__ */ jsx30(
2269
- AccountOrGroupText,
2270
- {
2271
- coId: member.id,
2272
- node,
2273
- showId: true,
2274
- onClick: () => {
2275
- onNavigate([{ coId: member.id, name: member.id }]);
2276
- }
2277
- }
2278
- ) }),
2279
- /* @__PURE__ */ jsx30(TableCell, { children: member.role }),
2280
- /* @__PURE__ */ jsx30(TableCell, { children: member.role !== "revoked" && /* @__PURE__ */ jsx30(
2281
- Button,
2282
- {
2283
- variant: "secondary",
2284
- onClick: () => onRemoveMember(member.id),
2285
- children: /* @__PURE__ */ jsx30(Icon, { name: "delete" })
2286
- }
2287
- ) })
2288
- ] }, member.id)),
2289
- parentGroups.map((group) => /* @__PURE__ */ jsxs17(TableRow, { children: [
2290
- /* @__PURE__ */ jsx30(TableCell, { children: /* @__PURE__ */ jsx30(
2291
- AccountOrGroupText,
2292
- {
2293
- coId: group.id,
2294
- node,
2295
- showId: true,
2296
- onClick: () => {
2297
- onNavigate([{ coId: group.id, name: group.id }]);
2298
- }
2299
- }
2300
- ) }),
2301
- /* @__PURE__ */ jsx30(TableCell, { children: group.role }),
2302
- /* @__PURE__ */ jsx30(TableCell, { children: group.role !== "revoked" && /* @__PURE__ */ jsx30(
2303
- Button,
2304
- {
2305
- variant: "secondary",
2306
- onClick: () => onRemoveGroup(group.id),
2307
- children: /* @__PURE__ */ jsx30(Icon, { name: "delete" })
2308
- }
2309
- ) })
2310
- ] }, group.id))
2311
- ] })
2312
- ] }),
2313
- /* @__PURE__ */ jsxs17(
2314
- "div",
2315
- {
2316
- style: {
2317
- display: "flex",
2318
- justifyContent: "flex-end",
2319
- gap: "0.75rem",
2320
- marginTop: "1rem"
2321
- },
2322
- children: [
2323
- /* @__PURE__ */ jsx30(Button, { variant: "primary", onClick: () => setAddMemberType("account"), children: "Add Account" }),
2324
- /* @__PURE__ */ jsx30(Button, { variant: "primary", onClick: () => setAddMemberType("group"), children: "Add Group" })
2325
- ]
2326
- }
2327
- ),
2328
- childGroups.length > 0 && /* @__PURE__ */ jsxs17(Table, { children: [
2329
- /* @__PURE__ */ jsx30(TableHead, { children: /* @__PURE__ */ jsx30(TableRow, { children: /* @__PURE__ */ jsx30(TableHeader, { children: "Member of" }) }) }),
2330
- /* @__PURE__ */ jsx30(TableBody, { children: childGroups.map((group) => /* @__PURE__ */ jsx30(TableRow, { children: /* @__PURE__ */ jsx30(TableCell, { children: /* @__PURE__ */ jsx30(
2331
- AccountOrGroupText,
2332
- {
2333
- coId: group.id,
2334
- node,
2335
- showId: true,
2336
- onClick: () => {
2337
- onNavigate([{ coId: group.id, name: group.id }]);
2338
- }
2339
- }
2340
- ) }) }, group.id)) })
2341
- ] }),
2342
- /* @__PURE__ */ jsx30(RawDataCard, { data }),
2343
- /* @__PURE__ */ jsx30(
2344
- Modal,
2345
- {
2346
- isOpen: addMemberType !== null,
2347
- onClose: () => setAddMemberType(null),
2348
- heading: addMemberType === "account" ? "Add Account" : "Add Group",
2349
- showButtons: false,
2350
- children: /* @__PURE__ */ jsx30("form", { onSubmit: handleAddMemberSubmit, children: /* @__PURE__ */ jsxs17(
2351
- "div",
2352
- {
2353
- style: { display: "flex", flexDirection: "column", gap: "1rem" },
2354
- children: [
2355
- /* @__PURE__ */ jsx30(
2356
- Input,
2357
- {
2358
- name: "memberId",
2359
- label: addMemberType === "account" ? "Account ID" : "Group ID",
2360
- placeholder: addMemberType === "account" ? "Enter account ID" : "Enter group ID",
2361
- required: true
2362
- }
2363
- ),
2364
- /* @__PURE__ */ jsxs17(Select, { name: "role", label: "Role", children: [
2365
- /* @__PURE__ */ jsx30("option", { value: "reader", children: "Reader" }),
2366
- /* @__PURE__ */ jsx30("option", { value: "writer", children: "Writer" }),
2367
- /* @__PURE__ */ jsx30("option", { value: "admin", children: "Admin" }),
2368
- addMemberType === "account" ? /* @__PURE__ */ jsx30(Fragment8, { children: /* @__PURE__ */ jsx30("option", { value: "writeOnly", children: "Write Only" }) }) : /* @__PURE__ */ jsx30(Fragment8, { children: /* @__PURE__ */ jsx30("option", { value: "inherit", children: "Inherit" }) })
2369
- ] }),
2370
- /* @__PURE__ */ jsxs17(
2371
- "div",
2372
- {
2373
- style: {
2374
- display: "flex",
2375
- gap: "0.75rem",
2376
- justifyContent: "flex-end",
2377
- marginTop: "0.5rem"
2378
- },
2379
- children: [
2380
- /* @__PURE__ */ jsx30(
2381
- Button,
2382
- {
2383
- type: "button",
2384
- variant: "secondary",
2385
- onClick: () => setAddMemberType(null),
2386
- children: "Cancel"
2387
- }
2388
- ),
2389
- /* @__PURE__ */ jsx30(Button, { type: "submit", variant: "primary", children: "Add" })
2390
- ]
2391
- }
2392
- )
2393
- ]
2394
- }
2395
- ) })
2396
- }
2397
- )
2398
- ] });
2399
- }
2400
-
2401
- // src/inspector/viewer/role-display.tsx
2402
- import { jsxs as jsxs18 } from "react/jsx-runtime";
2403
- function RoleDisplay({
2404
- node,
2405
- value
2406
- }) {
2407
- const { snapshot } = useResolvedCoValue(value.group.id, node);
2408
- if (!snapshot || snapshot === "unavailable") {
2409
- return null;
2410
- }
2411
- let role;
2412
- if (value.group.id == node.getCurrentAgent().id) {
2413
- role = "owner";
2414
- } else if (snapshot[node.getCurrentAgent().id]) {
2415
- role = snapshot[node.getCurrentAgent().id];
2416
- } else if (snapshot.everyone) {
2417
- role = snapshot.everyone;
2418
- } else {
2419
- role = "unauthorized";
2420
- }
2421
- return /* @__PURE__ */ jsxs18(Text, { children: [
2422
- "Role: ",
2423
- role
2424
- ] });
2425
- }
2426
-
2427
- // src/inspector/viewer/table-viewer.tsx
2428
- import { styled as styled19 } from "goober";
2429
- import { useMemo as useMemo2, useState as useState12 } from "react";
2430
- import { Fragment as Fragment9, jsx as jsx31, jsxs as jsxs19 } from "react/jsx-runtime";
2431
- var PaginationContainer = styled19("div")`
2432
- padding: 1rem 0;
2433
- display: flex;
2434
- align-items: center;
2435
- justify-content: space-between;
2436
- gap: 0.5rem;
2437
- `;
2438
- var RedTooltip = styled19("span")`
2439
- position:relative; /* making the .tooltip span a container for the tooltip text */
2440
- border-bottom:1px dashed #000; /* little indicater to indicate it's hoverable */
2441
-
2442
- &:before {
2443
- content: attr(data-text);
2444
- background-color: red;
2445
- position:absolute;
2446
-
2447
- /* vertically center */
2448
- top:50%;
2449
- transform:translateY(-50%);
2450
-
2451
- /* move to right */
2452
- left:100%;
2453
- margin-left:15px; /* and add a small left margin */
2454
-
2455
- /* basic styles */
2456
- width:200px;
2457
- padding:10px;
2458
- border-radius:10px;
2459
- color: #fff;
2460
- text-align:center;
2461
-
2462
- display:none; /* hide by default */
2463
- }
2464
-
2465
- &:hover:before {
2466
- display:block;
2467
- }
2468
- `;
2469
- function CoValuesTableView({
2470
- data,
2471
- node,
2472
- onNavigate,
2473
- onRemove
2474
- }) {
2475
- const [visibleRowsCount, setVisibleRowsCount] = useState12(10);
2476
- const [coIdArray, visibleRows] = useMemo2(() => {
2477
- const coIdArray2 = Array.isArray(data) ? data : Object.values(data).every((k) => typeof k === "string" && isCoId(k)) ? Object.values(data).map((k) => k) : [];
2478
- const visibleRows2 = coIdArray2.slice(0, visibleRowsCount);
2479
- return [coIdArray2, visibleRows2];
2480
- }, [data, visibleRowsCount]);
2481
- const resolvedRows = useResolvedCoValues(visibleRows, node);
2482
- const hasMore = visibleRowsCount < coIdArray.length;
2483
- if (!coIdArray.length) {
2484
- return /* @__PURE__ */ jsx31("div", { children: "No data to display" });
2485
- }
2486
- if (resolvedRows.length === 0) {
2487
- return /* @__PURE__ */ jsx31("div", { children: "Loading..." });
2488
- }
2489
- const keys = Array.from(
2490
- new Set(
2491
- resolvedRows.filter((item) => item.snapshot !== "unavailable").flatMap((item) => Object.keys(item.snapshot || {}))
2492
- )
2493
- );
2494
- const loadMore = () => {
2495
- setVisibleRowsCount((prevVisibleRows) => prevVisibleRows + 10);
2496
- };
2497
- return /* @__PURE__ */ jsxs19(Fragment9, { children: [
2498
- /* @__PURE__ */ jsxs19(Table, { children: [
2499
- /* @__PURE__ */ jsx31(TableHead, { children: /* @__PURE__ */ jsxs19(TableRow, { children: [
2500
- ["ID", ...keys, "Action"].map((key) => /* @__PURE__ */ jsx31(TableHeader, { children: key }, key)),
2501
- onRemove && /* @__PURE__ */ jsx31(TableHeader, {})
2502
- ] }) }),
2503
- /* @__PURE__ */ jsx31(TableBody, { children: resolvedRows.slice(0, visibleRowsCount).map((item, index) => /* @__PURE__ */ jsxs19(TableRow, { children: [
2504
- /* @__PURE__ */ jsx31(TableCell, { children: /* @__PURE__ */ jsx31(Text, { mono: true, children: item.snapshot === "unavailable" ? /* @__PURE__ */ jsxs19(RedTooltip, { "data-text": "Unavailable", children: [
2505
- /* @__PURE__ */ jsx31(
2506
- Icon,
2507
- {
2508
- name: "caution",
2509
- color: "red",
2510
- style: {
2511
- display: "inline-block",
2512
- marginRight: "0.5rem"
2513
- }
2514
- }
2515
- ),
2516
- visibleRows[index]
2517
- ] }) : visibleRows[index] }) }),
2518
- keys.map((key) => /* @__PURE__ */ jsx31(TableCell, { children: item.snapshot !== "unavailable" && /* @__PURE__ */ jsx31(
2519
- ValueRenderer,
2520
- {
2521
- json: item.snapshot[key],
2522
- onCoIDClick: (coId) => {
2523
- async function handleClick() {
2524
- onNavigate([
2525
- {
2526
- coId: item.value.id,
2527
- name: index.toString()
2528
- },
2529
- {
2530
- coId,
2531
- name: key
2532
- }
2533
- ]);
2534
- }
2535
- handleClick();
2536
- }
2537
- }
2538
- ) }, key)),
2539
- /* @__PURE__ */ jsx31(TableCell, { children: /* @__PURE__ */ jsx31(
2540
- Button,
2541
- {
2542
- variant: "secondary",
2543
- onClick: () => onNavigate([
2544
- {
2545
- coId: item.value.id,
2546
- name: index.toString()
2547
- }
2548
- ]),
2549
- children: "View"
2550
- }
2551
- ) }),
2552
- onRemove && /* @__PURE__ */ jsx31(TableCell, { children: /* @__PURE__ */ jsx31(Button, { variant: "secondary", onClick: () => onRemove(index), children: "Remove" }) })
2553
- ] }, index)) })
2554
- ] }),
2555
- /* @__PURE__ */ jsxs19(PaginationContainer, { children: [
2556
- /* @__PURE__ */ jsxs19(Text, { muted: true, small: true, children: [
2557
- "Showing ",
2558
- Math.min(visibleRowsCount, coIdArray.length),
2559
- " of",
2560
- " ",
2561
- coIdArray.length
2562
- ] }),
2563
- hasMore && /* @__PURE__ */ jsx31(Button, { variant: "secondary", onClick: loadMore, children: "Load more" })
2564
- ] })
2565
- ] });
2566
- }
2567
- function TableView({
2568
- data,
2569
- node,
2570
- onNavigate,
2571
- onRemove
2572
- }) {
2573
- const isListOfCoValues = useMemo2(() => {
2574
- return Array.isArray(data) && data.every((k) => isCoId(k));
2575
- }, [data]);
2576
- if (isListOfCoValues) {
2577
- return /* @__PURE__ */ jsx31(
2578
- CoValuesTableView,
2579
- {
2580
- data,
2581
- node,
2582
- onNavigate,
2583
- onRemove
2584
- }
2585
- );
2586
- }
2587
- return /* @__PURE__ */ jsxs19(Table, { children: [
2588
- /* @__PURE__ */ jsx31(TableHead, { children: /* @__PURE__ */ jsxs19(TableRow, { children: [
2589
- /* @__PURE__ */ jsx31(TableHeader, { style: { width: "5rem" }, children: "Index" }),
2590
- /* @__PURE__ */ jsx31(TableHeader, { children: "Value" }),
2591
- onRemove && /* @__PURE__ */ jsx31(TableHeader, { children: "Action" })
2592
- ] }) }),
2593
- /* @__PURE__ */ jsx31(TableBody, { children: Array.isArray(data) && data?.map((value, index) => /* @__PURE__ */ jsxs19(TableRow, { children: [
2594
- /* @__PURE__ */ jsx31(TableCell, { children: /* @__PURE__ */ jsx31(Text, { mono: true, children: index }) }),
2595
- /* @__PURE__ */ jsx31(TableCell, { children: /* @__PURE__ */ jsx31(ValueRenderer, { json: value }) }),
2596
- onRemove && /* @__PURE__ */ jsx31(TableCell, { children: /* @__PURE__ */ jsx31(Button, { variant: "secondary", onClick: () => onRemove(index), children: "Remove" }) })
2597
- ] }, index)) })
2598
- ] });
2599
- }
2600
-
2601
- // src/inspector/viewer/history-view.tsx
2602
- import { useMemo as useMemo3 } from "react";
2603
- import { styled as styled20 } from "goober";
2604
-
2605
- // src/inspector/utils/transactions-changes.ts
2606
- var isGroupExtension = (change) => {
2607
- return change?.op === "set" && change?.value === "extend";
2608
- };
2609
- var isGroupExtendRevocation = (change) => {
2610
- return change?.op === "set" && change?.value === "revoked";
2611
- };
2612
- var isGroupPromotion = (change) => {
2613
- return change?.op === "set" && change?.key.startsWith("parent_co_");
2614
- };
2615
- var isUserPromotion = (change) => {
2616
- return change?.op === "set" && (isCoId(change?.key) || change?.key === "everyone");
2617
- };
2618
- var isKeyRevelation = (change) => {
2619
- return change?.op === "set" && change?.key.includes("_for_");
2620
- };
2621
- var isPropertySet = (change) => {
2622
- return change?.op === "set" && "key" in change && "value" in change;
2623
- };
2624
- var isPropertyDeletion = (change) => {
2625
- return change?.op === "del" && "key" in change;
2626
- };
2627
- var isItemAppend = (change) => {
2628
- return change?.op === "app" && "after" in change && "value" in change;
2629
- };
2630
- var isItemPrepend = (change) => {
2631
- return change?.op === "pre" && "before" in change && "value" in change;
2632
- };
2633
- var isItemDeletion = (change) => {
2634
- return change?.op === "del" && "insertion" in change;
2635
- };
2636
- var isStreamStart = (change) => {
2637
- return change?.type === "start" && "mimeType" in change;
2638
- };
2639
- var isStreamChunk = (change) => {
2640
- return change?.type === "chunk" && "chunk" in change;
2641
- };
2642
- var isStreamEnd = (change) => {
2643
- return change?.type === "end";
2644
- };
2645
-
2646
- // src/inspector/utils/history.ts
2647
- import { stringifyOpID } from "cojson";
2648
- function areSameOpIds(opId1, opId2) {
2649
- if (typeof opId1 === "string" || typeof opId2 === "string") {
2650
- return opId1 === opId2;
2651
- }
2652
- return opId1.sessionID === opId2.sessionID && opId1.txIndex === opId2.txIndex && opId1.changeIdx === opId2.changeIdx;
2653
- }
2654
- function isCoPlainText(coValue) {
2655
- return coValue.type === "coplaintext";
2656
- }
2657
- function getTransactionChanges(tx, coValue) {
2658
- if (tx.isValid === false && tx.tx.privacy === "private") {
2659
- const readKey = coValue.core.getReadKey(tx.tx.keyUsed);
2660
- if (!readKey) {
2661
- return [
2662
- `Unable to decrypt transaction: read key ${tx.tx.keyUsed} not found.`
2663
- ];
2664
- }
2665
- return coValue.core.verified.decryptTransaction(
2666
- tx.txID.sessionID,
2667
- tx.txID.txIndex,
2668
- readKey
2669
- ) ?? [];
2670
- }
2671
- if (isCoPlainText(coValue)) {
2672
- if (tx.changes === void 0 || tx.changes.length === 0) return [];
2673
- const firstChange = tx.changes[0];
2674
- if (isItemAppend(firstChange) && tx.changes.every(
2675
- (c) => isItemAppend(c) && areSameOpIds(c.after, firstChange.after)
2676
- )) {
2677
- const changes = tx.changes;
2678
- if (firstChange.after !== "start") {
2679
- changes.reverse();
2680
- }
2681
- return [
2682
- {
2683
- op: "app",
2684
- value: changes.map((c) => c.value).join(""),
2685
- after: firstChange.after
2686
- }
2687
- ];
2688
- }
2689
- if (isItemPrepend(firstChange) && tx.changes.every(
2690
- (c) => isItemPrepend(c) && areSameOpIds(c.before, firstChange.before)
2691
- )) {
2692
- const changes = tx.changes;
2693
- if (firstChange.before !== "end") {
2694
- changes.reverse();
2695
- }
2696
- return [
2697
- {
2698
- op: "pre",
2699
- value: changes.map((c) => c.value).join(""),
2700
- before: firstChange.before
2701
- }
2702
- ];
2703
- }
2704
- if (isItemDeletion(firstChange) && tx.changes.every((c) => isItemDeletion(c))) {
2705
- let changesAreConsecutive2 = function(changes) {
2706
- if (changes.length < 2) return false;
2707
- const mapping = coValueBeforeDeletions.mapping.idxAfterOpID;
2708
- for (let i = 1; i < changes.length; ++i) {
2709
- const prevIdx = mapping[stringifyOpID(changes[i - 1].insertion)];
2710
- const currIdx = mapping[stringifyOpID(changes[i].insertion)];
2711
- if (currIdx !== prevIdx && currIdx !== (prevIdx ?? -2) + 1) {
2712
- return false;
2713
- }
2714
- }
2715
- return true;
2716
- };
2717
- var changesAreConsecutive = changesAreConsecutive2;
2718
- const coValueBeforeDeletions = coValue.atTime(tx.madeAt - 1);
2719
- if (changesAreConsecutive2(tx.changes)) {
2720
- const groupedBySession = /* @__PURE__ */ new Map();
2721
- for (const change of tx.changes) {
2722
- const group = `${change.insertion.sessionID}-${change.insertion.txIndex}`;
2723
- if (!groupedBySession.has(group)) groupedBySession.set(group, []);
2724
- groupedBySession.get(group).push(change);
2725
- }
2726
- return Array.from(groupedBySession.values()).map((changes) => {
2727
- const stringDeleted = changes.toSorted((a, b) => {
2728
- if (a.insertion.txIndex === b.insertion.txIndex) {
2729
- return a.insertion.changeIdx - b.insertion.changeIdx;
2730
- }
2731
- return a.insertion.txIndex - b.insertion.txIndex;
2732
- }).map(
2733
- (c) => coValueBeforeDeletions.get(
2734
- coValueBeforeDeletions.mapping.idxAfterOpID[stringifyOpID(c.insertion)]
2735
- )
2736
- ).join("");
2737
- return {
2738
- op: "custom",
2739
- action: `"${stringDeleted}" has been deleted`
2740
- };
2741
- });
2742
- }
2743
- }
2744
- }
2745
- return tx.changes ?? tx.tx.changes ?? [];
2746
- }
2747
- function restoreCoMapToTimestamp(coValue, timestamp, removeUnknownProperties) {
2748
- const myRole = coValue.group.myRole();
2749
- if (myRole === void 0 || !["admin", "manager", "writer", "writerOnly"].includes(myRole)) {
2750
- return;
2751
- }
2752
- const newCoValue = coValue.atTime(timestamp).toJSON();
2753
- const oldCoValue = coValue.toJSON();
2754
- if (newCoValue === null) return;
2755
- let changes = [];
2756
- if (removeUnknownProperties) {
2757
- for (const key in oldCoValue) {
2758
- if (!(key in newCoValue)) {
2759
- changes.push({
2760
- op: "del",
2761
- key
2762
- });
2763
- }
2764
- }
2765
- }
2766
- for (const key in newCoValue) {
2767
- if (newCoValue[key] !== oldCoValue[key]) {
2768
- changes.push({
2769
- op: "set",
2770
- key,
2771
- value: newCoValue[key]
2772
- });
2773
- }
2774
- }
2775
- if (changes.length > 0) {
2776
- coValue.core.makeTransaction(changes, "private");
2777
- }
2778
- }
2779
-
2780
- // src/inspector/viewer/history-view.tsx
2781
- import { Fragment as Fragment10, jsx as jsx32, jsxs as jsxs20 } from "react/jsx-runtime";
2782
- function HistoryView({
2783
- coValue,
2784
- node
2785
- }) {
2786
- const transactions = useMemo3(
2787
- () => getHistory(coValue),
2788
- [coValue.core.verifiedTransactions.length]
2789
- );
2790
- const columns = [
2791
- {
2792
- id: "author",
2793
- header: "Author",
2794
- accessor: (row) => /* @__PURE__ */ jsxs20(Fragment10, { children: [
2795
- row.isValid || /* @__PURE__ */ jsx32(RedTooltip2, { "data-text": "This transaction is invalid and is not used", children: /* @__PURE__ */ jsx32(
2796
- Icon,
2797
- {
2798
- name: "caution",
2799
- size: "xs",
2800
- color: "red",
2801
- style: {
2802
- display: "inline-block",
2803
- verticalAlign: "middle",
2804
- marginRight: "0.25rem"
2805
- }
2806
- }
2807
- ) }),
2808
- row.author.startsWith("co_") ? /* @__PURE__ */ jsx32(
2809
- AccountOrGroupText,
2810
- {
2811
- coId: row.author,
2812
- node,
2813
- showId: true
2814
- }
2815
- ) : row.author
2816
- ] }),
2817
- sortable: false,
2818
- filterable: true,
2819
- sortFn: (a, b) => a.author.localeCompare(b.author),
2820
- filterFn: (row, filterValue) => row.author.toLowerCase().includes(filterValue.toLowerCase())
2821
- },
2822
- {
2823
- id: "action",
2824
- header: "Action",
2825
- accessor: (row) => {
2826
- if (row.isValid) return row.action;
2827
- return /* @__PURE__ */ jsxs20(Fragment10, { children: [
2828
- row.action,
2829
- /* @__PURE__ */ jsxs20("span", { style: { color: "red", display: "block" }, children: [
2830
- "Invalid transaction: ",
2831
- row.validationErrorMessage
2832
- ] })
2833
- ] });
2834
- },
2835
- sortable: false,
2836
- filterable: true,
2837
- sortFn: (a, b) => a.action.localeCompare(b.action)
2838
- },
2839
- {
2840
- id: "timestamp",
2841
- header: "Timestamp",
2842
- accessor: (row) => row.timestamp.toISOString(),
2843
- sortable: true,
2844
- filterable: true,
2845
- sortFn: (a, b) => a.timestamp.getTime() - b.timestamp.getTime()
2846
- }
2847
- ];
2848
- return /* @__PURE__ */ jsx32(Accordion, { title: "CoValue history", storageKey: "jazz-inspector-show-history", children: /* @__PURE__ */ jsx32(
2849
- DataTable,
2850
- {
2851
- columns,
2852
- data: transactions,
2853
- pageSize: 10,
2854
- initialSort: { columnId: "timestamp", direction: "desc" },
2855
- getRowKey: (row) => row.id,
2856
- emptyMessage: "No history available"
2857
- }
2858
- ) });
2859
- }
2860
- function getHistory(coValue) {
2861
- return coValue.core.verifiedTransactions.flatMap((tx, index) => {
2862
- const changes = getTransactionChanges(tx, coValue);
2863
- return changes.map((change, changeIndex) => ({
2864
- id: `${tx.txID.sessionID.toString()}-${tx.txID.txIndex}-${index}-${changeIndex}`,
2865
- author: tx.author,
2866
- action: mapTransactionToAction(change, coValue),
2867
- timestamp: new Date(tx.currentMadeAt),
2868
- isValid: tx.isValid,
2869
- validationErrorMessage: tx.validationErrorMessage
2870
- }));
2871
- });
2872
- }
2873
- function mapTransactionToAction(change, coValue) {
2874
- if (isUserPromotion(change)) {
2875
- if (change.value === "revoked") {
2876
- return `${change.key} has been revoked`;
2877
- }
2878
- return `${change.key} has been promoted to ${change.value}`;
2879
- }
2880
- if (isGroupExtension(change)) {
2881
- const child = change.key.slice(6);
2882
- return `Group became a member of ${child}`;
2883
- }
2884
- if (isGroupExtendRevocation(change)) {
2885
- const child = change.key.slice(6);
2886
- return `Group's membership of ${child} has been revoked.`;
2887
- }
2888
- if (isGroupPromotion(change)) {
2889
- const parent = change.key.slice(7);
2890
- return `Group ${parent} has been promoted to ${change.value}`;
2891
- }
2892
- if (isKeyRevelation(change)) {
2893
- const [key, target] = change.key.split("_for_");
2894
- return `Key "${key}" has been revealed to "${target}"`;
2895
- }
2896
- if (isItemAppend(change)) {
2897
- if (change.after === "start") {
2898
- return `"${change.value}" has been appended`;
2899
- }
2900
- const after = findListChange(change.after, coValue);
2901
- if (after === void 0) {
2902
- return `"${change.value}" has been inserted after undefined item`;
2903
- }
2904
- return `"${change.value}" has been inserted after "${after.value}"`;
2905
- }
2906
- if (isItemPrepend(change)) {
2907
- if (change.before === "end") {
2908
- return `"${change.value}" has been prepended`;
2909
- }
2910
- const before = findListChange(change.before, coValue);
2911
- if (before === void 0) {
2912
- return `"${change.value}" has been inserted before undefined item`;
2913
- }
2914
- return `"${change.value}" has been inserted before "${before.value}"`;
2915
- }
2916
- if (isItemDeletion(change)) {
2917
- const insertion = findListChange(change.insertion, coValue);
2918
- if (insertion === void 0) {
2919
- return `An undefined item has been deleted`;
2920
- }
2921
- return `"${insertion.value}" has been deleted`;
2922
- }
2923
- if (isStreamStart(change)) {
2924
- return `Stream started with mime type "${change.mimeType}" and file name "${change.fileName}"`;
2925
- }
2926
- if (isStreamChunk(change)) {
2927
- return `Stream chunk added`;
2928
- }
2929
- if (isStreamEnd(change)) {
2930
- return `Stream ended`;
2931
- }
2932
- if (isPropertySet(change)) {
2933
- return `Property "${change.key}" has been set to ${JSON.stringify(change.value)}`;
2934
- }
2935
- if (isPropertyDeletion(change)) {
2936
- return `Property "${change.key}" has been deleted`;
2937
- }
2938
- if (change.op === "custom") {
2939
- return change.action;
2940
- }
2941
- return "Unknown action: " + JSON.stringify(change);
2942
- }
2943
- var findListChange = (opId, coValue) => {
2944
- return coValue.core.verifiedTransactions.find(
2945
- (tx) => tx.txID.sessionID === opId.sessionID && tx.txID.txIndex === opId.txIndex
2946
- )?.changes?.[opId.changeIdx];
2947
- };
2948
- var RedTooltip2 = styled20("span")`
2949
- position:relative; /* making the .tooltip span a container for the tooltip text */
2950
- border-bottom:1px dashed #000; /* little indicater to indicate it's hoverable */
2951
-
2952
- &:before {
2953
- content: attr(data-text);
2954
- background-color: red;
2955
- position:absolute;
2956
-
2957
- /* vertically center */
2958
- top:50%;
2959
- transform:translateY(-50%);
2960
-
2961
- /* move to right */
2962
- left:100%;
2963
- margin-left:15px; /* and add a small left margin */
2964
-
2965
- /* basic styles */
2966
- width:200px;
2967
- padding:10px;
2968
- border-radius:10px;
2969
- color: #fff;
2970
- text-align:center;
2971
-
2972
- display:none; /* hide by default */
2973
- }
2974
-
2975
- &:hover:before {
2976
- display:block;
2977
- }
2978
- `;
2979
-
2980
- // src/inspector/viewer/co-map-view.tsx
2981
- import { useState as useState13, useMemo as useMemo4 } from "react";
2982
- import { styled as styled21 } from "goober";
2983
- import { Fragment as Fragment11, jsx as jsx33, jsxs as jsxs21 } from "react/jsx-runtime";
2984
- function CoMapView({
2985
- coValue,
2986
- data,
2987
- node,
2988
- onNavigate
2989
- }) {
2990
- return /* @__PURE__ */ jsxs21(Fragment11, { children: [
2991
- /* @__PURE__ */ jsx33(
2992
- GridView,
2993
- {
2994
- data,
2995
- onNavigate,
2996
- node,
2997
- coValue
2998
- }
2999
- ),
3000
- /* @__PURE__ */ jsxs21("div", { children: [
3001
- /* @__PURE__ */ jsx33(
3002
- AddPropertyModal,
3003
- {
3004
- disabled: !isWriter(coValue.group.myRole()),
3005
- coValue,
3006
- node
3007
- }
3008
- ),
3009
- " ",
3010
- /* @__PURE__ */ jsx33(RestoreSnapshotModal, { coValue })
3011
- ] })
3012
- ] });
3013
- }
3014
- function AddPropertyModal({
3015
- coValue,
3016
- node,
3017
- disabled
3018
- }) {
3019
- const [isAddPropertyModalOpen, setIsAddPropertyModalOpen] = useState13(false);
3020
- const [propertyName, setPropertyName] = useState13("");
3021
- const openAddPropertyModal = () => {
3022
- setIsAddPropertyModalOpen(true);
3023
- setPropertyName("");
3024
- };
3025
- const handleCancel = () => {
3026
- setIsAddPropertyModalOpen(false);
3027
- setPropertyName("");
3028
- };
3029
- return /* @__PURE__ */ jsxs21(Fragment11, { children: [
3030
- /* @__PURE__ */ jsx33(
3031
- Button,
3032
- {
3033
- title: "Add Property",
3034
- variant: "secondary",
3035
- disabled,
3036
- onClick: openAddPropertyModal,
3037
- children: /* @__PURE__ */ jsx33(Icon, { name: "add" })
3038
- }
3039
- ),
3040
- /* @__PURE__ */ jsxs21(
3041
- Modal,
3042
- {
3043
- isOpen: isAddPropertyModalOpen,
3044
- onClose: handleCancel,
3045
- heading: "Add Property",
3046
- showButtons: false,
3047
- children: [
3048
- /* @__PURE__ */ jsx33(
3049
- Input,
3050
- {
3051
- label: "Property Name",
3052
- value: propertyName,
3053
- onChange: (e) => setPropertyName(e.target.value),
3054
- placeholder: "Enter property name"
3055
- }
3056
- ),
3057
- propertyName && /* @__PURE__ */ jsx33(EditorContainer, { children: /* @__PURE__ */ jsx33(
3058
- CoValueEditor,
3059
- {
3060
- node,
3061
- property: propertyName,
3062
- value: void 0,
3063
- coValue,
3064
- onCancel: handleCancel
3065
- }
3066
- ) })
3067
- ]
3068
- }
3069
- )
3070
- ] });
3071
- }
3072
- function RestoreSnapshotModal({ coValue }) {
3073
- const [isRestoreModalOpen, setIsRestoreModalOpen] = useState13(false);
3074
- const [selectedIndex, setSelectedIndex] = useState13(-1);
3075
- const [removeUnknownProperties, setRemoveUnknownProperties] = useState13(false);
3076
- const timestamps = useMemo4(
3077
- () => coValue.core.verifiedTransactions.map((tx) => tx.madeAt),
3078
- [coValue.core.verifiedTransactions.length]
3079
- );
3080
- const coMapAtSelectedIndex = useMemo4(() => {
3081
- if (selectedIndex === -1) return null;
3082
- return coValue.atTime(timestamps[selectedIndex]).toJSON();
3083
- }, [coValue, timestamps, selectedIndex]);
3084
- const openRestoreModal = () => {
3085
- setIsRestoreModalOpen(true);
3086
- setSelectedIndex(timestamps.length - 1);
3087
- };
3088
- const handleRestore = () => {
3089
- if (timestamps.length < 2) return;
3090
- if (timestamps.length === 0) return;
3091
- const selectedTimestamp = timestamps[selectedIndex];
3092
- if (selectedTimestamp === void 0) return;
3093
- restoreCoMapToTimestamp(
3094
- coValue,
3095
- selectedTimestamp,
3096
- removeUnknownProperties
3097
- );
3098
- setIsRestoreModalOpen(false);
3099
- };
3100
- const handleClose = () => {
3101
- setIsRestoreModalOpen(false);
3102
- };
3103
- const canRestore = isWriter(coValue.group.myRole());
3104
- return /* @__PURE__ */ jsxs21(Fragment11, { children: [
3105
- /* @__PURE__ */ jsx33(Button, { title: "Timeline", variant: "secondary", onClick: openRestoreModal, children: /* @__PURE__ */ jsx33(Icon, { name: "history" }) }),
3106
- /* @__PURE__ */ jsxs21(
3107
- Modal,
3108
- {
3109
- isOpen: isRestoreModalOpen,
3110
- onClose: handleClose,
3111
- heading: "Timeline",
3112
- confirmText: "Restore",
3113
- cancelText: "Cancel",
3114
- onConfirm: handleRestore,
3115
- onCancel: handleClose,
3116
- showButtons: timestamps.length > 1 && canRestore,
3117
- children: [
3118
- timestamps.length > 1 && /* @__PURE__ */ jsxs21(Fragment11, { children: [
3119
- /* @__PURE__ */ jsxs21(RangeContainer, { children: [
3120
- /* @__PURE__ */ jsx33(RangeLabel, { children: "Select Timestamp" }),
3121
- /* @__PURE__ */ jsx33(
3122
- RangeInput,
3123
- {
3124
- type: "range",
3125
- min: 0,
3126
- max: Math.max(0, timestamps.length - 1),
3127
- value: selectedIndex,
3128
- onChange: (e) => setSelectedIndex(Number(e.target.value)),
3129
- disabled: timestamps.length === 0
3130
- }
3131
- ),
3132
- /* @__PURE__ */ jsx33(TimestampDisplay, { children: timestamps[selectedIndex] !== void 0 ? new Date(timestamps[selectedIndex]).toISOString() : "No timestamps available" })
3133
- ] }),
3134
- canRestore && /* @__PURE__ */ jsxs21(CheckboxContainer, { children: [
3135
- /* @__PURE__ */ jsx33(
3136
- CheckboxInput,
3137
- {
3138
- type: "checkbox",
3139
- id: "remove-unknown-properties",
3140
- checked: removeUnknownProperties,
3141
- onChange: (e) => setRemoveUnknownProperties(e.target.checked)
3142
- }
3143
- ),
3144
- /* @__PURE__ */ jsx33(CheckboxLabel, { htmlFor: "remove-unknown-properties", children: "Remove unknown properties (properties that don't exist in the selected snapshot)" })
3145
- ] })
3146
- ] }),
3147
- timestamps.length > 0 && timestamps[selectedIndex] !== void 0 && /* @__PURE__ */ jsxs21(PreviewSection, { children: [
3148
- /* @__PURE__ */ jsx33(PreviewLabel, { children: "State at that time:" }),
3149
- /* @__PURE__ */ jsx33(PreviewPre, { children: JSON.stringify(coMapAtSelectedIndex, null, 2) })
3150
- ] }),
3151
- timestamps.length < 2 && /* @__PURE__ */ jsx33("div", { style: { color: "var(--j-text-color)" }, children: "At least 2 timestamps are required to restore a snapshot." })
3152
- ]
3153
- }
3154
- )
3155
- ] });
3156
- }
3157
- var PreviewSection = styled21("div")`
3158
- margin-top: 1.5rem;
3159
- `;
3160
- var PreviewLabel = styled21("div")`
3161
- font-weight: 500;
3162
- margin-bottom: 0.5rem;
3163
- color: var(--j-text-color-strong);
3164
- `;
3165
- var PreviewPre = styled21("pre")`
3166
- background-color: var(--j-foreground);
3167
- border: 1px solid var(--j-border-color);
3168
- border-radius: var(--j-radius-md);
3169
- padding: 1rem;
3170
- overflow-x: auto;
3171
- font-size: 0.875rem;
3172
- max-height: 400px;
3173
- overflow-y: auto;
3174
- color: var(--j-text-color);
3175
- font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
3176
- `;
3177
- var RangeContainer = styled21("div")`
3178
- display: flex;
3179
- flex-direction: column;
3180
- gap: 0.75rem;
3181
- `;
3182
- var RangeLabel = styled21("label")`
3183
- font-weight: 500;
3184
- color: var(--j-text-color-strong);
3185
- font-size: 0.875rem;
3186
- `;
3187
- var RangeInput = styled21("input")`
3188
- width: 100%;
3189
- height: 0.5rem;
3190
- border-radius: var(--j-radius-sm);
3191
- outline: none;
3192
- -webkit-appearance: none;
3193
- appearance: none;
3194
- background: var(--j-foreground);
3195
- cursor: pointer;
3196
-
3197
- &::-webkit-slider-thumb {
3198
- -webkit-appearance: none;
3199
- appearance: none;
3200
- width: 1.25rem;
3201
- height: 1.25rem;
3202
- border-radius: 50%;
3203
- background: var(--j-primary-color);
3204
- cursor: pointer;
3205
- border: 2px solid var(--j-background);
3206
- box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
3207
- }
3208
-
3209
- &::-moz-range-thumb {
3210
- width: 1.25rem;
3211
- height: 1.25rem;
3212
- border-radius: 50%;
3213
- background: var(--j-primary-color);
3214
- cursor: pointer;
3215
- border: 2px solid var(--j-background);
3216
- box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
3217
- }
3218
-
3219
- &:disabled {
3220
- opacity: 0.5;
3221
- cursor: not-allowed;
3222
- }
3223
- `;
3224
- var TimestampDisplay = styled21("div")`
3225
- font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
3226
- font-size: 0.875rem;
3227
- color: var(--j-text-color);
3228
- padding: 0.5rem;
3229
- background-color: var(--j-foreground);
3230
- border: 1px solid var(--j-border-color);
3231
- border-radius: var(--j-radius-md);
3232
- text-align: center;
3233
- `;
3234
- var CheckboxContainer = styled21("div")`
3235
- display: flex;
3236
- align-items: flex-start;
3237
- gap: 0.5rem;
3238
- margin-top: 1rem;
3239
- `;
3240
- var CheckboxInput = styled21("input")`
3241
- width: 1rem;
3242
- height: 1rem;
3243
- margin-top: 0.125rem;
3244
- cursor: pointer;
3245
- accent-color: var(--j-primary-color);
3246
- `;
3247
- var CheckboxLabel = styled21("label")`
3248
- font-size: 0.875rem;
3249
- color: var(--j-text-color);
3250
- cursor: pointer;
3251
- line-height: 1.25rem;
3252
- `;
3253
- var EditorContainer = styled21("div")`
3254
- margin-top: 1rem;
3255
- `;
3256
-
3257
- // src/inspector/viewer/page.tsx
3258
- import { Fragment as Fragment12, jsx as jsx34, jsxs as jsxs22 } from "react/jsx-runtime";
3259
- var BasePageContainer = React5.forwardRef(
3260
- ({ isTopLevel, ...rest }, ref) => /* @__PURE__ */ jsx34("div", { ref, ...rest })
3261
- );
3262
- var PageContainer = styled22(BasePageContainer)`
3263
- position: absolute;
3264
- z-index: 10;
3265
- inset: 0;
3266
- width: 100%;
3267
- height: 100%;
3268
- padding: 0 0.75rem;
3269
- `;
3270
- var BackButton = styled22("div")`
3271
- position: absolute;
3272
- left: 0;
3273
- right: 0;
3274
- top: 0;
3275
- height: 2.5rem;
3276
- `;
3277
- var HeaderContainer = styled22("div")`
3278
- display: flex;
3279
- justify-content: space-between;
3280
- align-items: center;
3281
- margin-bottom: 1rem;
3282
- `;
3283
- var TitleContainer = styled22("div")`
3284
- display: flex;
3285
- align-items: center;
3286
- gap: 0.75rem;
3287
- `;
3288
- var Title = styled22(Heading)`
3289
- display: flex;
3290
- flex-direction: column;
3291
- align-items: flex-start;
3292
- gap: 0.25rem;
3293
- `;
3294
- var BadgeContainer = styled22("div")`
3295
- display: flex;
3296
- align-items: center;
3297
- gap: 0.75rem;
3298
- `;
3299
- var ContentContainer = styled22("div")`
3300
- overflow: auto;
3301
- display: flex;
3302
- flex-direction: column;
3303
- gap: 1rem;
3304
- padding-bottom: 2rem;
3305
- `;
3306
- function canEdit(value) {
3307
- try {
3308
- const myRole = value.group.myRole();
3309
- return myRole === "writer" || myRole === "admin";
3310
- } catch (e) {
3311
- return false;
3312
- }
3313
- }
3314
- function View(props) {
3315
- const { type, extendedType } = props.coValue;
3316
- const { snapshot, value } = props.coValue;
3317
- const { node, onNavigate } = props;
3318
- if (!snapshot || snapshot === "unavailable") return;
3319
- if (type === "costream") {
3320
- return /* @__PURE__ */ jsx34(
3321
- CoStreamView,
3322
- {
3323
- data: snapshot,
3324
- onNavigate,
3325
- node,
3326
- value
3327
- }
3328
- );
3329
- }
3330
- if (extendedType === "group") {
3331
- return /* @__PURE__ */ jsx34(
3332
- GroupView,
3333
- {
3334
- coValue: value,
3335
- data: snapshot,
3336
- node,
3337
- onNavigate
3338
- }
3339
- );
3340
- }
3341
- if (extendedType === "account") {
3342
- return /* @__PURE__ */ jsx34(AccountView, { data: snapshot, node, onNavigate });
3343
- }
3344
- if (type === "coplaintext") {
3345
- return /* @__PURE__ */ jsx34(
3346
- CoPlainTextView,
3347
- {
3348
- data: snapshot,
3349
- coValue: value,
3350
- node
3351
- }
3352
- );
3353
- }
3354
- if (type === "colist") {
3355
- const handleRemove = (index) => {
3356
- if (confirm("Are you sure you want to remove this item?")) {
3357
- const list = value;
3358
- list.delete(index);
3359
- }
3360
- };
3361
- return /* @__PURE__ */ jsx34(
3362
- TableView,
3363
- {
3364
- data: snapshot,
3365
- node,
3366
- onNavigate,
3367
- onRemove: canEdit(value) ? handleRemove : void 0
3368
- }
3369
- );
3370
- }
3371
- if (extendedType === "record") {
3372
- return /* @__PURE__ */ jsx34(TableView, { data: snapshot, node, onNavigate });
3373
- }
3374
- if (type === "comap") {
3375
- return /* @__PURE__ */ jsx34(
3376
- CoMapView,
3377
- {
3378
- coValue: value,
3379
- data: snapshot,
3380
- node,
3381
- onNavigate
3382
- }
3383
- );
3384
- }
3385
- return /* @__PURE__ */ jsx34(GridView, { data: snapshot, onNavigate, node });
3386
- }
3387
- function Page(props) {
3388
- const {
3389
- coId,
3390
- node,
3391
- name,
3392
- onNavigate,
3393
- onHeaderClick,
3394
- style,
3395
- className = "",
3396
- isTopLevel
3397
- } = props;
3398
- const coValue = useResolvedCoValue(coId, node);
3399
- const { value, snapshot, type, extendedType } = coValue;
3400
- if (snapshot === "unavailable") {
3401
- return /* @__PURE__ */ jsx34("div", { style, children: "Data unavailable" });
3402
- }
3403
- if (!snapshot) {
3404
- return /* @__PURE__ */ jsx34("div", { style });
3405
- }
3406
- return /* @__PURE__ */ jsxs22(PageContainer, { style, className, isTopLevel, children: [
3407
- !isTopLevel && /* @__PURE__ */ jsx34(
3408
- BackButton,
3409
- {
3410
- "aria-label": "Back",
3411
- onClick: () => {
3412
- onHeaderClick?.();
3413
- },
3414
- "aria-hidden": "true"
3415
- }
3416
- ),
3417
- /* @__PURE__ */ jsx34(HeaderContainer, { children: /* @__PURE__ */ jsxs22(TitleContainer, { children: [
3418
- /* @__PURE__ */ jsx34(Title, { children: /* @__PURE__ */ jsxs22("span", { children: [
3419
- name,
3420
- typeof snapshot === "object" && "name" in snapshot ? /* @__PURE__ */ jsxs22("span", { style: { color: "#57534e", fontWeight: 500 }, children: [
3421
- " ",
3422
- snapshot.name
3423
- ] }) : null
3424
- ] }) }),
3425
- /* @__PURE__ */ jsxs22(BadgeContainer, { children: [
3426
- /* @__PURE__ */ jsx34(Badge, { children: type && /* @__PURE__ */ jsx34(TypeIcon, { type, extendedType }) }),
3427
- /* @__PURE__ */ jsx34(Badge, { children: coId })
3428
- ] })
3429
- ] }) }),
3430
- /* @__PURE__ */ jsxs22(ContentContainer, { children: [
3431
- /* @__PURE__ */ jsx34(View, { ...props, coValue }),
3432
- extendedType !== "account" && extendedType !== "group" && /* @__PURE__ */ jsxs22(Fragment12, { children: [
3433
- /* @__PURE__ */ jsx34(RoleDisplay, { node, value }),
3434
- /* @__PURE__ */ jsxs22(Text, { muted: true, children: [
3435
- "Owned by",
3436
- " ",
3437
- /* @__PURE__ */ jsx34(
3438
- AccountOrGroupText,
3439
- {
3440
- coId: value.group.id,
3441
- node,
3442
- showId: true,
3443
- onClick: () => {
3444
- onNavigate([{ coId: value.group.id, name: "owner" }]);
3445
- }
3446
- }
3447
- )
3448
- ] })
3449
- ] }),
3450
- value && /* @__PURE__ */ jsx34(HistoryView, { coValue: value, node })
3451
- ] })
3452
- ] });
3453
- }
3454
-
3455
- // src/inspector/ui/error-boundary.tsx
3456
- import React6 from "react";
3457
- import { styled as styled23 } from "goober";
3458
- import { jsx as jsx35, jsxs as jsxs23 } from "react/jsx-runtime";
3459
- var ErrorBoundary = class extends React6.Component {
3460
- constructor(props) {
3461
- super(props);
3462
- this.state = { hasError: false };
3463
- }
3464
- static getDerivedStateFromError(error) {
3465
- return { hasError: true, error };
3466
- }
3467
- componentDidCatch(error, errorInfo) {
3468
- console.error(error);
3469
- }
3470
- render() {
3471
- if (this.state.hasError) {
3472
- return /* @__PURE__ */ jsxs23("div", { style: { padding: "1rem" }, children: [
3473
- /* @__PURE__ */ jsx35(StyledHeading2, { children: this.props.title }),
3474
- /* @__PURE__ */ jsx35(Text, { mono: true, style: { marginTop: "0.5rem", color: "#ef4444" }, children: this.state.error?.message || "An unexpected error occurred" }),
3475
- /* @__PURE__ */ jsx35("pre", { style: { paddingLeft: "1rem", color: "#ef4444" }, children: this.state.error?.stack })
3476
- ] });
3477
- }
3478
- return this.props.children;
3479
- }
3480
- };
3481
- var StyledHeading2 = styled23("h1")`
3482
- font-size: 1.125rem;
3483
- font-weight: 500;
3484
- color: var(--j-text-color-strong);
3485
- `;
3486
-
3487
- // src/inspector/viewer/page-stack.tsx
3488
- import { Fragment as Fragment13, jsx as jsx36, jsxs as jsxs24 } from "react/jsx-runtime";
3489
- var PageStackContainer = styled24("div")`
3490
- position: relative;
3491
- padding: 0 0.75rem;
3492
- overflow-y: auto;
3493
- flex: 1;
3494
- color: var(--j-text-color);
3495
- font-size: 16px;
3496
- `;
3497
- function PageStack({
3498
- path,
3499
- node,
3500
- goBack,
3501
- addPages,
3502
- children
3503
- }) {
3504
- const page = path[path.length - 1];
3505
- const index = path.length - 1;
3506
- return /* @__PURE__ */ jsx36(Fragment13, { children: /* @__PURE__ */ jsxs24(PageStackContainer, { children: [
3507
- children,
3508
- node && page && /* @__PURE__ */ jsx36(ErrorBoundary, { title: "An error occurred while rendering this CoValue", children: /* @__PURE__ */ jsx36(
3509
- Page,
3510
- {
3511
- coId: page.coId,
3512
- node,
3513
- name: page.name || page.coId,
3514
- onHeaderClick: goBack,
3515
- onNavigate: addPages,
3516
- isTopLevel: index === path.length - 1
3517
- }
3518
- ) })
3519
- ] }) });
3520
- }
3521
-
3522
- // src/inspector/viewer/use-page-path.ts
3523
- import { useCallback, useEffect as useEffect8, useState as useState14 } from "react";
3524
- var STORAGE_KEY = "jazz-inspector-paths";
3525
- function usePagePath(defaultPath) {
3526
- const [path, setPath] = useState14(() => {
3527
- if (typeof window === "undefined") return [];
3528
- const stored = localStorage.getItem(STORAGE_KEY);
3529
- if (stored) {
3530
- try {
3531
- return JSON.parse(stored);
3532
- } catch (e) {
3533
- console.warn("Failed to parse stored path:", e);
3534
- }
3535
- }
3536
- return defaultPath || [];
3537
- });
3538
- const updatePath = useCallback((newPath) => {
3539
- setPath(newPath);
3540
- localStorage.setItem(STORAGE_KEY, JSON.stringify(newPath));
3541
- }, []);
3542
- useEffect8(() => {
3543
- if (defaultPath && JSON.stringify(path) !== JSON.stringify(defaultPath)) {
3544
- updatePath(defaultPath);
3545
- }
3546
- }, [defaultPath, path, updatePath]);
3547
- const addPages = useCallback(
3548
- (newPages) => {
3549
- updatePath([...path, ...newPages]);
3550
- },
3551
- [path, updatePath]
3552
- );
3553
- const goToIndex = useCallback(
3554
- (index) => {
3555
- updatePath(path.slice(0, index + 1));
3556
- },
3557
- [path, updatePath]
3558
- );
3559
- const setPage = useCallback(
3560
- (coId) => {
3561
- updatePath([{ coId, name: "Root" }]);
3562
- },
3563
- [updatePath]
3564
- );
3565
- const goBack = useCallback(() => {
3566
- if (path.length > 1) {
3567
- updatePath(path.slice(0, path.length - 1));
3568
- }
3569
- }, [path, updatePath]);
3570
- return {
3571
- path,
3572
- setPage,
3573
- addPages,
3574
- goToIndex,
3575
- goBack
3576
- };
3577
- }
3578
-
3579
- // src/inspector/ui/global-styles.tsx
3580
- import { styled as styled25 } from "goober";
3581
- var GlobalStyles = styled25("div")`
3582
- /* Colors */
3583
- --j-primary-color: #146AFF;
3584
- --j-link-color: var(--j-primary-color);
3585
- --j-success-color: oklch(52.7% 0.154 150.069);
3586
- --j-destructive-color: oklch(50.5% 0.213 27.518);
3587
-
3588
- /* Neutral Colors */
3589
- --j-neutral-100: #faf8f8;
3590
- --j-neutral-200: #e5e3e4;
3591
- --j-neutral-300: #d0cecf;
3592
- --j-neutral-400: #bbbaba;
3593
- --j-neutral-500: #a8a6a6;
3594
- --j-neutral-600: #858484;
3595
- --j-neutral-700: #6b696a;
3596
- --j-neutral-900: #2f2e2e;
3597
- --j-neutral-925: #1b1a1a;
3598
- --j-neutral-950: #151414;
3599
-
3600
- /* Text Colors */
3601
- --j-text-color: var(--j-neutral-700);
3602
- --j-text-color-strong: var(--j-neutral-900);
3603
-
3604
- /* Border Colors */
3605
- --j-border-color: var(--j-neutral-200);
3606
- --j-border-color-hover: var(--j-neutral-300);
3607
- --j-border-dark: var(--j-neutral-900);
3608
- --j-border-focus: var(--j-primary-color);
3609
-
3610
- /* Background Colors */
3611
- --j-background: #FFFFFF;
3612
- --j-foreground: var(--j-neutral-100);
3613
-
3614
- /* Border Radius */
3615
- --j-radius-sm: 0.25rem;
3616
- --j-radius-md: 0.375rem;
3617
- --j-radius-lg: 0.5rem;
3618
-
3619
- /* Shadows */
3620
- --j-shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
10
+ // src/inspector/index.tsx
11
+ import React, { useEffect as useEffect2, useState as useState2 } from "react";
12
+ import { setup } from "goober";
13
+ import { useJazzContext } from "jazz-tools/react-core";
3621
14
 
3622
- @media (prefers-color-scheme: dark) {
3623
- --j-text-color: var(--j-neutral-400);
3624
- --j-border-color: var(--j-neutral-900);
3625
- --j-background: var(--j-neutral-950);
3626
- --j-foreground: var(--j-neutral-925);
3627
- --j-border-color-hover: var(--j-neutral-700);
3628
- --j-text-color-strong: var(--j-neutral-100);
3629
- --j-success-color: oklch(72.3% 0.219 149.579);
3630
- --j-destructive-color: oklch(63.7% 0.237 25.331);
3631
- }
3632
-
3633
- *:focus {
3634
- outline: none;
3635
- }
3636
-
3637
- *:focus-visible {
3638
- box-shadow: 0 0 0 2px var(--j-link-color);
3639
- }
3640
-
3641
- .j-sr-only {
3642
- position: absolute;
3643
- width: 1px;
3644
- height: 1px;
3645
- padding: 0;
3646
- margin: -1px;
3647
- overflow: hidden;
3648
- clip: rect(0, 0, 0, 0);
3649
- white-space: nowrap;
3650
- border: 0;
3651
- }
3652
- `;
15
+ // src/inspector/in-app.tsx
16
+ import { styled as styled2 } from "goober";
3653
17
 
3654
18
  // src/inspector/viewer/inspector-button.tsx
3655
- import { styled as styled26 } from "goober";
3656
- import { jsx as jsx37, jsxs as jsxs25 } from "react/jsx-runtime";
3657
- var StyledInspectorButton = styled26("button")`
19
+ import { styled } from "goober";
20
+ import { jsx, jsxs } from "react/jsx-runtime";
21
+ var StyledInspectorButton = styled("button")`
3658
22
  position: fixed;
3659
23
  width: 2.5rem;
3660
24
  height: 2.5rem;
@@ -3685,7 +49,7 @@ var StyledInspectorButton = styled26("button")`
3685
49
  }
3686
50
  }}
3687
51
  `;
3688
- var JazzIcon = styled26("svg")`
52
+ var JazzIcon = styled("svg")`
3689
53
  width: 100%;
3690
54
  height: auto;
3691
55
  position: relative;
@@ -3696,8 +60,8 @@ function InspectorButton({
3696
60
  position = "right",
3697
61
  ...buttonProps
3698
62
  }) {
3699
- return /* @__PURE__ */ jsxs25(StyledInspectorButton, { position, ...buttonProps, children: [
3700
- /* @__PURE__ */ jsx37(
63
+ return /* @__PURE__ */ jsxs(StyledInspectorButton, { position, ...buttonProps, children: [
64
+ /* @__PURE__ */ jsx(
3701
65
  JazzIcon,
3702
66
  {
3703
67
  xmlns: "http://www.w3.org/2000/svg",
@@ -3705,7 +69,7 @@ function InspectorButton({
3705
69
  height: "115",
3706
70
  viewBox: "0 0 119 115",
3707
71
  fill: "none",
3708
- children: /* @__PURE__ */ jsx37(
72
+ children: /* @__PURE__ */ jsx(
3709
73
  "path",
3710
74
  {
3711
75
  fillRule: "evenodd",
@@ -3716,7 +80,7 @@ function InspectorButton({
3716
80
  )
3717
81
  }
3718
82
  ),
3719
- /* @__PURE__ */ jsx37(
83
+ /* @__PURE__ */ jsx(
3720
84
  "span",
3721
85
  {
3722
86
  style: {
@@ -3737,142 +101,44 @@ function InspectorButton({
3737
101
  }
3738
102
 
3739
103
  // src/inspector/viewer/use-open-inspector.ts
3740
- import { useEffect as useEffect9, useState as useState15 } from "react";
3741
- var STORAGE_KEY2 = "jazz-inspector-open";
104
+ import { useEffect, useState } from "react";
105
+ var STORAGE_KEY = "jazz-inspector-open";
3742
106
  function useOpenInspector() {
3743
- const [open, setOpen] = useState15(() => {
107
+ const [open, setOpen] = useState(() => {
3744
108
  if (typeof window === "undefined") return false;
3745
- const stored = localStorage.getItem(STORAGE_KEY2);
109
+ const stored = localStorage.getItem(STORAGE_KEY);
3746
110
  return stored ? JSON.parse(stored) : false;
3747
111
  });
3748
- useEffect9(() => {
3749
- localStorage.setItem(STORAGE_KEY2, JSON.stringify(open));
112
+ useEffect(() => {
113
+ localStorage.setItem(STORAGE_KEY, JSON.stringify(open));
3750
114
  }, [open]);
3751
115
  return [open, setOpen];
3752
116
  }
3753
117
 
3754
- // src/inspector/viewer/delete-local-data.tsx
3755
- import { useState as useState16 } from "react";
3756
- import { Fragment as Fragment14, jsx as jsx38, jsxs as jsxs26 } from "react/jsx-runtime";
3757
- var DELETE_LOCAL_DATA_STRING = "delete my local data";
3758
- function DeleteLocalData() {
3759
- const [showDeleteModal, setShowDeleteModal] = useState16(false);
3760
- const [confirmDeleteString, setConfirmDeleteString] = useState16("");
3761
- return /* @__PURE__ */ jsxs26(Fragment14, { children: [
3762
- /* @__PURE__ */ jsx38(Button, { variant: "destructive", onClick: () => setShowDeleteModal(true), children: "Delete my local data" }),
3763
- /* @__PURE__ */ jsxs26(
3764
- Modal,
118
+ // src/inspector/in-app.tsx
119
+ import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
120
+ function InspectorInApp({
121
+ position = "right",
122
+ localNode,
123
+ accountId
124
+ }) {
125
+ const [open, setOpen] = useOpenInspector();
126
+ if (!open) {
127
+ return /* @__PURE__ */ jsx2(InspectorButton, { position, onClick: () => setOpen(true) });
128
+ }
129
+ return /* @__PURE__ */ jsx2(NodeProvider, { localNode: localNode ?? null, accountID: accountId ?? null, children: /* @__PURE__ */ jsx2(InMemoryRouterProvider, { children: /* @__PURE__ */ jsxs2(InspectorContainer, { as: GlobalStyles, style: { zIndex: 999 }, children: [
130
+ /* @__PURE__ */ jsx2(
131
+ Header,
3765
132
  {
3766
- isOpen: showDeleteModal,
3767
- onClose: () => setShowDeleteModal(false),
3768
- heading: "Delete Local Data",
3769
- showButtons: false,
3770
- children: [
3771
- /* @__PURE__ */ jsxs26(
3772
- "div",
3773
- {
3774
- style: {
3775
- margin: "0 0 1rem 0",
3776
- color: "var(--j-text-color)",
3777
- display: "flex",
3778
- flexDirection: "column",
3779
- gap: "0.5rem"
3780
- },
3781
- children: [
3782
- /* @__PURE__ */ jsxs26("p", { children: [
3783
- "This action ",
3784
- /* @__PURE__ */ jsx38("strong", { children: "cannot" }),
3785
- " be undone."
3786
- ] }),
3787
- /* @__PURE__ */ jsxs26("p", { children: [
3788
- "Be aware that the following data will be",
3789
- " ",
3790
- /* @__PURE__ */ jsx38("strong", { children: "permanently" }),
3791
- " deleted:"
3792
- ] }),
3793
- /* @__PURE__ */ jsxs26("ul", { style: { listStyleType: "disc", paddingLeft: "1rem" }, children: [
3794
- /* @__PURE__ */ jsxs26("li", { children: [
3795
- "Unsynced data for ",
3796
- /* @__PURE__ */ jsx38("strong", { children: "all apps" }),
3797
- " on",
3798
- " ",
3799
- /* @__PURE__ */ jsx38("code", { children: window.location.origin })
3800
- ] }),
3801
- /* @__PURE__ */ jsx38("li", { children: "Accounts" }),
3802
- /* @__PURE__ */ jsx38("li", { children: "Logged in sessions" })
3803
- ] }),
3804
- /* @__PURE__ */ jsx38("p", {})
3805
- ]
3806
- }
3807
- ),
3808
- /* @__PURE__ */ jsx38(
3809
- Input,
3810
- {
3811
- label: `Type "${DELETE_LOCAL_DATA_STRING}" to confirm`,
3812
- placeholder: DELETE_LOCAL_DATA_STRING,
3813
- value: confirmDeleteString,
3814
- onChange: (e) => {
3815
- setConfirmDeleteString(e.target.value);
3816
- }
3817
- }
3818
- ),
3819
- /* @__PURE__ */ jsx38(
3820
- "p",
3821
- {
3822
- style: {
3823
- margin: "0 0 1rem 0",
3824
- color: "var(--j-text-color)",
3825
- display: "flex",
3826
- flexDirection: "column",
3827
- gap: "0.5rem"
3828
- },
3829
- children: /* @__PURE__ */ jsxs26("small", { children: [
3830
- "Data synced to a sync server will ",
3831
- /* @__PURE__ */ jsx38("strong", { children: "not" }),
3832
- " be deleted, and will be synced when you log in again."
3833
- ] })
3834
- }
3835
- ),
3836
- /* @__PURE__ */ jsxs26(
3837
- "div",
3838
- {
3839
- style: {
3840
- display: "flex",
3841
- marginTop: "0.5rem",
3842
- justifyContent: "flex-end",
3843
- gap: "0.5rem"
3844
- },
3845
- children: [
3846
- /* @__PURE__ */ jsx38(Button, { variant: "secondary", onClick: () => setShowDeleteModal(false), children: "Cancel" }),
3847
- /* @__PURE__ */ jsx38(
3848
- Button,
3849
- {
3850
- variant: "destructive",
3851
- disabled: confirmDeleteString !== DELETE_LOCAL_DATA_STRING,
3852
- onClick: () => {
3853
- const jazzKeys = Object.keys(localStorage).filter(
3854
- (key) => key.startsWith("jazz-") || key.startsWith("co_z")
3855
- );
3856
- jazzKeys.forEach((key) => localStorage.removeItem(key));
3857
- indexedDB.deleteDatabase("jazz-storage");
3858
- window.location.reload();
3859
- setShowDeleteModal(false);
3860
- },
3861
- children: "I'm sure, delete my local data"
3862
- }
3863
- )
3864
- ]
3865
- }
3866
- )
3867
- ]
133
+ showDeleteLocalData: true,
134
+ showClose: true,
135
+ onClose: () => setOpen(false)
3868
136
  }
3869
- )
3870
- ] });
137
+ ),
138
+ /* @__PURE__ */ jsx2(PageStack, {})
139
+ ] }) }) });
3871
140
  }
3872
-
3873
- // src/inspector/viewer/new-app.tsx
3874
- import { Fragment as Fragment15, jsx as jsx39, jsxs as jsxs27 } from "react/jsx-runtime";
3875
- var InspectorContainer = styled27("div")`
141
+ var InspectorContainer = styled2("div")`
3876
142
  position: fixed;
3877
143
  height: 50vh;
3878
144
  max-height: 800px;
@@ -3884,136 +150,27 @@ var InspectorContainer = styled27("div")`
3884
150
  background-color: white;
3885
151
  border-top: 1px solid var(--j-border-color);
3886
152
  color: var(--j-text-color);
3887
-
153
+
3888
154
  @media (prefers-color-scheme: dark) {
3889
155
  background-color: var(--j-background);
3890
156
  }
3891
157
  `;
3892
- var HeaderContainer2 = styled27("div")`
3893
- display: flex;
3894
- align-items: center;
3895
- gap: 1rem;
3896
- padding: 0 0.75rem;
3897
- margin: 0.75rem 0;
3898
- `;
3899
- var Form = styled27("form")`
3900
- width: 24rem;
3901
- `;
3902
- var InitialForm = styled27("form")`
3903
- display: flex;
3904
- flex-direction: column;
3905
- position: relative;
3906
- top: -1.5rem;
3907
- justify-content: center;
3908
- gap: 0.5rem;
3909
- height: 100%;
3910
- width: 100%;
3911
- max-width: 24rem;
3912
- margin: 0 auto;
3913
- `;
3914
- var OrText = styled27("p")`
3915
- text-align: center;
3916
- `;
3917
- function JazzInspectorInternal({
3918
- position = "right",
3919
- localNode,
3920
- accountId
3921
- }) {
3922
- const [open, setOpen] = useOpenInspector();
3923
- const [coValueId, setCoValueId] = useState17("");
3924
- const { path, addPages, goToIndex, goBack, setPage } = usePagePath();
3925
- const handleCoValueIdSubmit = (e) => {
3926
- e.preventDefault();
3927
- if (coValueId) {
3928
- setPage(coValueId);
3929
- }
3930
- setCoValueId("");
3931
- };
3932
- if (!open) {
3933
- return /* @__PURE__ */ jsx39(InspectorButton, { position, onClick: () => setOpen(true) });
3934
- }
3935
- return /* @__PURE__ */ jsxs27(InspectorContainer, { as: GlobalStyles, style: { zIndex: 999 }, children: [
3936
- /* @__PURE__ */ jsxs27(HeaderContainer2, { children: [
3937
- /* @__PURE__ */ jsx39(Breadcrumbs, { path, onBreadcrumbClick: goToIndex }),
3938
- path.length !== 0 && /* @__PURE__ */ jsx39(Form, { onSubmit: handleCoValueIdSubmit, children: /* @__PURE__ */ jsx39(
3939
- Input,
3940
- {
3941
- label: "CoValue ID",
3942
- style: { fontFamily: "monospace" },
3943
- hideLabel: true,
3944
- placeholder: "co_z1234567890abcdef123456789",
3945
- value: coValueId,
3946
- onChange: (e) => setCoValueId(e.target.value)
3947
- }
3948
- ) }),
3949
- /* @__PURE__ */ jsx39(DeleteLocalData, {}),
3950
- /* @__PURE__ */ jsx39(Button, { variant: "plain", type: "button", onClick: () => setOpen(false), children: "Close" })
3951
- ] }),
3952
- /* @__PURE__ */ jsx39(
3953
- PageStack,
3954
- {
3955
- path,
3956
- node: localNode,
3957
- goBack,
3958
- addPages,
3959
- children: path.length <= 0 && /* @__PURE__ */ jsxs27(
3960
- InitialForm,
3961
- {
3962
- onSubmit: handleCoValueIdSubmit,
3963
- "aria-hidden": path.length !== 0,
3964
- children: [
3965
- /* @__PURE__ */ jsx39(Heading, { children: "Jazz CoValue Inspector" }),
3966
- /* @__PURE__ */ jsx39(
3967
- Input,
3968
- {
3969
- label: "CoValue ID",
3970
- style: { minWidth: "21rem", fontFamily: "monospace" },
3971
- hideLabel: true,
3972
- placeholder: "co_z1234567890abcdef123456789",
3973
- value: coValueId,
3974
- onChange: (e) => setCoValueId(e.target.value)
3975
- }
3976
- ),
3977
- /* @__PURE__ */ jsx39(Button, { type: "submit", variant: "primary", children: "Inspect CoValue" }),
3978
- accountId && /* @__PURE__ */ jsxs27(Fragment15, { children: [
3979
- /* @__PURE__ */ jsx39(OrText, { children: "or" }),
3980
- /* @__PURE__ */ jsx39(
3981
- Button,
3982
- {
3983
- variant: "secondary",
3984
- onClick: () => {
3985
- setCoValueId(accountId);
3986
- setPage(accountId);
3987
- },
3988
- children: "Inspect my account"
3989
- }
3990
- )
3991
- ] })
3992
- ]
3993
- }
3994
- )
3995
- }
3996
- )
3997
- ] });
3998
- }
3999
158
 
4000
159
  // src/inspector/index.tsx
4001
- import { setup } from "goober";
4002
- import { useJazzContext } from "jazz-tools/react-core";
4003
- import { jsx as jsx40 } from "react/jsx-runtime";
160
+ import { jsx as jsx3 } from "react/jsx-runtime";
4004
161
  function JazzInspector({ position = "right" }) {
4005
162
  const context = useJazzContext();
4006
163
  const localNode = context.node;
4007
164
  const me = "me" in context ? context.me : void 0;
4008
- const [isCSR, setIsCSR] = useState18(false);
4009
- useEffect10(() => {
165
+ const [isCSR, setIsCSR] = useState2(false);
166
+ useEffect2(() => {
4010
167
  setIsCSR(true);
4011
168
  }, []);
4012
169
  if (!isCSR) {
4013
170
  return null;
4014
171
  }
4015
- return /* @__PURE__ */ jsx40(
4016
- JazzInspectorInternal,
172
+ return /* @__PURE__ */ jsx3(
173
+ InspectorInApp,
4017
174
  {
4018
175
  position,
4019
176
  localNode,
@@ -4021,19 +178,8 @@ function JazzInspector({ position = "right" }) {
4021
178
  }
4022
179
  );
4023
180
  }
4024
- setup(React8.createElement);
181
+ setup(React.createElement);
4025
182
  export {
4026
- AccountOrGroupText,
4027
- Breadcrumbs,
4028
- Button,
4029
- GlobalStyles,
4030
- Icon,
4031
- Input,
4032
- JazzInspector,
4033
- JazzInspectorInternal,
4034
- PageStack,
4035
- Select,
4036
- resolveCoValue,
4037
- useResolvedCoValue
183
+ JazzInspector
4038
184
  };
4039
185
  //# sourceMappingURL=index.js.map