@dxos/plugin-explorer 0.6.8-main.046e6cf

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 (124) hide show
  1. package/LICENSE +8 -0
  2. package/README.md +3 -0
  3. package/dist/lib/browser/ExplorerArticle-IPAJQMAX.mjs +27 -0
  4. package/dist/lib/browser/ExplorerArticle-IPAJQMAX.mjs.map +7 -0
  5. package/dist/lib/browser/ExplorerMain-3KFXOEYO.mjs +33 -0
  6. package/dist/lib/browser/ExplorerMain-3KFXOEYO.mjs.map +7 -0
  7. package/dist/lib/browser/chunk-7YEM64IQ.mjs +473 -0
  8. package/dist/lib/browser/chunk-7YEM64IQ.mjs.map +7 -0
  9. package/dist/lib/browser/chunk-JIDPF2GF.mjs +27 -0
  10. package/dist/lib/browser/chunk-JIDPF2GF.mjs.map +7 -0
  11. package/dist/lib/browser/chunk-TL6ADY3P.mjs +21 -0
  12. package/dist/lib/browser/chunk-TL6ADY3P.mjs.map +7 -0
  13. package/dist/lib/browser/index.mjs +38151 -0
  14. package/dist/lib/browser/index.mjs.map +7 -0
  15. package/dist/lib/browser/meta.json +1 -0
  16. package/dist/lib/browser/meta.mjs +9 -0
  17. package/dist/lib/browser/meta.mjs.map +7 -0
  18. package/dist/lib/browser/types/index.mjs +10 -0
  19. package/dist/lib/browser/types/index.mjs.map +7 -0
  20. package/dist/lib/node/ExplorerArticle-PYOGBY3Z.cjs +53 -0
  21. package/dist/lib/node/ExplorerArticle-PYOGBY3Z.cjs.map +7 -0
  22. package/dist/lib/node/ExplorerMain-HGCLO5O4.cjs +59 -0
  23. package/dist/lib/node/ExplorerMain-HGCLO5O4.cjs.map +7 -0
  24. package/dist/lib/node/chunk-2GOPBQBC.cjs +494 -0
  25. package/dist/lib/node/chunk-2GOPBQBC.cjs.map +7 -0
  26. package/dist/lib/node/chunk-HYXFS3AG.cjs +45 -0
  27. package/dist/lib/node/chunk-HYXFS3AG.cjs.map +7 -0
  28. package/dist/lib/node/chunk-UJZYAOD2.cjs +54 -0
  29. package/dist/lib/node/chunk-UJZYAOD2.cjs.map +7 -0
  30. package/dist/lib/node/index.cjs +38158 -0
  31. package/dist/lib/node/index.cjs.map +7 -0
  32. package/dist/lib/node/meta.cjs +30 -0
  33. package/dist/lib/node/meta.cjs.map +7 -0
  34. package/dist/lib/node/meta.json +1 -0
  35. package/dist/lib/node/types/index.cjs +32 -0
  36. package/dist/lib/node/types/index.cjs.map +7 -0
  37. package/dist/types/src/ExplorerPlugin.d.ts +4 -0
  38. package/dist/types/src/ExplorerPlugin.d.ts.map +1 -0
  39. package/dist/types/src/components/Chart/Chart.d.ts +10 -0
  40. package/dist/types/src/components/Chart/Chart.d.ts.map +1 -0
  41. package/dist/types/src/components/Chart/Chart.stories.d.ts +11 -0
  42. package/dist/types/src/components/Chart/Chart.stories.d.ts.map +1 -0
  43. package/dist/types/src/components/Chart/index.d.ts +2 -0
  44. package/dist/types/src/components/Chart/index.d.ts.map +1 -0
  45. package/dist/types/src/components/ExplorerArticle.d.ts +7 -0
  46. package/dist/types/src/components/ExplorerArticle.d.ts.map +1 -0
  47. package/dist/types/src/components/ExplorerMain.d.ts +7 -0
  48. package/dist/types/src/components/ExplorerMain.d.ts.map +1 -0
  49. package/dist/types/src/components/Globe/Globe.d.ts +12 -0
  50. package/dist/types/src/components/Globe/Globe.d.ts.map +1 -0
  51. package/dist/types/src/components/Globe/Globe.stories.d.ts +12 -0
  52. package/dist/types/src/components/Globe/Globe.stories.d.ts.map +1 -0
  53. package/dist/types/src/components/Globe/index.d.ts +2 -0
  54. package/dist/types/src/components/Globe/index.d.ts.map +1 -0
  55. package/dist/types/src/components/Graph/Graph.d.ts +8 -0
  56. package/dist/types/src/components/Graph/Graph.d.ts.map +1 -0
  57. package/dist/types/src/components/Graph/Graph.stories.d.ts +14 -0
  58. package/dist/types/src/components/Graph/Graph.stories.d.ts.map +1 -0
  59. package/dist/types/src/components/Graph/graph-model.d.ts +33 -0
  60. package/dist/types/src/components/Graph/graph-model.d.ts.map +1 -0
  61. package/dist/types/src/components/Graph/index.d.ts +3 -0
  62. package/dist/types/src/components/Graph/index.d.ts.map +1 -0
  63. package/dist/types/src/components/Tree/Tree.d.ts +27 -0
  64. package/dist/types/src/components/Tree/Tree.d.ts.map +1 -0
  65. package/dist/types/src/components/Tree/Tree.stories.d.ts +29 -0
  66. package/dist/types/src/components/Tree/Tree.stories.d.ts.map +1 -0
  67. package/dist/types/src/components/Tree/index.d.ts +2 -0
  68. package/dist/types/src/components/Tree/index.d.ts.map +1 -0
  69. package/dist/types/src/components/Tree/layout/HierarchicalEdgeBundling.d.ts +5 -0
  70. package/dist/types/src/components/Tree/layout/HierarchicalEdgeBundling.d.ts.map +1 -0
  71. package/dist/types/src/components/Tree/layout/RadialTree.d.ts +4 -0
  72. package/dist/types/src/components/Tree/layout/RadialTree.d.ts.map +1 -0
  73. package/dist/types/src/components/Tree/layout/TidyTree.d.ts +4 -0
  74. package/dist/types/src/components/Tree/layout/TidyTree.d.ts.map +1 -0
  75. package/dist/types/src/components/Tree/layout/index.d.ts +5 -0
  76. package/dist/types/src/components/Tree/layout/index.d.ts.map +1 -0
  77. package/dist/types/src/components/Tree/types.d.ts +8 -0
  78. package/dist/types/src/components/Tree/types.d.ts.map +1 -0
  79. package/dist/types/src/components/index.d.ts +12 -0
  80. package/dist/types/src/components/index.d.ts.map +1 -0
  81. package/dist/types/src/components/plot.d.ts +12 -0
  82. package/dist/types/src/components/plot.d.ts.map +1 -0
  83. package/dist/types/src/index.d.ts +5 -0
  84. package/dist/types/src/index.d.ts.map +1 -0
  85. package/dist/types/src/meta.d.ts +15 -0
  86. package/dist/types/src/meta.d.ts.map +1 -0
  87. package/dist/types/src/translations.d.ts +12 -0
  88. package/dist/types/src/translations.d.ts.map +1 -0
  89. package/dist/types/src/types/index.d.ts +3 -0
  90. package/dist/types/src/types/index.d.ts.map +1 -0
  91. package/dist/types/src/types/types.d.ts +7 -0
  92. package/dist/types/src/types/types.d.ts.map +1 -0
  93. package/dist/types/src/types/view.d.ts +14 -0
  94. package/dist/types/src/types/view.d.ts.map +1 -0
  95. package/package.json +98 -0
  96. package/src/ExplorerPlugin.tsx +103 -0
  97. package/src/components/Chart/Chart.stories.tsx +46 -0
  98. package/src/components/Chart/Chart.tsx +54 -0
  99. package/src/components/Chart/index.ts +5 -0
  100. package/src/components/ExplorerArticle.tsx +28 -0
  101. package/src/components/ExplorerMain.tsx +34 -0
  102. package/src/components/Globe/Globe.stories.tsx +115 -0
  103. package/src/components/Globe/Globe.tsx +65 -0
  104. package/src/components/Globe/index.ts +5 -0
  105. package/src/components/Graph/Graph.stories.tsx +59 -0
  106. package/src/components/Graph/Graph.tsx +151 -0
  107. package/src/components/Graph/graph-model.ts +146 -0
  108. package/src/components/Graph/index.ts +7 -0
  109. package/src/components/Tree/Tree.stories.tsx +97 -0
  110. package/src/components/Tree/Tree.tsx +109 -0
  111. package/src/components/Tree/index.ts +5 -0
  112. package/src/components/Tree/layout/HierarchicalEdgeBundling.ts +164 -0
  113. package/src/components/Tree/layout/RadialTree.ts +96 -0
  114. package/src/components/Tree/layout/TidyTree.ts +102 -0
  115. package/src/components/Tree/layout/index.ts +9 -0
  116. package/src/components/Tree/types.ts +39 -0
  117. package/src/components/index.ts +14 -0
  118. package/src/components/plot.ts +15 -0
  119. package/src/index.ts +12 -0
  120. package/src/meta.tsx +19 -0
  121. package/src/translations.ts +18 -0
  122. package/src/types/index.ts +6 -0
  123. package/src/types/types.ts +27 -0
  124. package/src/types/view.ts +11 -0
