@eqtylab/explorer 0.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (140) hide show
  1. package/.env.api +6 -0
  2. package/.env.iframe +2 -0
  3. package/.env.manifest +2 -0
  4. package/.envrc +1 -0
  5. package/.eslintrc.cjs +17 -0
  6. package/.github/workflows/ci.yml +46 -0
  7. package/.github/workflows/publish.yml +44 -0
  8. package/.husky/pre-push +2 -0
  9. package/.prettierignore +2 -0
  10. package/.prettierrc.json +13 -0
  11. package/LICENSE +201 -0
  12. package/README.md +84 -0
  13. package/flake.lock +61 -0
  14. package/flake.nix +23 -0
  15. package/index.html +13 -0
  16. package/package.json +93 -0
  17. package/postcss.config.js +5 -0
  18. package/public/logos/eci.svg +23 -0
  19. package/public/logos/eqty.svg +3 -0
  20. package/public/manifests/B-200-merged.json +773 -0
  21. package/public/manifests/amd-sev.json +426 -0
  22. package/public/manifests/anchors.json +609 -0
  23. package/public/manifests/association-no-metadata.json +1393 -0
  24. package/public/manifests/association.json +1402 -0
  25. package/public/manifests/eqty-docker.json +562 -0
  26. package/public/manifests/governance.json +1324 -0
  27. package/public/manifests/intel-tdx-with-nvidia.json +441 -0
  28. package/public/manifests/intel-tdx.json +404 -0
  29. package/public/manifests/iroh-collections.json +1285 -0
  30. package/public/manifests/model-signing.json +1536 -0
  31. package/public/manifests/multiple-registrations.json +129 -0
  32. package/public/manifests/no-vcs.json +114 -0
  33. package/public/manifests/storage.json +294 -0
  34. package/public/manifests/sub-graphs.json +1 -0
  35. package/src/animations/variants.ts +52 -0
  36. package/src/app/apiClient/integrityService/fetchAttributes.ts +29 -0
  37. package/src/app/apiClient/integrityService/fetchManifest.ts +28 -0
  38. package/src/app/apiClient/integrityService/types.ts +12 -0
  39. package/src/app/components/integrityService/IntegrityService.tsx +105 -0
  40. package/src/app/components/integrityService/components/AuthButton.tsx +26 -0
  41. package/src/app/components/integrityService/components/FiltersModal.tsx +214 -0
  42. package/src/app/components/integrityService/components/FiltersToggle.tsx +28 -0
  43. package/src/app/components/manifestViewer/ManifestViewer.tsx +90 -0
  44. package/src/app/components/manifestViewer/components/ManifestButtons.tsx +215 -0
  45. package/src/app/config.json +23 -0
  46. package/src/app/config.ts +28 -0
  47. package/src/app/pages/index.tsx +34 -0
  48. package/src/app/stores/manifestStore.ts +19 -0
  49. package/src/app/utils/appMode.ts +37 -0
  50. package/src/assets/fonts/TWKLausanne-300.woff +0 -0
  51. package/src/assets/fonts/TWKLausanne-300.woff2 +0 -0
  52. package/src/assets/fonts/TWKLausanne-400.woff +0 -0
  53. package/src/assets/fonts/TWKLausanne-400.woff2 +0 -0
  54. package/src/assets/fonts/TWKLausanne-500.woff +0 -0
  55. package/src/assets/fonts/TWKLausanne-500.woff2 +0 -0
  56. package/src/assets/fonts/TWKLausanne-600.woff +0 -0
  57. package/src/assets/fonts/TWKLausanne-600.woff2 +0 -0
  58. package/src/assets/vectors/eqtylab.svg +6 -0
  59. package/src/components/app-header.tsx +61 -0
  60. package/src/components/dark-mode-switch.tsx +16 -0
  61. package/src/components/ui/accordion.tsx +47 -0
  62. package/src/components/ui/certificate-chain.tsx +60 -0
  63. package/src/components/ui/certificate-code.tsx +39 -0
  64. package/src/components/ui/details.tsx +20 -0
  65. package/src/components/ui/display-code.tsx +47 -0
  66. package/src/components/ui/panel-label.tsx +12 -0
  67. package/src/components/ui/verify-state-badge.tsx +32 -0
  68. package/src/explorer-component/LineageExplorer.tsx +89 -0
  69. package/src/explorer-component/components/CustomEdge.tsx +28 -0
  70. package/src/explorer-component/components/LineageFlow.tsx +220 -0
  71. package/src/explorer-component/components/NodeIconLoader.tsx +26 -0
  72. package/src/explorer-component/components/nodes/ComputationNode.tsx +56 -0
  73. package/src/explorer-component/components/nodes/CustomNode.tsx +112 -0
  74. package/src/explorer-component/components/nodes/index.ts +4 -0
  75. package/src/explorer-component/components/nodes/nodes.tsx +144 -0
  76. package/src/explorer-component/components/nodes/types.ts +167 -0
  77. package/src/explorer-component/components/sidebar/SectionList.tsx +54 -0
  78. package/src/explorer-component/components/sidebar/SectionTitle.tsx +10 -0
  79. package/src/explorer-component/components/sidebar/Sidebar.tsx +70 -0
  80. package/src/explorer-component/components/sidebar/SidebarWrapper.tsx +76 -0
  81. package/src/explorer-component/components/sidebar/sections/CustomSection.tsx +238 -0
  82. package/src/explorer-component/components/sidebar/sections/FileViewer.tsx +229 -0
  83. package/src/explorer-component/components/sidebar/sections/GovernanceSection.tsx +52 -0
  84. package/src/explorer-component/components/sidebar/sections/RegistrationSection.tsx +254 -0
  85. package/src/explorer-component/components/sidebar/sections/SigstoreSection.tsx +37 -0
  86. package/src/explorer-component/components/sidebar/sections/StorageSection.tsx +73 -0
  87. package/src/explorer-component/components/sidebar/sections/custom/IrohCollectionsView.tsx +139 -0
  88. package/src/explorer-component/components/sidebar/sections/registration/VerificationIcon.tsx +108 -0
  89. package/src/explorer-component/components/sidebar/sections/registration/actor/ActorBadge.tsx +62 -0
  90. package/src/explorer-component/components/sidebar/sections/registration/actor/svg/AMDLogo.tsx +40 -0
  91. package/src/explorer-component/components/sidebar/sections/registration/actor/svg/AzureLogo.tsx +65 -0
  92. package/src/explorer-component/components/sidebar/sections/registration/actor/svg/IntelLogo.tsx +24 -0
  93. package/src/explorer-component/components/sidebar/sections/registration/actor/svg/NvidiaLogo.tsx +27 -0
  94. package/src/explorer-component/components/sidebar/sections/registration/verifierClient.ts +13 -0
  95. package/src/explorer-component/icons/AttributionIcon.svg +6 -0
  96. package/src/explorer-component/icons/BenchmarkIcon.svg +6 -0
  97. package/src/explorer-component/icons/BenchmarkResultIcon.svg +6 -0
  98. package/src/explorer-component/icons/CertificateIcon.svg +6 -0
  99. package/src/explorer-component/icons/CodeIcon.svg +6 -0
  100. package/src/explorer-component/icons/ComputationIcon.svg +6 -0
  101. package/src/explorer-component/icons/DataIcon.svg +6 -0
  102. package/src/explorer-component/icons/DatabaseIcon.svg +6 -0
  103. package/src/explorer-component/icons/DatasetIcon.svg +6 -0
  104. package/src/explorer-component/icons/DeltaLakeIcon.svg +7 -0
  105. package/src/explorer-component/icons/DocumentIcon.svg +6 -0
  106. package/src/explorer-component/icons/MediaIcon.svg +6 -0
  107. package/src/explorer-component/icons/ModelIcon.svg +6 -0
  108. package/src/explorer-component/icons/TeamIcon.svg +3 -0
  109. package/src/explorer-component/icons/TokenIcon.svg +6 -0
  110. package/src/explorer-component/icons/UnknownIcon.svg +6 -0
  111. package/src/explorer-component/icons/index.ts +35 -0
  112. package/src/explorer-component/index.ts +5 -0
  113. package/src/explorer-component/integrityTypes/AnchorTypes.ts +31 -0
  114. package/src/explorer-component/integrityTypes/StatementTypes.ts +333 -0
  115. package/src/explorer-component/integrityTypes/VCTypes.ts +85 -0
  116. package/src/explorer-component/integrityTypes/types.ts +3 -0
  117. package/src/explorer-component/utils/config.ts +163 -0
  118. package/src/explorer-component/utils/formatTimestamp.ts +5 -0
  119. package/src/explorer-component/utils/generateGraph.ts +271 -0
  120. package/src/explorer-component/utils/layoutGraph.ts +148 -0
  121. package/src/explorer-component/utils/resolveIrohBlobs.ts +117 -0
  122. package/src/explorer-component/utils/statementHelpers.ts +252 -0
  123. package/src/explorer-component/utils/stripPrefix.ts +4 -0
  124. package/src/hooks/use-mobile.tsx +19 -0
  125. package/src/index.ts +3 -0
  126. package/src/lib/resource-types.ts +31 -0
  127. package/src/lib/use-escape-key.tsx +16 -0
  128. package/src/lib/utils.ts +19 -0
  129. package/src/main.css +82 -0
  130. package/src/main.tsx +39 -0
  131. package/src/v-comp-viewer/components/container-did-details.tsx +53 -0
  132. package/src/v-comp-viewer/components/system-did-details.tsx +356 -0
  133. package/src/v-comp-viewer/useVComp.ts +196 -0
  134. package/src/v-comp-viewer/utils.tsx +824 -0
  135. package/src/vite-env.d.ts +1 -0
  136. package/tsconfig.json +33 -0
  137. package/tsconfig.node.json +10 -0
  138. package/vercel.json +13 -0
  139. package/vite.app.config.ts +48 -0
  140. package/vite.lib.config.ts +61 -0