package/LICENSE ADDED
@@ -0,0 +1,8 @@
1
+ MIT License
2
+ Copyright (c) 2022 DXOS
3
+
4
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
5
+
6
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
7
+
8
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,3 @@
1
+ # @dxos/plugin-explorer
2
+
3
+ Surface plugin for data visualization.
@@ -0,0 +1,27 @@
1
+ import {
2
+ Graph
3
+ } from "./chunk-7YEM64IQ.mjs";
4
+
5
+ // packages/plugins/experimental/plugin-explorer/src/components/ExplorerArticle.tsx
6
+ import React from "react";
7
+ import { useGlobalSearch } from "@dxos/plugin-search";
8
+ import { getSpace } from "@dxos/react-client/echo";
9
+ var ExplorerArticle = ({ view }) => {
10
+ const space = getSpace(view);
11
+ const { match } = useGlobalSearch();
12
+ if (!space) {
13
+ return null;
14
+ }
15
+ return /* @__PURE__ */ React.createElement("div", {
16
+ role: "none",
17
+ className: "row-span-2 overflow-auto"
18
+ }, /* @__PURE__ */ React.createElement(Graph, {
19
+ space,
20
+ match
21
+ }));
22
+ };
23
+ var ExplorerArticle_default = ExplorerArticle;
24
+ export {
25
+ ExplorerArticle_default as default
26
+ };
27
+ //# sourceMappingURL=ExplorerArticle-IPAJQMAX.mjs.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/components/ExplorerArticle.tsx"],
4
+ "sourcesContent": ["//\n// Copyright 2023 DXOS.org\n//\n\nimport React from 'react';\n\nimport { useGlobalSearch } from '@dxos/plugin-search';\nimport { getSpace } from '@dxos/react-client/echo';\n\nimport { Graph } from './Graph';\nimport { type ViewType } from '../types';\n\nconst ExplorerArticle = ({ view }: { view: ViewType }) => {\n const space = getSpace(view);\n const { match } = useGlobalSearch();\n\n if (!space) {\n return null;\n }\n\n return (\n <div role='none' className='row-span-2 overflow-auto'>\n <Graph space={space} match={match} />\n </div>\n );\n};\n\nexport default ExplorerArticle;\n"],
5
+ "mappings": ";;;;;AAIA,OAAOA,WAAW;AAElB,SAASC,uBAAuB;AAChC,SAASC,gBAAgB;AAKzB,IAAMC,kBAAkB,CAAC,EAAEC,KAAI,MAAsB;AACnD,QAAMC,QAAQC,SAASF,IAAAA;AACvB,QAAM,EAAEG,MAAK,IAAKC,gBAAAA;AAElB,MAAI,CAACH,OAAO;AACV,WAAO;EACT;AAEA,SACE,sBAAA,cAACI,OAAAA;IAAIC,MAAK;IAAOC,WAAU;KACzB,sBAAA,cAACC,OAAAA;IAAMP;IAAcE;;AAG3B;AAEA,IAAA,0BAAeJ;",
6
+ "names": ["React", "useGlobalSearch", "getSpace", "ExplorerArticle", "view", "space", "getSpace", "match", "useGlobalSearch", "div", "role", "className", "Graph"]
7
+ }
@@ -0,0 +1,33 @@
1
+ import {
2
+ Graph
3
+ } from "./chunk-7YEM64IQ.mjs";
4
+
5
+ // packages/plugins/experimental/plugin-explorer/src/components/ExplorerMain.tsx
6
+ import React from "react";
7
+ import { useGlobalSearch } from "@dxos/plugin-search";
8
+ import { getSpace } from "@dxos/react-client/echo";
9
+ import { Main } from "@dxos/react-ui";
10
+ import { baseSurface, topbarBlockPaddingStart, fixedInsetFlexLayout, bottombarBlockPaddingEnd } from "@dxos/react-ui-theme";
11
+ var ExplorerMain = ({ view }) => {
12
+ const space = getSpace(view);
13
+ const { match } = useGlobalSearch();
14
+ if (!space) {
15
+ return null;
16
+ }
17
+ return /* @__PURE__ */ React.createElement(Main.Content, {
18
+ classNames: [
19
+ baseSurface,
20
+ fixedInsetFlexLayout,
21
+ topbarBlockPaddingStart,
22
+ bottombarBlockPaddingEnd
23
+ ]
24
+ }, /* @__PURE__ */ React.createElement(Graph, {
25
+ space,
26
+ match
27
+ }));
28
+ };
29
+ var ExplorerMain_default = ExplorerMain;
30
+ export {
31
+ ExplorerMain_default as default
32
+ };
33
+ //# sourceMappingURL=ExplorerMain-3KFXOEYO.mjs.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/components/ExplorerMain.tsx"],
4
+ "sourcesContent": ["//\n// Copyright 2023 DXOS.org\n//\n\nimport React from 'react';\n\nimport { useGlobalSearch } from '@dxos/plugin-search';\nimport { getSpace } from '@dxos/react-client/echo';\nimport { Main } from '@dxos/react-ui';\nimport {\n baseSurface,\n topbarBlockPaddingStart,\n fixedInsetFlexLayout,\n bottombarBlockPaddingEnd,\n} from '@dxos/react-ui-theme';\n\nimport { Graph } from './Graph';\nimport { type ViewType } from '../types';\n\nconst ExplorerMain = ({ view }: { view: ViewType }) => {\n const space = getSpace(view);\n const { match } = useGlobalSearch();\n if (!space) {\n return null;\n }\n\n return (\n <Main.Content classNames={[baseSurface, fixedInsetFlexLayout, topbarBlockPaddingStart, bottombarBlockPaddingEnd]}>\n <Graph space={space} match={match} />\n </Main.Content>\n );\n};\n\nexport default ExplorerMain;\n"],
5
+ "mappings": ";;;;;AAIA,OAAOA,WAAW;AAElB,SAASC,uBAAuB;AAChC,SAASC,gBAAgB;AACzB,SAASC,YAAY;AACrB,SACEC,aACAC,yBACAC,sBACAC,gCACK;AAKP,IAAMC,eAAe,CAAC,EAAEC,KAAI,MAAsB;AAChD,QAAMC,QAAQC,SAASF,IAAAA;AACvB,QAAM,EAAEG,MAAK,IAAKC,gBAAAA;AAClB,MAAI,CAACH,OAAO;AACV,WAAO;EACT;AAEA,SACE,sBAAA,cAACI,KAAKC,SAAO;IAACC,YAAY;MAACC;MAAaC;MAAsBC;MAAyBC;;KACrF,sBAAA,cAACC,OAAAA;IAAMX;IAAcE;;AAG3B;AAEA,IAAA,uBAAeJ;",
6
+ "names": ["React", "useGlobalSearch", "getSpace", "Main", "baseSurface", "topbarBlockPaddingStart", "fixedInsetFlexLayout", "bottombarBlockPaddingEnd", "ExplorerMain", "view", "space", "getSpace", "match", "useGlobalSearch", "Main", "Content", "classNames", "baseSurface", "fixedInsetFlexLayout", "topbarBlockPaddingStart", "bottombarBlockPaddingEnd", "Graph"]
7
+ }
@@ -0,0 +1,473 @@
1
+ // packages/plugins/experimental/plugin-explorer/src/components/Graph/graph-model.ts
2
+ import { AST, DynamicSchema, getSchema, getType, ReferenceAnnotationId, SchemaValidator, StoredSchema } from "@dxos/echo-schema";
3
+ import { GraphModel } from "@dxos/gem-spore";
4
+ import { log } from "@dxos/log";
5
+ import { CollectionType } from "@dxos/plugin-space/types";
6
+ var __dxlog_file = "/home/runner/work/dxos/dxos/packages/plugins/experimental/plugin-explorer/src/components/Graph/graph-model.ts";
7
+ var SpaceGraphModel = class extends GraphModel {
8
+ constructor(_options = {}) {
9
+ super();
10
+ this._options = _options;
11
+ this._graph = {
12
+ nodes: [],
13
+ links: []
14
+ };
15
+ }
16
+ get graph() {
17
+ return this._graph;
18
+ }
19
+ get objects() {
20
+ return this._objects ?? [];
21
+ }
22
+ open(space, objectId) {
23
+ if (!this._subscription) {
24
+ const query = space.db.query((object) => !(object instanceof CollectionType));
25
+ this._subscription = query.subscribe(({ objects }) => {
26
+ this._objects = objects;
27
+ this._graph.nodes = objects.map((object) => {
28
+ if (object instanceof StoredSchema) {
29
+ const effectSchema = space.db.schema.getSchemaById(object.id);
30
+ return {
31
+ type: "schema",
32
+ id: object.id,
33
+ schema: effectSchema.schema
34
+ };
35
+ }
36
+ return {
37
+ type: "echo-object",
38
+ id: object.id,
39
+ object
40
+ };
41
+ });
42
+ this._graph.links = objects.reduce((links, object) => {
43
+ const objectSchema = getSchema(object);
44
+ const typename = getType(object)?.objectId;
45
+ if (objectSchema == null || typename == null) {
46
+ log.info("no schema for object:", {
47
+ id: object.id.slice(0, 8)
48
+ }, {
49
+ F: __dxlog_file,
50
+ L: 81,
51
+ S: this,
52
+ C: (f, a) => f(...a)
53
+ });
54
+ return links;
55
+ }
56
+ if (!(objectSchema instanceof DynamicSchema)) {
57
+ const idx = objects.findIndex((obj) => obj.id === typename);
58
+ if (idx === -1) {
59
+ this._graph.nodes.push({
60
+ id: typename,
61
+ type: "schema",
62
+ schema: objectSchema
63
+ });
64
+ }
65
+ }
66
+ if (this._options.schema) {
67
+ links.push({
68
+ id: `${object.id}-${typename}`,
69
+ source: object.id,
70
+ target: typename
71
+ });
72
+ }
73
+ AST.getPropertySignatures(objectSchema.ast).forEach((prop) => {
74
+ if (!SchemaValidator.hasTypeAnnotation(objectSchema, prop.name.toString(), ReferenceAnnotationId)) {
75
+ return;
76
+ }
77
+ const value = object[String(prop.name)];
78
+ if (value) {
79
+ const refs = Array.isArray(value) ? value : [
80
+ value
81
+ ];
82
+ for (const ref of refs) {
83
+ if (objects.findIndex((obj) => obj.id === ref.id) !== -1) {
84
+ links.push({
85
+ id: `${object.id}-${String(prop.name)}-${ref.id}`,
86
+ source: object.id,
87
+ target: ref.id
88
+ });
89
+ }
90
+ }
91
+ }
92
+ });
93
+ return links;
94
+ }, []);
95
+ this.triggerUpdate();
96
+ }, {
97
+ fire: true
98
+ });
99
+ }
100
+ this.setSelected(objectId);
101
+ return this;
102
+ }
103
+ close() {
104
+ if (this._subscription) {
105
+ this._subscription();
106
+ this._subscription = void 0;
107
+ }
108
+ return this;
109
+ }
110
+ };
111
+
112
+ // packages/plugins/experimental/plugin-explorer/src/components/Tree/Tree.tsx
113
+ import React2, { useEffect as useEffect2, useMemo as useMemo2, useState as useState2 } from "react";
114
+ import { useResizeDetector } from "react-resize-detector";
115
+ import { createSvgContext as createSvgContext2, SVG as SVG2, SVGContextProvider as SVGContextProvider2 } from "@dxos/gem-core";
116
+
117
+ // packages/plugins/experimental/plugin-explorer/src/components/Tree/layout/HierarchicalEdgeBundling.ts
118
+ import * as d3 from "d3";
119
+ var HierarchicalEdgeBundling = (s, data, options) => {
120
+ const svg = d3.select(s);
121
+ svg.selectAll("*").remove();
122
+ const { radius = 600, padding = 100, slots: slots2 } = options;
123
+ const root = d3.hierarchy(flatten(data));
124
+ const tree3 = d3.cluster().size([
125
+ 2 * Math.PI,
126
+ radius - padding
127
+ ]);
128
+ const layout = tree3(addLinks(root));
129
+ const node = svg.append("g").selectAll().data(layout.leaves()).join("g").attr("transform", (d) => `rotate(${d.x * (180 / Math.PI) - 90}) translate(${d.y},0)`).append("text").attr("class", slots2?.text ?? "").attr("dy", "0.31em").attr("x", (d) => d.x < Math.PI ? 6 : -6).attr("text-anchor", (d) => d.x < Math.PI ? "start" : "end").attr("transform", (d) => d.x >= Math.PI ? "rotate(180)" : null).call((text) => text.text((d) => d.data.id.slice(0, 8)));
130
+ const line = d3.lineRadial().curve(d3.curveBundle.beta(0.85)).radius((d) => d.y).angle((d) => d.x);
131
+ const links = svg.append("g").selectAll().data(layout.leaves().flatMap((leaf) => leaf.outgoing)).join("path").style("mix-blend-mode", "multiply").attr("class", slots2?.path ?? "").attr("d", ([i, o]) => {
132
+ return line(i.path(o));
133
+ }).each(function(d) {
134
+ d.path = this;
135
+ });
136
+ };
137
+ var addLinks = (root) => {
138
+ const nodes = new Map(root.descendants().map((d) => [
139
+ d.data.id,
140
+ d
141
+ ]));
142
+ const parents = root.descendants().reduce((map, d) => {
143
+ if (d.children?.length) {
144
+ map.set(d.data.id, d);
145
+ }
146
+ return map;
147
+ }, /* @__PURE__ */ new Map());
148
+ for (const d of root.leaves()) {
149
+ const parent = parents.get(d.data.id);
150
+ if (parent) {
151
+ d.outgoing = parent.data.children?.slice(1).map((child) => {
152
+ return [
153
+ d,
154
+ nodes.get(child.id)
155
+ ];
156
+ }) ?? [];
157
+ } else {
158
+ d.outgoing = [];
159
+ }
160
+ }
161
+ return root;
162
+ };
163
+ var flatten = (node) => {
164
+ const clone = {
165
+ id: node.id
166
+ };
167
+ if (node.children?.length) {
168
+ const children = node.children.map((child) => flatten(child));
169
+ clone.children = [
170
+ {
171
+ id: node.id
172
+ },
173
+ ...children
174
+ ];
175
+ }
176
+ return clone;
177
+ };
178
+ var HierarchicalEdgeBundling_default = HierarchicalEdgeBundling;
179
+
180
+ // packages/plugins/experimental/plugin-explorer/src/components/Tree/layout/RadialTree.ts
181
+ import * as d32 from "d3";
182
+ var RadialTree = (s, data, options) => {
183
+ const svg = d32.select(s);
184
+ svg.selectAll("*").remove();
185
+ const { label, radius = 400, r = 4, slots: slots2 } = options;
186
+ const arc = 2 * Math.PI;
187
+ const root = d32.hierarchy(data);
188
+ const descendants = root.descendants();
189
+ const getLabel = label === null ? null : descendants.map((d) => label(d.data));
190
+ const layout = d32.tree().size([
191
+ arc,
192
+ radius
193
+ ]).separation((a, b) => (a.parent === b.parent ? 1 : 2) / a.depth);
194
+ layout(root);
195
+ svg.append("g").selectAll("path").data(root.links()).join("path").attr("class", slots2?.path ?? "").attr("d", d32.linkRadial().angle((d) => d.x + Math.PI / 2).radius((d) => d.y));
196
+ const node = svg.append("g").selectAll("a").data(root.descendants()).join("a").attr("transform", (d) => `rotate(${d.x * 180 / Math.PI}) translate(${d.y},0)`);
197
+ node.append("circle").attr("class", slots2?.node ?? "").attr("r", r);
198
+ if (getLabel) {
199
+ node.append("text").attr("transform", (d) => `rotate(${d.x >= Math.PI ? 180 : 0})`).attr("dy", "0.32em").attr("x", (d) => d.x < Math.PI === !d.children ? 6 : -6).attr("text-anchor", (d) => d.x < Math.PI === !d.children ? "start" : "end").attr("class", slots2?.text ?? "").text((d, i) => getLabel[i]);
200
+ }
201
+ return svg.node();
202
+ };
203
+ var RadialTree_default = RadialTree;
204
+
205
+ // packages/plugins/experimental/plugin-explorer/src/components/Tree/layout/TidyTree.ts
206
+ import * as d33 from "d3";
207
+ var TidyTree = (s, data, options) => {
208
+ const svg = d33.select(s);
209
+ svg.selectAll("*").remove();
210
+ const { label, width, height, r = 4, padding = 4, margin = 60, slots: slots2 } = options;
211
+ const root = d33.hierarchy(data);
212
+ const descendants = root.descendants();
213
+ const getLabel = label == null ? null : descendants.map((d) => label(d.data));
214
+ const dx = 16;
215
+ const dy = width / (root.height + padding);
216
+ const layout = d33.tree().nodeSize([
217
+ dx,
218
+ dy
219
+ ]);
220
+ layout(root);
221
+ let x0 = Infinity;
222
+ let x1 = -x0;
223
+ let y0 = Infinity;
224
+ let y1 = -y0;
225
+ root.each((d) => {
226
+ if (d.x > x1) {
227
+ x1 = d.x;
228
+ }
229
+ if (d.x < x0) {
230
+ x0 = d.x;
231
+ }
232
+ if (d.y > y1) {
233
+ y1 = d.y;
234
+ }
235
+ if (d.y < y0) {
236
+ y0 = d.y;
237
+ }
238
+ });
239
+ const sx = Math.min(2, Math.max(1, (height - margin * 2) / (x1 - x0)));
240
+ const oy = -(width - (y1 - y0)) / 2;
241
+ svg.append("g").selectAll("path").data(root.links()).join("path").attr("class", slots2?.path ?? "").attr("d", d33.link(d33.curveBumpX).x((d) => d.y + oy).y((d) => d.x * sx));
242
+ const node = svg.append("g").selectAll("a").data(root.descendants()).join("a").attr("transform", (d) => `translate(${d.y + oy},${d.x * sx})`);
243
+ node.append("circle").attr("class", slots2?.node ?? "").attr("r", r);
244
+ if (getLabel) {
245
+ node.append("text").attr("dy", "0.32em").attr("x", (d) => d.children ? -6 : 6).attr("text-anchor", (d) => d.children ? "end" : "start").attr("class", slots2?.text ?? "").text((d, i) => getLabel[i]);
246
+ }
247
+ };
248
+ var TidyTree_default = TidyTree;
249
+
250
+ // packages/plugins/experimental/plugin-explorer/src/components/Tree/types.ts
251
+ var mapGraphToTreeData = (model, maxDepth = 8) => {
252
+ const mapNode = (node, depth = 0) => {
253
+ const treeNode = {
254
+ id: model.idAccessor(node),
255
+ label: model.idAccessor(node).slice(0, 8)
256
+ };
257
+ const links = model.graph.links.filter((link2) => link2.source === treeNode.id);
258
+ if (depth < maxDepth) {
259
+ treeNode.children = links.map((link2) => mapNode(model.graph.nodes.find((node2) => model.idAccessor(node2) === link2.target), depth + 1));
260
+ }
261
+ return treeNode;
262
+ };
263
+ let data;
264
+ if (model.selected) {
265
+ const node = model.graph.nodes.find((node2) => model.idAccessor(node2) === model.selected);
266
+ if (node) {
267
+ data = mapNode(node);
268
+ }
269
+ }
270
+ return data;
271
+ };
272
+
273
+ // packages/plugins/experimental/plugin-explorer/src/components/Graph/Graph.tsx
274
+ import React, { useEffect, useMemo, useRef, useState } from "react";
275
+ import { getType as getType2 } from "@dxos/echo-schema";
276
+ import { createSvgContext, darkGridStyles, defaultGridStyles, Grid, SVG, SVGContextProvider, Zoom } from "@dxos/gem-core";
277
+ import { Graph as GraphComponent, GraphForceProjector, Markers } from "@dxos/gem-spore";
278
+ import { filterObjectsSync } from "@dxos/plugin-search";
279
+ import { useThemeContext } from "@dxos/react-ui";
280
+ import { mx } from "@dxos/react-ui-theme";
281
+ var slots = {};
282
+ var colors = [
283
+ "[&>circle]:!fill-black-300 [&>circle]:!stroke-black-600",
284
+ "[&>circle]:!fill-slate-300 [&>circle]:!stroke-slate-600",
285
+ "[&>circle]:!fill-green-300 [&>circle]:!stroke-green-600",
286
+ "[&>circle]:!fill-sky-300 [&>circle]:!stroke-sky-600",
287
+ "[&>circle]:!fill-cyan-300 [&>circle]:!stroke-cyan-600",
288
+ "[&>circle]:!fill-rose-300 [&>circle]:!stroke-rose-600",
289
+ "[&>circle]:!fill-purple-300 [&>circle]:!stroke-purple-600",
290
+ "[&>circle]:!fill-orange-300 [&>circle]:!stroke-orange-600",
291
+ "[&>circle]:!fill-teal-300 [&>circle]:!stroke-teal-600",
292
+ "[&>circle]:!fill-indigo-300 [&>circle]:!stroke-indigo-600"
293
+ ];
294
+ var Graph = ({ space, match }) => {
295
+ const model = useMemo(() => space ? new SpaceGraphModel({
296
+ schema: true
297
+ }).open(space) : void 0, [
298
+ space
299
+ ]);
300
+ const [selected, setSelected] = useState();
301
+ const { themeMode } = useThemeContext();
302
+ const context = createSvgContext();
303
+ const projector = useMemo(() => new GraphForceProjector(context, {
304
+ forces: {
305
+ manyBody: {
306
+ strength: -100
307
+ },
308
+ link: {
309
+ distance: 180
310
+ },
311
+ radial: {
312
+ radius: 200,
313
+ strength: 0.05
314
+ }
315
+ },
316
+ attributes: {
317
+ radius: (node) => node.data?.type === "schema" ? 24 : 12
318
+ }
319
+ }), []);
320
+ const filteredRef = useRef();
321
+ filteredRef.current = filterObjectsSync(model?.objects ?? [], match);
322
+ useEffect(() => {
323
+ void projector.start();
324
+ }, [
325
+ match
326
+ ]);
327
+ const [colorMap] = useState(/* @__PURE__ */ new Map());
328
+ if (!model) {
329
+ return null;
330
+ }
331
+ if (selected) {
332
+ return /* @__PURE__ */ React.createElement(Tree, {
333
+ space,
334
+ selected,
335
+ variant: "tidy",
336
+ onNodeClick: () => setSelected(void 0)
337
+ });
338
+ }
339
+ return /* @__PURE__ */ React.createElement(SVGContextProvider, {
340
+ context
341
+ }, /* @__PURE__ */ React.createElement(SVG, {
342
+ className: slots?.root?.className
343
+ }, /* @__PURE__ */ React.createElement(Markers, {
344
+ arrowSize: 6
345
+ }), /* @__PURE__ */ React.createElement(Grid, {
346
+ className: slots?.grid?.className ?? themeMode === "dark" ? darkGridStyles : defaultGridStyles
347
+ }), /* @__PURE__ */ React.createElement(Zoom, {
348
+ extent: [
349
+ 1 / 2,
350
+ 4
351
+ ]
352
+ }, /* @__PURE__ */ React.createElement(GraphComponent, {
353
+ model,
354
+ projector,
355
+ drag: true,
356
+ arrows: true,
357
+ onSelect: (node) => setSelected(node?.data?.id),
358
+ labels: {
359
+ text: (node) => {
360
+ if (filteredRef.current?.length && !filteredRef.current.some((object) => object.id === node.data?.id)) {
361
+ return void 0;
362
+ }
363
+ return node.data?.label ?? node.data?.title ?? node.data?.name ?? node.data?.id.slice(0, 8);
364
+ }
365
+ },
366
+ attributes: {
367
+ node: (node) => {
368
+ let className;
369
+ if (node.data) {
370
+ const typename = getType2(node.data)?.objectId;
371
+ if (typename) {
372
+ className = colorMap.get(typename);
373
+ if (!className) {
374
+ className = colors[colorMap.size % colors.length];
375
+ colorMap.set(typename, className);
376
+ }
377
+ }
378
+ }
379
+ const selected2 = filteredRef.current?.some((object) => object.id === node.data?.id);
380
+ return {
381
+ class: mx(filteredRef.current?.length ? selected2 ? [
382
+ className
383
+ ] : "[&>text]:!fill-neutral-300" : [
384
+ "[&>text]:!fill-neutral-700",
385
+ className
386
+ ])
387
+ };
388
+ },
389
+ link: () => ({
390
+ class: "[&>path]:!stroke-neutral-300"
391
+ })
392
+ }
393
+ }))));
394
+ };
395
+
396
+ // packages/plugins/experimental/plugin-explorer/src/components/Tree/Tree.tsx
397
+ var defaultTreeLayoutSlots = {
398
+ node: "fill-blue-600",
399
+ path: "fill-none stroke-blue-400 stroke-[0.5px]",
400
+ text: "stroke-[0.5px] stroke-neutral-700 text-xs"
401
+ };
402
+ var renderers = /* @__PURE__ */ new Map([
403
+ [
404
+ "tidy",
405
+ TidyTree_default
406
+ ],
407
+ [
408
+ "radial",
409
+ RadialTree_default
410
+ ],
411
+ [
412
+ "edge",
413
+ HierarchicalEdgeBundling_default
414
+ ]
415
+ ]);
416
+ var Tree = ({ space, selected, variant = "tidy", onNodeClick }) => {
417
+ const model = useMemo2(() => space ? new SpaceGraphModel().open(space, selected) : void 0, [
418
+ space,
419
+ selected
420
+ ]);
421
+ const [tree3, setTree] = useState2();
422
+ useEffect2(() => {
423
+ return model?.subscribe(() => {
424
+ const tree4 = mapGraphToTreeData(model);
425
+ setTree(tree4);
426
+ }, true);
427
+ }, [
428
+ model
429
+ ]);
430
+ const context = createSvgContext2();
431
+ const { ref, width = 0, height = 0 } = useResizeDetector();
432
+ useEffect2(() => {
433
+ if (width && height) {
434
+ const size = Math.min(width, height);
435
+ const radius = size * 0.4;
436
+ const options = {
437
+ // TODO(burdon): Type.
438
+ label: (d) => d.label ?? d.id,
439
+ width,
440
+ height,
441
+ radius,
442
+ marginLeft: (width - radius * 2) / 2,
443
+ marginRight: (width - radius * 2) / 2,
444
+ marginTop: (height - radius * 2) / 2,
445
+ marginBottom: (height - radius * 2) / 2,
446
+ slots: defaultTreeLayoutSlots
447
+ };
448
+ if (tree3) {
449
+ const renderer = renderers.get(variant);
450
+ renderer?.(context.ref.current, tree3, options);
451
+ }
452
+ }
453
+ }, [
454
+ tree3,
455
+ width,
456
+ height
457
+ ]);
458
+ return /* @__PURE__ */ React2.createElement("div", {
459
+ ref,
460
+ className: "flex grow overflow-hidden",
461
+ onClick: () => onNodeClick?.()
462
+ }, /* @__PURE__ */ React2.createElement(SVGContextProvider2, {
463
+ context
464
+ }, /* @__PURE__ */ React2.createElement(SVG2, null)));
465
+ };
466
+
467
+ export {
468
+ SpaceGraphModel,
469
+ defaultTreeLayoutSlots,
470
+ Tree,
471
+ Graph
472
+ };
473
+ //# sourceMappingURL=chunk-7YEM64IQ.mjs.map