@@ -0,0 +1,252 @@
1
+ import { stripCidPrefix } from "./stripPrefix.ts";
2
+ import {
3
+ Actor,
4
+ createEmptyActor,
5
+ vcFromString,
6
+ isVCompType,
7
+ VCompType,
8
+ VCompEvidence,
9
+ VCompEvidenceList,
10
+ Statement,
11
+ StorageStatement,
12
+ StorageStatementFromJSON,
13
+ VcStatement,
14
+ MetadataStatement,
15
+ MetadataStatementFromJSON,
16
+ VcStatementFromJSON,
17
+ RegistrationTypes,
18
+ GovernanceStatement,
19
+ GovernanceStatementFromJSON,
20
+ SigstoreStatement,
21
+ SigstoreStatementFromJSON,
22
+ SigstoreBundle,
23
+ } from "../integrityTypes/types";
24
+ import { MetadataLineage, StorageLineage } from "@/explorer-component/components/nodes/types.ts";
25
+
26
+ const statementTypePriority: Record<string, number> = {
27
+ CredentialRegistration: 0,
28
+ MetadataRegistration: 1,
29
+ DidRegistration: 2,
30
+ DataRegistration: 3,
31
+ ComputationRegistration: 4,
32
+ };
33
+
34
+ // Sort the statements by type, and then by timestamp to that indexing doesn't need to repeatedly iterate all the statements looking for VCs, metadata, etc
35
+ export function sortStatements(statements: Record<string, object>): Map<string, object> {
36
+ const sortedStatements = Object.entries(statements).sort(([, a], [, b]) => {
37
+ const typeA = (a as any)["@type"] || "";
38
+ const typeB = (b as any)["@type"] || "";
39
+
40
+ const priorityDiff = (statementTypePriority[typeA] ?? 99) - (statementTypePriority[typeB] ?? 99);
41
+ if (priorityDiff !== 0) return priorityDiff;
42
+
43
+ const timeA = new Date((a as any)["timestamp"] ?? 0).getTime();
44
+ const timeB = new Date((b as any)["timestamp"] ?? 0).getTime();
45
+
46
+ return timeB - timeA; // sort by descending timestamp
47
+ });
48
+
49
+ return new Map(sortedStatements);
50
+ }
51
+
52
+ /// Iterates over the statments to resolve related nodes (metadata, etc)
53
+ // The provided statements Map MUST be sorted
54
+ export function indexStatements(
55
+ statements: Map<string, object>,
56
+ blobs: Record<string, string>,
57
+ ): {
58
+ metadataLineage: Map<string, MetadataLineage[]>;
59
+ vcs: Map<string, VcStatement[]>;
60
+ actors: Map<string, any>;
61
+ storage: Map<string, StorageLineage>;
62
+ governance: Map<string, GovernanceStatement>;
63
+ sigstoreBundles: Map<string, SigstoreBundle[]>;
64
+ } {
65
+ const metadataJsonMap: Map<string, any[]> = new Map(); // key=subject cid, value=user defined json
66
+ const metadataStatements: Map<string, MetadataLineage[]> = new Map(); // key=subject cid
67
+ const vcMap: Map<string, VcStatement[]> = new Map(); // key=subject ID
68
+ const actorsMap: Map<string, Actor> = new Map(); // key=did
69
+ const storageMap: Map<string, StorageLineage> = new Map(); // key=data CID
70
+ const governanceMap: Map<string, GovernanceStatement> = new Map(); // key=subject CID
71
+ const sbMap: Map<string, SigstoreBundle[]> = new Map(); // key=subject CID, value=sigstore statement
72
+
73
+ for (const [, statement] of statements) {
74
+ // @ts-ignore
75
+ switch (statement["@type"]) {
76
+ case RegistrationTypes.Metadata: {
77
+ const metadataStatement: MetadataStatement = MetadataStatementFromJSON(statement);
78
+
79
+ if (metadataStatement.subject.startsWith("urn:cid:")) {
80
+ // metadata for a CID
81
+ const blobStr = blobs[stripCidPrefix(metadataStatement.metadata)] || "";
82
+
83
+ const metadataJson = blobStr.length > 0 ? JSON.parse(atob(blobStr)) : null;
84
+ const existingJson = metadataJsonMap.get(metadataStatement.subject) || [];
85
+ existingJson.push(metadataJson);
86
+ metadataJsonMap.set(metadataStatement.subject, existingJson);
87
+
88
+ const existingStatement = metadataStatements.get(metadataStatement.subject) || [];
89
+ const metadataVC = vcMap.get(metadataStatement.id);
90
+ existingStatement.push({
91
+ statement: metadataStatement,
92
+ metadata: metadataJson,
93
+ vc: metadataVC?.[0]?.credential,
94
+ });
95
+ metadataStatements.set(metadataStatement.subject, existingStatement);
96
+ } else if (metadataStatement.subject.startsWith("did:")) {
97
+ // metadata for a DID
98
+ const did = metadataStatement.subject;
99
+
100
+ const blobStr = blobs[stripCidPrefix(metadataStatement.metadata)] || "";
101
+
102
+ const metadataJson = blobStr.length > 0 ? JSON.parse(atob(blobStr)) : null;
103
+
104
+ // TODO: handle multiple metadata statements for the same DID similarly to how we handle metadata for CIDs
105
+ if (!actorsMap.has(did)) {
106
+ actorsMap.set(did, createEmptyActor(did));
107
+ }
108
+ const actor = actorsMap.get(did);
109
+ if (actor) {
110
+ actor.actorName = metadataJson.name || null;
111
+ actor.metadata = metadataJson;
112
+ }
113
+ }
114
+
115
+ break;
116
+ }
117
+ case RegistrationTypes.Credential: {
118
+ if ("sigstoreBundle" in statement) {
119
+ const sbStatement: SigstoreStatement = SigstoreStatementFromJSON(statement);
120
+ const sb = JSON.parse(atob(sbStatement.sigstoreBundle));
121
+ const subjectId = sbStatement.subject;
122
+ if (!sbMap.has(subjectId)) {
123
+ sbMap.set(subjectId, []);
124
+ }
125
+ sbMap.get(subjectId)!.push(sb);
126
+ } else {
127
+ const vcStatement: VcStatement = VcStatementFromJSON(statement);
128
+ const vc = vcFromString(vcStatement.credential);
129
+ if (!vc) {
130
+ continue;
131
+ }
132
+ const subjectId = vc.credentialSubject.id;
133
+
134
+ if (!vcMap.has(subjectId)) {
135
+ vcMap.set(subjectId, []);
136
+ }
137
+
138
+ vcMap.get(subjectId)!.push(vcStatement);
139
+ }
140
+ break;
141
+ }
142
+ case RegistrationTypes.Did: {
143
+ handleDidRegistration(statement, actorsMap, vcMap);
144
+ break;
145
+ }
146
+ case RegistrationTypes.Storage: {
147
+ const storageStatement: StorageStatement = StorageStatementFromJSON(statement);
148
+ const blobStr = blobs[stripCidPrefix(storageStatement.storedOn)] || "";
149
+ const data = blobStr.length > 0 ? JSON.parse(atob(blobStr)) : null;
150
+
151
+ const storage = { statement: storageStatement, metadata: data };
152
+ storageMap.set(storageStatement.data, storage);
153
+ break;
154
+ }
155
+ case RegistrationTypes.Governance: {
156
+ const governanceStatement: GovernanceStatement = GovernanceStatementFromJSON(statement);
157
+ governanceMap.set(governanceStatement.subject, governanceStatement);
158
+ break;
159
+ }
160
+ }
161
+ }
162
+
163
+ if (metadataJsonMap.keys.length !== metadataStatements.keys.length) {
164
+ throw new Error("Count mismatch with the number of metadatastatements and metadata blobs");
165
+ }
166
+ return {
167
+ metadataLineage: metadataStatements,
168
+ vcs: vcMap,
169
+ actors: actorsMap,
170
+ storage: storageMap,
171
+ governance: governanceMap,
172
+ sigstoreBundles: sbMap,
173
+ };
174
+ }
175
+
176
+ // Update the ActorMap with DidRegistration details
177
+ function handleDidRegistration(statement: object, actorsMap: Map<string, Actor>, vcMap: Map<string, VcStatement[]>) {
178
+ const sVal = JSON.parse(JSON.stringify(statement));
179
+ const id = sVal["@id"];
180
+ const did = sVal["did"];
181
+ const vcomp = sVal["vcomp"];
182
+ if (!vcomp || typeof vcomp !== "object") return;
183
+
184
+ const vcompType = vcomp["@type"];
185
+
186
+ if (!isVCompType(vcompType)) {
187
+ console.warn("Unknown vcomp type:", vcompType);
188
+ return;
189
+ }
190
+
191
+ const vcompStatementsMap = new Map<VCompType, Statement[]>();
192
+ const vcompEvidenceMap = new Map<VCompEvidence, VcStatement[]>();
193
+
194
+ if (!vcompStatementsMap.has(vcompType)) {
195
+ vcompStatementsMap.set(vcompType, []);
196
+ }
197
+
198
+ vcompStatementsMap.get(vcompType)!.push(VcStatementFromJSON(statement));
199
+
200
+ for (const evidenceType of VCompEvidenceList) {
201
+ const vcStatements = vcMap.get(id);
202
+ if (vcStatements) {
203
+ for (const vc of vcStatements) {
204
+ const type = (vc.credential as any)?.evidence?.type;
205
+ if (Array.isArray(type) && type.includes(evidenceType)) {
206
+ vcompEvidenceMap.set(evidenceType, vcStatements);
207
+ }
208
+ }
209
+ }
210
+ }
211
+
212
+ const teeEnv = (() => {
213
+ if (!vcompStatementsMap) return null;
214
+
215
+ if (vcompStatementsMap.has("EqtyVCompAmdSevV1") && vcompEvidenceMap.has("EqtyVCompAmdSevV1Evidence")) {
216
+ return "AMD SEV";
217
+ }
218
+
219
+ if (vcompStatementsMap.has("EqtyVCompIntelTdxV0") && vcompEvidenceMap.has("EqtyVCompIntelTdxV0Evidence")) {
220
+ return "Intel TDX";
221
+ }
222
+
223
+ if (vcompStatementsMap.has("EqtyVCompAzureV1") && vcompEvidenceMap.has("EqtyVCompAzureV1Evidence")) {
224
+ return "Azure";
225
+ }
226
+
227
+ if (vcompStatementsMap.has("EqtyVCompDockerV1")) {
228
+ return "EQTY Docker";
229
+ }
230
+
231
+ return null;
232
+ })();
233
+
234
+ const usesNvidia = (() => {
235
+ if (vcompEvidenceMap.has("EqtyVCompNvidiaCcV0Evidence")) {
236
+ return true;
237
+ }
238
+
239
+ return false;
240
+ })();
241
+
242
+ if (!actorsMap.has(did)) {
243
+ actorsMap.set(did, createEmptyActor(did));
244
+ }
245
+ const actor = actorsMap.get(did);
246
+ if (actor) {
247
+ actor.vcompStatements = vcompStatementsMap;
248
+ actor.vcompEvidence = vcompEvidenceMap;
249
+ actor.usesNvidia = usesNvidia;
250
+ actor.teeEnv = teeEnv;
251
+ }
252
+ }
@@ -0,0 +1,4 @@
1
+ export function stripCidPrefix(cid: string) {
2
+ const prefix = "urn:cid:";
3
+ return cid.startsWith(prefix) ? cid.slice(prefix.length) : cid;
4
+ }
@@ -0,0 +1,19 @@
1
+ import * as React from "react";
2
+
3
+ const MOBILE_BREAKPOINT = 768;
4
+
5
+ export function useIsMobile() {
6
+ const [isMobile, setIsMobile] = React.useState<boolean | undefined>(undefined);
7
+
8
+ React.useEffect(() => {
9
+ const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`);
10
+ const onChange = () => {
11
+ setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);
12
+ };
13
+ mql.addEventListener("change", onChange);
14
+ setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);
15
+ return () => mql.removeEventListener("change", onChange);
16
+ }, []);
17
+
18
+ return !!isMobile;
19
+ }
package/src/index.ts ADDED
@@ -0,0 +1,3 @@
1
+ import "./main.css";
2
+ export * from "./explorer-component";
3
+ export { useVComp } from "./v-comp-viewer/useVComp";
@@ -0,0 +1,31 @@
1
+ import { ResourceType } from "@eqtylab/equality";
2
+
3
+ // lowercase display type to resource type
4
+ const DISPLAY_TYPE_TO_RESOURCE_TYPE: Record<string, ResourceType> = {
5
+ default: "unknown",
6
+ unknown: "unknown",
7
+ dataset: "dataset",
8
+ model: "model",
9
+ code: "code",
10
+ document: "document",
11
+ prompt: "prompt",
12
+ token: "token",
13
+ inference: "inference",
14
+ tool: "tools",
15
+ benchmarks: "benchmark",
16
+ benchmark: "benchmark",
17
+ guards: "guard",
18
+ agent: "agent",
19
+ guardrail: "guardrail",
20
+ computation: "compute",
21
+ systemprompt: "system-prompt",
22
+ context: "context",
23
+ reasoning: "reasoning",
24
+ systemparameters: "system-parameters",
25
+ database: "database",
26
+ };
27
+
28
+ export const getResourceTypeFromDisplayType = (displayType: string): ResourceType => {
29
+ const lowercasedDisplayType = displayType.toLowerCase() as keyof typeof DISPLAY_TYPE_TO_RESOURCE_TYPE;
30
+ return DISPLAY_TYPE_TO_RESOURCE_TYPE[lowercasedDisplayType] || "unknown";
31
+ };
@@ -0,0 +1,16 @@
1
+ import { useEffect } from "react";
2
+
3
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
4
+ export const useEscapeKey = (value: any, callback: () => void) =>
5
+ useEffect(() => {
6
+ const handleDocumentKeydown = (event: KeyboardEvent) => {
7
+ if (!value) return;
8
+ if (event.key === "Escape") {
9
+ callback();
10
+ }
11
+ };
12
+ document.addEventListener("keydown", handleDocumentKeydown);
13
+ return () => {
14
+ document.removeEventListener("keydown", handleDocumentKeydown);
15
+ };
16
+ }, [value, callback]);
@@ -0,0 +1,19 @@
1
+ import { clsx, type ClassValue } from "clsx";
2
+ import { twMerge } from "tailwind-merge";
3
+
4
+ export function cn(...inputs: ClassValue[]) {
5
+ return twMerge(clsx(inputs));
6
+ }
7
+
8
+ export function toNumber(value: string | undefined | null) {
9
+ return value ? parseInt(value, 10) : undefined;
10
+ }
11
+
12
+ export function formatFileSize(bytes: number): string {
13
+ if (bytes === 0) return "0 Bytes";
14
+
15
+ const sizes = ["Bytes", "KB", "MB", "GB", "TB"];
16
+ const i = Math.floor(Math.log(bytes) / Math.log(1024));
17
+
18
+ return `${parseFloat((bytes / Math.pow(1024, i)).toFixed(2))} ${sizes[i]}`;
19
+ }
package/src/main.css ADDED
@@ -0,0 +1,82 @@
1
+ @layer theme, base, components, utilities;
2
+
3
+ @import "tailwindcss/theme.css" layer(theme) theme(inline);
4
+ @import "tailwindcss/utilities.css" layer(utilities);
5
+
6
+ @import "@eqtylab/equality/theme-config.css";
7
+
8
+ @layer base {
9
+ main {
10
+ @apply bg-background font-sans text-text-primary transition-colors;
11
+ }
12
+
13
+ /* COLORS */
14
+ html {
15
+ /* Primary */
16
+ --brand-lineage-explorer: var(--color-blue-600);
17
+ }
18
+
19
+ html[data-equality-theme="dark"] {
20
+ --brand-lineage-explorer: var(--color-blue-300);
21
+ }
22
+ }
23
+
24
+ @theme inline {
25
+ /* COLORS */
26
+ --color-brand-lineage-explorer: var(--brand-lineage-explorer);
27
+ }
28
+
29
+ @layer utilities {
30
+ :root {
31
+ font-synthesis: none;
32
+ text-rendering: optimizeLegibility;
33
+ -webkit-font-smoothing: antialiased;
34
+ -moz-osx-font-smoothing: grayscale;
35
+ }
36
+ }
37
+
38
+ @font-face {
39
+ font-family: "TWK Lausanne";
40
+ src:
41
+ url("./assets/fonts/TWKLausanne-300.woff") format("woff"),
42
+ url("./assets/fonts/TWKLausanne-300.woff2") format("woff2");
43
+ font-style: normal;
44
+ font-weight: 300;
45
+ }
46
+
47
+ @font-face {
48
+ font-family: "TWK Lausanne";
49
+ src:
50
+ url("./assets/fonts/TWKLausanne-400.woff") format("woff"),
51
+ url("./assets/fonts/TWKLausanne-400.woff2") format("woff2");
52
+ font-style: normal;
53
+ font-weight: 400;
54
+ }
55
+
56
+ @font-face {
57
+ font-family: "TWK Lausanne";
58
+ src:
59
+ url("./assets/fonts/TWKLausanne-500.woff") format("woff"),
60
+ url("./assets/fonts/TWKLausanne-500.woff2") format("woff2");
61
+ font-style: normal;
62
+ font-weight: 500;
63
+ }
64
+
65
+ @font-face {
66
+ font-family: "TWK Lausanne";
67
+ src:
68
+ url("./assets/fonts/TWKLausanne-600.woff") format("woff"),
69
+ url("./assets/fonts/TWKLausanne-600.woff2") format("woff2");
70
+ font-style: normal;
71
+ font-weight: 600;
72
+ }
73
+
74
+ iframe {
75
+ color-scheme: light;
76
+ }
77
+
78
+ /* This is needed to prevent edges from getting cut off*/
79
+ .react-flow__pane {
80
+ width: 320rem !important;
81
+ height: 320rem !important;
82
+ }
package/src/main.tsx ADDED
@@ -0,0 +1,39 @@
1
+ import React from "react";
2
+ import ReactDOM from "react-dom/client";
3
+ import { createBrowserRouter, redirect, RouterProvider } from "react-router-dom";
4
+ import "@fontsource/ibm-plex-mono";
5
+
6
+ import "./main.css";
7
+
8
+ const router = createBrowserRouter([
9
+ {
10
+ children: [
11
+ {
12
+ path: "/",
13
+ lazy: () => import("./app/pages/index"),
14
+ id: "graph",
15
+ },
16
+ {
17
+ // adding redirect to root to catch any static links/demos that are using this url
18
+ path: "/explorer/lineage",
19
+ loader: async ({ request }) => {
20
+ const url = new URL(request.url);
21
+ const searchParams = url.searchParams.toString();
22
+ return redirect(`/?${searchParams}`);
23
+ },
24
+ },
25
+ // {
26
+ // path: "/prolly-proof/:cid/:id",
27
+ // loader: async (req) => prollyProofLoader(req),
28
+ // },
29
+ ],
30
+ },
31
+ ]);
32
+
33
+ ReactDOM.createRoot(document.getElementById("root")!).render(
34
+ <React.StrictMode>
35
+ <main>
36
+ <RouterProvider router={router} />
37
+ </main>
38
+ </React.StrictMode>,
39
+ );
@@ -0,0 +1,53 @@
1
+ import Details from "@/components/ui/details";
2
+ import { SectionList } from "@/explorer-component/components/sidebar/SectionList";
3
+ import { VCompContainerInfo } from "@/v-comp-viewer/utils";
4
+ import DisplayCode from "@/components/ui/display-code";
5
+
6
+ const ContainerDidDetails = ({ containerInfo }: { containerInfo: VCompContainerInfo }) => {
7
+ const data = [
8
+ {
9
+ label: "Container Notary",
10
+ value: <DisplayCode value={`${containerInfo.did.value}`} validated={containerInfo.did.validated} />,
11
+ offsetTopLabel: true,
12
+ },
13
+ {
14
+ label: "Docker Compose",
15
+ value: (
16
+ <DisplayCode
17
+ value={`cid:${containerInfo.dockerComposeId.value}`}
18
+ validated={containerInfo.dockerComposeId.validated}
19
+ />
20
+ ),
21
+ offsetTopLabel: true,
22
+ },
23
+ {
24
+ label: "Docker Images",
25
+ value: (
26
+ <div className="space-y-4">
27
+ {containerInfo.dockerImages.images.map((image: { name: string; sha256: string }) => {
28
+ return (
29
+ <DisplayCode
30
+ key={image.name}
31
+ value={`sha256:${image.sha256}`}
32
+ validated={containerInfo.dockerImages.validated}
33
+ slot={<code>{image.name}</code>}
34
+ />
35
+ );
36
+ })}
37
+ </div>
38
+ ),
39
+ offsetTopLabel: true,
40
+ },
41
+ {
42
+ label: "Signed By",
43
+ value: (
44
+ <DisplayCode value={`${containerInfo.signedBy.value}`} validated={containerInfo.signedBy.validated} />
45
+ ),
46
+ offsetTopLabel: true,
47
+ },
48
+ ];
49
+
50
+ return <Details title="Details" content={<SectionList data={data} className="mt-4 pb-4" />} />;
51
+ };
52
+
53
+ export default ContainerDidDetails;